summaryrefslogtreecommitdiff
path: root/doc/optparse/ruby/float.rb
diff options
context:
space:
mode:
Diffstat (limited to 'doc/optparse/ruby/float.rb')
-rw-r--r--doc/optparse/ruby/float.rb6
1 files changed, 6 insertions, 0 deletions
diff --git a/doc/optparse/ruby/float.rb b/doc/optparse/ruby/float.rb
new file mode 100644
index 0000000000..390df7f7bd
--- /dev/null
+++ b/doc/optparse/ruby/float.rb
@@ -0,0 +1,6 @@
+require 'optparse'
+parser = OptionParser.new
+parser.on('--float=FLOAT', Float) do |value|
+ p [value, value.class]
+end
+parser.parse!
09b96f8467cd014bc5dd4c'>spec/ruby/README.md26
-rwxr-xr-xspec/ruby/bin/rubocop12
-rw-r--r--spec/ruby/command_line/backtrace_limit_spec.rb49
-rwxr-xr-xspec/ruby/command_line/dash_0_spec.rb13
-rw-r--r--spec/ruby/command_line/dash_a_spec.rb4
-rw-r--r--spec/ruby/command_line/dash_l_spec.rb8
-rw-r--r--spec/ruby/command_line/dash_n_spec.rb8
-rw-r--r--spec/ruby/command_line/dash_p_spec.rb4
-rw-r--r--spec/ruby/command_line/dash_r_spec.rb8
-rw-r--r--spec/ruby/command_line/dash_upper_f_spec.rb2
-rw-r--r--spec/ruby/command_line/dash_upper_i_spec.rb10
-rw-r--r--spec/ruby/command_line/dash_upper_s_spec.rb40
-rw-r--r--spec/ruby/command_line/dash_upper_u_spec.rb31
-rw-r--r--spec/ruby/command_line/dash_v_spec.rb6
-rw-r--r--spec/ruby/command_line/dash_x_spec.rb2
-rw-r--r--spec/ruby/command_line/error_message_spec.rb5
-rw-r--r--spec/ruby/command_line/feature_spec.rb10
-rw-r--r--spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt2
-rw-r--r--spec/ruby/command_line/fixtures/bin/embedded_ruby.txt4
-rw-r--r--spec/ruby/command_line/fixtures/debug_info.rb1
-rw-r--r--spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rbbin121 -> 90 bytes-rw-r--r--spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb4
-rw-r--r--spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb4
-rw-r--r--spec/ruby/command_line/fixtures/string_literal_raw.rb3
-rw-r--r--spec/ruby/command_line/frozen_strings_spec.rb73
-rw-r--r--spec/ruby/command_line/rubylib_spec.rb16
-rw-r--r--spec/ruby/command_line/rubyopt_spec.rb20
-rw-r--r--spec/ruby/command_line/syntax_error_spec.rb4
-rw-r--r--spec/ruby/core/argf/argf_spec.rb4
-rw-r--r--spec/ruby/core/argf/argv_spec.rb2
-rw-r--r--spec/ruby/core/argf/binmode_spec.rb2
-rw-r--r--spec/ruby/core/argf/bytes_spec.rb16
-rw-r--r--spec/ruby/core/argf/chars_spec.rb16
-rw-r--r--spec/ruby/core/argf/close_spec.rb8
-rw-r--r--spec/ruby/core/argf/closed_spec.rb2
-rw-r--r--spec/ruby/core/argf/codepoints_spec.rb16
-rw-r--r--spec/ruby/core/argf/each_byte_spec.rb58
-rw-r--r--spec/ruby/core/argf/each_char_spec.rb58
-rw-r--r--spec/ruby/core/argf/each_codepoint_spec.rb58
-rw-r--r--spec/ruby/core/argf/each_line_spec.rb62
-rw-r--r--spec/ruby/core/argf/each_spec.rb5
-rw-r--r--spec/ruby/core/argf/eof_spec.rb28
-rw-r--r--spec/ruby/core/argf/filename_spec.rb28
-rw-r--r--spec/ruby/core/argf/fileno_spec.rb24
-rw-r--r--spec/ruby/core/argf/inspect_spec.rb7
-rw-r--r--spec/ruby/core/argf/lines_spec.rb16
-rw-r--r--spec/ruby/core/argf/path_spec.rb5
-rw-r--r--spec/ruby/core/argf/pos_spec.rb31
-rw-r--r--spec/ruby/core/argf/read_nonblock_spec.rb2
-rw-r--r--spec/ruby/core/argf/readchar_spec.rb2
-rw-r--r--spec/ruby/core/argf/readline_spec.rb2
-rw-r--r--spec/ruby/core/argf/readlines_spec.rb22
-rw-r--r--spec/ruby/core/argf/readpartial_spec.rb10
-rw-r--r--spec/ruby/core/argf/rewind_spec.rb2
-rw-r--r--spec/ruby/core/argf/seek_spec.rb2
-rw-r--r--spec/ruby/core/argf/shared/each_byte.rb58
-rw-r--r--spec/ruby/core/argf/shared/each_char.rb58
-rw-r--r--spec/ruby/core/argf/shared/each_codepoint.rb58
-rw-r--r--spec/ruby/core/argf/shared/each_line.rb62
-rw-r--r--spec/ruby/core/argf/shared/eof.rb24
-rw-r--r--spec/ruby/core/argf/shared/filename.rb28
-rw-r--r--spec/ruby/core/argf/shared/fileno.rb24
-rw-r--r--spec/ruby/core/argf/shared/getc.rb2
-rw-r--r--spec/ruby/core/argf/shared/pos.rb31
-rw-r--r--spec/ruby/core/argf/shared/read.rb4
-rw-r--r--spec/ruby/core/argf/shared/readlines.rb22
-rw-r--r--spec/ruby/core/argf/skip_spec.rb2
-rw-r--r--spec/ruby/core/argf/tell_spec.rb5
-rw-r--r--spec/ruby/core/argf/to_a_spec.rb5
-rw-r--r--spec/ruby/core/argf/to_i_spec.rb5
-rw-r--r--spec/ruby/core/argf/to_io_spec.rb2
-rw-r--r--spec/ruby/core/array/all_spec.rb13
-rw-r--r--spec/ruby/core/array/allocate_spec.rb4
-rw-r--r--spec/ruby/core/array/any_spec.rb12
-rw-r--r--spec/ruby/core/array/append_spec.rb11
-rw-r--r--spec/ruby/core/array/assoc_spec.rb40
-rw-r--r--spec/ruby/core/array/at_spec.rb4
-rw-r--r--spec/ruby/core/array/bsearch_index_spec.rb32
-rw-r--r--spec/ruby/core/array/bsearch_spec.rb26
-rw-r--r--spec/ruby/core/array/clear_spec.rb8
-rw-r--r--spec/ruby/core/array/clone_spec.rb8
-rw-r--r--spec/ruby/core/array/collect_spec.rb138
-rw-r--r--spec/ruby/core/array/combination_spec.rb6
-rw-r--r--spec/ruby/core/array/compact_spec.rb14
-rw-r--r--spec/ruby/core/array/comparison_spec.rb2
-rw-r--r--spec/ruby/core/array/concat_spec.rb10
-rw-r--r--spec/ruby/core/array/constructor_spec.rb4
-rw-r--r--spec/ruby/core/array/count_spec.rb11
-rw-r--r--spec/ruby/core/array/cycle_spec.rb20
-rw-r--r--spec/ruby/core/array/deconstruct_spec.rb2
-rw-r--r--spec/ruby/core/array/delete_at_spec.rb2
-rw-r--r--spec/ruby/core/array/delete_if_spec.rb46
-rw-r--r--spec/ruby/core/array/delete_spec.rb2
-rw-r--r--spec/ruby/core/array/difference_spec.rb4
-rw-r--r--spec/ruby/core/array/dig_spec.rb8
-rw-r--r--spec/ruby/core/array/drop_spec.rb18
-rw-r--r--spec/ruby/core/array/drop_while_spec.rb16
-rw-r--r--spec/ruby/core/array/dup_spec.rb12
-rw-r--r--spec/ruby/core/array/each_index_spec.rb20
-rw-r--r--spec/ruby/core/array/each_spec.rb9
-rw-r--r--spec/ruby/core/array/element_reference_spec.rb861
-rw-r--r--spec/ruby/core/array/element_set_spec.rb48
-rw-r--r--spec/ruby/core/array/eql_spec.rb4
-rw-r--r--spec/ruby/core/array/equal_value_spec.rb10
-rw-r--r--spec/ruby/core/array/fetch_spec.rb10
-rw-r--r--spec/ruby/core/array/fetch_values_spec.rb55
-rw-r--r--spec/ruby/core/array/fill_spec.rb132
-rw-r--r--spec/ruby/core/array/filter_spec.rb11
-rw-r--r--spec/ruby/core/array/find_index_spec.rb40
-rw-r--r--spec/ruby/core/array/first_spec.rb24
-rw-r--r--spec/ruby/core/array/fixtures/classes.rb754
-rw-r--r--spec/ruby/core/array/fixtures/encoded_strings.rb18
-rw-r--r--spec/ruby/core/array/flatten_spec.rb52
-rw-r--r--spec/ruby/core/array/hash_spec.rb8
-rw-r--r--spec/ruby/core/array/index_spec.rb5
-rw-r--r--spec/ruby/core/array/initialize_spec.rb34
-rw-r--r--spec/ruby/core/array/insert_spec.rb14
-rw-r--r--spec/ruby/core/array/inspect_spec.rb105
-rw-r--r--spec/ruby/core/array/intersect_spec.rb65
-rw-r--r--spec/ruby/core/array/join_spec.rb102
-rw-r--r--spec/ruby/core/array/keep_if_spec.rb3
-rw-r--r--spec/ruby/core/array/last_spec.rb22
-rw-r--r--spec/ruby/core/array/length_spec.rb11
-rw-r--r--spec/ruby/core/array/map_spec.rb10
-rw-r--r--spec/ruby/core/array/max_spec.rb8
-rw-r--r--spec/ruby/core/array/min_spec.rb10
-rw-r--r--spec/ruby/core/array/multiply_spec.rb34
-rw-r--r--spec/ruby/core/array/new_spec.rb30
-rw-r--r--spec/ruby/core/array/none_spec.rb13
-rw-r--r--spec/ruby/core/array/one_spec.rb13
-rw-r--r--spec/ruby/core/array/pack/a_spec.rb10
-rw-r--r--spec/ruby/core/array/pack/at_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/b_spec.rb6
-rw-r--r--spec/ruby/core/array/pack/buffer_spec.rb26
-rw-r--r--spec/ruby/core/array/pack/c_spec.rb8
-rw-r--r--spec/ruby/core/array/pack/comment_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/h_spec.rb6
-rw-r--r--spec/ruby/core/array/pack/l_spec.rb16
-rw-r--r--spec/ruby/core/array/pack/m_spec.rb24
-rw-r--r--spec/ruby/core/array/pack/percent_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/r_spec.rb89
-rw-r--r--spec/ruby/core/array/pack/shared/basic.rb34
-rw-r--r--spec/ruby/core/array/pack/shared/encodings.rb4
-rw-r--r--spec/ruby/core/array/pack/shared/float.rb52
-rw-r--r--spec/ruby/core/array/pack/shared/integer.rb48
-rw-r--r--spec/ruby/core/array/pack/shared/numeric_basic.rb24
-rw-r--r--spec/ruby/core/array/pack/shared/string.rb10
-rw-r--r--spec/ruby/core/array/pack/shared/unicode.rb14
-rw-r--r--spec/ruby/core/array/pack/u_spec.rb12
-rw-r--r--spec/ruby/core/array/pack/w_spec.rb10
-rw-r--r--spec/ruby/core/array/pack/x_spec.rb6
-rw-r--r--spec/ruby/core/array/pack/z_spec.rb6
-rw-r--r--spec/ruby/core/array/partition_spec.rb6
-rw-r--r--spec/ruby/core/array/permutation_spec.rb10
-rw-r--r--spec/ruby/core/array/plus_spec.rb27
-rw-r--r--spec/ruby/core/array/pop_spec.rb24
-rw-r--r--spec/ruby/core/array/prepend_spec.rb6
-rw-r--r--spec/ruby/core/array/product_spec.rb19
-rw-r--r--spec/ruby/core/array/push_spec.rb33
-rw-r--r--spec/ruby/core/array/rassoc_spec.rb16
-rw-r--r--spec/ruby/core/array/reject_spec.rb29
-rw-r--r--spec/ruby/core/array/repeated_combination_spec.rb8
-rw-r--r--spec/ruby/core/array/repeated_permutation_spec.rb4
-rw-r--r--spec/ruby/core/array/replace_spec.rb60
-rw-r--r--spec/ruby/core/array/reverse_each_spec.rb18
-rw-r--r--spec/ruby/core/array/reverse_spec.rb6
-rw-r--r--spec/ruby/core/array/rindex_spec.rb21
-rw-r--r--spec/ruby/core/array/rotate_spec.rb42
-rw-r--r--spec/ruby/core/array/sample_spec.rb39
-rw-r--r--spec/ruby/core/array/select_spec.rb35
-rw-r--r--spec/ruby/core/array/shared/clone.rb8
-rw-r--r--spec/ruby/core/array/shared/collect.rb109
-rw-r--r--spec/ruby/core/array/shared/difference.rb8
-rw-r--r--spec/ruby/core/array/shared/enumeratorize.rb2
-rw-r--r--spec/ruby/core/array/shared/eql.rb66
-rw-r--r--spec/ruby/core/array/shared/index.rb37
-rw-r--r--spec/ruby/core/array/shared/inspect.rb107
-rw-r--r--spec/ruby/core/array/shared/intersection.rb9
-rw-r--r--spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb25
-rw-r--r--spec/ruby/core/array/shared/join.rb97
-rw-r--r--spec/ruby/core/array/shared/keep_if.rb49
-rw-r--r--spec/ruby/core/array/shared/length.rb11
-rw-r--r--spec/ruby/core/array/shared/push.rb33
-rw-r--r--spec/ruby/core/array/shared/replace.rb60
-rw-r--r--spec/ruby/core/array/shared/select.rb32
-rw-r--r--spec/ruby/core/array/shared/slice.rb793
-rw-r--r--spec/ruby/core/array/shared/union.rb6
-rw-r--r--spec/ruby/core/array/shared/unshift.rb46
-rw-r--r--spec/ruby/core/array/shift_spec.rb20
-rw-r--r--spec/ruby/core/array/shuffle_spec.rb51
-rw-r--r--spec/ruby/core/array/size_spec.rb6
-rw-r--r--spec/ruby/core/array/slice_spec.rb71
-rw-r--r--spec/ruby/core/array/sort_by_spec.rb47
-rw-r--r--spec/ruby/core/array/sort_spec.rb40
-rw-r--r--spec/ruby/core/array/sum_spec.rb23
-rw-r--r--spec/ruby/core/array/take_spec.rb14
-rw-r--r--spec/ruby/core/array/take_while_spec.rb16
-rw-r--r--spec/ruby/core/array/to_a_spec.rb4
-rw-r--r--spec/ruby/core/array/to_ary_spec.rb4
-rw-r--r--spec/ruby/core/array/to_h_spec.rb28
-rw-r--r--spec/ruby/core/array/to_s_spec.rb7
-rw-r--r--spec/ruby/core/array/transpose_spec.rb10
-rw-r--r--spec/ruby/core/array/try_convert_spec.rb16
-rw-r--r--spec/ruby/core/array/union_spec.rb2
-rw-r--r--spec/ruby/core/array/uniq_spec.rb56
-rw-r--r--spec/ruby/core/array/unshift_spec.rb64
-rw-r--r--spec/ruby/core/array/values_at_spec.rb3
-rw-r--r--spec/ruby/core/array/zip_spec.rb8
-rw-r--r--spec/ruby/core/basicobject/__send___spec.rb2
-rw-r--r--spec/ruby/core/basicobject/basicobject_spec.rb20
-rw-r--r--spec/ruby/core/basicobject/equal_spec.rb20
-rw-r--r--spec/ruby/core/basicobject/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/basicobject/fixtures/classes.rb228
-rw-r--r--spec/ruby/core/basicobject/initialize_spec.rb4
-rw-r--r--spec/ruby/core/basicobject/instance_eval_spec.rb203
-rw-r--r--spec/ruby/core/basicobject/instance_exec_spec.rb48
-rw-r--r--spec/ruby/core/basicobject/method_missing_spec.rb3
-rw-r--r--spec/ruby/core/basicobject/not_equal_spec.rb16
-rw-r--r--spec/ruby/core/basicobject/not_spec.rb4
-rw-r--r--spec/ruby/core/basicobject/singleton_method_added_spec.rb14
-rw-r--r--spec/ruby/core/basicobject/singleton_method_removed_spec.rb2
-rw-r--r--spec/ruby/core/basicobject/singleton_method_undefined_spec.rb2
-rw-r--r--spec/ruby/core/binding/clone_spec.rb6
-rw-r--r--spec/ruby/core/binding/dup_spec.rb23
-rw-r--r--spec/ruby/core/binding/eval_spec.rb103
-rw-r--r--spec/ruby/core/binding/fixtures/irb.rb3
-rw-r--r--spec/ruby/core/binding/fixtures/irbrc1
-rw-r--r--spec/ruby/core/binding/irb_spec.rb16
-rw-r--r--spec/ruby/core/binding/local_variable_get_spec.rb10
-rw-r--r--spec/ruby/core/binding/local_variable_set_spec.rb8
-rw-r--r--spec/ruby/core/binding/local_variables_spec.rb2
-rw-r--r--spec/ruby/core/binding/shared/clone.rb22
-rw-r--r--spec/ruby/core/binding/source_location_spec.rb5
-rw-r--r--spec/ruby/core/builtin_constants/builtin_constants_spec.rb118
-rw-r--r--spec/ruby/core/class/allocate_spec.rb6
-rw-r--r--spec/ruby/core/class/attached_object_spec.rb29
-rw-r--r--spec/ruby/core/class/dup_spec.rb7
-rw-r--r--spec/ruby/core/class/inherited_spec.rb21
-rw-r--r--spec/ruby/core/class/initialize_spec.rb10
-rw-r--r--spec/ruby/core/class/new_spec.rb24
-rw-r--r--spec/ruby/core/class/subclasses_spec.rb95
-rw-r--r--spec/ruby/core/class/superclass_spec.rb2
-rw-r--r--spec/ruby/core/comparable/clamp_spec.rb179
-rw-r--r--spec/ruby/core/comparable/equal_value_spec.rb10
-rw-r--r--spec/ruby/core/comparable/fixtures/classes.rb1
-rw-r--r--spec/ruby/core/comparable/gt_spec.rb2
-rw-r--r--spec/ruby/core/comparable/gte_spec.rb2
-rw-r--r--spec/ruby/core/comparable/lt_spec.rb6
-rw-r--r--spec/ruby/core/comparable/lte_spec.rb2
-rw-r--r--spec/ruby/core/complex/abs_spec.rb10
-rw-r--r--spec/ruby/core/complex/angle_spec.rb5
-rw-r--r--spec/ruby/core/complex/arg_spec.rb9
-rw-r--r--spec/ruby/core/complex/coerce_spec.rb32
-rw-r--r--spec/ruby/core/complex/comparison_spec.rb12
-rw-r--r--spec/ruby/core/complex/conj_spec.rb5
-rw-r--r--spec/ruby/core/complex/conjugate_spec.rb8
-rw-r--r--spec/ruby/core/complex/constants_spec.rb2
-rw-r--r--spec/ruby/core/complex/divide_spec.rb82
-rw-r--r--spec/ruby/core/complex/eql_spec.rb12
-rw-r--r--spec/ruby/core/complex/equal_value_spec.rb10
-rw-r--r--spec/ruby/core/complex/exponent_spec.rb4
-rw-r--r--spec/ruby/core/complex/fdiv_spec.rb42
-rw-r--r--spec/ruby/core/complex/imag_spec.rb5
-rw-r--r--spec/ruby/core/complex/imaginary_spec.rb8
-rw-r--r--spec/ruby/core/complex/inspect_spec.rb21
-rw-r--r--spec/ruby/core/complex/integer_spec.rb4
-rw-r--r--spec/ruby/core/complex/magnitude_spec.rb5
-rw-r--r--spec/ruby/core/complex/marshal_dump_spec.rb2
-rw-r--r--spec/ruby/core/complex/negative_spec.rb4
-rw-r--r--spec/ruby/core/complex/phase_spec.rb5
-rw-r--r--spec/ruby/core/complex/polar_spec.rb18
-rw-r--r--spec/ruby/core/complex/positive_spec.rb4
-rw-r--r--spec/ruby/core/complex/quo_spec.rb5
-rw-r--r--spec/ruby/core/complex/rationalize_spec.rb8
-rw-r--r--spec/ruby/core/complex/real_spec.rb8
-rw-r--r--spec/ruby/core/complex/rect_spec.rb9
-rw-r--r--spec/ruby/core/complex/rectangular_spec.rb110
-rw-r--r--spec/ruby/core/complex/shared/abs.rb10
-rw-r--r--spec/ruby/core/complex/shared/arg.rb9
-rw-r--r--spec/ruby/core/complex/shared/conjugate.rb8
-rw-r--r--spec/ruby/core/complex/shared/divide.rb82
-rw-r--r--spec/ruby/core/complex/shared/image.rb8
-rw-r--r--spec/ruby/core/complex/shared/rect.rb94
-rw-r--r--spec/ruby/core/complex/to_c_spec.rb2
-rw-r--r--spec/ruby/core/complex/to_f_spec.rb4
-rw-r--r--spec/ruby/core/complex/to_i_spec.rb4
-rw-r--r--spec/ruby/core/complex/to_r_spec.rb14
-rw-r--r--spec/ruby/core/complex/to_s_spec.rb11
-rw-r--r--spec/ruby/core/conditionvariable/broadcast_spec.rb3
-rw-r--r--spec/ruby/core/conditionvariable/marshal_dump_spec.rb3
-rw-r--r--spec/ruby/core/conditionvariable/signal_spec.rb3
-rw-r--r--spec/ruby/core/conditionvariable/wait_spec.rb3
-rw-r--r--spec/ruby/core/data/constants_spec.rb22
-rw-r--r--spec/ruby/core/data/deconstruct_keys_spec.rb110
-rw-r--r--spec/ruby/core/data/deconstruct_spec.rb8
-rw-r--r--spec/ruby/core/data/define_spec.rb34
-rw-r--r--spec/ruby/core/data/eql_spec.rb63
-rw-r--r--spec/ruby/core/data/equal_value_spec.rb63
-rw-r--r--spec/ruby/core/data/fixtures/classes.rb41
-rw-r--r--spec/ruby/core/data/hash_spec.rb25
-rw-r--r--spec/ruby/core/data/initialize_spec.rb204
-rw-r--r--spec/ruby/core/data/inspect_spec.rb63
-rw-r--r--spec/ruby/core/data/members_spec.rb21
-rw-r--r--spec/ruby/core/data/to_h_spec.rb63
-rw-r--r--spec/ruby/core/data/to_s_spec.rb9
-rw-r--r--spec/ruby/core/data/with_spec.rb55
-rw-r--r--spec/ruby/core/dir/chdir_spec.rb126
-rw-r--r--spec/ruby/core/dir/children_spec.rb31
-rw-r--r--spec/ruby/core/dir/chroot_spec.rb6
-rw-r--r--spec/ruby/core/dir/close_spec.rb42
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb19
-rw-r--r--spec/ruby/core/dir/each_spec.rb15
-rw-r--r--spec/ruby/core/dir/empty_spec.rb8
-rw-r--r--spec/ruby/core/dir/entries_spec.rb10
-rw-r--r--spec/ruby/core/dir/exist_spec.rb63
-rw-r--r--spec/ruby/core/dir/fchdir_spec.rb71
-rw-r--r--spec/ruby/core/dir/fileno_spec.rb4
-rw-r--r--spec/ruby/core/dir/fixtures/common.rb50
-rw-r--r--spec/ruby/core/dir/for_fd_spec.rb77
-rw-r--r--spec/ruby/core/dir/foreach_spec.rb6
-rw-r--r--spec/ruby/core/dir/getwd_spec.rb12
-rw-r--r--spec/ruby/core/dir/glob_spec.rb161
-rw-r--r--spec/ruby/core/dir/home_spec.rb54
-rw-r--r--spec/ruby/core/dir/inspect_spec.rb4
-rw-r--r--spec/ruby/core/dir/mkdir_spec.rb26
-rw-r--r--spec/ruby/core/dir/open_spec.rb73
-rw-r--r--spec/ruby/core/dir/path_spec.rb26
-rw-r--r--spec/ruby/core/dir/pos_spec.rb23
-rw-r--r--spec/ruby/core/dir/pwd_spec.rb45
-rw-r--r--spec/ruby/core/dir/read_spec.rb4
-rw-r--r--spec/ruby/core/dir/scan_spec.rb224
-rw-r--r--spec/ruby/core/dir/shared/chroot.rb15
-rw-r--r--spec/ruby/core/dir/shared/closed.rb2
-rw-r--r--spec/ruby/core/dir/shared/delete.rb24
-rw-r--r--spec/ruby/core/dir/shared/exist.rb56
-rw-r--r--spec/ruby/core/dir/shared/glob.rb98
-rw-r--r--spec/ruby/core/dir/shared/open.rb73
-rw-r--r--spec/ruby/core/dir/shared/path.rb30
-rw-r--r--spec/ruby/core/dir/shared/pos.rb27
-rw-r--r--spec/ruby/core/dir/shared/pwd.rb45
-rw-r--r--spec/ruby/core/dir/tell_spec.rb27
-rw-r--r--spec/ruby/core/dir/to_path_spec.rb12
-rw-r--r--spec/ruby/core/encoding/aliases_spec.rb10
-rw-r--r--spec/ruby/core/encoding/ascii_compatible_spec.rb15
-rw-r--r--spec/ruby/core/encoding/compatible_spec.rb499
-rw-r--r--spec/ruby/core/encoding/converter/asciicompat_encoding_spec.rb6
-rw-r--r--spec/ruby/core/encoding/converter/constants_spec.rb52
-rw-r--r--spec/ruby/core/encoding/converter/convert_spec.rb22
-rw-r--r--spec/ruby/core/encoding/converter/finish_spec.rb6
-rw-r--r--spec/ruby/core/encoding/converter/last_error_spec.rb50
-rw-r--r--spec/ruby/core/encoding/converter/new_spec.rb14
-rw-r--r--spec/ruby/core/encoding/converter/primitive_convert_spec.rb31
-rw-r--r--spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb7
-rw-r--r--spec/ruby/core/encoding/converter/putback_spec.rb18
-rw-r--r--spec/ruby/core/encoding/converter/replacement_spec.rb28
-rw-r--r--spec/ruby/core/encoding/converter/search_convpath_spec.rb6
-rw-r--r--spec/ruby/core/encoding/default_external_spec.rb14
-rw-r--r--spec/ruby/core/encoding/default_internal_spec.rb12
-rw-r--r--spec/ruby/core/encoding/dummy_spec.rb21
-rw-r--r--spec/ruby/core/encoding/find_spec.rb8
-rw-r--r--spec/ruby/core/encoding/fixtures/classes.rb2
-rw-r--r--spec/ruby/core/encoding/inspect_spec.rb22
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_name_spec.rb5
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_spec.rb5
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb7
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb12
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb11
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_name_spec.rb3
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_spec.rb5
-rw-r--r--spec/ruby/core/encoding/list_spec.rb10
-rw-r--r--spec/ruby/core/encoding/locale_charmap_spec.rb76
-rw-r--r--spec/ruby/core/encoding/name_list_spec.rb8
-rw-r--r--spec/ruby/core/encoding/name_spec.rb14
-rw-r--r--spec/ruby/core/encoding/names_spec.rb6
-rw-r--r--spec/ruby/core/encoding/replicate_spec.rb65
-rw-r--r--spec/ruby/core/encoding/shared/name.rb15
-rw-r--r--spec/ruby/core/encoding/to_s_spec.rb6
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_name_spec.rb3
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_spec.rb3
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/error_char_spec.rb5
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/source_encoding_name_spec.rb3
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/source_encoding_spec.rb5
-rw-r--r--spec/ruby/core/enumerable/all_spec.rb26
-rw-r--r--spec/ruby/core/enumerable/any_spec.rb26
-rw-r--r--spec/ruby/core/enumerable/chain_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/chunk_spec.rb13
-rw-r--r--spec/ruby/core/enumerable/chunk_while_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/collect_concat_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/collect_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/compact_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/cycle_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/detect_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/drop_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/drop_while_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/each_cons_spec.rb22
-rw-r--r--spec/ruby/core/enumerable/each_entry_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/each_slice_spec.rb24
-rw-r--r--spec/ruby/core/enumerable/each_with_index_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/each_with_object_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/entries_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/filter_map_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/filter_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/find_all_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/find_index_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/find_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/first_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/fixtures/classes.rb5
-rw-r--r--spec/ruby/core/enumerable/flat_map_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/grep_spec.rb51
-rw-r--r--spec/ruby/core/enumerable/grep_v_spec.rb53
-rw-r--r--spec/ruby/core/enumerable/group_by_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/lazy_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/map_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/max_by_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/max_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/min_by_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/min_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/minmax_by_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/none_spec.rb34
-rw-r--r--spec/ruby/core/enumerable/one_spec.rb39
-rw-r--r--spec/ruby/core/enumerable/partition_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/reject_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/reverse_each_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/select_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/shared/collect.rb4
-rw-r--r--spec/ruby/core/enumerable/shared/collect_concat.rb4
-rw-r--r--spec/ruby/core/enumerable/shared/find.rb2
-rw-r--r--spec/ruby/core/enumerable/shared/find_all.rb2
-rw-r--r--spec/ruby/core/enumerable/shared/include.rb2
-rw-r--r--spec/ruby/core/enumerable/shared/inject.rb89
-rw-r--r--spec/ruby/core/enumerable/shared/take.rb8
-rw-r--r--spec/ruby/core/enumerable/shared/value_packing.rb26
-rw-r--r--spec/ruby/core/enumerable/slice_after_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/slice_before_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/slice_when_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/sort_by_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/sort_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/sum_spec.rb19
-rw-r--r--spec/ruby/core/enumerable/take_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/take_while_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/tally_spec.rb103
-rw-r--r--spec/ruby/core/enumerable/to_a_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/to_h_spec.rb20
-rw-r--r--spec/ruby/core/enumerable/to_set_spec.rb30
-rw-r--r--spec/ruby/core/enumerable/zip_spec.rb5
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/chain/initialize_spec.rb12
-rw-r--r--spec/ruby/core/enumerator/chain/inspect_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/chain/rewind_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/each_spec.rb47
-rw-r--r--spec/ruby/core/enumerator/each_with_index_spec.rb12
-rw-r--r--spec/ruby/core/enumerator/each_with_object_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/enum_for_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/feed_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/fixtures/classes.rb (renamed from spec/ruby/fixtures/enumerator/classes.rb)0
-rw-r--r--spec/ruby/core/enumerator/generator/each_spec.rb40
-rw-r--r--spec/ruby/core/enumerator/generator/initialize_spec.rb26
-rw-r--r--spec/ruby/core/enumerator/initialize_spec.rb24
-rw-r--r--spec/ruby/core/enumerator/inspect_spec.rb5
-rw-r--r--spec/ruby/core/enumerator/lazy/chunk_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/lazy/chunk_while_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/lazy/compact_spec.rb14
-rw-r--r--spec/ruby/core/enumerator/lazy/drop_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/lazy/drop_while_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/lazy/grep_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/lazy/grep_v_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/lazy/initialize_spec.rb16
-rw-r--r--spec/ruby/core/enumerator/lazy/lazy_spec.rb27
-rw-r--r--spec/ruby/core/enumerator/lazy/reject_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/lazy/shared/collect.rb4
-rw-r--r--spec/ruby/core/enumerator/lazy/shared/collect_concat.rb10
-rw-r--r--spec/ruby/core/enumerator/lazy/shared/select.rb6
-rw-r--r--spec/ruby/core/enumerator/lazy/shared/to_enum.rb6
-rw-r--r--spec/ruby/core/enumerator/lazy/slice_after_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/lazy/slice_before_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/lazy/slice_when_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/lazy/take_spec.rb12
-rw-r--r--spec/ruby/core/enumerator/lazy/take_while_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/lazy/uniq_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/lazy/with_index_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/lazy/zip_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/new_spec.rb106
-rw-r--r--spec/ruby/core/enumerator/next_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/next_values_spec.rb10
-rw-r--r--spec/ruby/core/enumerator/peek_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/peek_values_spec.rb10
-rw-r--r--spec/ruby/core/enumerator/plus_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/produce_spec.rb44
-rw-r--r--spec/ruby/core/enumerator/product/each_spec.rb85
-rw-r--r--spec/ruby/core/enumerator/product/initialize_copy_spec.rb52
-rw-r--r--spec/ruby/core/enumerator/product/initialize_spec.rb31
-rw-r--r--spec/ruby/core/enumerator/product/inspect_spec.rb20
-rw-r--r--spec/ruby/core/enumerator/product/rewind_spec.rb62
-rw-r--r--spec/ruby/core/enumerator/product/size_spec.rb64
-rw-r--r--spec/ruby/core/enumerator/product_spec.rb91
-rw-r--r--spec/ruby/core/enumerator/rewind_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/shared/enum_for.rb57
-rw-r--r--spec/ruby/core/enumerator/shared/with_index.rb33
-rw-r--r--spec/ruby/core/enumerator/shared/with_object.rb42
-rw-r--r--spec/ruby/core/enumerator/size_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/to_enum_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/with_index_spec.rb27
-rw-r--r--spec/ruby/core/enumerator/with_object_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/yielder/append_spec.rb35
-rw-r--r--spec/ruby/core/enumerator/yielder/initialize_spec.rb18
-rw-r--r--spec/ruby/core/enumerator/yielder/to_proc_spec.rb16
-rw-r--r--spec/ruby/core/enumerator/yielder/yield_spec.rb33
-rw-r--r--spec/ruby/core/env/assoc_spec.rb2
-rw-r--r--spec/ruby/core/env/clear_spec.rb2
-rw-r--r--spec/ruby/core/env/clone_spec.rb21
-rw-r--r--spec/ruby/core/env/delete_if_spec.rb10
-rw-r--r--spec/ruby/core/env/delete_spec.rb18
-rw-r--r--spec/ruby/core/env/dup_spec.rb9
-rw-r--r--spec/ruby/core/env/each_key_spec.rb8
-rw-r--r--spec/ruby/core/env/each_value_spec.rb8
-rw-r--r--spec/ruby/core/env/element_reference_spec.rb6
-rw-r--r--spec/ruby/core/env/except_spec.rb44
-rw-r--r--spec/ruby/core/env/fetch_spec.rb6
-rw-r--r--spec/ruby/core/env/fetch_values_spec.rb51
-rw-r--r--spec/ruby/core/env/index_spec.rb14
-rw-r--r--spec/ruby/core/env/indexes_spec.rb1
-rw-r--r--spec/ruby/core/env/indices_spec.rb1
-rw-r--r--spec/ruby/core/env/inspect_spec.rb2
-rw-r--r--spec/ruby/core/env/keep_if_spec.rb10
-rw-r--r--spec/ruby/core/env/key_spec.rb32
-rw-r--r--spec/ruby/core/env/length_spec.rb2
-rw-r--r--spec/ruby/core/env/rassoc_spec.rb2
-rw-r--r--spec/ruby/core/env/reject_spec.rb14
-rw-r--r--spec/ruby/core/env/replace_spec.rb16
-rw-r--r--spec/ruby/core/env/shared/each.rb12
-rw-r--r--spec/ruby/core/env/shared/include.rb9
-rw-r--r--spec/ruby/core/env/shared/key.rb31
-rw-r--r--spec/ruby/core/env/shared/select.rb4
-rw-r--r--spec/ruby/core/env/shared/store.rb14
-rw-r--r--spec/ruby/core/env/shared/to_hash.rb4
-rw-r--r--spec/ruby/core/env/shared/update.rb25
-rw-r--r--spec/ruby/core/env/shared/value.rb7
-rw-r--r--spec/ruby/core/env/shift_spec.rb8
-rw-r--r--spec/ruby/core/env/size_spec.rb2
-rw-r--r--spec/ruby/core/env/slice_spec.rb12
-rw-r--r--spec/ruby/core/env/to_a_spec.rb5
-rw-r--r--spec/ruby/core/env/to_h_spec.rb20
-rw-r--r--spec/ruby/core/env/values_at_spec.rb2
-rw-r--r--spec/ruby/core/exception/backtrace_locations_spec.rb6
-rw-r--r--spec/ruby/core/exception/backtrace_spec.rb37
-rw-r--r--spec/ruby/core/exception/case_compare_spec.rb2
-rw-r--r--spec/ruby/core/exception/cause_spec.rb54
-rw-r--r--spec/ruby/core/exception/detailed_message_spec.rb50
-rw-r--r--spec/ruby/core/exception/dup_spec.rb14
-rw-r--r--spec/ruby/core/exception/equal_value_spec.rb18
-rw-r--r--spec/ruby/core/exception/errno_spec.rb12
-rw-r--r--spec/ruby/core/exception/exception_spec.rb4
-rw-r--r--spec/ruby/core/exception/exit_value_spec.rb2
-rw-r--r--spec/ruby/core/exception/fixtures/common.rb7
-rw-r--r--spec/ruby/core/exception/fixtures/syntax_error.rb3
-rw-r--r--spec/ruby/core/exception/fixtures/thread_fiber_ensure.rb22
-rw-r--r--spec/ruby/core/exception/fixtures/thread_fiber_ensure_non_root_fiber.rb25
-rw-r--r--spec/ruby/core/exception/frozen_error_spec.rb38
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb144
-rw-r--r--spec/ruby/core/exception/interrupt_spec.rb2
-rw-r--r--spec/ruby/core/exception/io_error_spec.rb16
-rw-r--r--spec/ruby/core/exception/name_spec.rb12
-rw-r--r--spec/ruby/core/exception/no_method_error_spec.rb166
-rw-r--r--spec/ruby/core/exception/reason_spec.rb2
-rw-r--r--spec/ruby/core/exception/receiver_spec.rb16
-rw-r--r--spec/ruby/core/exception/result_spec.rb4
-rw-r--r--spec/ruby/core/exception/set_backtrace_spec.rb51
-rw-r--r--spec/ruby/core/exception/shared/new.rb4
-rw-r--r--spec/ruby/core/exception/shared/set_backtrace.rb64
-rw-r--r--spec/ruby/core/exception/signal_exception_spec.rb10
-rw-r--r--spec/ruby/core/exception/signm_spec.rb2
-rw-r--r--spec/ruby/core/exception/signo_spec.rb2
-rw-r--r--spec/ruby/core/exception/standard_error_spec.rb2
-rw-r--r--spec/ruby/core/exception/status_spec.rb2
-rw-r--r--spec/ruby/core/exception/success_spec.rb4
-rw-r--r--spec/ruby/core/exception/syntax_error_spec.rb25
-rw-r--r--spec/ruby/core/exception/system_call_error_spec.rb60
-rw-r--r--spec/ruby/core/exception/to_s_spec.rb2
-rw-r--r--spec/ruby/core/exception/top_level_spec.rb42
-rw-r--r--spec/ruby/core/false/case_compare_spec.rb14
-rw-r--r--spec/ruby/core/false/dup_spec.rb2
-rw-r--r--spec/ruby/core/false/falseclass_spec.rb4
-rw-r--r--spec/ruby/core/false/singleton_method_spec.rb13
-rw-r--r--spec/ruby/core/false/to_s_spec.rb2
-rw-r--r--spec/ruby/core/fiber/alive_spec.rb44
-rw-r--r--spec/ruby/core/fiber/blocking_spec.rb77
-rw-r--r--spec/ruby/core/fiber/current_spec.rb50
-rw-r--r--spec/ruby/core/fiber/fixtures/classes.rb16
-rw-r--r--spec/ruby/core/fiber/fixtures/scheduler.rb35
-rw-r--r--spec/ruby/core/fiber/inspect_spec.rb35
-rw-r--r--spec/ruby/core/fiber/kill_spec.rb88
-rw-r--r--spec/ruby/core/fiber/new_spec.rb8
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb92
-rw-r--r--spec/ruby/core/fiber/resume_spec.rb30
-rw-r--r--spec/ruby/core/fiber/scheduler_spec.rb8
-rw-r--r--spec/ruby/core/fiber/set_scheduler_spec.rb8
-rw-r--r--spec/ruby/core/fiber/shared/resume.rb58
-rw-r--r--spec/ruby/core/fiber/shared/scheduler.rb51
-rw-r--r--spec/ruby/core/fiber/storage_spec.rb177
-rw-r--r--spec/ruby/core/fiber/transfer_spec.rb84
-rw-r--r--spec/ruby/core/fiber/yield_spec.rb4
-rw-r--r--spec/ruby/core/file/absolute_path_spec.rb26
-rw-r--r--spec/ruby/core/file/atime_spec.rb13
-rw-r--r--spec/ruby/core/file/basename_spec.rb36
-rw-r--r--spec/ruby/core/file/birthtime_spec.rb68
-rw-r--r--spec/ruby/core/file/chmod_spec.rb12
-rw-r--r--spec/ruby/core/file/chown_spec.rb18
-rw-r--r--spec/ruby/core/file/constants/constants_spec.rb8
-rw-r--r--spec/ruby/core/file/ctime_spec.rb11
-rw-r--r--spec/ruby/core/file/dirname_spec.rb88
-rw-r--r--spec/ruby/core/file/empty_spec.rb6
-rw-r--r--spec/ruby/core/file/exist_spec.rb6
-rw-r--r--spec/ruby/core/file/expand_path_spec.rb22
-rw-r--r--spec/ruby/core/file/extname_spec.rb12
-rw-r--r--spec/ruby/core/file/flock_spec.rb36
-rw-r--r--spec/ruby/core/file/ftype_spec.rb8
-rw-r--r--spec/ruby/core/file/inspect_spec.rb2
-rw-r--r--spec/ruby/core/file/join_spec.rb14
-rw-r--r--spec/ruby/core/file/lchmod_spec.rb2
-rw-r--r--spec/ruby/core/file/link_spec.rb12
-rw-r--r--spec/ruby/core/file/lutime_spec.rb9
-rw-r--r--spec/ruby/core/file/mkfifo_spec.rb4
-rw-r--r--spec/ruby/core/file/mtime_spec.rb27
-rw-r--r--spec/ruby/core/file/new_spec.rb99
-rw-r--r--spec/ruby/core/file/open_spec.rb141
-rw-r--r--spec/ruby/core/file/path_spec.rb41
-rw-r--r--spec/ruby/core/file/readlink_spec.rb6
-rw-r--r--spec/ruby/core/file/realdirpath_spec.rb6
-rw-r--r--spec/ruby/core/file/realpath_spec.rb10
-rw-r--r--spec/ruby/core/file/rename_spec.rb8
-rw-r--r--spec/ruby/core/file/setuid_spec.rb4
-rw-r--r--spec/ruby/core/file/shared/fnmatch.rb75
-rw-r--r--spec/ruby/core/file/shared/open.rb2
-rw-r--r--spec/ruby/core/file/shared/path.rb16
-rw-r--r--spec/ruby/core/file/shared/read.rb4
-rw-r--r--spec/ruby/core/file/shared/stat.rb6
-rw-r--r--spec/ruby/core/file/shared/unlink.rb4
-rw-r--r--spec/ruby/core/file/shared/update_time.rb105
-rw-r--r--spec/ruby/core/file/size_spec.rb6
-rw-r--r--spec/ruby/core/file/socket_spec.rb32
-rw-r--r--spec/ruby/core/file/split_spec.rb6
-rw-r--r--spec/ruby/core/file/stat/atime_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/birthtime_spec.rb36
-rw-r--r--spec/ruby/core/file/stat/blocks_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/ctime_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/dev_major_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/dev_minor_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/dev_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/ftype_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/ino_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/mtime_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/new_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/rdev_major_spec.rb17
-rw-r--r--spec/ruby/core/file/stat/rdev_minor_spec.rb17
-rw-r--r--spec/ruby/core/file/stat/rdev_spec.rb2
-rw-r--r--spec/ruby/core/file/stat_spec.rb12
-rw-r--r--spec/ruby/core/file/symlink_spec.rb12
-rw-r--r--spec/ruby/core/file/truncate_spec.rb24
-rw-r--r--spec/ruby/core/file/umask_spec.rb8
-rw-r--r--spec/ruby/core/file/utime_spec.rb98
-rw-r--r--spec/ruby/core/file/world_readable_spec.rb2
-rw-r--r--spec/ruby/core/file/world_writable_spec.rb2
-rw-r--r--spec/ruby/core/file/zero_spec.rb6
-rw-r--r--spec/ruby/core/filetest/exist_spec.rb6
-rw-r--r--spec/ruby/core/filetest/grpowned_spec.rb2
-rw-r--r--spec/ruby/core/filetest/socket_spec.rb4
-rw-r--r--spec/ruby/core/filetest/zero_spec.rb6
-rw-r--r--spec/ruby/core/float/ceil_spec.rb31
-rw-r--r--spec/ruby/core/float/comparison_spec.rb49
-rw-r--r--spec/ruby/core/float/constants_spec.rb2
-rw-r--r--spec/ruby/core/float/denominator_spec.rb2
-rw-r--r--spec/ruby/core/float/divide_spec.rb20
-rw-r--r--spec/ruby/core/float/divmod_spec.rb22
-rw-r--r--spec/ruby/core/float/dup_spec.rb2
-rw-r--r--spec/ruby/core/float/eql_spec.rb8
-rw-r--r--spec/ruby/core/float/float_spec.rb4
-rw-r--r--spec/ruby/core/float/floor_spec.rb31
-rw-r--r--spec/ruby/core/float/gt_spec.rb25
-rw-r--r--spec/ruby/core/float/gte_spec.rb25
-rw-r--r--spec/ruby/core/float/lt_spec.rb25
-rw-r--r--spec/ruby/core/float/lte_spec.rb25
-rw-r--r--spec/ruby/core/float/magnitude_spec.rb1
-rw-r--r--spec/ruby/core/float/multiply_spec.rb4
-rw-r--r--spec/ruby/core/float/negative_spec.rb10
-rw-r--r--spec/ruby/core/float/next_float_spec.rb2
-rw-r--r--spec/ruby/core/float/numerator_spec.rb4
-rw-r--r--spec/ruby/core/float/positive_spec.rb10
-rw-r--r--spec/ruby/core/float/prev_float_spec.rb2
-rw-r--r--spec/ruby/core/float/rationalize_spec.rb8
-rw-r--r--spec/ruby/core/float/round_spec.rb232
-rw-r--r--spec/ruby/core/float/shared/abs.rb2
-rw-r--r--spec/ruby/core/float/shared/arg.rb4
-rw-r--r--spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb2
-rw-r--r--spec/ruby/core/float/shared/comparison_exception_in_coerce.rb2
-rw-r--r--spec/ruby/core/float/shared/equal.rb21
-rw-r--r--spec/ruby/core/float/shared/modulo.rb12
-rw-r--r--spec/ruby/core/float/shared/quo.rb8
-rw-r--r--spec/ruby/core/float/shared/to_i.rb16
-rw-r--r--spec/ruby/core/float/shared/to_s.rb4
-rw-r--r--spec/ruby/core/float/truncate_spec.rb10
-rw-r--r--spec/ruby/core/float/uplus_spec.rb2
-rw-r--r--spec/ruby/core/gc/auto_compact_spec.rb36
-rw-r--r--spec/ruby/core/gc/config_spec.rb97
-rw-r--r--spec/ruby/core/gc/count_spec.rb2
-rw-r--r--spec/ruby/core/gc/measure_total_time_spec.rb24
-rw-r--r--spec/ruby/core/gc/profiler/enabled_spec.rb4
-rw-r--r--spec/ruby/core/gc/profiler/result_spec.rb2
-rw-r--r--spec/ruby/core/gc/profiler/total_time_spec.rb2
-rw-r--r--spec/ruby/core/gc/stat_spec.rb28
-rw-r--r--spec/ruby/core/gc/stress_spec.rb8
-rw-r--r--spec/ruby/core/gc/total_time_spec.rb18
-rw-r--r--spec/ruby/core/hash/allocate_spec.rb2
-rw-r--r--spec/ruby/core/hash/assoc_spec.rb14
-rw-r--r--spec/ruby/core/hash/clear_spec.rb6
-rw-r--r--spec/ruby/core/hash/clone_spec.rb2
-rw-r--r--spec/ruby/core/hash/compact_spec.rb30
-rw-r--r--spec/ruby/core/hash/compare_by_identity_spec.rb47
-rw-r--r--spec/ruby/core/hash/constructor_spec.rb53
-rw-r--r--spec/ruby/core/hash/deconstruct_keys_spec.rb4
-rw-r--r--spec/ruby/core/hash/default_proc_spec.rb20
-rw-r--r--spec/ruby/core/hash/default_spec.rb4
-rw-r--r--spec/ruby/core/hash/delete_if_spec.rb8
-rw-r--r--spec/ruby/core/hash/delete_spec.rb20
-rw-r--r--spec/ruby/core/hash/dig_spec.rb18
-rw-r--r--spec/ruby/core/hash/each_key_spec.rb2
-rw-r--r--spec/ruby/core/hash/each_pair_spec.rb106
-rw-r--r--spec/ruby/core/hash/each_spec.rb10
-rw-r--r--spec/ruby/core/hash/each_value_spec.rb2
-rw-r--r--spec/ruby/core/hash/element_reference_spec.rb6
-rw-r--r--spec/ruby/core/hash/element_set_spec.rb118
-rw-r--r--spec/ruby/core/hash/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/hash/except_spec.rb60
-rw-r--r--spec/ruby/core/hash/fetch_spec.rb8
-rw-r--r--spec/ruby/core/hash/fetch_values_spec.rb2
-rw-r--r--spec/ruby/core/hash/filter_spec.rb9
-rw-r--r--spec/ruby/core/hash/flatten_spec.rb4
-rw-r--r--spec/ruby/core/hash/gt_spec.rb2
-rw-r--r--spec/ruby/core/hash/gte_spec.rb2
-rw-r--r--spec/ruby/core/hash/has_key_spec.rb6
-rw-r--r--spec/ruby/core/hash/has_value_spec.rb15
-rw-r--r--spec/ruby/core/hash/hash_spec.rb7
-rw-r--r--spec/ruby/core/hash/include_spec.rb39
-rw-r--r--spec/ruby/core/hash/index_spec.rb9
-rw-r--r--spec/ruby/core/hash/initialize_spec.rb12
-rw-r--r--spec/ruby/core/hash/inspect_spec.rb122
-rw-r--r--spec/ruby/core/hash/invert_spec.rb21
-rw-r--r--spec/ruby/core/hash/keep_if_spec.rb10
-rw-r--r--spec/ruby/core/hash/key_spec.rb30
-rw-r--r--spec/ruby/core/hash/keys_spec.rb4
-rw-r--r--spec/ruby/core/hash/length_spec.rb6
-rw-r--r--spec/ruby/core/hash/lt_spec.rb2
-rw-r--r--spec/ruby/core/hash/lte_spec.rb2
-rw-r--r--spec/ruby/core/hash/member_spec.rb6
-rw-r--r--spec/ruby/core/hash/merge_spec.rb39
-rw-r--r--spec/ruby/core/hash/new_spec.rb40
-rw-r--r--spec/ruby/core/hash/rassoc_spec.rb10
-rw-r--r--spec/ruby/core/hash/rehash_spec.rb36
-rw-r--r--spec/ruby/core/hash/reject_spec.rb31
-rw-r--r--spec/ruby/core/hash/replace_spec.rb76
-rw-r--r--spec/ruby/core/hash/ruby2_keywords_hash_spec.rb26
-rw-r--r--spec/ruby/core/hash/select_spec.rb108
-rw-r--r--spec/ruby/core/hash/shared/comparison.rb10
-rw-r--r--spec/ruby/core/hash/shared/each.rb124
-rw-r--r--spec/ruby/core/hash/shared/eql.rb88
-rw-r--r--spec/ruby/core/hash/shared/equal.rb90
-rw-r--r--spec/ruby/core/hash/shared/greater_than.rb6
-rw-r--r--spec/ruby/core/hash/shared/index.rb37
-rw-r--r--spec/ruby/core/hash/shared/iteration.rb6
-rw-r--r--spec/ruby/core/hash/shared/key.rb38
-rw-r--r--spec/ruby/core/hash/shared/length.rb12
-rw-r--r--spec/ruby/core/hash/shared/less_than.rb6
-rw-r--r--spec/ruby/core/hash/shared/replace.rb51
-rw-r--r--spec/ruby/core/hash/shared/select.rb91
-rw-r--r--spec/ruby/core/hash/shared/store.rb115
-rw-r--r--spec/ruby/core/hash/shared/to_s.rb89
-rw-r--r--spec/ruby/core/hash/shared/update.rb76
-rw-r--r--spec/ruby/core/hash/shared/value.rb14
-rw-r--r--spec/ruby/core/hash/shared/values_at.rb9
-rw-r--r--spec/ruby/core/hash/shift_spec.rb47
-rw-r--r--spec/ruby/core/hash/size_spec.rb13
-rw-r--r--spec/ruby/core/hash/slice_spec.rb25
-rw-r--r--spec/ruby/core/hash/store_spec.rb6
-rw-r--r--spec/ruby/core/hash/to_a_spec.rb14
-rw-r--r--spec/ruby/core/hash/to_h_spec.rb50
-rw-r--r--spec/ruby/core/hash/to_hash_spec.rb4
-rw-r--r--spec/ruby/core/hash/to_proc_spec.rb32
-rw-r--r--spec/ruby/core/hash/to_s_spec.rb6
-rw-r--r--spec/ruby/core/hash/transform_keys_spec.rb93
-rw-r--r--spec/ruby/core/hash/transform_values_spec.rb39
-rw-r--r--spec/ruby/core/hash/try_convert_spec.rb16
-rw-r--r--spec/ruby/core/hash/update_spec.rb76
-rw-r--r--spec/ruby/core/hash/value_spec.rb6
-rw-r--r--spec/ruby/core/hash/values_at_spec.rb10
-rw-r--r--spec/ruby/core/hash/values_spec.rb2
-rw-r--r--spec/ruby/core/integer/allbits_spec.rb6
-rw-r--r--spec/ruby/core/integer/anybits_spec.rb6
-rw-r--r--spec/ruby/core/integer/bit_and_spec.rb10
-rw-r--r--spec/ruby/core/integer/bit_or_spec.rb16
-rw-r--r--spec/ruby/core/integer/bit_xor_spec.rb14
-rw-r--r--spec/ruby/core/integer/ceil_spec.rb12
-rw-r--r--spec/ruby/core/integer/ceildiv_spec.rb20
-rw-r--r--spec/ruby/core/integer/chr_spec.rb62
-rw-r--r--spec/ruby/core/integer/coerce_spec.rb41
-rw-r--r--spec/ruby/core/integer/comparison_spec.rb14
-rw-r--r--spec/ruby/core/integer/constants_spec.rb36
-rw-r--r--spec/ruby/core/integer/digits_spec.rb6
-rw-r--r--spec/ruby/core/integer/div_spec.rb48
-rw-r--r--spec/ruby/core/integer/divide_spec.rb53
-rw-r--r--spec/ruby/core/integer/divmod_spec.rb34
-rw-r--r--spec/ruby/core/integer/downto_spec.rb8
-rw-r--r--spec/ruby/core/integer/dup_spec.rb4
-rw-r--r--spec/ruby/core/integer/element_reference_spec.rb14
-rw-r--r--spec/ruby/core/integer/eql_spec.rb25
-rw-r--r--spec/ruby/core/integer/even_spec.rb26
-rw-r--r--spec/ruby/core/integer/fdiv_spec.rb8
-rw-r--r--spec/ruby/core/integer/fixtures/classes.rb10
-rw-r--r--spec/ruby/core/integer/floor_spec.rb12
-rw-r--r--spec/ruby/core/integer/gcd_spec.rb16
-rw-r--r--spec/ruby/core/integer/gcdlcm_spec.rb16
-rw-r--r--spec/ruby/core/integer/gt_spec.rb13
-rw-r--r--spec/ruby/core/integer/gte_spec.rb13
-rw-r--r--spec/ruby/core/integer/integer_spec.rb4
-rw-r--r--spec/ruby/core/integer/lcm_spec.rb16
-rw-r--r--spec/ruby/core/integer/left_shift_spec.rb58
-rw-r--r--spec/ruby/core/integer/lt_spec.rb13
-rw-r--r--spec/ruby/core/integer/lte_spec.rb13
-rw-r--r--spec/ruby/core/integer/minus_spec.rb29
-rw-r--r--spec/ruby/core/integer/multiply_spec.rb12
-rw-r--r--spec/ruby/core/integer/nobits_spec.rb6
-rw-r--r--spec/ruby/core/integer/odd_spec.rb26
-rw-r--r--spec/ruby/core/integer/ord_spec.rb16
-rw-r--r--spec/ruby/core/integer/plus_spec.rb29
-rw-r--r--spec/ruby/core/integer/pow_spec.rb28
-rw-r--r--spec/ruby/core/integer/pred_spec.rb10
-rw-r--r--spec/ruby/core/integer/rationalize_spec.rb6
-rw-r--r--spec/ruby/core/integer/remainder_spec.rb18
-rw-r--r--spec/ruby/core/integer/right_shift_spec.rb58
-rw-r--r--spec/ruby/core/integer/round_spec.rb66
-rw-r--r--spec/ruby/core/integer/shared/arithmetic_coerce.rb22
-rw-r--r--spec/ruby/core/integer/shared/comparison_coerce.rb2
-rw-r--r--spec/ruby/core/integer/shared/equal.rb5
-rw-r--r--spec/ruby/core/integer/shared/exponent.rb134
-rw-r--r--spec/ruby/core/integer/shared/integer_ceil_precision.rb54
-rw-r--r--spec/ruby/core/integer/shared/integer_floor_precision.rb42
-rw-r--r--spec/ruby/core/integer/shared/integer_rounding.rb6
-rw-r--r--spec/ruby/core/integer/shared/modulo.rb78
-rw-r--r--spec/ruby/core/integer/shared/to_i.rb8
-rw-r--r--spec/ruby/core/integer/size_spec.rb4
-rw-r--r--spec/ruby/core/integer/sqrt_spec.rb6
-rw-r--r--spec/ruby/core/integer/to_f_spec.rb6
-rw-r--r--spec/ruby/core/integer/to_r_spec.rb8
-rw-r--r--spec/ruby/core/integer/to_s_spec.rb24
-rw-r--r--spec/ruby/core/integer/truncate_spec.rb12
-rw-r--r--spec/ruby/core/integer/try_convert_spec.rb68
-rw-r--r--spec/ruby/core/integer/upto_spec.rb8
-rw-r--r--spec/ruby/core/integer/zero_spec.rb12
-rw-r--r--spec/ruby/core/io/advise_spec.rb28
-rw-r--r--spec/ruby/core/io/autoclose_spec.rb77
-rw-r--r--spec/ruby/core/io/binmode_spec.rb10
-rw-r--r--spec/ruby/core/io/binread_spec.rb14
-rw-r--r--spec/ruby/core/io/buffer/and_spec.rb62
-rw-r--r--spec/ruby/core/io/buffer/bit_count_spec.rb64
-rw-r--r--spec/ruby/core/io/buffer/empty_spec.rb27
-rw-r--r--spec/ruby/core/io/buffer/external_spec.rb23
-rw-r--r--spec/ruby/core/io/buffer/for_spec.rb95
-rw-r--r--spec/ruby/core/io/buffer/free_spec.rb102
-rw-r--r--spec/ruby/core/io/buffer/initialize_spec.rb119
-rw-r--r--spec/ruby/core/io/buffer/internal_spec.rb23
-rw-r--r--spec/ruby/core/io/buffer/locked_spec.rb75
-rw-r--r--spec/ruby/core/io/buffer/map_spec.rb343
-rw-r--r--spec/ruby/core/io/buffer/mapped_spec.rb23
-rw-r--r--spec/ruby/core/io/buffer/not_spec.rb37
-rw-r--r--spec/ruby/core/io/buffer/null_spec.rb27
-rw-r--r--spec/ruby/core/io/buffer/or_spec.rb62
-rw-r--r--spec/ruby/core/io/buffer/private_spec.rb23
-rw-r--r--spec/ruby/core/io/buffer/readonly_spec.rb28
-rw-r--r--spec/ruby/core/io/buffer/resize_spec.rb151
-rw-r--r--spec/ruby/core/io/buffer/shared/null_and_empty.rb57
-rw-r--r--spec/ruby/core/io/buffer/shared_spec.rb33
-rw-r--r--spec/ruby/core/io/buffer/string_spec.rb62
-rw-r--r--spec/ruby/core/io/buffer/transfer_spec.rb117
-rw-r--r--spec/ruby/core/io/buffer/valid_spec.rb99
-rw-r--r--spec/ruby/core/io/buffer/xor_spec.rb62
-rw-r--r--spec/ruby/core/io/bytes_spec.rb47
-rw-r--r--spec/ruby/core/io/chars_spec.rb30
-rw-r--r--spec/ruby/core/io/close_on_exec_spec.rb4
-rw-r--r--spec/ruby/core/io/close_read_spec.rb13
-rw-r--r--spec/ruby/core/io/close_spec.rb12
-rw-r--r--spec/ruby/core/io/close_write_spec.rb24
-rw-r--r--spec/ruby/core/io/closed_spec.rb4
-rw-r--r--spec/ruby/core/io/codepoints_spec.rb38
-rw-r--r--spec/ruby/core/io/copy_stream_spec.rb53
-rw-r--r--spec/ruby/core/io/dup_spec.rb36
-rw-r--r--spec/ruby/core/io/each_byte_spec.rb6
-rw-r--r--spec/ruby/core/io/each_codepoint_spec.rb4
-rw-r--r--spec/ruby/core/io/eof_spec.rb8
-rw-r--r--spec/ruby/core/io/external_encoding_spec.rb54
-rw-r--r--spec/ruby/core/io/fcntl_spec.rb2
-rw-r--r--spec/ruby/core/io/fileno_spec.rb2
-rw-r--r--spec/ruby/core/io/fixtures/classes.rb12
-rw-r--r--spec/ruby/core/io/flush_spec.rb16
-rw-r--r--spec/ruby/core/io/foreach_spec.rb55
-rw-r--r--spec/ruby/core/io/fsync_spec.rb2
-rw-r--r--spec/ruby/core/io/getbyte_spec.rb18
-rw-r--r--spec/ruby/core/io/getc_spec.rb6
-rw-r--r--spec/ruby/core/io/gets_spec.rb63
-rw-r--r--spec/ruby/core/io/initialize_spec.rb21
-rw-r--r--spec/ruby/core/io/inspect_spec.rb4
-rw-r--r--spec/ruby/core/io/internal_encoding_spec.rb36
-rw-r--r--spec/ruby/core/io/ioctl_spec.rb8
-rw-r--r--spec/ruby/core/io/lineno_spec.rb27
-rw-r--r--spec/ruby/core/io/lines_spec.rb46
-rw-r--r--spec/ruby/core/io/new_spec.rb8
-rw-r--r--spec/ruby/core/io/nonblock_spec.rb46
-rw-r--r--spec/ruby/core/io/open_spec.rb19
-rw-r--r--spec/ruby/core/io/output_spec.rb2
-rw-r--r--spec/ruby/core/io/path_spec.rb12
-rw-r--r--spec/ruby/core/io/pid_spec.rb4
-rw-r--r--spec/ruby/core/io/pipe_spec.rb39
-rw-r--r--spec/ruby/core/io/popen_spec.rb34
-rw-r--r--spec/ruby/core/io/pread_spec.rb162
-rw-r--r--spec/ruby/core/io/print_spec.rb27
-rw-r--r--spec/ruby/core/io/printf_spec.rb2
-rw-r--r--spec/ruby/core/io/puts_spec.rb6
-rw-r--r--spec/ruby/core/io/pwrite_spec.rb86
-rw-r--r--spec/ruby/core/io/read_nonblock_spec.rb67
-rw-r--r--spec/ruby/core/io/read_spec.rb273
-rw-r--r--spec/ruby/core/io/readbyte_spec.rb2
-rw-r--r--spec/ruby/core/io/readchar_spec.rb72
-rw-r--r--spec/ruby/core/io/readline_spec.rb20
-rw-r--r--spec/ruby/core/io/readlines_spec.rb97
-rw-r--r--spec/ruby/core/io/readpartial_spec.rb41
-rw-r--r--spec/ruby/core/io/reopen_spec.rb26
-rw-r--r--spec/ruby/core/io/rewind_spec.rb17
-rw-r--r--spec/ruby/core/io/seek_spec.rb2
-rw-r--r--spec/ruby/core/io/select_spec.rb110
-rw-r--r--spec/ruby/core/io/set_encoding_by_bom_spec.rb197
-rw-r--r--spec/ruby/core/io/set_encoding_spec.rb79
-rw-r--r--spec/ruby/core/io/shared/binwrite.rb15
-rw-r--r--spec/ruby/core/io/shared/chars.rb10
-rw-r--r--spec/ruby/core/io/shared/codepoints.rb6
-rw-r--r--spec/ruby/core/io/shared/each.rb76
-rw-r--r--spec/ruby/core/io/shared/gets_ascii.rb2
-rw-r--r--spec/ruby/core/io/shared/new.rb119
-rw-r--r--spec/ruby/core/io/shared/pos.rb14
-rw-r--r--spec/ruby/core/io/shared/readlines.rb50
-rw-r--r--spec/ruby/core/io/shared/tty.rb2
-rw-r--r--spec/ruby/core/io/shared/write.rb81
-rw-r--r--spec/ruby/core/io/stat_spec.rb9
-rw-r--r--spec/ruby/core/io/sync_spec.rb4
-rw-r--r--spec/ruby/core/io/sysopen_spec.rb16
-rw-r--r--spec/ruby/core/io/sysread_spec.rb52
-rw-r--r--spec/ruby/core/io/sysseek_spec.rb6
-rw-r--r--spec/ruby/core/io/syswrite_spec.rb11
-rw-r--r--spec/ruby/core/io/to_i_spec.rb2
-rw-r--r--spec/ruby/core/io/to_io_spec.rb4
-rw-r--r--spec/ruby/core/io/try_convert_spec.rb12
-rw-r--r--spec/ruby/core/io/ungetbyte_spec.rb12
-rw-r--r--spec/ruby/core/io/ungetc_spec.rb28
-rw-r--r--spec/ruby/core/io/write_nonblock_spec.rb21
-rw-r--r--spec/ruby/core/io/write_spec.rb180
-rw-r--r--spec/ruby/core/kernel/Array_spec.rb6
-rw-r--r--spec/ruby/core/kernel/Complex_spec.rb135
-rw-r--r--spec/ruby/core/kernel/Float_spec.rb240
-rw-r--r--spec/ruby/core/kernel/Hash_spec.rb6
-rw-r--r--spec/ruby/core/kernel/Integer_spec.rb266
-rw-r--r--spec/ruby/core/kernel/Rational_spec.rb234
-rw-r--r--spec/ruby/core/kernel/String_spec.rb16
-rw-r--r--spec/ruby/core/kernel/__dir___spec.rb16
-rw-r--r--spec/ruby/core/kernel/abort_spec.rb2
-rw-r--r--spec/ruby/core/kernel/at_exit_spec.rb63
-rw-r--r--spec/ruby/core/kernel/autoload_relative_spec.rb114
-rw-r--r--spec/ruby/core/kernel/autoload_spec.rb19
-rw-r--r--spec/ruby/core/kernel/backtick_spec.rb14
-rw-r--r--spec/ruby/core/kernel/binding_spec.rb4
-rw-r--r--spec/ruby/core/kernel/block_given_spec.rb7
-rw-r--r--spec/ruby/core/kernel/caller_locations_spec.rb47
-rw-r--r--spec/ruby/core/kernel/caller_spec.rb83
-rw-r--r--spec/ruby/core/kernel/case_compare_spec.rb14
-rw-r--r--spec/ruby/core/kernel/catch_spec.rb10
-rw-r--r--spec/ruby/core/kernel/chomp_spec.rb2
-rw-r--r--spec/ruby/core/kernel/chop_spec.rb2
-rw-r--r--spec/ruby/core/kernel/class_spec.rb22
-rw-r--r--spec/ruby/core/kernel/clone_spec.rb96
-rw-r--r--spec/ruby/core/kernel/comparison_spec.rb6
-rw-r--r--spec/ruby/core/kernel/define_singleton_method_spec.rb24
-rw-r--r--spec/ruby/core/kernel/dup_spec.rb8
-rw-r--r--spec/ruby/core/kernel/eql_spec.rb2
-rw-r--r--spec/ruby/core/kernel/eval_spec.rb225
-rw-r--r--spec/ruby/core/kernel/exec_spec.rb6
-rw-r--r--spec/ruby/core/kernel/exit_spec.rb14
-rw-r--r--spec/ruby/core/kernel/extend_spec.rb20
-rw-r--r--spec/ruby/core/kernel/fail_spec.rb10
-rw-r--r--spec/ruby/core/kernel/fixtures/Complex.rb5
-rw-r--r--spec/ruby/core/kernel/fixtures/at_exit.rb3
-rw-r--r--spec/ruby/core/kernel/fixtures/autoload_relative_b.rb7
-rw-r--r--spec/ruby/core/kernel/fixtures/autoload_relative_d.rb5
-rw-r--r--spec/ruby/core/kernel/fixtures/classes.rb73
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_core_method.rb2
-rw-r--r--spec/ruby/core/kernel/fork_spec.rb2
-rw-r--r--spec/ruby/core/kernel/format_spec.rb34
-rw-r--r--spec/ruby/core/kernel/freeze_spec.rb28
-rw-r--r--spec/ruby/core/kernel/frozen_spec.rb22
-rw-r--r--spec/ruby/core/kernel/gets_spec.rb2
-rw-r--r--spec/ruby/core/kernel/global_variables_spec.rb6
-rw-r--r--spec/ruby/core/kernel/gsub_spec.rb8
-rw-r--r--spec/ruby/core/kernel/initialize_clone_spec.rb12
-rw-r--r--spec/ruby/core/kernel/initialize_copy_spec.rb21
-rw-r--r--spec/ruby/core/kernel/initialize_dup_spec.rb2
-rw-r--r--spec/ruby/core/kernel/inspect_spec.rb76
-rw-r--r--spec/ruby/core/kernel/instance_of_spec.rb6
-rw-r--r--spec/ruby/core/kernel/instance_variable_defined_spec.rb12
-rw-r--r--spec/ruby/core/kernel/instance_variable_get_spec.rb28
-rw-r--r--spec/ruby/core/kernel/instance_variable_set_spec.rb28
-rw-r--r--spec/ruby/core/kernel/instance_variables_spec.rb2
-rw-r--r--spec/ruby/core/kernel/is_a_spec.rb2
-rw-r--r--spec/ruby/core/kernel/iterator_spec.rb14
-rw-r--r--spec/ruby/core/kernel/itself_spec.rb2
-rw-r--r--spec/ruby/core/kernel/kind_of_spec.rb2
-rw-r--r--spec/ruby/core/kernel/lambda_spec.rb82
-rw-r--r--spec/ruby/core/kernel/load_spec.rb2
-rw-r--r--spec/ruby/core/kernel/local_variables_spec.rb11
-rw-r--r--spec/ruby/core/kernel/loop_spec.rb6
-rw-r--r--spec/ruby/core/kernel/match_spec.rb27
-rw-r--r--spec/ruby/core/kernel/method_spec.rb37
-rw-r--r--spec/ruby/core/kernel/methods_spec.rb34
-rw-r--r--spec/ruby/core/kernel/not_match_spec.rb4
-rw-r--r--spec/ruby/core/kernel/open_spec.rb147
-rw-r--r--spec/ruby/core/kernel/p_spec.rb8
-rw-r--r--spec/ruby/core/kernel/print_spec.rb2
-rw-r--r--spec/ruby/core/kernel/printf_spec.rb9
-rw-r--r--spec/ruby/core/kernel/private_methods_spec.rb10
-rw-r--r--spec/ruby/core/kernel/proc_spec.rb30
-rw-r--r--spec/ruby/core/kernel/protected_methods_spec.rb10
-rw-r--r--spec/ruby/core/kernel/public_method_spec.rb6
-rw-r--r--spec/ruby/core/kernel/public_methods_spec.rb19
-rw-r--r--spec/ruby/core/kernel/public_send_spec.rb16
-rw-r--r--spec/ruby/core/kernel/putc_spec.rb2
-rw-r--r--spec/ruby/core/kernel/puts_spec.rb2
-rw-r--r--spec/ruby/core/kernel/raise_spec.rb201
-rw-r--r--spec/ruby/core/kernel/rand_spec.rb94
-rw-r--r--spec/ruby/core/kernel/readline_spec.rb2
-rw-r--r--spec/ruby/core/kernel/readlines_spec.rb2
-rw-r--r--spec/ruby/core/kernel/remove_instance_variable_spec.rb20
-rw-r--r--spec/ruby/core/kernel/require_relative_spec.rb140
-rw-r--r--spec/ruby/core/kernel/require_spec.rb35
-rw-r--r--spec/ruby/core/kernel/respond_to_missing_spec.rb20
-rw-r--r--spec/ruby/core/kernel/respond_to_spec.rb33
-rw-r--r--spec/ruby/core/kernel/select_spec.rb6
-rw-r--r--spec/ruby/core/kernel/set_trace_func_spec.rb2
-rw-r--r--spec/ruby/core/kernel/shared/dup_clone.rb8
-rw-r--r--spec/ruby/core/kernel/shared/kind_of.rb8
-rw-r--r--spec/ruby/core/kernel/shared/lambda.rb2
-rw-r--r--spec/ruby/core/kernel/shared/load.rb123
-rw-r--r--spec/ruby/core/kernel/shared/method.rb12
-rw-r--r--spec/ruby/core/kernel/shared/require.rb305
-rw-r--r--spec/ruby/core/kernel/shared/sprintf.rb162
-rw-r--r--spec/ruby/core/kernel/shared/sprintf_encoding.rb49
-rw-r--r--spec/ruby/core/kernel/shared/then.rb12
-rw-r--r--spec/ruby/core/kernel/singleton_class_spec.rb51
-rw-r--r--spec/ruby/core/kernel/singleton_method_spec.rb52
-rw-r--r--spec/ruby/core/kernel/singleton_methods_spec.rb65
-rw-r--r--spec/ruby/core/kernel/sleep_spec.rb78
-rw-r--r--spec/ruby/core/kernel/spawn_spec.rb2
-rw-r--r--spec/ruby/core/kernel/sprintf_spec.rb48
-rw-r--r--spec/ruby/core/kernel/srand_spec.rb8
-rw-r--r--spec/ruby/core/kernel/sub_spec.rb4
-rw-r--r--spec/ruby/core/kernel/syscall_spec.rb2
-rw-r--r--spec/ruby/core/kernel/system_spec.rb35
-rw-r--r--spec/ruby/core/kernel/taint_spec.rb15
-rw-r--r--spec/ruby/core/kernel/tainted_spec.rb17
-rw-r--r--spec/ruby/core/kernel/tap_spec.rb4
-rw-r--r--spec/ruby/core/kernel/test_spec.rb16
-rw-r--r--spec/ruby/core/kernel/throw_spec.rb14
-rw-r--r--spec/ruby/core/kernel/trace_var_spec.rb4
-rw-r--r--spec/ruby/core/kernel/trap_spec.rb2
-rw-r--r--spec/ruby/core/kernel/trust_spec.rb16
-rw-r--r--spec/ruby/core/kernel/untaint_spec.rb16
-rw-r--r--spec/ruby/core/kernel/untrace_var_spec.rb2
-rw-r--r--spec/ruby/core/kernel/untrust_spec.rb15
-rw-r--r--spec/ruby/core/kernel/untrusted_spec.rb16
-rw-r--r--spec/ruby/core/kernel/warn_spec.rb163
-rw-r--r--spec/ruby/core/main/define_method_spec.rb6
-rw-r--r--spec/ruby/core/main/fixtures/using.rb1
-rw-r--r--spec/ruby/core/main/fixtures/using_in_main.rb5
-rw-r--r--spec/ruby/core/main/fixtures/using_in_method.rb5
-rw-r--r--spec/ruby/core/main/include_spec.rb4
-rw-r--r--spec/ruby/core/main/private_spec.rb32
-rw-r--r--spec/ruby/core/main/public_spec.rb32
-rw-r--r--spec/ruby/core/main/ruby2_keywords_spec.rb2
-rw-r--r--spec/ruby/core/main/using_spec.rb26
-rw-r--r--spec/ruby/core/marshal/dump_spec.rb593
-rw-r--r--spec/ruby/core/marshal/fixtures/classes.rb4
-rw-r--r--spec/ruby/core/marshal/fixtures/marshal_data.rb155
-rw-r--r--spec/ruby/core/marshal/fixtures/marshal_multibyte_data.rb12
-rw-r--r--spec/ruby/core/marshal/float_spec.rb2
-rw-r--r--spec/ruby/core/marshal/shared/load.rb697
-rw-r--r--spec/ruby/core/matchdata/allocate_spec.rb2
-rw-r--r--spec/ruby/core/matchdata/begin_spec.rb30
-rw-r--r--spec/ruby/core/matchdata/bytebegin_spec.rb132
-rw-r--r--spec/ruby/core/matchdata/byteend_spec.rb104
-rw-r--r--spec/ruby/core/matchdata/byteoffset_spec.rb93
-rw-r--r--spec/ruby/core/matchdata/captures_spec.rb13
-rw-r--r--spec/ruby/core/matchdata/deconstruct_keys_spec.rb78
-rw-r--r--spec/ruby/core/matchdata/deconstruct_spec.rb6
-rw-r--r--spec/ruby/core/matchdata/element_reference_spec.rb39
-rw-r--r--spec/ruby/core/matchdata/end_spec.rb2
-rw-r--r--spec/ruby/core/matchdata/inspect_spec.rb2
-rw-r--r--spec/ruby/core/matchdata/integer_at_spec.rb38
-rw-r--r--spec/ruby/core/matchdata/match_length_spec.rb46
-rw-r--r--spec/ruby/core/matchdata/match_spec.rb46
-rw-r--r--spec/ruby/core/matchdata/named_captures_spec.rb10
-rw-r--r--spec/ruby/core/matchdata/names_spec.rb4
-rw-r--r--spec/ruby/core/matchdata/offset_spec.rb106
-rw-r--r--spec/ruby/core/matchdata/post_match_spec.rb16
-rw-r--r--spec/ruby/core/matchdata/pre_match_spec.rb16
-rw-r--r--spec/ruby/core/matchdata/regexp_spec.rb2
-rw-r--r--spec/ruby/core/matchdata/shared/captures.rb13
-rw-r--r--spec/ruby/core/matchdata/shared/eql.rb8
-rw-r--r--spec/ruby/core/matchdata/string_spec.rb7
-rw-r--r--spec/ruby/core/matchdata/to_a_spec.rb8
-rw-r--r--spec/ruby/core/matchdata/to_s_spec.rb8
-rw-r--r--spec/ruby/core/matchdata/values_at_spec.rb71
-rw-r--r--spec/ruby/core/math/acos_spec.rb14
-rw-r--r--spec/ruby/core/math/acosh_spec.rb14
-rw-r--r--spec/ruby/core/math/asin_spec.rb12
-rw-r--r--spec/ruby/core/math/asinh_spec.rb8
-rw-r--r--spec/ruby/core/math/atan2_spec.rb14
-rw-r--r--spec/ruby/core/math/atan_spec.rb8
-rw-r--r--spec/ruby/core/math/atanh_spec.rb4
-rw-r--r--spec/ruby/core/math/cbrt_spec.rb6
-rw-r--r--spec/ruby/core/math/cos_spec.rb32
-rw-r--r--spec/ruby/core/math/cosh_spec.rb8
-rw-r--r--spec/ruby/core/math/erf_spec.rb8
-rw-r--r--spec/ruby/core/math/erfc_spec.rb8
-rw-r--r--spec/ruby/core/math/exp_spec.rb8
-rw-r--r--spec/ruby/core/math/expm1_spec.rb37
-rw-r--r--spec/ruby/core/math/fixtures/common.rb (renamed from spec/ruby/fixtures/math/common.rb)0
-rw-r--r--spec/ruby/core/math/frexp_spec.rb6
-rw-r--r--spec/ruby/core/math/gamma_spec.rb6
-rw-r--r--spec/ruby/core/math/hypot_spec.rb12
-rw-r--r--spec/ruby/core/math/ldexp_spec.rb14
-rw-r--r--spec/ruby/core/math/lgamma_spec.rb13
-rw-r--r--spec/ruby/core/math/log10_spec.rb14
-rw-r--r--spec/ruby/core/math/log1p_spec.rb49
-rw-r--r--spec/ruby/core/math/log2_spec.rb10
-rw-r--r--spec/ruby/core/math/log_spec.rb16
-rw-r--r--spec/ruby/core/math/shared/atanh.rb44
-rw-r--r--spec/ruby/core/math/sin_spec.rb8
-rw-r--r--spec/ruby/core/math/sinh_spec.rb8
-rw-r--r--spec/ruby/core/math/sqrt_spec.rb10
-rw-r--r--spec/ruby/core/math/tan_spec.rb8
-rw-r--r--spec/ruby/core/math/tanh_spec.rb8
-rw-r--r--spec/ruby/core/method/clone_spec.rb15
-rw-r--r--spec/ruby/core/method/compose_spec.rb3
-rw-r--r--spec/ruby/core/method/curry_spec.rb18
-rw-r--r--spec/ruby/core/method/dup_spec.rb15
-rw-r--r--spec/ruby/core/method/fixtures/classes.rb31
-rw-r--r--spec/ruby/core/method/inspect_spec.rb2
-rw-r--r--spec/ruby/core/method/original_name_spec.rb37
-rw-r--r--spec/ruby/core/method/owner_spec.rb4
-rw-r--r--spec/ruby/core/method/parameters_spec.rb67
-rw-r--r--spec/ruby/core/method/private_spec.rb9
-rw-r--r--spec/ruby/core/method/protected_spec.rb9
-rw-r--r--spec/ruby/core/method/public_spec.rb9
-rw-r--r--spec/ruby/core/method/receiver_spec.rb8
-rw-r--r--spec/ruby/core/method/shared/aliased_inspect.rb31
-rw-r--r--spec/ruby/core/method/shared/call.rb4
-rw-r--r--spec/ruby/core/method/shared/dup.rb32
-rw-r--r--spec/ruby/core/method/shared/eql.rb32
-rw-r--r--spec/ruby/core/method/shared/to_s.rb34
-rw-r--r--spec/ruby/core/method/source_location_spec.rb21
-rw-r--r--spec/ruby/core/method/super_method_spec.rb19
-rw-r--r--spec/ruby/core/method/to_proc_spec.rb2
-rw-r--r--spec/ruby/core/method/to_s_spec.rb2
-rw-r--r--spec/ruby/core/method/unbind_spec.rb4
-rw-r--r--spec/ruby/core/module/alias_method_spec.rb62
-rw-r--r--spec/ruby/core/module/ancestors_spec.rb40
-rw-r--r--spec/ruby/core/module/append_features_spec.rb14
-rw-r--r--spec/ruby/core/module/attr_accessor_spec.rb35
-rw-r--r--spec/ruby/core/module/attr_reader_spec.rb27
-rw-r--r--spec/ruby/core/module/attr_spec.rb37
-rw-r--r--spec/ruby/core/module/attr_writer_spec.rb29
-rw-r--r--spec/ruby/core/module/autoload_relative_spec.rb128
-rw-r--r--spec/ruby/core/module/autoload_spec.rb378
-rw-r--r--spec/ruby/core/module/class_variable_defined_spec.rb12
-rw-r--r--spec/ruby/core/module/class_variable_get_spec.rb16
-rw-r--r--spec/ruby/core/module/class_variable_set_spec.rb12
-rw-r--r--spec/ruby/core/module/class_variables_spec.rb8
-rw-r--r--spec/ruby/core/module/const_added_spec.rb253
-rw-r--r--spec/ruby/core/module/const_defined_spec.rb84
-rw-r--r--spec/ruby/core/module/const_get_spec.rb72
-rw-r--r--spec/ruby/core/module/const_missing_spec.rb2
-rw-r--r--spec/ruby/core/module/const_set_spec.rb55
-rw-r--r--spec/ruby/core/module/const_source_location_spec.rb84
-rw-r--r--spec/ruby/core/module/constants_spec.rb7
-rw-r--r--spec/ruby/core/module/define_method_spec.rb192
-rw-r--r--spec/ruby/core/module/deprecate_constant_spec.rb17
-rw-r--r--spec/ruby/core/module/extend_object_spec.rb10
-rw-r--r--spec/ruby/core/module/extended_spec.rb2
-rw-r--r--spec/ruby/core/module/fixtures/autoload_const_source_location.rb6
-rw-r--r--spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb6
-rw-r--r--spec/ruby/core/module/fixtures/autoload_relative_a.rb9
-rw-r--r--spec/ruby/core/module/fixtures/classes.rb37
-rw-r--r--spec/ruby/core/module/fixtures/const_added.rb4
-rw-r--r--spec/ruby/core/module/fixtures/module.rb4
-rw-r--r--spec/ruby/core/module/fixtures/name.rb3
-rw-r--r--spec/ruby/core/module/fixtures/set_temporary_name.rb4
-rw-r--r--spec/ruby/core/module/gt_spec.rb10
-rw-r--r--spec/ruby/core/module/gte_spec.rb2
-rw-r--r--spec/ruby/core/module/include_spec.rb89
-rw-r--r--spec/ruby/core/module/included_modules_spec.rb8
-rw-r--r--spec/ruby/core/module/included_spec.rb2
-rw-r--r--spec/ruby/core/module/instance_method_spec.rb53
-rw-r--r--spec/ruby/core/module/instance_methods_spec.rb30
-rw-r--r--spec/ruby/core/module/lt_spec.rb10
-rw-r--r--spec/ruby/core/module/lte_spec.rb2
-rw-r--r--spec/ruby/core/module/method_added_spec.rb77
-rw-r--r--spec/ruby/core/module/method_defined_spec.rb6
-rw-r--r--spec/ruby/core/module/method_removed_spec.rb2
-rw-r--r--spec/ruby/core/module/method_undefined_spec.rb2
-rw-r--r--spec/ruby/core/module/module_function_spec.rb191
-rw-r--r--spec/ruby/core/module/name_spec.rb117
-rw-r--r--spec/ruby/core/module/new_spec.rb4
-rw-r--r--spec/ruby/core/module/prepend_features_spec.rb8
-rw-r--r--spec/ruby/core/module/prepend_spec.rb158
-rw-r--r--spec/ruby/core/module/prepended_spec.rb2
-rw-r--r--spec/ruby/core/module/private_class_method_spec.rb34
-rw-r--r--spec/ruby/core/module/private_constant_spec.rb8
-rw-r--r--spec/ruby/core/module/private_instance_methods_spec.rb18
-rw-r--r--spec/ruby/core/module/private_method_defined_spec.rb10
-rw-r--r--spec/ruby/core/module/private_spec.rb40
-rw-r--r--spec/ruby/core/module/protected_instance_methods_spec.rb12
-rw-r--r--spec/ruby/core/module/protected_method_defined_spec.rb10
-rw-r--r--spec/ruby/core/module/protected_spec.rb38
-rw-r--r--spec/ruby/core/module/public_class_method_spec.rb34
-rw-r--r--spec/ruby/core/module/public_constant_spec.rb2
-rw-r--r--spec/ruby/core/module/public_instance_method_spec.rb20
-rw-r--r--spec/ruby/core/module/public_instance_methods_spec.rb14
-rw-r--r--spec/ruby/core/module/public_method_defined_spec.rb10
-rw-r--r--spec/ruby/core/module/public_spec.rb36
-rw-r--r--spec/ruby/core/module/refine_spec.rb370
-rw-r--r--spec/ruby/core/module/refinements_spec.rb43
-rw-r--r--spec/ruby/core/module/remove_class_variable_spec.rb12
-rw-r--r--spec/ruby/core/module/remove_const_spec.rb32
-rw-r--r--spec/ruby/core/module/remove_method_spec.rb16
-rw-r--r--spec/ruby/core/module/ruby2_keywords_spec.rb197
-rw-r--r--spec/ruby/core/module/set_temporary_name_spec.rb145
-rw-r--r--spec/ruby/core/module/shared/attr_added.rb34
-rw-r--r--spec/ruby/core/module/shared/class_eval.rb29
-rw-r--r--spec/ruby/core/module/shared/class_exec.rb12
-rw-r--r--spec/ruby/core/module/shared/set_visibility.rb60
-rw-r--r--spec/ruby/core/module/to_s_spec.rb2
-rw-r--r--spec/ruby/core/module/undef_method_spec.rb34
-rw-r--r--spec/ruby/core/module/undefined_instance_methods_spec.rb25
-rw-r--r--spec/ruby/core/module/used_refinements_spec.rb85
-rw-r--r--spec/ruby/core/module/using_spec.rb14
-rw-r--r--spec/ruby/core/mutex/lock_spec.rb70
-rw-r--r--spec/ruby/core/mutex/locked_spec.rb8
-rw-r--r--spec/ruby/core/mutex/owned_spec.rb22
-rw-r--r--spec/ruby/core/mutex/sleep_spec.rb28
-rw-r--r--spec/ruby/core/mutex/synchronize_spec.rb8
-rw-r--r--spec/ruby/core/mutex/try_lock_spec.rb8
-rw-r--r--spec/ruby/core/mutex/unlock_spec.rb6
-rw-r--r--spec/ruby/core/nil/dup_spec.rb2
-rw-r--r--spec/ruby/core/nil/match_spec.rb14
-rw-r--r--spec/ruby/core/nil/nilclass_spec.rb4
-rw-r--r--spec/ruby/core/nil/rationalize_spec.rb4
-rw-r--r--spec/ruby/core/nil/singleton_method_spec.rb13
-rw-r--r--spec/ruby/core/nil/to_c_spec.rb2
-rw-r--r--spec/ruby/core/nil/to_s_spec.rb2
-rw-r--r--spec/ruby/core/numeric/abs2_spec.rb4
-rw-r--r--spec/ruby/core/numeric/clone_spec.rb18
-rw-r--r--spec/ruby/core/numeric/coerce_spec.rb12
-rw-r--r--spec/ruby/core/numeric/comparison_spec.rb8
-rw-r--r--spec/ruby/core/numeric/div_spec.rb6
-rw-r--r--spec/ruby/core/numeric/dup_spec.rb4
-rw-r--r--spec/ruby/core/numeric/eql_spec.rb12
-rw-r--r--spec/ruby/core/numeric/fdiv_spec.rb5
-rw-r--r--spec/ruby/core/numeric/finite_spec.rb2
-rw-r--r--spec/ruby/core/numeric/i_spec.rb2
-rw-r--r--spec/ruby/core/numeric/magnitude_spec.rb1
-rw-r--r--spec/ruby/core/numeric/negative_spec.rb12
-rw-r--r--spec/ruby/core/numeric/polar_spec.rb6
-rw-r--r--spec/ruby/core/numeric/positive_spec.rb12
-rw-r--r--spec/ruby/core/numeric/quo_spec.rb25
-rw-r--r--spec/ruby/core/numeric/real_spec.rb4
-rw-r--r--spec/ruby/core/numeric/remainder_spec.rb7
-rw-r--r--spec/ruby/core/numeric/shared/conj.rb2
-rw-r--r--spec/ruby/core/numeric/shared/imag.rb6
-rw-r--r--spec/ruby/core/numeric/shared/quo.rb7
-rw-r--r--spec/ruby/core/numeric/shared/rect.rb28
-rw-r--r--spec/ruby/core/numeric/shared/step.rb98
-rw-r--r--spec/ruby/core/numeric/singleton_method_added_spec.rb8
-rw-r--r--spec/ruby/core/numeric/step_spec.rb93
-rw-r--r--spec/ruby/core/numeric/to_c_spec.rb4
-rw-r--r--spec/ruby/core/objectspace/_id2ref_spec.rb87
-rw-r--r--spec/ruby/core/objectspace/add_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/call_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb147
-rw-r--r--spec/ruby/core/objectspace/each_object_spec.rb46
-rw-r--r--spec/ruby/core/objectspace/finalizers_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/garbage_collect_spec.rb4
-rw-r--r--spec/ruby/core/objectspace/remove_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/undefine_finalizer_spec.rb30
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/clear_spec.rb25
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/delete_spec.rb49
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb105
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb80
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb5
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb26
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb19
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/key_spec.rb42
-rw-r--r--spec/ruby/core/objectspace/weakmap/delete_spec.rb28
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/each.rb2
-rw-r--r--spec/ruby/core/proc/allocate_spec.rb2
-rw-r--r--spec/ruby/core/proc/arity_spec.rb16
-rw-r--r--spec/ruby/core/proc/binding_spec.rb2
-rw-r--r--spec/ruby/core/proc/block_pass_spec.rb4
-rw-r--r--spec/ruby/core/proc/clone_spec.rb22
-rw-r--r--spec/ruby/core/proc/compose_spec.rb46
-rw-r--r--spec/ruby/core/proc/curry_spec.rb69
-rw-r--r--spec/ruby/core/proc/dup_spec.rb20
-rw-r--r--spec/ruby/core/proc/element_reference_spec.rb10
-rw-r--r--spec/ruby/core/proc/eql_spec.rb8
-rw-r--r--spec/ruby/core/proc/equal_value_spec.rb8
-rw-r--r--spec/ruby/core/proc/fixtures/common.rb23
-rw-r--r--spec/ruby/core/proc/fixtures/proc_aref.rb1
-rw-r--r--spec/ruby/core/proc/hash_spec.rb6
-rw-r--r--spec/ruby/core/proc/lambda_spec.rb43
-rw-r--r--spec/ruby/core/proc/new_spec.rb57
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb111
-rw-r--r--spec/ruby/core/proc/ruby2_keywords_spec.rb38
-rw-r--r--spec/ruby/core/proc/shared/call.rb8
-rw-r--r--spec/ruby/core/proc/shared/compose.rb4
-rw-r--r--spec/ruby/core/proc/shared/dup.rb31
-rw-r--r--spec/ruby/core/proc/shared/equal.rb51
-rw-r--r--spec/ruby/core/proc/shared/to_s.rb14
-rw-r--r--spec/ruby/core/proc/source_location_spec.rb37
-rw-r--r--spec/ruby/core/proc/to_proc_spec.rb2
-rw-r--r--spec/ruby/core/process/_fork_spec.rb24
-rw-r--r--spec/ruby/core/process/argv0_spec.rb23
-rw-r--r--spec/ruby/core/process/clock_gettime_spec.rb62
-rw-r--r--spec/ruby/core/process/constants_spec.rb135
-rw-r--r--spec/ruby/core/process/daemon_spec.rb5
-rw-r--r--spec/ruby/core/process/detach_spec.rb41
-rw-r--r--spec/ruby/core/process/egid_spec.rb8
-rw-r--r--spec/ruby/core/process/euid_spec.rb8
-rw-r--r--spec/ruby/core/process/exec_spec.rb62
-rw-r--r--spec/ruby/core/process/exit_spec.rb2
-rw-r--r--spec/ruby/core/process/fixtures/argv0.rb6
-rw-r--r--spec/ruby/core/process/fixtures/clocks.rb2
-rw-r--r--spec/ruby/core/process/fixtures/kill.rb2
-rw-r--r--spec/ruby/core/process/getpriority_spec.rb8
-rw-r--r--spec/ruby/core/process/getrlimit_spec.rb14
-rw-r--r--spec/ruby/core/process/gid_spec.rb4
-rw-r--r--spec/ruby/core/process/groups_spec.rb4
-rw-r--r--spec/ruby/core/process/initgroups_spec.rb2
-rw-r--r--spec/ruby/core/process/kill_spec.rb8
-rw-r--r--spec/ruby/core/process/last_status_spec.rb2
-rw-r--r--spec/ruby/core/process/maxgroups_spec.rb2
-rw-r--r--spec/ruby/core/process/pid_spec.rb2
-rw-r--r--spec/ruby/core/process/set_proctitle_spec.rb2
-rw-r--r--spec/ruby/core/process/setrlimit_spec.rb108
-rw-r--r--spec/ruby/core/process/spawn_spec.rb136
-rw-r--r--spec/ruby/core/process/status/bit_and_spec.rb37
-rw-r--r--spec/ruby/core/process/status/exited_spec.rb6
-rw-r--r--spec/ruby/core/process/status/right_shift_spec.rb36
-rw-r--r--spec/ruby/core/process/status/signaled_spec.rb6
-rw-r--r--spec/ruby/core/process/status/success_spec.rb8
-rw-r--r--spec/ruby/core/process/status/termsig_spec.rb6
-rw-r--r--spec/ruby/core/process/status/to_i_spec.rb4
-rw-r--r--spec/ruby/core/process/status/wait_spec.rb158
-rw-r--r--spec/ruby/core/process/times_spec.rb34
-rw-r--r--spec/ruby/core/process/tms/cstime_spec.rb17
-rw-r--r--spec/ruby/core/process/tms/cutime_spec.rb17
-rw-r--r--spec/ruby/core/process/tms/stime_spec.rb17
-rw-r--r--spec/ruby/core/process/tms/utime_spec.rb17
-rw-r--r--spec/ruby/core/process/uid_spec.rb6
-rw-r--r--spec/ruby/core/process/wait2_spec.rb14
-rw-r--r--spec/ruby/core/process/wait_spec.rb18
-rw-r--r--spec/ruby/core/process/waitall_spec.rb10
-rw-r--r--spec/ruby/core/process/waitpid_spec.rb3
-rw-r--r--spec/ruby/core/process/warmup_spec.rb9
-rw-r--r--spec/ruby/core/queue/deq_spec.rb5
-rw-r--r--spec/ruby/core/queue/freeze_spec.rb6
-rw-r--r--spec/ruby/core/queue/initialize_spec.rb46
-rw-r--r--spec/ruby/core/queue/pop_spec.rb5
-rw-r--r--spec/ruby/core/queue/shift_spec.rb5
-rw-r--r--spec/ruby/core/random/bytes_spec.rb3
-rw-r--r--spec/ruby/core/random/default_spec.rb42
-rw-r--r--spec/ruby/core/random/new_seed_spec.rb2
-rw-r--r--spec/ruby/core/random/new_spec.rb9
-rw-r--r--spec/ruby/core/random/rand_spec.rb34
-rw-r--r--spec/ruby/core/random/seed_spec.rb2
-rw-r--r--spec/ruby/core/random/shared/bytes.rb2
-rw-r--r--spec/ruby/core/random/shared/rand.rb4
-rw-r--r--spec/ruby/core/random/urandom_spec.rb4
-rw-r--r--spec/ruby/core/range/bsearch_spec.rb136
-rw-r--r--spec/ruby/core/range/case_compare_spec.rb4
-rw-r--r--spec/ruby/core/range/cover_spec.rb6
-rw-r--r--spec/ruby/core/range/each_spec.rb45
-rw-r--r--spec/ruby/core/range/eql_spec.rb2
-rw-r--r--spec/ruby/core/range/first_spec.rb10
-rw-r--r--spec/ruby/core/range/frozen_spec.rb34
-rw-r--r--spec/ruby/core/range/hash_spec.rb8
-rw-r--r--spec/ruby/core/range/include_spec.rb6
-rw-r--r--spec/ruby/core/range/initialize_spec.rb31
-rw-r--r--spec/ruby/core/range/last_spec.rb14
-rw-r--r--spec/ruby/core/range/max_spec.rb54
-rw-r--r--spec/ruby/core/range/member_spec.rb2
-rw-r--r--spec/ruby/core/range/min_spec.rb26
-rw-r--r--spec/ruby/core/range/minmax_spec.rb38
-rw-r--r--spec/ruby/core/range/new_spec.rb20
-rw-r--r--spec/ruby/core/range/overlap_spec.rb87
-rw-r--r--spec/ruby/core/range/reverse_each_spec.rb125
-rw-r--r--spec/ruby/core/range/shared/cover.rb144
-rw-r--r--spec/ruby/core/range/shared/cover_and_include.rb48
-rw-r--r--spec/ruby/core/range/shared/include.rb34
-rw-r--r--spec/ruby/core/range/size_spec.rb82
-rw-r--r--spec/ruby/core/range/step_spec.rb535
-rw-r--r--spec/ruby/core/range/to_a_spec.rb6
-rw-r--r--spec/ruby/core/range/to_set_spec.rb54
-rw-r--r--spec/ruby/core/rational/abs_spec.rb3
-rw-r--r--spec/ruby/core/rational/ceil_spec.rb47
-rw-r--r--spec/ruby/core/rational/coerce_spec.rb5
-rw-r--r--spec/ruby/core/rational/comparison_spec.rb85
-rw-r--r--spec/ruby/core/rational/denominator_spec.rb13
-rw-r--r--spec/ruby/core/rational/div_spec.rb47
-rw-r--r--spec/ruby/core/rational/divide_spec.rb67
-rw-r--r--spec/ruby/core/rational/divmod_spec.rb37
-rw-r--r--spec/ruby/core/rational/equal_value_spec.rb32
-rw-r--r--spec/ruby/core/rational/exponent_spec.rb235
-rw-r--r--spec/ruby/core/rational/fdiv_spec.rb4
-rw-r--r--spec/ruby/core/rational/fixtures/rational.rb (renamed from spec/ruby/fixtures/rational.rb)0
-rw-r--r--spec/ruby/core/rational/floor_spec.rb48
-rw-r--r--spec/ruby/core/rational/hash_spec.rb8
-rw-r--r--spec/ruby/core/rational/inspect_spec.rb13
-rw-r--r--spec/ruby/core/rational/integer_spec.rb5
-rw-r--r--spec/ruby/core/rational/magnitude_spec.rb3
-rw-r--r--spec/ruby/core/rational/marshal_dump_spec.rb2
-rw-r--r--spec/ruby/core/rational/minus_spec.rb16
-rw-r--r--spec/ruby/core/rational/modulo_spec.rb42
-rw-r--r--spec/ruby/core/rational/multiply_spec.rb58
-rw-r--r--spec/ruby/core/rational/numerator_spec.rb9
-rw-r--r--spec/ruby/core/rational/plus_spec.rb44
-rw-r--r--spec/ruby/core/rational/quo_spec.rb24
-rw-r--r--spec/ruby/core/rational/rational_spec.rb2
-rw-r--r--spec/ruby/core/rational/rationalize_spec.rb4
-rw-r--r--spec/ruby/core/rational/remainder_spec.rb4
-rw-r--r--spec/ruby/core/rational/round_spec.rb104
-rw-r--r--spec/ruby/core/rational/shared/abs.rb11
-rw-r--r--spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb11
-rw-r--r--spec/ruby/core/rational/to_f_spec.rb15
-rw-r--r--spec/ruby/core/rational/to_i_spec.rb11
-rw-r--r--spec/ruby/core/rational/to_r_spec.rb14
-rw-r--r--spec/ruby/core/rational/to_s_spec.rb13
-rw-r--r--spec/ruby/core/rational/truncate_spec.rb70
-rw-r--r--spec/ruby/core/rational/zero_spec.rb7
-rw-r--r--spec/ruby/core/refinement/append_features_spec.rb24
-rw-r--r--spec/ruby/core/refinement/extend_object_spec.rb26
-rw-r--r--spec/ruby/core/refinement/fixtures/classes.rb10
-rw-r--r--spec/ruby/core/refinement/import_methods_spec.rb287
-rw-r--r--spec/ruby/core/refinement/include_spec.rb13
-rw-r--r--spec/ruby/core/refinement/prepend_features_spec.rb24
-rw-r--r--spec/ruby/core/refinement/prepend_spec.rb13
-rw-r--r--spec/ruby/core/refinement/refined_class_spec.rb34
-rw-r--r--spec/ruby/core/refinement/shared/target.rb13
-rw-r--r--spec/ruby/core/refinement/target_spec.rb6
-rw-r--r--spec/ruby/core/regexp/case_compare_spec.rb14
-rw-r--r--spec/ruby/core/regexp/compile_spec.rb4
-rw-r--r--spec/ruby/core/regexp/encoding_spec.rb2
-rw-r--r--spec/ruby/core/regexp/fixed_encoding_spec.rb16
-rw-r--r--spec/ruby/core/regexp/initialize_spec.rb24
-rw-r--r--spec/ruby/core/regexp/last_match_spec.rb6
-rw-r--r--spec/ruby/core/regexp/linear_time_spec.rb80
-rw-r--r--spec/ruby/core/regexp/match_spec.rb38
-rw-r--r--spec/ruby/core/regexp/named_captures_spec.rb4
-rw-r--r--spec/ruby/core/regexp/names_spec.rb4
-rw-r--r--spec/ruby/core/regexp/new_spec.rb14
-rw-r--r--spec/ruby/core/regexp/options_spec.rb6
-rw-r--r--spec/ruby/core/regexp/shared/new.rb444
-rw-r--r--spec/ruby/core/regexp/shared/quote.rb20
-rw-r--r--spec/ruby/core/regexp/source_spec.rb4
-rw-r--r--spec/ruby/core/regexp/timeout_spec.rb33
-rw-r--r--spec/ruby/core/regexp/try_convert_spec.rb8
-rw-r--r--spec/ruby/core/regexp/union_spec.rb51
-rw-r--r--spec/ruby/core/set/add_spec.rb34
-rw-r--r--spec/ruby/core/set/append_spec.rb6
-rw-r--r--spec/ruby/core/set/case_compare_spec.rb11
-rw-r--r--spec/ruby/core/set/case_equality_spec.rb6
-rw-r--r--spec/ruby/core/set/classify_spec.rb26
-rw-r--r--spec/ruby/core/set/clear_spec.rb16
-rw-r--r--spec/ruby/core/set/collect_spec.rb6
-rw-r--r--spec/ruby/core/set/compare_by_identity_spec.rb153
-rw-r--r--spec/ruby/core/set/comparison_spec.rb26
-rw-r--r--spec/ruby/core/set/constructor_spec.rb14
-rw-r--r--spec/ruby/core/set/delete_if_spec.rb37
-rw-r--r--spec/ruby/core/set/delete_spec.rb36
-rw-r--r--spec/ruby/core/set/difference_spec.rb6
-rw-r--r--spec/ruby/core/set/disjoint_spec.rb22
-rw-r--r--spec/ruby/core/set/divide_spec.rb68
-rw-r--r--spec/ruby/core/set/each_spec.rb26
-rw-r--r--spec/ruby/core/set/empty_spec.rb9
-rw-r--r--spec/ruby/core/set/enumerable/to_set_spec.rb12
-rw-r--r--spec/ruby/core/set/eql_spec.rb14
-rw-r--r--spec/ruby/core/set/equal_value_spec.rb34
-rw-r--r--spec/ruby/core/set/exclusion_spec.rb17
-rw-r--r--spec/ruby/core/set/filter_spec.rb (renamed from spec/ruby/library/set/filter_spec.rb)0
-rw-r--r--spec/ruby/core/set/fixtures/set_like.rb30
-rw-r--r--spec/ruby/core/set/flatten_merge_spec.rb24
-rw-r--r--spec/ruby/core/set/flatten_spec.rb49
-rw-r--r--spec/ruby/core/set/hash_spec.rb19
-rw-r--r--spec/ruby/core/set/include_spec.rb6
-rw-r--r--spec/ruby/core/set/initialize_clone_spec.rb15
-rw-r--r--spec/ruby/core/set/initialize_spec.rb88
-rw-r--r--spec/ruby/core/set/inspect_spec.rb6
-rw-r--r--spec/ruby/core/set/intersect_spec.rb22
-rw-r--r--spec/ruby/core/set/intersection_spec.rb10
-rw-r--r--spec/ruby/core/set/join_spec.rb30
-rw-r--r--spec/ruby/core/set/keep_if_spec.rb37
-rw-r--r--spec/ruby/core/set/length_spec.rb6
-rw-r--r--spec/ruby/core/set/map_spec.rb6
-rw-r--r--spec/ruby/core/set/member_spec.rb6
-rw-r--r--spec/ruby/core/set/merge_spec.rb29
-rw-r--r--spec/ruby/core/set/minus_spec.rb6
-rw-r--r--spec/ruby/core/set/plus_spec.rb6
-rw-r--r--spec/ruby/core/set/pretty_print_cycle_spec.rb14
-rw-r--r--spec/ruby/core/set/proper_subset_spec.rb35
-rw-r--r--spec/ruby/core/set/proper_superset_spec.rb42
-rw-r--r--spec/ruby/core/set/reject_spec.rb41
-rw-r--r--spec/ruby/core/set/replace_spec.rb24
-rw-r--r--spec/ruby/core/set/select_spec.rb (renamed from spec/ruby/library/set/select_spec.rb)0
-rw-r--r--spec/ruby/core/set/set_spec.rb10
-rw-r--r--spec/ruby/core/set/shared/add.rb14
-rw-r--r--spec/ruby/core/set/shared/collect.rb20
-rw-r--r--spec/ruby/core/set/shared/difference.rb15
-rw-r--r--spec/ruby/core/set/shared/include.rb29
-rw-r--r--spec/ruby/core/set/shared/inspect.rb45
-rw-r--r--spec/ruby/core/set/shared/intersection.rb15
-rw-r--r--spec/ruby/core/set/shared/length.rb (renamed from spec/ruby/library/set/shared/length.rb)0
-rw-r--r--spec/ruby/core/set/shared/select.rb41
-rw-r--r--spec/ruby/core/set/shared/union.rb15
-rw-r--r--spec/ruby/core/set/size_spec.rb6
-rw-r--r--spec/ruby/core/set/sortedset/sortedset_spec.rb13
-rw-r--r--spec/ruby/core/set/subset_spec.rb35
-rw-r--r--spec/ruby/core/set/subtract_spec.rb16
-rw-r--r--spec/ruby/core/set/superset_spec.rb42
-rw-r--r--spec/ruby/core/set/to_a_spec.rb7
-rw-r--r--spec/ruby/core/set/to_s_spec.rb11
-rw-r--r--spec/ruby/core/set/union_spec.rb10
-rw-r--r--spec/ruby/core/signal/signame_spec.rb14
-rw-r--r--spec/ruby/core/signal/trap_spec.rb59
-rw-r--r--spec/ruby/core/sizedqueue/append_spec.rb5
-rw-r--r--spec/ruby/core/sizedqueue/deq_spec.rb5
-rw-r--r--spec/ruby/core/sizedqueue/enq_spec.rb5
-rw-r--r--spec/ruby/core/sizedqueue/freeze_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/pop_spec.rb5
-rw-r--r--spec/ruby/core/sizedqueue/push_spec.rb5
-rw-r--r--spec/ruby/core/sizedqueue/shift_spec.rb5
-rw-r--r--spec/ruby/core/string/allocate_spec.rb2
-rw-r--r--spec/ruby/core/string/append_as_bytes_spec.rb60
-rw-r--r--spec/ruby/core/string/append_spec.rb5
-rw-r--r--spec/ruby/core/string/ascii_only_spec.rb41
-rw-r--r--spec/ruby/core/string/b_spec.rb3
-rw-r--r--spec/ruby/core/string/byteindex_spec.rb298
-rw-r--r--spec/ruby/core/string/byterindex_spec.rb353
-rw-r--r--spec/ruby/core/string/bytes_spec.rb8
-rw-r--r--spec/ruby/core/string/bytesize_spec.rb10
-rw-r--r--spec/ruby/core/string/byteslice_spec.rb18
-rw-r--r--spec/ruby/core/string/bytesplice_spec.rb290
-rw-r--r--spec/ruby/core/string/capitalize_spec.rb63
-rw-r--r--spec/ruby/core/string/casecmp_spec.rb20
-rw-r--r--spec/ruby/core/string/center_spec.rb53
-rw-r--r--spec/ruby/core/string/chars_spec.rb8
-rw-r--r--spec/ruby/core/string/chilled_string_spec.rb151
-rw-r--r--spec/ruby/core/string/chomp_spec.rb54
-rw-r--r--spec/ruby/core/string/chop_spec.rb23
-rw-r--r--spec/ruby/core/string/chr_spec.rb4
-rw-r--r--spec/ruby/core/string/clear_spec.rb7
-rw-r--r--spec/ruby/core/string/clone_spec.rb8
-rw-r--r--spec/ruby/core/string/codepoints_spec.rb8
-rw-r--r--spec/ruby/core/string/comparison_spec.rb12
-rw-r--r--spec/ruby/core/string/concat_spec.rb9
-rw-r--r--spec/ruby/core/string/count_spec.rb14
-rw-r--r--spec/ruby/core/string/crypt_spec.rb30
-rw-r--r--spec/ruby/core/string/dedup_spec.rb4
-rw-r--r--spec/ruby/core/string/delete_prefix_spec.rb30
-rw-r--r--spec/ruby/core/string/delete_spec.rb33
-rw-r--r--spec/ruby/core/string/delete_suffix_spec.rb30
-rw-r--r--spec/ruby/core/string/downcase_spec.rb41
-rw-r--r--spec/ruby/core/string/dump_spec.rb22
-rw-r--r--spec/ruby/core/string/dup_spec.rb12
-rw-r--r--spec/ruby/core/string/each_byte_spec.rb20
-rw-r--r--spec/ruby/core/string/each_char_spec.rb1
-rw-r--r--spec/ruby/core/string/each_grapheme_cluster_spec.rb11
-rw-r--r--spec/ruby/core/string/element_set_spec.rb87
-rw-r--r--spec/ruby/core/string/encode_spec.rb78
-rw-r--r--spec/ruby/core/string/encoding_spec.rb36
-rw-r--r--spec/ruby/core/string/eql_spec.rb8
-rw-r--r--spec/ruby/core/string/fixtures/to_c.rb5
-rw-r--r--spec/ruby/core/string/fixtures/utf-8-encoding.rb7
-rw-r--r--spec/ruby/core/string/force_encoding_spec.rb11
-rw-r--r--spec/ruby/core/string/freeze_spec.rb5
-rw-r--r--spec/ruby/core/string/getbyte_spec.rb12
-rw-r--r--spec/ruby/core/string/grapheme_clusters_spec.rb1
-rw-r--r--spec/ruby/core/string/gsub_spec.rb103
-rw-r--r--spec/ruby/core/string/include_spec.rb20
-rw-r--r--spec/ruby/core/string/index_spec.rb38
-rw-r--r--spec/ruby/core/string/initialize_spec.rb4
-rw-r--r--spec/ruby/core/string/insert_spec.rb18
-rw-r--r--spec/ruby/core/string/inspect_spec.rb4
-rw-r--r--spec/ruby/core/string/lines_spec.rb1
-rw-r--r--spec/ruby/core/string/ljust_spec.rb51
-rw-r--r--spec/ruby/core/string/lstrip_spec.rb45
-rw-r--r--spec/ruby/core/string/match_spec.rb34
-rw-r--r--spec/ruby/core/string/modulo_spec.rb199
-rw-r--r--spec/ruby/core/string/new_spec.rb10
-rw-r--r--spec/ruby/core/string/ord_spec.rb8
-rw-r--r--spec/ruby/core/string/partition_spec.rb26
-rw-r--r--spec/ruby/core/string/plus_spec.rb23
-rw-r--r--spec/ruby/core/string/prepend_spec.rb13
-rw-r--r--spec/ruby/core/string/reverse_spec.rb35
-rw-r--r--spec/ruby/core/string/rindex_spec.rb34
-rw-r--r--spec/ruby/core/string/rjust_spec.rb51
-rw-r--r--spec/ruby/core/string/rpartition_spec.rb26
-rw-r--r--spec/ruby/core/string/rstrip_spec.rb29
-rw-r--r--spec/ruby/core/string/scan_spec.rb46
-rw-r--r--spec/ruby/core/string/scrub_spec.rb49
-rw-r--r--spec/ruby/core/string/setbyte_spec.rb17
-rw-r--r--spec/ruby/core/string/shared/byte_index_common.rb63
-rw-r--r--spec/ruby/core/string/shared/chars.rb38
-rw-r--r--spec/ruby/core/string/shared/codepoints.rb27
-rw-r--r--spec/ruby/core/string/shared/concat.rb63
-rw-r--r--spec/ruby/core/string/shared/dedup.rb32
-rw-r--r--spec/ruby/core/string/shared/each_char_without_block.rb2
-rw-r--r--spec/ruby/core/string/shared/each_codepoint_without_block.rb14
-rw-r--r--spec/ruby/core/string/shared/each_line.rb84
-rw-r--r--spec/ruby/core/string/shared/each_line_without_block.rb2
-rw-r--r--spec/ruby/core/string/shared/encode.rb215
-rw-r--r--spec/ruby/core/string/shared/eql.rb20
-rw-r--r--spec/ruby/core/string/shared/equal_value.rb10
-rw-r--r--spec/ruby/core/string/shared/grapheme_clusters.rb11
-rw-r--r--spec/ruby/core/string/shared/length.rb10
-rw-r--r--spec/ruby/core/string/shared/partition.rb43
-rw-r--r--spec/ruby/core/string/shared/replace.rb15
-rw-r--r--spec/ruby/core/string/shared/slice.rb202
-rw-r--r--spec/ruby/core/string/shared/strip.rb18
-rw-r--r--spec/ruby/core/string/shared/succ.rb27
-rw-r--r--spec/ruby/core/string/shared/to_a.rb9
-rw-r--r--spec/ruby/core/string/shared/to_s.rb4
-rw-r--r--spec/ruby/core/string/shared/to_sym.rb38
-rw-r--r--spec/ruby/core/string/slice_spec.rb137
-rw-r--r--spec/ruby/core/string/split_spec.rb209
-rw-r--r--spec/ruby/core/string/squeeze_spec.rb38
-rw-r--r--spec/ruby/core/string/start_with_spec.rb6
-rw-r--r--spec/ruby/core/string/strip_spec.rb25
-rw-r--r--spec/ruby/core/string/sub_spec.rb104
-rw-r--r--spec/ruby/core/string/swapcase_spec.rb50
-rw-r--r--spec/ruby/core/string/to_c_spec.rb116
-rw-r--r--spec/ruby/core/string/to_f_spec.rb104
-rw-r--r--spec/ruby/core/string/to_i_spec.rb30
-rw-r--r--spec/ruby/core/string/to_r_spec.rb6
-rw-r--r--spec/ruby/core/string/tr_s_spec.rb26
-rw-r--r--spec/ruby/core/string/tr_spec.rb30
-rw-r--r--spec/ruby/core/string/try_convert_spec.rb16
-rw-r--r--spec/ruby/core/string/undump_spec.rb38
-rw-r--r--spec/ruby/core/string/unicode_normalize_spec.rb9
-rw-r--r--spec/ruby/core/string/unicode_normalized_spec.rb21
-rw-r--r--spec/ruby/core/string/unpack/a_spec.rb4
-rw-r--r--spec/ruby/core/string/unpack/at_spec.rb4
-rw-r--r--spec/ruby/core/string/unpack/b_spec.rb22
-rw-r--r--spec/ruby/core/string/unpack/c_spec.rb8
-rw-r--r--spec/ruby/core/string/unpack/carret_spec.rb43
-rw-r--r--spec/ruby/core/string/unpack/comment_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/h_spec.rb14
-rw-r--r--spec/ruby/core/string/unpack/l_spec.rb16
-rw-r--r--spec/ruby/core/string/unpack/m_spec.rb9
-rw-r--r--spec/ruby/core/string/unpack/p_spec.rb4
-rw-r--r--spec/ruby/core/string/unpack/percent_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/r_spec.rb85
-rw-r--r--spec/ruby/core/string/unpack/shared/basic.rb38
-rw-r--r--spec/ruby/core/string/unpack/shared/float.rb36
-rw-r--r--spec/ruby/core/string/unpack/shared/integer.rb40
-rw-r--r--spec/ruby/core/string/unpack/shared/unicode.rb6
-rw-r--r--spec/ruby/core/string/unpack/u_spec.rb8
-rw-r--r--spec/ruby/core/string/unpack/w_spec.rb8
-rw-r--r--spec/ruby/core/string/unpack/x_spec.rb8
-rw-r--r--spec/ruby/core/string/unpack/z_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack1_spec.rb53
-rw-r--r--spec/ruby/core/string/unpack_spec.rb46
-rw-r--r--spec/ruby/core/string/upcase_spec.rb43
-rw-r--r--spec/ruby/core/string/uplus_spec.rb48
-rw-r--r--spec/ruby/core/string/upto_spec.rb14
-rw-r--r--spec/ruby/core/string/valid_encoding/utf_8_spec.rb214
-rw-r--r--spec/ruby/core/string/valid_encoding_spec.rb210
-rw-r--r--spec/ruby/core/struct/constants_spec.rb13
-rw-r--r--spec/ruby/core/struct/deconstruct_keys_spec.rb66
-rw-r--r--spec/ruby/core/struct/dig_spec.rb4
-rw-r--r--spec/ruby/core/struct/each_pair_spec.rb4
-rw-r--r--spec/ruby/core/struct/each_spec.rb2
-rw-r--r--spec/ruby/core/struct/element_reference_spec.rb14
-rw-r--r--spec/ruby/core/struct/element_set_spec.rb15
-rw-r--r--spec/ruby/core/struct/eql_spec.rb2
-rw-r--r--spec/ruby/core/struct/fixtures/classes.rb9
-rw-r--r--spec/ruby/core/struct/hash_spec.rb4
-rw-r--r--spec/ruby/core/struct/initialize_spec.rb33
-rw-r--r--spec/ruby/core/struct/inspect_spec.rb5
-rw-r--r--spec/ruby/core/struct/instance_variable_get_spec.rb2
-rw-r--r--spec/ruby/core/struct/keyword_init_spec.rb45
-rw-r--r--spec/ruby/core/struct/members_spec.rb12
-rw-r--r--spec/ruby/core/struct/new_spec.rb139
-rw-r--r--spec/ruby/core/struct/shared/inspect.rb35
-rw-r--r--spec/ruby/core/struct/shared/select.rb6
-rw-r--r--spec/ruby/core/struct/struct_spec.rb9
-rw-r--r--spec/ruby/core/struct/to_h_spec.rb20
-rw-r--r--spec/ruby/core/struct/values_at_spec.rb55
-rw-r--r--spec/ruby/core/symbol/all_symbols_spec.rb8
-rw-r--r--spec/ruby/core/symbol/capitalize_spec.rb2
-rw-r--r--spec/ruby/core/symbol/casecmp_spec.rb14
-rw-r--r--spec/ruby/core/symbol/comparison_spec.rb6
-rw-r--r--spec/ruby/core/symbol/downcase_spec.rb2
-rw-r--r--spec/ruby/core/symbol/dup_spec.rb2
-rw-r--r--spec/ruby/core/symbol/empty_spec.rb4
-rw-r--r--spec/ruby/core/symbol/inspect_spec.rb34
-rw-r--r--spec/ruby/core/symbol/intern_spec.rb2
-rw-r--r--spec/ruby/core/symbol/match_spec.rb18
-rw-r--r--spec/ruby/core/symbol/name_spec.rb24
-rw-r--r--spec/ruby/core/symbol/shared/id2name.rb21
-rw-r--r--spec/ruby/core/symbol/shared/slice.rb58
-rw-r--r--spec/ruby/core/symbol/swapcase_spec.rb2
-rw-r--r--spec/ruby/core/symbol/symbol_spec.rb4
-rw-r--r--spec/ruby/core/symbol/to_proc_spec.rb60
-rw-r--r--spec/ruby/core/symbol/upcase_spec.rb2
-rw-r--r--spec/ruby/core/thread/abort_on_exception_spec.rb10
-rw-r--r--spec/ruby/core/thread/allocate_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/limit_spec.rb13
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb30
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/classes.rb104
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb11
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb1
-rw-r--r--spec/ruby/core/thread/backtrace/location/inspect_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/label_spec.rb204
-rw-r--r--spec/ruby/core/thread/backtrace/location/lineno_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/path_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/to_s_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace_locations_spec.rb14
-rw-r--r--spec/ruby/core/thread/backtrace_spec.rb6
-rw-r--r--spec/ruby/core/thread/current_spec.rb10
-rw-r--r--spec/ruby/core/thread/each_caller_location_spec.rb47
-rw-r--r--spec/ruby/core/thread/element_reference_spec.rb15
-rw-r--r--spec/ruby/core/thread/element_set_spec.rb31
-rw-r--r--spec/ruby/core/thread/exclusive_spec.rb49
-rw-r--r--spec/ruby/core/thread/exit_spec.rb2
-rw-r--r--spec/ruby/core/thread/fetch_spec.rb36
-rw-r--r--spec/ruby/core/thread/fixtures/classes.rb27
-rw-r--r--spec/ruby/core/thread/group_spec.rb15
-rw-r--r--spec/ruby/core/thread/handle_interrupt_spec.rb6
-rw-r--r--spec/ruby/core/thread/ignore_deadlock_spec.rb26
-rw-r--r--spec/ruby/core/thread/initialize_spec.rb2
-rw-r--r--spec/ruby/core/thread/join_spec.rb20
-rw-r--r--spec/ruby/core/thread/key_spec.rb23
-rw-r--r--spec/ruby/core/thread/keys_spec.rb12
-rw-r--r--spec/ruby/core/thread/kill_spec.rb6
-rw-r--r--spec/ruby/core/thread/list_spec.rb12
-rw-r--r--spec/ruby/core/thread/name_spec.rb2
-rw-r--r--spec/ruby/core/thread/native_thread_id_spec.rb31
-rw-r--r--spec/ruby/core/thread/new_spec.rb4
-rw-r--r--spec/ruby/core/thread/pending_interrupt_spec.rb2
-rw-r--r--spec/ruby/core/thread/priority_spec.rb8
-rw-r--r--spec/ruby/core/thread/raise_spec.rb67
-rw-r--r--spec/ruby/core/thread/report_on_exception_spec.rb58
-rw-r--r--spec/ruby/core/thread/shared/exit.rb25
-rw-r--r--spec/ruby/core/thread/shared/start.rb8
-rw-r--r--spec/ruby/core/thread/shared/to_s.rb20
-rw-r--r--spec/ruby/core/thread/shared/wakeup.rb2
-rw-r--r--spec/ruby/core/thread/thread_variable_get_spec.rb45
-rw-r--r--spec/ruby/core/thread/thread_variable_set_spec.rb44
-rw-r--r--spec/ruby/core/thread/thread_variable_spec.rb47
-rw-r--r--spec/ruby/core/thread/thread_variables_spec.rb25
-rw-r--r--spec/ruby/core/thread/value_spec.rb2
-rw-r--r--spec/ruby/core/threadgroup/default_spec.rb2
-rw-r--r--spec/ruby/core/threadgroup/enclose_spec.rb2
-rw-r--r--spec/ruby/core/threadgroup/enclosed_spec.rb4
-rw-r--r--spec/ruby/core/threadgroup/list_spec.rb4
-rw-r--r--spec/ruby/core/time/_dump_spec.rb6
-rw-r--r--spec/ruby/core/time/_load_spec.rb7
-rw-r--r--spec/ruby/core/time/at_spec.rb90
-rw-r--r--spec/ruby/core/time/ceil_spec.rb4
-rw-r--r--spec/ruby/core/time/comparison_spec.rb28
-rw-r--r--spec/ruby/core/time/deconstruct_keys_spec.rb43
-rw-r--r--spec/ruby/core/time/dup_spec.rb14
-rw-r--r--spec/ruby/core/time/eql_spec.rb16
-rw-r--r--spec/ruby/core/time/fixtures/classes.rb1
-rw-r--r--spec/ruby/core/time/floor_spec.rb4
-rw-r--r--spec/ruby/core/time/getlocal_spec.rb67
-rw-r--r--spec/ruby/core/time/hash_spec.rb2
-rw-r--r--spec/ruby/core/time/iso8601_spec.rb6
-rw-r--r--spec/ruby/core/time/localtime_spec.rb83
-rw-r--r--spec/ruby/core/time/minus_spec.rb16
-rw-r--r--spec/ruby/core/time/new_spec.rb524
-rw-r--r--spec/ruby/core/time/now_spec.rb175
-rw-r--r--spec/ruby/core/time/plus_spec.rb16
-rw-r--r--spec/ruby/core/time/round_spec.rb4
-rw-r--r--spec/ruby/core/time/shared/gmtime.rb17
-rw-r--r--spec/ruby/core/time/shared/inspect.rb2
-rw-r--r--spec/ruby/core/time/shared/local.rb11
-rw-r--r--spec/ruby/core/time/shared/now.rb4
-rw-r--r--spec/ruby/core/time/shared/time_params.rb41
-rw-r--r--spec/ruby/core/time/shared/xmlschema.rb31
-rw-r--r--spec/ruby/core/time/strftime_spec.rb41
-rw-r--r--spec/ruby/core/time/subsec_spec.rb12
-rw-r--r--spec/ruby/core/time/succ_spec.rb39
-rw-r--r--spec/ruby/core/time/to_r_spec.rb4
-rw-r--r--spec/ruby/core/time/utc_spec.rb49
-rw-r--r--spec/ruby/core/time/xmlschema_spec.rb6
-rw-r--r--spec/ruby/core/time/yday_spec.rb13
-rw-r--r--spec/ruby/core/time/zone_spec.rb31
-rw-r--r--spec/ruby/core/tracepoint/allow_reentry_spec.rb30
-rw-r--r--spec/ruby/core/tracepoint/binding_spec.rb2
-rw-r--r--spec/ruby/core/tracepoint/defined_class_spec.rb10
-rw-r--r--spec/ruby/core/tracepoint/enable_spec.rb91
-rw-r--r--spec/ruby/core/tracepoint/event_spec.rb6
-rw-r--r--spec/ruby/core/tracepoint/inspect_spec.rb36
-rw-r--r--spec/ruby/core/tracepoint/lineno_spec.rb2
-rw-r--r--spec/ruby/core/tracepoint/method_id_spec.rb2
-rw-r--r--spec/ruby/core/tracepoint/new_spec.rb22
-rw-r--r--spec/ruby/core/tracepoint/path_spec.rb4
-rw-r--r--spec/ruby/core/tracepoint/raised_exception_spec.rb18
-rw-r--r--spec/ruby/core/tracepoint/self_spec.rb4
-rw-r--r--spec/ruby/core/true/dup_spec.rb2
-rw-r--r--spec/ruby/core/true/singleton_method_spec.rb13
-rw-r--r--spec/ruby/core/true/to_s_spec.rb2
-rw-r--r--spec/ruby/core/true/trueclass_spec.rb4
-rw-r--r--spec/ruby/core/unboundmethod/bind_call_spec.rb12
-rw-r--r--spec/ruby/core/unboundmethod/bind_spec.rb24
-rw-r--r--spec/ruby/core/unboundmethod/clone_spec.rb13
-rw-r--r--spec/ruby/core/unboundmethod/dup_spec.rb15
-rw-r--r--spec/ruby/core/unboundmethod/equal_value_spec.rb86
-rw-r--r--spec/ruby/core/unboundmethod/fixtures/classes.rb37
-rw-r--r--spec/ruby/core/unboundmethod/hash_spec.rb7
-rw-r--r--spec/ruby/core/unboundmethod/inspect_spec.rb2
-rw-r--r--spec/ruby/core/unboundmethod/original_name_spec.rb37
-rw-r--r--spec/ruby/core/unboundmethod/owner_spec.rb5
-rw-r--r--spec/ruby/core/unboundmethod/private_spec.rb9
-rw-r--r--spec/ruby/core/unboundmethod/protected_spec.rb9
-rw-r--r--spec/ruby/core/unboundmethod/public_spec.rb9
-rw-r--r--spec/ruby/core/unboundmethod/shared/dup.rb32
-rw-r--r--spec/ruby/core/unboundmethod/shared/to_s.rb9
-rw-r--r--spec/ruby/core/unboundmethod/source_location_spec.rb13
-rw-r--r--spec/ruby/core/unboundmethod/super_method_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/to_s_spec.rb2
-rw-r--r--spec/ruby/core/warning/categories_spec.rb12
-rw-r--r--spec/ruby/core/warning/element_reference_spec.rb25
-rw-r--r--spec/ruby/core/warning/element_set_spec.rb26
-rw-r--r--spec/ruby/core/warning/performance_warning_spec.rb28
-rw-r--r--spec/ruby/core/warning/warn_spec.rb139
-rw-r--r--spec/ruby/default.mspec6
-rw-r--r--spec/ruby/fixtures/code/concurrent_require_fixture.rb4
-rw-r--r--spec/ruby/fixtures/code/d/load_fixture.rb.rb1
-rw-r--r--spec/ruby/fixtures/code/load_wrap_fixture.rb12
-rw-r--r--spec/ruby/fixtures/code/wrap_fixture.rb9
-rw-r--r--spec/ruby/fixtures/constants.rb16
-rw-r--r--spec/ruby/fixtures/io.rb12
-rw-r--r--spec/ruby/language/BEGIN_spec.rb2
-rw-r--r--spec/ruby/language/END_spec.rb26
-rw-r--r--spec/ruby/language/alias_spec.rb34
-rw-r--r--spec/ruby/language/and_spec.rb16
-rw-r--r--spec/ruby/language/array_spec.rb18
-rw-r--r--spec/ruby/language/assignments_spec.rb582
-rw-r--r--spec/ruby/language/block_spec.rb553
-rw-r--r--spec/ruby/language/break_spec.rb37
-rw-r--r--spec/ruby/language/case_spec.rb205
-rw-r--r--spec/ruby/language/class_spec.rb121
-rw-r--r--spec/ruby/language/class_variable_spec.rb70
-rw-r--r--spec/ruby/language/constants_spec.rb231
-rw-r--r--spec/ruby/language/def_spec.rb161
-rw-r--r--spec/ruby/language/defined_spec.rb375
-rw-r--r--spec/ruby/language/delegation_spec.rb143
-rw-r--r--spec/ruby/language/encoding_spec.rb12
-rw-r--r--spec/ruby/language/ensure_spec.rb47
-rw-r--r--spec/ruby/language/execution_spec.rb78
-rw-r--r--spec/ruby/language/file_spec.rb6
-rw-r--r--spec/ruby/language/fixtures/class_with_class_variable.rb9
-rw-r--r--spec/ruby/language/fixtures/defined.rb33
-rw-r--r--spec/ruby/language/fixtures/delegation.rb4
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_across_files.rb3
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_across_files_diff_enc.rb3
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_across_files_no_comment.rb3
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_one_literal.rb4
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_required.rb2
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_required_diff_enc.rbbin181 -> 107 bytes-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_required_no_comment.rb2
-rw-r--r--spec/ruby/language/fixtures/module.rb9
-rw-r--r--spec/ruby/language/fixtures/private.rb26
-rw-r--r--spec/ruby/language/fixtures/rescue/top_level.rb7
-rw-r--r--spec/ruby/language/fixtures/send.rb16
-rw-r--r--spec/ruby/language/fixtures/super.rb64
-rw-r--r--spec/ruby/language/fixtures/variables.rb72
-rw-r--r--spec/ruby/language/for_spec.rb202
-rw-r--r--spec/ruby/language/hash_spec.rb213
-rw-r--r--spec/ruby/language/heredoc_spec.rb12
-rw-r--r--spec/ruby/language/if_spec.rb53
-rw-r--r--spec/ruby/language/it_parameter_spec.rb108
-rw-r--r--spec/ruby/language/keyword_arguments_spec.rb558
-rw-r--r--spec/ruby/language/lambda_spec.rb229
-rw-r--r--spec/ruby/language/line_spec.rb2
-rw-r--r--spec/ruby/language/loop_spec.rb2
-rw-r--r--spec/ruby/language/magic_comment_spec.rb3
-rw-r--r--spec/ruby/language/match_spec.rb8
-rw-r--r--spec/ruby/language/metaclass_spec.rb22
-rw-r--r--spec/ruby/language/method_spec.rb1053
-rw-r--r--spec/ruby/language/module_spec.rb93
-rw-r--r--spec/ruby/language/next_spec.rb4
-rw-r--r--spec/ruby/language/not_spec.rb32
-rw-r--r--spec/ruby/language/numbered_parameters_spec.rb97
-rw-r--r--spec/ruby/language/numbers_spec.rb6
-rw-r--r--spec/ruby/language/optional_assignments_spec.rb306
-rw-r--r--spec/ruby/language/or_spec.rb32
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb1569
-rw-r--r--spec/ruby/language/precedence_spec.rb114
-rw-r--r--spec/ruby/language/predefined_spec.rb785
-rw-r--r--spec/ruby/language/private_spec.rb22
-rw-r--r--spec/ruby/language/proc_spec.rb73
-rw-r--r--spec/ruby/language/redo_spec.rb2
-rw-r--r--spec/ruby/language/regexp/anchors_spec.rb62
-rw-r--r--spec/ruby/language/regexp/back-references_spec.rb63
-rw-r--r--spec/ruby/language/regexp/character_classes_spec.rb238
-rw-r--r--spec/ruby/language/regexp/encoding_spec.rb56
-rw-r--r--spec/ruby/language/regexp/escapes_spec.rb12
-rw-r--r--spec/ruby/language/regexp/grouping_spec.rb6
-rw-r--r--spec/ruby/language/regexp/interpolation_spec.rb6
-rw-r--r--spec/ruby/language/regexp/modifiers_spec.rb40
-rw-r--r--spec/ruby/language/regexp/repetition_spec.rb10
-rw-r--r--spec/ruby/language/regexp_spec.rb34
-rw-r--r--spec/ruby/language/rescue_spec.rb135
-rw-r--r--spec/ruby/language/reserved_keywords.rb149
-rw-r--r--spec/ruby/language/retry_spec.rb7
-rw-r--r--spec/ruby/language/return_spec.rb29
-rw-r--r--spec/ruby/language/safe_navigator_spec.rb84
-rw-r--r--spec/ruby/language/safe_spec.rb28
-rw-r--r--spec/ruby/language/send_spec.rb107
-rw-r--r--spec/ruby/language/shared/__FILE__.rb4
-rw-r--r--spec/ruby/language/shared/__LINE__.rb2
-rw-r--r--spec/ruby/language/singleton_class_spec.rb112
-rw-r--r--spec/ruby/language/source_encoding_spec.rb6
-rw-r--r--spec/ruby/language/string_spec.rb58
-rw-r--r--spec/ruby/language/super_spec.rb54
-rw-r--r--spec/ruby/language/symbol_spec.rb34
-rw-r--r--spec/ruby/language/throw_spec.rb10
-rw-r--r--spec/ruby/language/undef_spec.rb23
-rw-r--r--spec/ruby/language/variables_spec.rb144
-rw-r--r--spec/ruby/language/while_spec.rb16
-rw-r--r--spec/ruby/language/yield_spec.rb69
-rw-r--r--spec/ruby/library/English/English_spec.rb62
-rw-r--r--spec/ruby/library/English/alias_spec.rb6
-rw-r--r--spec/ruby/library/base64/strict_decode64_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/BigDecimal_spec.rb80
-rw-r--r--spec/ruby/library/bigdecimal/add_spec.rb20
-rw-r--r--spec/ruby/library/bigdecimal/ceil_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/constants_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/core_spec.rb62
-rw-r--r--spec/ruby/library/bigdecimal/div_spec.rb28
-rw-r--r--spec/ruby/library/bigdecimal/divmod_spec.rb88
-rw-r--r--spec/ruby/library/bigdecimal/exponent_spec.rb11
-rw-r--r--spec/ruby/library/bigdecimal/fix_spec.rb30
-rw-r--r--spec/ruby/library/bigdecimal/floor_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/gt_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/gte_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/lt_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/lte_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/mode_spec.rb10
-rw-r--r--spec/ruby/library/bigdecimal/mult_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/nonzero_spec.rb10
-rw-r--r--spec/ruby/library/bigdecimal/precs_spec.rb55
-rw-r--r--spec/ruby/library/bigdecimal/remainder_spec.rb27
-rw-r--r--spec/ruby/library/bigdecimal/round_spec.rb16
-rw-r--r--spec/ruby/library/bigdecimal/shared/clone.rb2
-rw-r--r--spec/ruby/library/bigdecimal/shared/modulo.rb22
-rw-r--r--spec/ruby/library/bigdecimal/shared/power.rb4
-rw-r--r--spec/ruby/library/bigdecimal/shared/quo.rb1
-rw-r--r--spec/ruby/library/bigdecimal/shared/to_int.rb6
-rw-r--r--spec/ruby/library/bigdecimal/split_spec.rb20
-rw-r--r--spec/ruby/library/bigdecimal/sqrt_spec.rb24
-rw-r--r--spec/ruby/library/bigdecimal/sub_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/to_f_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/to_i_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/to_r_spec.rb18
-rw-r--r--spec/ruby/library/bigdecimal/to_s_spec.rb27
-rw-r--r--spec/ruby/library/bigdecimal/truncate_spec.rb16
-rw-r--r--spec/ruby/library/bigdecimal/util_spec.rb2
-rw-r--r--spec/ruby/library/bigmath/log_spec.rb10
-rw-r--r--spec/ruby/library/cgi/cookie/domain_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/expires_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/initialize_spec.rb235
-rw-r--r--spec/ruby/library/cgi/cookie/name_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/parse_spec.rb41
-rw-r--r--spec/ruby/library/cgi/cookie/path_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/secure_spec.rb99
-rw-r--r--spec/ruby/library/cgi/cookie/to_s_spec.rb51
-rw-r--r--spec/ruby/library/cgi/cookie/value_spec.rb121
-rw-r--r--spec/ruby/library/cgi/escapeElement_spec.rb8
-rw-r--r--spec/ruby/library/cgi/escapeHTML_spec.rb6
-rw-r--r--spec/ruby/library/cgi/escapeURIComponent_spec.rb78
-rw-r--r--spec/ruby/library/cgi/escape_spec.rb6
-rw-r--r--spec/ruby/library/cgi/htmlextension/a_spec.rb73
-rw-r--r--spec/ruby/library/cgi/htmlextension/base_spec.rb47
-rw-r--r--spec/ruby/library/cgi/htmlextension/blockquote_spec.rb47
-rw-r--r--spec/ruby/library/cgi/htmlextension/br_spec.rb31
-rw-r--r--spec/ruby/library/cgi/htmlextension/caption_spec.rb47
-rw-r--r--spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb121
-rw-r--r--spec/ruby/library/cgi/htmlextension/checkbox_spec.rb113
-rw-r--r--spec/ruby/library/cgi/htmlextension/doctype_spec.rb41
-rw-r--r--spec/ruby/library/cgi/htmlextension/file_field_spec.rb105
-rw-r--r--spec/ruby/library/cgi/htmlextension/form_spec.rb85
-rw-r--r--spec/ruby/library/cgi/htmlextension/frame_spec.rb21
-rw-r--r--spec/ruby/library/cgi/htmlextension/frameset_spec.rb21
-rw-r--r--spec/ruby/library/cgi/htmlextension/hidden_spec.rb87
-rw-r--r--spec/ruby/library/cgi/htmlextension/html_spec.rb99
-rw-r--r--spec/ruby/library/cgi/htmlextension/image_button_spec.rb101
-rw-r--r--spec/ruby/library/cgi/htmlextension/img_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb93
-rw-r--r--spec/ruby/library/cgi/htmlextension/password_field_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb13
-rw-r--r--spec/ruby/library/cgi/htmlextension/radio_button_spec.rb113
-rw-r--r--spec/ruby/library/cgi/htmlextension/radio_group_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/reset_spec.rb83
-rw-r--r--spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb13
-rw-r--r--spec/ruby/library/cgi/htmlextension/submit_spec.rb83
-rw-r--r--spec/ruby/library/cgi/htmlextension/text_field_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/textarea_spec.rb107
-rw-r--r--spec/ruby/library/cgi/http_header_spec.rb11
-rw-r--r--spec/ruby/library/cgi/initialize_spec.rb209
-rw-r--r--spec/ruby/library/cgi/out_spec.rb97
-rw-r--r--spec/ruby/library/cgi/parse_spec.rb37
-rw-r--r--spec/ruby/library/cgi/pretty_spec.rb19
-rw-r--r--spec/ruby/library/cgi/print_spec.rb39
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_charset_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_language_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/auth_type_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/cache_control_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/content_length_spec.rb39
-rw-r--r--spec/ruby/library/cgi/queryextension/content_type_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/cookies_spec.rb15
-rw-r--r--spec/ruby/library/cgi/queryextension/element_reference_spec.rb41
-rw-r--r--spec/ruby/library/cgi/queryextension/from_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/has_key_spec.rb11
-rw-r--r--spec/ruby/library/cgi/queryextension/host_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/include_spec.rb11
-rw-r--r--spec/ruby/library/cgi/queryextension/key_spec.rb11
-rw-r--r--spec/ruby/library/cgi/queryextension/keys_spec.rb29
-rw-r--r--spec/ruby/library/cgi/queryextension/multipart_spec.rb47
-rw-r--r--spec/ruby/library/cgi/queryextension/negotiate_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/params_spec.rb55
-rw-r--r--spec/ruby/library/cgi/queryextension/path_info_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/path_translated_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/pragma_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/query_string_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/referer_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_addr_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_host_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_ident_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_user_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/request_method_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/script_name_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/server_name_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/server_port_spec.rb39
-rw-r--r--spec/ruby/library/cgi/queryextension/server_protocol_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/server_software_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/shared/has_key.rb6
-rw-r--r--spec/ruby/library/cgi/queryextension/user_agent_spec.rb33
-rw-r--r--spec/ruby/library/cgi/rfc1123_date_spec.rb15
-rw-r--r--spec/ruby/library/cgi/shared/http_header.rb10
-rw-r--r--spec/ruby/library/cgi/unescapeElement_spec.rb8
-rw-r--r--spec/ruby/library/cgi/unescapeHTML_spec.rb6
-rw-r--r--spec/ruby/library/cgi/unescapeURIComponent_spec.rb128
-rw-r--r--spec/ruby/library/cgi/unescape_spec.rb8
-rw-r--r--spec/ruby/library/cmath/math/acos_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/acosh_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/asin_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/asinh_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/atan2_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/atan_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/atanh_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/cos_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/cosh_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/exp_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/fixtures/classes.rb4
-rw-r--r--spec/ruby/library/cmath/math/log10_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/log_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/shared/acos.rb41
-rw-r--r--spec/ruby/library/cmath/math/shared/acosh.rb37
-rw-r--r--spec/ruby/library/cmath/math/shared/asin.rb47
-rw-r--r--spec/ruby/library/cmath/math/shared/asinh.rb32
-rw-r--r--spec/ruby/library/cmath/math/shared/atan.rb32
-rw-r--r--spec/ruby/library/cmath/math/shared/atan2.rb34
-rw-r--r--spec/ruby/library/cmath/math/shared/atanh.rb30
-rw-r--r--spec/ruby/library/cmath/math/shared/cos.rb30
-rw-r--r--spec/ruby/library/cmath/math/shared/cosh.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/exp.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/log.rb39
-rw-r--r--spec/ruby/library/cmath/math/shared/log10.rb41
-rw-r--r--spec/ruby/library/cmath/math/shared/sin.rb30
-rw-r--r--spec/ruby/library/cmath/math/shared/sinh.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/sqrt.rb34
-rw-r--r--spec/ruby/library/cmath/math/shared/tan.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/tanh.rb32
-rw-r--r--spec/ruby/library/cmath/math/sin_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/sinh_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/sqrt_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/tan_spec.rb1
-rw-r--r--spec/ruby/library/cmath/math/tanh_spec.rb1
-rw-r--r--spec/ruby/library/coverage/fixtures/code_with_begin.rb3
-rw-r--r--spec/ruby/library/coverage/result_spec.rb288
-rw-r--r--spec/ruby/library/coverage/running_spec.rb20
-rw-r--r--spec/ruby/library/coverage/start_spec.rb83
-rw-r--r--spec/ruby/library/coverage/supported_spec.rb30
-rw-r--r--spec/ruby/library/csv/generate_spec.rb4
-rw-r--r--spec/ruby/library/csv/parse_spec.rb4
-rw-r--r--spec/ruby/library/csv/readlines_spec.rb2
-rw-r--r--spec/ruby/library/date/accessor_spec.rb2
-rw-r--r--spec/ruby/library/date/add_month_spec.rb8
-rw-r--r--spec/ruby/library/date/add_spec.rb8
-rw-r--r--spec/ruby/library/date/civil_spec.rb7
-rw-r--r--spec/ruby/library/date/constants_spec.rb4
-rw-r--r--spec/ruby/library/date/deconstruct_keys_spec.rb42
-rw-r--r--spec/ruby/library/date/eql_spec.rb4
-rw-r--r--spec/ruby/library/date/friday_spec.rb4
-rw-r--r--spec/ruby/library/date/gregorian_leap_spec.rb10
-rw-r--r--spec/ruby/library/date/gregorian_spec.rb6
-rw-r--r--spec/ruby/library/date/iso8601_spec.rb23
-rw-r--r--spec/ruby/library/date/julian_leap_spec.rb10
-rw-r--r--spec/ruby/library/date/julian_spec.rb4
-rw-r--r--spec/ruby/library/date/minus_month_spec.rb8
-rw-r--r--spec/ruby/library/date/minus_spec.rb6
-rw-r--r--spec/ruby/library/date/mon_spec.rb3
-rw-r--r--spec/ruby/library/date/monday_spec.rb2
-rw-r--r--spec/ruby/library/date/month_spec.rb6
-rw-r--r--spec/ruby/library/date/new_spec.rb1
-rw-r--r--spec/ruby/library/date/parse_spec.rb16
-rw-r--r--spec/ruby/library/date/plus_spec.rb2
-rw-r--r--spec/ruby/library/date/saturday_spec.rb2
-rw-r--r--spec/ruby/library/date/shared/civil.rb16
-rw-r--r--spec/ruby/library/date/shared/commercial.rb18
-rw-r--r--spec/ruby/library/date/shared/month.rb6
-rw-r--r--spec/ruby/library/date/shared/new_bang.rb14
-rw-r--r--spec/ruby/library/date/shared/parse.rb4
-rw-r--r--spec/ruby/library/date/shared/parse_eu.rb8
-rw-r--r--spec/ruby/library/date/shared/parse_us.rb8
-rw-r--r--spec/ruby/library/date/shared/valid_civil.rb16
-rw-r--r--spec/ruby/library/date/shared/valid_commercial.rb24
-rw-r--r--spec/ruby/library/date/shared/valid_jd.rb14
-rw-r--r--spec/ruby/library/date/strftime_spec.rb18
-rw-r--r--spec/ruby/library/date/sunday_spec.rb2
-rw-r--r--spec/ruby/library/date/thursday_spec.rb2
-rw-r--r--spec/ruby/library/date/time/to_date_spec.rb42
-rw-r--r--spec/ruby/library/date/today_spec.rb2
-rw-r--r--spec/ruby/library/date/tuesday_spec.rb2
-rw-r--r--spec/ruby/library/date/wednesday_spec.rb2
-rw-r--r--spec/ruby/library/date/yday_spec.rb3
-rw-r--r--spec/ruby/library/datetime/deconstruct_keys_spec.rb44
-rw-r--r--spec/ruby/library/datetime/hour_spec.rb10
-rw-r--r--spec/ruby/library/datetime/new_spec.rb2
-rw-r--r--spec/ruby/library/datetime/now_spec.rb2
-rw-r--r--spec/ruby/library/datetime/parse_spec.rb12
-rw-r--r--spec/ruby/library/datetime/rfc2822_spec.rb4
-rw-r--r--spec/ruby/library/datetime/shared/min.rb10
-rw-r--r--spec/ruby/library/datetime/shared/sec.rb6
-rw-r--r--spec/ruby/library/datetime/strftime_spec.rb17
-rw-r--r--spec/ruby/library/datetime/time/to_datetime_spec.rb40
-rw-r--r--spec/ruby/library/datetime/to_date_spec.rb2
-rw-r--r--spec/ruby/library/datetime/to_s_spec.rb2
-rw-r--r--spec/ruby/library/datetime/to_time_spec.rb18
-rw-r--r--spec/ruby/library/datetime/yday_spec.rb7
-rw-r--r--spec/ruby/library/delegate/delegate_class/instance_method_spec.rb14
-rw-r--r--spec/ruby/library/delegate/delegate_class/instance_methods_spec.rb12
-rw-r--r--spec/ruby/library/delegate/delegate_class/private_instance_methods_spec.rb12
-rw-r--r--spec/ruby/library/delegate/delegate_class/protected_instance_methods_spec.rb12
-rw-r--r--spec/ruby/library/delegate/delegate_class/public_instance_methods_spec.rb10
-rw-r--r--spec/ruby/library/delegate/delegate_class/respond_to_missing_spec.rb1
-rw-r--r--spec/ruby/library/delegate/delegator/eql_spec.rb8
-rw-r--r--spec/ruby/library/delegate/delegator/equal_spec.rb6
-rw-r--r--spec/ruby/library/delegate/delegator/equal_value_spec.rb6
-rw-r--r--spec/ruby/library/delegate/delegator/frozen_spec.rb14
-rw-r--r--spec/ruby/library/delegate/delegator/marshal_spec.rb2
-rw-r--r--spec/ruby/library/delegate/delegator/method_spec.rb18
-rw-r--r--spec/ruby/library/delegate/delegator/methods_spec.rb14
-rw-r--r--spec/ruby/library/delegate/delegator/not_equal_spec.rb6
-rw-r--r--spec/ruby/library/delegate/delegator/private_methods_spec.rb8
-rw-r--r--spec/ruby/library/delegate/delegator/protected_methods_spec.rb4
-rw-r--r--spec/ruby/library/delegate/delegator/public_methods_spec.rb4
-rw-r--r--spec/ruby/library/delegate/delegator/send_spec.rb8
-rw-r--r--spec/ruby/library/delegate/delegator/tap_spec.rb2
-rw-r--r--spec/ruby/library/digest/bubblebabble_spec.rb6
-rw-r--r--spec/ruby/library/digest/hexencode_spec.rb4
-rw-r--r--spec/ruby/library/digest/instance/shared/update.rb2
-rw-r--r--spec/ruby/library/digest/md5/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/md5/file_spec.rb8
-rw-r--r--spec/ruby/library/digest/md5/shared/constants.rb2
-rw-r--r--spec/ruby/library/digest/md5/shared/sample.rb17
-rw-r--r--spec/ruby/library/digest/sha1/file_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha1/shared/constants.rb2
-rw-r--r--spec/ruby/library/digest/sha256/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/sha256/file_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha256/shared/constants.rb2
-rw-r--r--spec/ruby/library/digest/sha384/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/sha384/file_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha384/shared/constants.rb2
-rw-r--r--spec/ruby/library/digest/sha512/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/sha512/file_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha512/shared/constants.rb2
-rw-r--r--spec/ruby/library/drb/start_service_spec.rb47
-rw-r--r--spec/ruby/library/erb/def_class_spec.rb2
-rw-r--r--spec/ruby/library/erb/def_module_spec.rb3
-rw-r--r--spec/ruby/library/erb/defmethod/def_erb_method_spec.rb2
-rw-r--r--spec/ruby/library/erb/filename_spec.rb4
-rw-r--r--spec/ruby/library/erb/new_spec.rb22
-rw-r--r--spec/ruby/library/erb/result_spec.rb4
-rw-r--r--spec/ruby/library/erb/run_spec.rb6
-rw-r--r--spec/ruby/library/etc/confstr_spec.rb6
-rw-r--r--spec/ruby/library/etc/getgrgid_spec.rb8
-rw-r--r--spec/ruby/library/etc/getgrnam_spec.rb2
-rw-r--r--spec/ruby/library/etc/getlogin_spec.rb4
-rw-r--r--spec/ruby/library/etc/getpwnam_spec.rb2
-rw-r--r--spec/ruby/library/etc/getpwuid_spec.rb2
-rw-r--r--spec/ruby/library/etc/group_spec.rb4
-rw-r--r--spec/ruby/library/etc/nprocessors_spec.rb2
-rw-r--r--spec/ruby/library/etc/passwd_spec.rb4
-rw-r--r--spec/ruby/library/etc/sysconf_spec.rb4
-rw-r--r--spec/ruby/library/etc/sysconfdir_spec.rb4
-rw-r--r--spec/ruby/library/etc/systmpdir_spec.rb4
-rw-r--r--spec/ruby/library/etc/uname_spec.rb14
-rw-r--r--spec/ruby/library/expect/expect_spec.rb7
-rw-r--r--spec/ruby/library/fiber/alive_spec.rb46
-rw-r--r--spec/ruby/library/fiber/current_spec.rb63
-rw-r--r--spec/ruby/library/fiber/resume_spec.rb35
-rw-r--r--spec/ruby/library/fiber/transfer_spec.rb128
-rw-r--r--spec/ruby/library/fiddle/handle/initialize_spec.rb10
-rw-r--r--spec/ruby/library/find/find_spec.rb2
-rw-r--r--spec/ruby/library/find/fixtures/common.rb14
-rw-r--r--spec/ruby/library/getoptlong/error_message_spec.rb2
-rw-r--r--spec/ruby/library/getoptlong/ordering_spec.rb4
-rw-r--r--spec/ruby/library/getoptlong/set_options_spec.rb14
-rw-r--r--spec/ruby/library/getoptlong/shared/get.rb2
-rw-r--r--spec/ruby/library/io-wait/wait_readable_spec.rb42
-rw-r--r--spec/ruby/library/io-wait/wait_spec.rb162
-rw-r--r--spec/ruby/library/io-wait/wait_writable_spec.rb37
-rw-r--r--spec/ruby/library/ipaddr/new_spec.rb46
-rw-r--r--spec/ruby/library/ipaddr/operator_spec.rb16
-rw-r--r--spec/ruby/library/ipaddr/reverse_spec.rb4
-rw-r--r--spec/ruby/library/irb/fixtures/irb.rb3
-rw-r--r--spec/ruby/library/irb/irb_spec.rb19
-rw-r--r--spec/ruby/library/logger/device/close_spec.rb15
-rw-r--r--spec/ruby/library/logger/device/new_spec.rb8
-rw-r--r--spec/ruby/library/logger/device/write_spec.rb15
-rw-r--r--spec/ruby/library/logger/logger/add_spec.rb6
-rw-r--r--spec/ruby/library/logger/logger/datetime_format_spec.rb2
-rw-r--r--spec/ruby/library/logger/logger/new_spec.rb32
-rw-r--r--spec/ruby/library/logger/logger/unknown_spec.rb2
-rw-r--r--spec/ruby/library/matrix/I_spec.rb9
-rw-r--r--spec/ruby/library/matrix/antisymmetric_spec.rb54
-rw-r--r--spec/ruby/library/matrix/build_spec.rb117
-rw-r--r--spec/ruby/library/matrix/clone_spec.rb37
-rw-r--r--spec/ruby/library/matrix/coerce_spec.rb11
-rw-r--r--spec/ruby/library/matrix/collect_spec.rb9
-rw-r--r--spec/ruby/library/matrix/column_size_spec.rb19
-rw-r--r--spec/ruby/library/matrix/column_spec.rb53
-rw-r--r--spec/ruby/library/matrix/column_vector_spec.rb37
-rw-r--r--spec/ruby/library/matrix/column_vectors_spec.rb37
-rw-r--r--spec/ruby/library/matrix/columns_spec.rb67
-rw-r--r--spec/ruby/library/matrix/conj_spec.rb9
-rw-r--r--spec/ruby/library/matrix/conjugate_spec.rb9
-rw-r--r--spec/ruby/library/matrix/constructor_spec.rb101
-rw-r--r--spec/ruby/library/matrix/det_spec.rb11
-rw-r--r--spec/ruby/library/matrix/determinant_spec.rb11
-rw-r--r--spec/ruby/library/matrix/diagonal_spec.rb105
-rw-r--r--spec/ruby/library/matrix/divide_spec.rb83
-rw-r--r--spec/ruby/library/matrix/each_spec.rb119
-rw-r--r--spec/ruby/library/matrix/each_with_index_spec.rb133
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb13
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb35
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb33
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb37
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb39
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb27
-rw-r--r--spec/ruby/library/matrix/element_reference_spec.rb31
-rw-r--r--spec/ruby/library/matrix/empty_spec.rb107
-rw-r--r--spec/ruby/library/matrix/eql_spec.rb15
-rw-r--r--spec/ruby/library/matrix/equal_value_spec.rb15
-rw-r--r--spec/ruby/library/matrix/exponent_spec.rb97
-rw-r--r--spec/ruby/library/matrix/find_index_spec.rb221
-rw-r--r--spec/ruby/library/matrix/hash_spec.rb21
-rw-r--r--spec/ruby/library/matrix/hermitian_spec.rb53
-rw-r--r--spec/ruby/library/matrix/identity_spec.rb9
-rw-r--r--spec/ruby/library/matrix/imag_spec.rb9
-rw-r--r--spec/ruby/library/matrix/imaginary_spec.rb9
-rw-r--r--spec/ruby/library/matrix/inspect_spec.rb39
-rw-r--r--spec/ruby/library/matrix/inv_spec.rb11
-rw-r--r--spec/ruby/library/matrix/inverse_from_spec.rb9
-rw-r--r--spec/ruby/library/matrix/inverse_spec.rb11
-rw-r--r--spec/ruby/library/matrix/lower_triangular_spec.rb39
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb33
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb21
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/l_spec.rb27
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/p_spec.rb27
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/solve_spec.rb85
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb53
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/u_spec.rb27
-rw-r--r--spec/ruby/library/matrix/map_spec.rb9
-rw-r--r--spec/ruby/library/matrix/minor_spec.rb135
-rw-r--r--spec/ruby/library/matrix/minus_spec.rb65
-rw-r--r--spec/ruby/library/matrix/multiply_spec.rb104
-rw-r--r--spec/ruby/library/matrix/new_spec.rb11
-rw-r--r--spec/ruby/library/matrix/normal_spec.rb41
-rw-r--r--spec/ruby/library/matrix/orthogonal_spec.rb41
-rw-r--r--spec/ruby/library/matrix/permutation_spec.rb51
-rw-r--r--spec/ruby/library/matrix/plus_spec.rb65
-rw-r--r--spec/ruby/library/matrix/rank_spec.rb29
-rw-r--r--spec/ruby/library/matrix/real_spec.rb63
-rw-r--r--spec/ruby/library/matrix/rect_spec.rb9
-rw-r--r--spec/ruby/library/matrix/rectangular_spec.rb9
-rw-r--r--spec/ruby/library/matrix/regular_spec.rb45
-rw-r--r--spec/ruby/library/matrix/round_spec.rb31
-rw-r--r--spec/ruby/library/matrix/row_size_spec.rb19
-rw-r--r--spec/ruby/library/matrix/row_spec.rb55
-rw-r--r--spec/ruby/library/matrix/row_vector_spec.rb33
-rw-r--r--spec/ruby/library/matrix/row_vectors_spec.rb37
-rw-r--r--spec/ruby/library/matrix/rows_spec.rb65
-rw-r--r--spec/ruby/library/matrix/scalar/Fail_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/Raise_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/divide_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/exponent_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/included_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/initialize_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/minus_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/multiply_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/plus_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar_spec.rb93
-rw-r--r--spec/ruby/library/matrix/shared/collect.rb6
-rw-r--r--spec/ruby/library/matrix/shared/conjugate.rb2
-rw-r--r--spec/ruby/library/matrix/shared/determinant.rb4
-rw-r--r--spec/ruby/library/matrix/shared/equal_value.rb20
-rw-r--r--spec/ruby/library/matrix/shared/identity.rb4
-rw-r--r--spec/ruby/library/matrix/shared/imaginary.rb2
-rw-r--r--spec/ruby/library/matrix/shared/inverse.rb6
-rw-r--r--spec/ruby/library/matrix/shared/rectangular.rb2
-rw-r--r--spec/ruby/library/matrix/shared/trace.rb2
-rw-r--r--spec/ruby/library/matrix/shared/transpose.rb2
-rw-r--r--spec/ruby/library/matrix/singular_spec.rb47
-rw-r--r--spec/ruby/library/matrix/square_spec.rb41
-rw-r--r--spec/ruby/library/matrix/symmetric_spec.rb45
-rw-r--r--spec/ruby/library/matrix/t_spec.rb9
-rw-r--r--spec/ruby/library/matrix/to_a_spec.rb17
-rw-r--r--spec/ruby/library/matrix/to_s_spec.rb9
-rw-r--r--spec/ruby/library/matrix/tr_spec.rb11
-rw-r--r--spec/ruby/library/matrix/trace_spec.rb11
-rw-r--r--spec/ruby/library/matrix/transpose_spec.rb9
-rw-r--r--spec/ruby/library/matrix/unit_spec.rb9
-rw-r--r--spec/ruby/library/matrix/unitary_spec.rb50
-rw-r--r--spec/ruby/library/matrix/upper_triangular_spec.rb39
-rw-r--r--spec/ruby/library/matrix/vector/cross_product_spec.rb21
-rw-r--r--spec/ruby/library/matrix/vector/each2_spec.rb81
-rw-r--r--spec/ruby/library/matrix/vector/eql_spec.rb23
-rw-r--r--spec/ruby/library/matrix/vector/inner_product_spec.rb33
-rw-r--r--spec/ruby/library/matrix/vector/normalize_spec.rb29
-rw-r--r--spec/ruby/library/matrix/zero_spec.rb75
-rw-r--r--spec/ruby/library/monitor/exit_spec.rb10
-rw-r--r--spec/ruby/library/monitor/mon_initialize_spec.rb2
-rw-r--r--spec/ruby/library/monitor/synchronize_spec.rb4
-rw-r--r--spec/ruby/library/net-ftp/FTPError_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/FTPPermError_spec.rb15
-rw-r--r--spec/ruby/library/net-ftp/FTPProtoError_spec.rb15
-rw-r--r--spec/ruby/library/net-ftp/FTPReplyError_spec.rb15
-rw-r--r--spec/ruby/library/net-ftp/FTPTempError_spec.rb15
-rw-r--r--spec/ruby/library/net-ftp/abort_spec.rb65
-rw-r--r--spec/ruby/library/net-ftp/acct_spec.rb61
-rw-r--r--spec/ruby/library/net-ftp/binary_spec.rb27
-rw-r--r--spec/ruby/library/net-ftp/chdir_spec.rb102
-rw-r--r--spec/ruby/library/net-ftp/close_spec.rb33
-rw-r--r--spec/ruby/library/net-ftp/closed_spec.rb24
-rw-r--r--spec/ruby/library/net-ftp/connect_spec.rb46
-rw-r--r--spec/ruby/library/net-ftp/debug_mode_spec.rb26
-rw-r--r--spec/ruby/library/net-ftp/default_passive_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/delete_spec.rb62
-rw-r--r--spec/ruby/library/net-ftp/dir_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/fixtures/default_passive.rb (renamed from spec/ruby/library/net/ftp/fixtures/default_passive.rb)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/passive.rb (renamed from spec/ruby/library/net/ftp/fixtures/passive.rb)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/putbinaryfile (renamed from spec/ruby/library/net/ftp/fixtures/putbinaryfile)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/puttextfile (renamed from spec/ruby/library/net/ftp/fixtures/puttextfile)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/server.rb279
-rw-r--r--spec/ruby/library/net-ftp/get_spec.rb24
-rw-r--r--spec/ruby/library/net-ftp/getbinaryfile_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/getdir_spec.rb10
-rw-r--r--spec/ruby/library/net-ftp/gettextfile_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/help_spec.rb69
-rw-r--r--spec/ruby/library/net-ftp/initialize_spec.rb408
-rw-r--r--spec/ruby/library/net-ftp/last_response_code_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/last_response_spec.rb28
-rw-r--r--spec/ruby/library/net-ftp/lastresp_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/list_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/login_spec.rb198
-rw-r--r--spec/ruby/library/net-ftp/ls_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/mdtm_spec.rb41
-rw-r--r--spec/ruby/library/net-ftp/mkdir_spec.rb64
-rw-r--r--spec/ruby/library/net-ftp/mtime_spec.rb53
-rw-r--r--spec/ruby/library/net-ftp/nlst_spec.rb95
-rw-r--r--spec/ruby/library/net-ftp/noop_spec.rb41
-rw-r--r--spec/ruby/library/net-ftp/open_spec.rb58
-rw-r--r--spec/ruby/library/net-ftp/passive_spec.rb31
-rw-r--r--spec/ruby/library/net-ftp/put_spec.rb24
-rw-r--r--spec/ruby/library/net-ftp/putbinaryfile_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/puttextfile_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/pwd_spec.rb56
-rw-r--r--spec/ruby/library/net-ftp/quit_spec.rb36
-rw-r--r--spec/ruby/library/net-ftp/rename_spec.rb97
-rw-r--r--spec/ruby/library/net-ftp/resume_spec.rb26
-rw-r--r--spec/ruby/library/net-ftp/retrbinary_spec.rb33
-rw-r--r--spec/ruby/library/net-ftp/retrlines_spec.rb37
-rw-r--r--spec/ruby/library/net-ftp/return_code_spec.rb27
-rw-r--r--spec/ruby/library/net-ftp/rmdir_spec.rb61
-rw-r--r--spec/ruby/library/net-ftp/sendcmd_spec.rb57
-rw-r--r--spec/ruby/library/net-ftp/set_socket_spec.rb11
-rw-r--r--spec/ruby/library/net-ftp/shared/getbinaryfile.rb152
-rw-r--r--spec/ruby/library/net-ftp/shared/gettextfile.rb102
-rw-r--r--spec/ruby/library/net-ftp/shared/last_response_code.rb27
-rw-r--r--spec/ruby/library/net-ftp/shared/list.rb106
-rw-r--r--spec/ruby/library/net-ftp/shared/putbinaryfile.rb169
-rw-r--r--spec/ruby/library/net-ftp/shared/puttextfile.rb130
-rw-r--r--spec/ruby/library/net-ftp/shared/pwd.rb5
-rw-r--r--spec/ruby/library/net-ftp/site_spec.rb56
-rw-r--r--spec/ruby/library/net-ftp/size_spec.rb51
-rw-r--r--spec/ruby/library/net-ftp/spec_helper.rb7
-rw-r--r--spec/ruby/library/net-ftp/status_spec.rb70
-rw-r--r--spec/ruby/library/net-ftp/storbinary_spec.rb52
-rw-r--r--spec/ruby/library/net-ftp/storlines_spec.rb47
-rw-r--r--spec/ruby/library/net-ftp/system_spec.rb51
-rw-r--r--spec/ruby/library/net-ftp/voidcmd_spec.rb57
-rw-r--r--spec/ruby/library/net-ftp/welcome_spec.rb28
-rw-r--r--spec/ruby/library/net-http/HTTPBadResponse_spec.rb8
-rw-r--r--spec/ruby/library/net-http/HTTPClientExcepton_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPError_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPFatalError_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPHeaderSyntaxError_spec.rb8
-rw-r--r--spec/ruby/library/net-http/HTTPRetriableError_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPServerException_spec.rb12
-rw-r--r--spec/ruby/library/net-http/http/Proxy_spec.rb35
-rw-r--r--spec/ruby/library/net-http/http/active_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/address_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/close_on_empty_response_spec.rb10
-rw-r--r--spec/ruby/library/net-http/http/copy_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/default_port_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/delete_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/finish_spec.rb29
-rw-r--r--spec/ruby/library/net-http/http/fixtures/http_server.rb (renamed from spec/ruby/library/net/http/http/fixtures/http_server.rb)0
-rw-r--r--spec/ruby/library/net-http/http/get2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/get_print_spec.rb30
-rw-r--r--spec/ruby/library/net-http/http/get_response_spec.rb30
-rw-r--r--spec/ruby/library/net-http/http/get_spec.rb94
-rw-r--r--spec/ruby/library/net-http/http/head2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/head_spec.rb25
-rw-r--r--spec/ruby/library/net-http/http/http_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/https_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/initialize_spec.rb46
-rw-r--r--spec/ruby/library/net-http/http/inspect_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/is_version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net-http/http/is_version_1_2_spec.rb7
-rw-r--r--spec/ruby/library/net-http/http/lock_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/mkcol_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/move_spec.rb25
-rw-r--r--spec/ruby/library/net-http/http/new_spec.rb86
-rw-r--r--spec/ruby/library/net-http/http/newobj_spec.rb48
-rw-r--r--spec/ruby/library/net-http/http/open_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/options_spec.rb25
-rw-r--r--spec/ruby/library/net-http/http/port_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/post2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/post_form_spec.rb22
-rw-r--r--spec/ruby/library/net-http/http/post_spec.rb76
-rw-r--r--spec/ruby/library/net-http/http/propfind_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/proppatch_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/proxy_address_spec.rb31
-rw-r--r--spec/ruby/library/net-http/http/proxy_class_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/proxy_pass_spec.rb39
-rw-r--r--spec/ruby/library/net-http/http/proxy_port_spec.rb39
-rw-r--r--spec/ruby/library/net-http/http/proxy_user_spec.rb39
-rw-r--r--spec/ruby/library/net-http/http/put2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/put_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/read_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/request_get_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_head_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_post_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_put_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_spec.rb109
-rw-r--r--spec/ruby/library/net-http/http/request_types_spec.rb254
-rw-r--r--spec/ruby/library/net-http/http/send_request_spec.rb61
-rw-r--r--spec/ruby/library/net-http/http/set_debug_output_spec.rb33
-rw-r--r--spec/ruby/library/net-http/http/shared/request_get.rb41
-rw-r--r--spec/ruby/library/net-http/http/shared/request_head.rb41
-rw-r--r--spec/ruby/library/net-http/http/shared/request_post.rb41
-rw-r--r--spec/ruby/library/net-http/http/shared/request_put.rb41
-rw-r--r--spec/ruby/library/net-http/http/shared/started.rb26
-rw-r--r--spec/ruby/library/net-http/http/shared/version_1_1.rb6
-rw-r--r--spec/ruby/library/net-http/http/shared/version_1_2.rb6
-rw-r--r--spec/ruby/library/net-http/http/socket_type_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/start_spec.rb111
-rw-r--r--spec/ruby/library/net-http/http/started_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/trace_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/unlock_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/use_ssl_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net-http/http/version_1_2_spec.rb20
-rw-r--r--spec/ruby/library/net-http/httpexceptions/fixtures/classes.rb (renamed from spec/ruby/library/net/http/httpexceptions/fixtures/classes.rb)0
-rw-r--r--spec/ruby/library/net-http/httpexceptions/initialize_spec.rb17
-rw-r--r--spec/ruby/library/net-http/httpexceptions/response_spec.rb10
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/body_exist_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/body_spec.rb30
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/body_stream_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/exec_spec.rb135
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/inspect_spec.rb25
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/method_spec.rb15
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/path_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/request_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/response_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/set_body_internal_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpheader/add_field_spec.rb31
-rw-r--r--spec/ruby/library/net-http/httpheader/basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net-http/httpheader/canonical_each_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/chunked_spec.rb22
-rw-r--r--spec/ruby/library/net-http/httpheader/content_length_spec.rb54
-rw-r--r--spec/ruby/library/net-http/httpheader/content_range_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpheader/content_type_spec.rb26
-rw-r--r--spec/ruby/library/net-http/httpheader/delete_spec.rb30
-rw-r--r--spec/ruby/library/net-http/httpheader/each_capitalized_name_spec.rb35
-rw-r--r--spec/ruby/library/net-http/httpheader/each_capitalized_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_header_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_key_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_name_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_value_spec.rb35
-rw-r--r--spec/ruby/library/net-http/httpheader/element_reference_spec.rb39
-rw-r--r--spec/ruby/library/net-http/httpheader/element_set_spec.rb41
-rw-r--r--spec/ruby/library/net-http/httpheader/fetch_spec.rb68
-rw-r--r--spec/ruby/library/net-http/httpheader/fixtures/classes.rb (renamed from spec/ruby/library/net/http/httpheader/fixtures/classes.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/form_data_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/get_fields_spec.rb39
-rw-r--r--spec/ruby/library/net-http/httpheader/initialize_http_header_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpheader/key_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpheader/length_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/main_type_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpheader/proxy_basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net-http/httpheader/range_length_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpheader/range_spec.rb48
-rw-r--r--spec/ruby/library/net-http/httpheader/set_content_type_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/set_form_data_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/set_range_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/each_capitalized.rb31
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/each_header.rb31
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/each_name.rb31
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/set_content_type.rb (renamed from spec/ruby/library/net/http/httpheader/shared/set_content_type.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/set_form_data.rb (renamed from spec/ruby/library/net/http/httpheader/shared/set_form_data.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/set_range.rb89
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/size.rb18
-rw-r--r--spec/ruby/library/net-http/httpheader/size_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/sub_type_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpheader/to_hash_spec.rb25
-rw-r--r--spec/ruby/library/net-http/httpheader/type_params_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httprequest/initialize_spec.rb45
-rw-r--r--spec/ruby/library/net-http/httpresponse/body_permitted_spec.rb13
-rw-r--r--spec/ruby/library/net-http/httpresponse/body_spec.rb7
-rw-r--r--spec/ruby/library/net-http/httpresponse/code_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/code_type_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/entity_spec.rb7
-rw-r--r--spec/ruby/library/net-http/httpresponse/error_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/error_type_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/exception_type_spec.rb13
-rw-r--r--spec/ruby/library/net-http/httpresponse/header_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/http_version_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpresponse/initialize_spec.rb11
-rw-r--r--spec/ruby/library/net-http/httpresponse/inspect_spec.rb15
-rw-r--r--spec/ruby/library/net-http/httpresponse/message_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/msg_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_body_spec.rb86
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_header_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_new_spec.rb23
-rw-r--r--spec/ruby/library/net-http/httpresponse/reading_body_spec.rb58
-rw-r--r--spec/ruby/library/net-http/httpresponse/response_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/shared/body.rb20
-rw-r--r--spec/ruby/library/net-http/httpresponse/value_spec.rb24
-rw-r--r--spec/ruby/library/net/FTPError_spec.rb11
-rw-r--r--spec/ruby/library/net/FTPPermError_spec.rb15
-rw-r--r--spec/ruby/library/net/FTPProtoError_spec.rb15
-rw-r--r--spec/ruby/library/net/FTPReplyError_spec.rb15
-rw-r--r--spec/ruby/library/net/FTPTempError_spec.rb15
-rw-r--r--spec/ruby/library/net/ftp/abort_spec.rb65
-rw-r--r--spec/ruby/library/net/ftp/acct_spec.rb61
-rw-r--r--spec/ruby/library/net/ftp/binary_spec.rb27
-rw-r--r--spec/ruby/library/net/ftp/chdir_spec.rb102
-rw-r--r--spec/ruby/library/net/ftp/close_spec.rb33
-rw-r--r--spec/ruby/library/net/ftp/closed_spec.rb24
-rw-r--r--spec/ruby/library/net/ftp/connect_spec.rb52
-rw-r--r--spec/ruby/library/net/ftp/debug_mode_spec.rb26
-rw-r--r--spec/ruby/library/net/ftp/default_passive_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/delete_spec.rb62
-rw-r--r--spec/ruby/library/net/ftp/dir_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/fixtures/server.rb277
-rw-r--r--spec/ruby/library/net/ftp/get_spec.rb24
-rw-r--r--spec/ruby/library/net/ftp/getbinaryfile_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/getdir_spec.rb10
-rw-r--r--spec/ruby/library/net/ftp/gettextfile_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/help_spec.rb69
-rw-r--r--spec/ruby/library/net/ftp/initialize_spec.rb408
-rw-r--r--spec/ruby/library/net/ftp/last_response_code_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/last_response_spec.rb28
-rw-r--r--spec/ruby/library/net/ftp/lastresp_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/list_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/login_spec.rb198
-rw-r--r--spec/ruby/library/net/ftp/ls_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/mdtm_spec.rb41
-rw-r--r--spec/ruby/library/net/ftp/mkdir_spec.rb64
-rw-r--r--spec/ruby/library/net/ftp/mtime_spec.rb53
-rw-r--r--spec/ruby/library/net/ftp/nlst_spec.rb95
-rw-r--r--spec/ruby/library/net/ftp/noop_spec.rb41
-rw-r--r--spec/ruby/library/net/ftp/open_spec.rb58
-rw-r--r--spec/ruby/library/net/ftp/passive_spec.rb31
-rw-r--r--spec/ruby/library/net/ftp/put_spec.rb24
-rw-r--r--spec/ruby/library/net/ftp/putbinaryfile_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/puttextfile_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/pwd_spec.rb56
-rw-r--r--spec/ruby/library/net/ftp/quit_spec.rb36
-rw-r--r--spec/ruby/library/net/ftp/rename_spec.rb97
-rw-r--r--spec/ruby/library/net/ftp/resume_spec.rb26
-rw-r--r--spec/ruby/library/net/ftp/retrbinary_spec.rb33
-rw-r--r--spec/ruby/library/net/ftp/retrlines_spec.rb37
-rw-r--r--spec/ruby/library/net/ftp/return_code_spec.rb27
-rw-r--r--spec/ruby/library/net/ftp/rmdir_spec.rb61
-rw-r--r--spec/ruby/library/net/ftp/sendcmd_spec.rb57
-rw-r--r--spec/ruby/library/net/ftp/set_socket_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/shared/getbinaryfile.rb150
-rw-r--r--spec/ruby/library/net/ftp/shared/gettextfile.rb100
-rw-r--r--spec/ruby/library/net/ftp/shared/last_response_code.rb25
-rw-r--r--spec/ruby/library/net/ftp/shared/list.rb104
-rw-r--r--spec/ruby/library/net/ftp/shared/putbinaryfile.rb167
-rw-r--r--spec/ruby/library/net/ftp/shared/puttextfile.rb120
-rw-r--r--spec/ruby/library/net/ftp/shared/pwd.rb3
-rw-r--r--spec/ruby/library/net/ftp/site_spec.rb56
-rw-r--r--spec/ruby/library/net/ftp/size_spec.rb51
-rw-r--r--spec/ruby/library/net/ftp/spec_helper.rb5
-rw-r--r--spec/ruby/library/net/ftp/status_spec.rb70
-rw-r--r--spec/ruby/library/net/ftp/storbinary_spec.rb51
-rw-r--r--spec/ruby/library/net/ftp/storlines_spec.rb46
-rw-r--r--spec/ruby/library/net/ftp/system_spec.rb51
-rw-r--r--spec/ruby/library/net/ftp/voidcmd_spec.rb57
-rw-r--r--spec/ruby/library/net/ftp/welcome_spec.rb28
-rw-r--r--spec/ruby/library/net/http/HTTPBadResponse_spec.rb8
-rw-r--r--spec/ruby/library/net/http/HTTPClientExcepton_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPError_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPFatalError_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPHeaderSyntaxError_spec.rb8
-rw-r--r--spec/ruby/library/net/http/HTTPRetriableError_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPServerException_spec.rb12
-rw-r--r--spec/ruby/library/net/http/http/Proxy_spec.rb35
-rw-r--r--spec/ruby/library/net/http/http/active_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/address_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/close_on_empty_response_spec.rb10
-rw-r--r--spec/ruby/library/net/http/http/copy_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/delete_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/finish_spec.rb29
-rw-r--r--spec/ruby/library/net/http/http/get2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/get_print_spec.rb30
-rw-r--r--spec/ruby/library/net/http/http/get_response_spec.rb30
-rw-r--r--spec/ruby/library/net/http/http/get_spec.rb96
-rw-r--r--spec/ruby/library/net/http/http/head2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/head_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/http_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/https_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/initialize_spec.rb46
-rw-r--r--spec/ruby/library/net/http/http/inspect_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/is_version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/is_version_1_2_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/lock_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/mkcol_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/move_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/new_spec.rb86
-rw-r--r--spec/ruby/library/net/http/http/newobj_spec.rb48
-rw-r--r--spec/ruby/library/net/http/http/open_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/options_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/port_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/post2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/post_form_spec.rb22
-rw-r--r--spec/ruby/library/net/http/http/post_spec.rb74
-rw-r--r--spec/ruby/library/net/http/http/propfind_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/proppatch_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/proxy_address_spec.rb31
-rw-r--r--spec/ruby/library/net/http/http/proxy_class_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/proxy_pass_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/proxy_port_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/proxy_user_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/put2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/put_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/read_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/request_get_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_head_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_post_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_put_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_spec.rb109
-rw-r--r--spec/ruby/library/net/http/http/request_types_spec.rb254
-rw-r--r--spec/ruby/library/net/http/http/send_request_spec.rb61
-rw-r--r--spec/ruby/library/net/http/http/set_debug_output_spec.rb33
-rw-r--r--spec/ruby/library/net/http/http/shared/request_get.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/request_head.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/request_post.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/request_put.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/started.rb26
-rw-r--r--spec/ruby/library/net/http/http/shared/version_1_1.rb6
-rw-r--r--spec/ruby/library/net/http/http/shared/version_1_2.rb6
-rw-r--r--spec/ruby/library/net/http/http/socket_type_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/start_spec.rb111
-rw-r--r--spec/ruby/library/net/http/http/started_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/trace_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/unlock_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/use_ssl_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/version_1_2_spec.rb20
-rw-r--r--spec/ruby/library/net/http/httpexceptions/initialize_spec.rb17
-rw-r--r--spec/ruby/library/net/http/httpexceptions/response_spec.rb10
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/body_exist_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/body_spec.rb30
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/body_stream_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/exec_spec.rb131
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/inspect_spec.rb25
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/method_spec.rb15
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/path_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/request_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/response_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/set_body_internal_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpheader/add_field_spec.rb31
-rw-r--r--spec/ruby/library/net/http/httpheader/basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net/http/httpheader/canonical_each_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/chunked_spec.rb22
-rw-r--r--spec/ruby/library/net/http/httpheader/content_length_spec.rb54
-rw-r--r--spec/ruby/library/net/http/httpheader/content_range_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpheader/content_type_spec.rb26
-rw-r--r--spec/ruby/library/net/http/httpheader/delete_spec.rb30
-rw-r--r--spec/ruby/library/net/http/httpheader/each_capitalized_name_spec.rb35
-rw-r--r--spec/ruby/library/net/http/httpheader/each_capitalized_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_header_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_key_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_name_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_value_spec.rb35
-rw-r--r--spec/ruby/library/net/http/httpheader/element_reference_spec.rb39
-rw-r--r--spec/ruby/library/net/http/httpheader/element_set_spec.rb41
-rw-r--r--spec/ruby/library/net/http/httpheader/fetch_spec.rb68
-rw-r--r--spec/ruby/library/net/http/httpheader/form_data_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/get_fields_spec.rb39
-rw-r--r--spec/ruby/library/net/http/httpheader/initialize_http_header_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpheader/key_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpheader/length_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/main_type_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpheader/proxy_basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net/http/httpheader/range_length_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpheader/range_spec.rb48
-rw-r--r--spec/ruby/library/net/http/httpheader/set_content_type_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/set_form_data_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/set_range_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/each_capitalized.rb31
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/each_header.rb31
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/each_name.rb31
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/set_range.rb89
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/size.rb18
-rw-r--r--spec/ruby/library/net/http/httpheader/size_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/sub_type_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpheader/to_hash_spec.rb25
-rw-r--r--spec/ruby/library/net/http/httpheader/type_params_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httprequest/initialize_spec.rb45
-rw-r--r--spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb13
-rw-r--r--spec/ruby/library/net/http/httpresponse/body_spec.rb7
-rw-r--r--spec/ruby/library/net/http/httpresponse/code_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/code_type_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/entity_spec.rb7
-rw-r--r--spec/ruby/library/net/http/httpresponse/error_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/error_type_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/exception_type_spec.rb13
-rw-r--r--spec/ruby/library/net/http/httpresponse/header_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/http_version_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpresponse/initialize_spec.rb11
-rw-r--r--spec/ruby/library/net/http/httpresponse/inspect_spec.rb15
-rw-r--r--spec/ruby/library/net/http/httpresponse/message_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/msg_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/read_body_spec.rb86
-rw-r--r--spec/ruby/library/net/http/httpresponse/read_header_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/read_new_spec.rb23
-rw-r--r--spec/ruby/library/net/http/httpresponse/reading_body_spec.rb58
-rw-r--r--spec/ruby/library/net/http/httpresponse/response_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/shared/body.rb20
-rw-r--r--spec/ruby/library/net/http/httpresponse/value_spec.rb24
-rw-r--r--spec/ruby/library/objectspace/dump_all_spec.rb112
-rw-r--r--spec/ruby/library/objectspace/dump_spec.rb70
-rw-r--r--spec/ruby/library/objectspace/fixtures/trace.rb6
-rw-r--r--spec/ruby/library/objectspace/memsize_of_all_spec.rb4
-rw-r--r--spec/ruby/library/objectspace/memsize_of_spec.rb4
-rw-r--r--spec/ruby/library/objectspace/reachable_objects_from_spec.rb14
-rw-r--r--spec/ruby/library/objectspace/trace_object_allocations_spec.rb34
-rw-r--r--spec/ruby/library/objectspace/trace_spec.rb13
-rw-r--r--spec/ruby/library/observer/notify_observers_spec.rb2
-rw-r--r--spec/ruby/library/open3/popen3_spec.rb8
-rw-r--r--spec/ruby/library/openssl/cipher_spec.rb2
-rw-r--r--spec/ruby/library/openssl/config/freeze_spec.rb22
-rw-r--r--spec/ruby/library/openssl/digest/append_spec.rb6
-rw-r--r--spec/ruby/library/openssl/digest/block_length_spec.rb44
-rw-r--r--spec/ruby/library/openssl/digest/digest_length_spec.rb44
-rw-r--r--spec/ruby/library/openssl/digest/digest_spec.rb62
-rw-r--r--spec/ruby/library/openssl/digest/initialize_spec.rb137
-rw-r--r--spec/ruby/library/openssl/digest/name_spec.rb16
-rw-r--r--spec/ruby/library/openssl/digest/reset_spec.rb36
-rw-r--r--spec/ruby/library/openssl/digest/shared/update.rb123
-rw-r--r--spec/ruby/library/openssl/digest/update_spec.rb6
-rw-r--r--spec/ruby/library/openssl/digest_spec.rb63
-rw-r--r--spec/ruby/library/openssl/fixed_length_secure_compare_spec.rb42
-rw-r--r--spec/ruby/library/openssl/kdf/pbkdf2_hmac_spec.rb162
-rw-r--r--spec/ruby/library/openssl/kdf/scrypt_spec.rb210
-rw-r--r--spec/ruby/library/openssl/random/shared/random_bytes.rb6
-rw-r--r--spec/ruby/library/openssl/secure_compare_spec.rb38
-rw-r--r--spec/ruby/library/openssl/shared/constants.rb2
-rw-r--r--spec/ruby/library/openssl/x509/name/parse_spec.rb4
-rw-r--r--spec/ruby/library/openssl/x509/name/verify_spec.rb78
-rw-r--r--spec/ruby/library/openssl/x509/store/verify_spec.rb78
-rw-r--r--spec/ruby/library/openstruct/delete_field_spec.rb6
-rw-r--r--spec/ruby/library/openstruct/equal_value_spec.rb22
-rw-r--r--spec/ruby/library/openstruct/frozen_spec.rb12
-rw-r--r--spec/ruby/library/openstruct/initialize_spec.rb2
-rw-r--r--spec/ruby/library/openstruct/marshal_load_spec.rb2
-rw-r--r--spec/ruby/library/openstruct/method_missing_spec.rb6
-rw-r--r--spec/ruby/library/openstruct/new_spec.rb4
-rw-r--r--spec/ruby/library/openstruct/shared/inspect.rb2
-rw-r--r--spec/ruby/library/openstruct/to_h_spec.rb10
-rw-r--r--spec/ruby/library/pathname/birthtime_spec.rb4
-rw-r--r--spec/ruby/library/pathname/empty_spec.rb8
-rw-r--r--spec/ruby/library/pathname/glob_spec.rb12
-rw-r--r--spec/ruby/library/pathname/inspect_spec.rb2
-rw-r--r--spec/ruby/library/pathname/new_spec.rb12
-rw-r--r--spec/ruby/library/pathname/pathname_spec.rb4
-rw-r--r--spec/ruby/library/pathname/realdirpath_spec.rb2
-rw-r--r--spec/ruby/library/pathname/realpath_spec.rb2
-rw-r--r--spec/ruby/library/pathname/relative_path_from_spec.rb8
-rw-r--r--spec/ruby/library/pp/pp_spec.rb2
-rw-r--r--spec/ruby/library/prime/each_spec.rb247
-rw-r--r--spec/ruby/library/prime/instance_spec.rb31
-rw-r--r--spec/ruby/library/prime/int_from_prime_division_spec.rb19
-rw-r--r--spec/ruby/library/prime/integer/each_prime_spec.rb19
-rw-r--r--spec/ruby/library/prime/integer/from_prime_division_spec.rb19
-rw-r--r--spec/ruby/library/prime/integer/prime_division_spec.rb31
-rw-r--r--spec/ruby/library/prime/integer/prime_spec.rb27
-rw-r--r--spec/ruby/library/prime/next_spec.rb11
-rw-r--r--spec/ruby/library/prime/prime_division_spec.rb37
-rw-r--r--spec/ruby/library/prime/prime_spec.rb27
-rw-r--r--spec/ruby/library/prime/succ_spec.rb11
-rw-r--r--spec/ruby/library/random/formatter/alphanumeric_spec.rb54
-rw-r--r--spec/ruby/library/rbconfig/rbconfig_spec.rb70
-rw-r--r--spec/ruby/library/rbconfig/sizeof/limits_spec.rb6
-rw-r--r--spec/ruby/library/rbconfig/sizeof/sizeof_spec.rb6
-rw-r--r--spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb18
-rw-r--r--spec/ruby/library/rbconfig/unicode_version_spec.rb18
-rw-r--r--spec/ruby/library/readline/basic_quote_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/basic_word_break_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/completer_quote_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/completer_word_break_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/completion_append_character_spec.rb2
-rw-r--r--spec/ruby/library/readline/completion_case_fold_spec.rb2
-rw-r--r--spec/ruby/library/readline/completion_proc_spec.rb4
-rw-r--r--spec/ruby/library/readline/constants_spec.rb4
-rw-r--r--spec/ruby/library/readline/emacs_editing_mode_spec.rb2
-rw-r--r--spec/ruby/library/readline/filename_quote_characters_spec.rb2
-rw-r--r--spec/ruby/library/readline/history/append_spec.rb2
-rw-r--r--spec/ruby/library/readline/history/delete_at_spec.rb4
-rw-r--r--spec/ruby/library/readline/history/element_reference_spec.rb12
-rw-r--r--spec/ruby/library/readline/history/element_set_spec.rb4
-rw-r--r--spec/ruby/library/readline/history/empty_spec.rb6
-rw-r--r--spec/ruby/library/readline/history/history_spec.rb2
-rw-r--r--spec/ruby/library/readline/history/pop_spec.rb2
-rw-r--r--spec/ruby/library/readline/history/push_spec.rb2
-rw-r--r--spec/ruby/library/readline/history/shift_spec.rb2
-rw-r--r--spec/ruby/library/readline/vi_editing_mode_spec.rb2
-rw-r--r--spec/ruby/library/resolv/get_address_spec.rb2
-rw-r--r--spec/ruby/library/resolv/get_name_spec.rb2
-rw-r--r--spec/ruby/library/rexml/attribute/clone_spec.rb14
-rw-r--r--spec/ruby/library/rexml/attribute/element_spec.rb26
-rw-r--r--spec/ruby/library/rexml/attribute/equal_value_spec.rb21
-rw-r--r--spec/ruby/library/rexml/attribute/hash_spec.rb16
-rw-r--r--spec/ruby/library/rexml/attribute/initialize_spec.rb32
-rw-r--r--spec/ruby/library/rexml/attribute/inspect_spec.rb22
-rw-r--r--spec/ruby/library/rexml/attribute/namespace_spec.rb27
-rw-r--r--spec/ruby/library/rexml/attribute/node_type_spec.rb13
-rw-r--r--spec/ruby/library/rexml/attribute/prefix_spec.rb21
-rw-r--r--spec/ruby/library/rexml/attribute/remove_spec.rb23
-rw-r--r--spec/ruby/library/rexml/attribute/to_s_spec.rb17
-rw-r--r--spec/ruby/library/rexml/attribute/to_string_spec.rb17
-rw-r--r--spec/ruby/library/rexml/attribute/value_spec.rb17
-rw-r--r--spec/ruby/library/rexml/attribute/write_spec.rb26
-rw-r--r--spec/ruby/library/rexml/attribute/xpath_spec.rb22
-rw-r--r--spec/ruby/library/rexml/attributes/add_spec.rb10
-rw-r--r--spec/ruby/library/rexml/attributes/append_spec.rb10
-rw-r--r--spec/ruby/library/rexml/attributes/delete_all_spec.rb34
-rw-r--r--spec/ruby/library/rexml/attributes/delete_spec.rb30
-rw-r--r--spec/ruby/library/rexml/attributes/each_attribute_spec.rb25
-rw-r--r--spec/ruby/library/rexml/attributes/each_spec.rb26
-rw-r--r--spec/ruby/library/rexml/attributes/element_reference_spec.rb21
-rw-r--r--spec/ruby/library/rexml/attributes/element_set_spec.rb28
-rw-r--r--spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb17
-rw-r--r--spec/ruby/library/rexml/attributes/get_attribute_spec.rb32
-rw-r--r--spec/ruby/library/rexml/attributes/initialize_spec.rb21
-rw-r--r--spec/ruby/library/rexml/attributes/length_spec.rb10
-rw-r--r--spec/ruby/library/rexml/attributes/namespaces_spec.rb9
-rw-r--r--spec/ruby/library/rexml/attributes/prefixes_spec.rb27
-rw-r--r--spec/ruby/library/rexml/attributes/shared/add.rb17
-rw-r--r--spec/ruby/library/rexml/attributes/shared/length.rb13
-rw-r--r--spec/ruby/library/rexml/attributes/size_spec.rb10
-rw-r--r--spec/ruby/library/rexml/attributes/to_a_spec.rb22
-rw-r--r--spec/ruby/library/rexml/cdata/clone_spec.rb13
-rw-r--r--spec/ruby/library/rexml/cdata/initialize_spec.rb27
-rw-r--r--spec/ruby/library/rexml/cdata/shared/to_s.rb11
-rw-r--r--spec/ruby/library/rexml/cdata/to_s_spec.rb10
-rw-r--r--spec/ruby/library/rexml/cdata/value_spec.rb10
-rw-r--r--spec/ruby/library/rexml/document/add_element_spec.rb34
-rw-r--r--spec/ruby/library/rexml/document/add_spec.rb60
-rw-r--r--spec/ruby/library/rexml/document/clone_spec.rb23
-rw-r--r--spec/ruby/library/rexml/document/doctype_spec.rb18
-rw-r--r--spec/ruby/library/rexml/document/encoding_spec.rb25
-rw-r--r--spec/ruby/library/rexml/document/expanded_name_spec.rb19
-rw-r--r--spec/ruby/library/rexml/document/new_spec.rb39
-rw-r--r--spec/ruby/library/rexml/document/node_type_spec.rb11
-rw-r--r--spec/ruby/library/rexml/document/root_spec.rb15
-rw-r--r--spec/ruby/library/rexml/document/stand_alone_spec.rb22
-rw-r--r--spec/ruby/library/rexml/document/version_spec.rb17
-rw-r--r--spec/ruby/library/rexml/document/write_spec.rb38
-rw-r--r--spec/ruby/library/rexml/document/xml_decl_spec.rb18
-rw-r--r--spec/ruby/library/rexml/element/add_attribute_spec.rb44
-rw-r--r--spec/ruby/library/rexml/element/add_attributes_spec.rb25
-rw-r--r--spec/ruby/library/rexml/element/add_element_spec.rb41
-rw-r--r--spec/ruby/library/rexml/element/add_namespace_spec.rb26
-rw-r--r--spec/ruby/library/rexml/element/add_text_spec.rb27
-rw-r--r--spec/ruby/library/rexml/element/attribute_spec.rb20
-rw-r--r--spec/ruby/library/rexml/element/attributes_spec.rb22
-rw-r--r--spec/ruby/library/rexml/element/cdatas_spec.rb27
-rw-r--r--spec/ruby/library/rexml/element/clone_spec.rb32
-rw-r--r--spec/ruby/library/rexml/element/comments_spec.rb23
-rw-r--r--spec/ruby/library/rexml/element/delete_attribute_spec.rb42
-rw-r--r--spec/ruby/library/rexml/element/delete_element_spec.rb52
-rw-r--r--spec/ruby/library/rexml/element/delete_namespace_spec.rb28
-rw-r--r--spec/ruby/library/rexml/element/document_spec.rb19
-rw-r--r--spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb38
-rw-r--r--spec/ruby/library/rexml/element/each_element_with_text_spec.rb34
-rw-r--r--spec/ruby/library/rexml/element/element_reference_spec.rb23
-rw-r--r--spec/ruby/library/rexml/element/get_text_spec.rb21
-rw-r--r--spec/ruby/library/rexml/element/has_attributes_spec.rb20
-rw-r--r--spec/ruby/library/rexml/element/has_elements_spec.rb21
-rw-r--r--spec/ruby/library/rexml/element/has_text_spec.rb19
-rw-r--r--spec/ruby/library/rexml/element/inspect_spec.rb30
-rw-r--r--spec/ruby/library/rexml/element/instructions_spec.rb24
-rw-r--r--spec/ruby/library/rexml/element/namespace_spec.rb30
-rw-r--r--spec/ruby/library/rexml/element/namespaces_spec.rb35
-rw-r--r--spec/ruby/library/rexml/element/new_spec.rb38
-rw-r--r--spec/ruby/library/rexml/element/next_element_spec.rb22
-rw-r--r--spec/ruby/library/rexml/element/node_type_spec.rb11
-rw-r--r--spec/ruby/library/rexml/element/prefixes_spec.rb26
-rw-r--r--spec/ruby/library/rexml/element/previous_element_spec.rb23
-rw-r--r--spec/ruby/library/rexml/element/raw_spec.rb27
-rw-r--r--spec/ruby/library/rexml/element/root_spec.rb31
-rw-r--r--spec/ruby/library/rexml/element/text_spec.rb49
-rw-r--r--spec/ruby/library/rexml/element/texts_spec.rb19
-rw-r--r--spec/ruby/library/rexml/element/whitespace_spec.rb26
-rw-r--r--spec/ruby/library/rexml/node/each_recursive_spec.rb24
-rw-r--r--spec/ruby/library/rexml/node/find_first_recursive_spec.rb28
-rw-r--r--spec/ruby/library/rexml/node/index_in_parent_spec.rb18
-rw-r--r--spec/ruby/library/rexml/node/next_sibling_node_spec.rb24
-rw-r--r--spec/ruby/library/rexml/node/parent_spec.rb23
-rw-r--r--spec/ruby/library/rexml/node/previous_sibling_node_spec.rb24
-rw-r--r--spec/ruby/library/rexml/shared/each_element.rb36
-rw-r--r--spec/ruby/library/rexml/shared/elements_to_a.rb34
-rw-r--r--spec/ruby/library/rexml/text/append_spec.rb13
-rw-r--r--spec/ruby/library/rexml/text/clone_spec.rb13
-rw-r--r--spec/ruby/library/rexml/text/comparison_spec.rb28
-rw-r--r--spec/ruby/library/rexml/text/empty_spec.rb15
-rw-r--r--spec/ruby/library/rexml/text/indent_text_spec.rb26
-rw-r--r--spec/ruby/library/rexml/text/inspect_spec.rb11
-rw-r--r--spec/ruby/library/rexml/text/new_spec.rb51
-rw-r--r--spec/ruby/library/rexml/text/node_type_spec.rb11
-rw-r--r--spec/ruby/library/rexml/text/normalize_spec.rb11
-rw-r--r--spec/ruby/library/rexml/text/read_with_substitution_spec.rb15
-rw-r--r--spec/ruby/library/rexml/text/to_s_spec.rb20
-rw-r--r--spec/ruby/library/rexml/text/unnormalize_spec.rb11
-rw-r--r--spec/ruby/library/rexml/text/value_spec.rb40
-rw-r--r--spec/ruby/library/rexml/text/wrap_spec.rb23
-rw-r--r--spec/ruby/library/rexml/text/write_with_substitution_spec.rb36
-rw-r--r--spec/ruby/library/ripper/lex_spec.rb6
-rw-r--r--spec/ruby/library/rubygems/gem/bin_path_spec.rb1
-rw-r--r--spec/ruby/library/rubygems/gem/load_path_insert_index_spec.rb4
-rw-r--r--spec/ruby/library/scanf/io/block_scanf_spec.rb1
-rw-r--r--spec/ruby/library/scanf/io/fixtures/date.txt4
-rw-r--r--spec/ruby/library/scanf/io/fixtures/helloworld.txt1
-rw-r--r--spec/ruby/library/scanf/io/scanf_spec.rb1
-rw-r--r--spec/ruby/library/scanf/io/shared/block_scanf.rb28
-rw-r--r--spec/ruby/library/scanf/string/block_scanf_spec.rb1
-rw-r--r--spec/ruby/library/scanf/string/scanf_spec.rb1
-rw-r--r--spec/ruby/library/scanf/string/shared/block_scanf.rb25
-rw-r--r--spec/ruby/library/securerandom/base64_spec.rb10
-rw-r--r--spec/ruby/library/securerandom/hex_spec.rb14
-rw-r--r--spec/ruby/library/securerandom/random_bytes_spec.rb12
-rw-r--r--spec/ruby/library/securerandom/random_number_spec.rb52
-rw-r--r--spec/ruby/library/set/add_spec.rb27
-rw-r--r--spec/ruby/library/set/append_spec.rb7
-rw-r--r--spec/ruby/library/set/case_compare_spec.rb12
-rw-r--r--spec/ruby/library/set/case_equality_spec.rb7
-rw-r--r--spec/ruby/library/set/classify_spec.rb27
-rw-r--r--spec/ruby/library/set/clear_spec.rb17
-rw-r--r--spec/ruby/library/set/collect_spec.rb7
-rw-r--r--spec/ruby/library/set/compare_by_identity_spec.rb143
-rw-r--r--spec/ruby/library/set/comparison_spec.rb29
-rw-r--r--spec/ruby/library/set/constructor_spec.rb15
-rw-r--r--spec/ruby/library/set/delete_if_spec.rb38
-rw-r--r--spec/ruby/library/set/delete_spec.rb37
-rw-r--r--spec/ruby/library/set/difference_spec.rb7
-rw-r--r--spec/ruby/library/set/disjoint_spec.rb23
-rw-r--r--spec/ruby/library/set/divide_spec.rb34
-rw-r--r--spec/ruby/library/set/each_spec.rb26
-rw-r--r--spec/ruby/library/set/empty_spec.rb10
-rw-r--r--spec/ruby/library/set/enumerable/to_set_spec.rb21
-rw-r--r--spec/ruby/library/set/eql_spec.rb15
-rw-r--r--spec/ruby/library/set/equal_value_spec.rb33
-rw-r--r--spec/ruby/library/set/exclusion_spec.rb18
-rw-r--r--spec/ruby/library/set/fixtures/set_like.rb31
-rw-r--r--spec/ruby/library/set/flatten_merge_spec.rb23
-rw-r--r--spec/ruby/library/set/flatten_spec.rb53
-rw-r--r--spec/ruby/library/set/hash_spec.rb13
-rw-r--r--spec/ruby/library/set/include_spec.rb7
-rw-r--r--spec/ruby/library/set/initialize_clone_spec.rb18
-rw-r--r--spec/ruby/library/set/initialize_spec.rb73
-rw-r--r--spec/ruby/library/set/inspect_spec.rb7
-rw-r--r--spec/ruby/library/set/intersect_spec.rb23
-rw-r--r--spec/ruby/library/set/intersection_spec.rb11
-rw-r--r--spec/ruby/library/set/join_spec.rb31
-rw-r--r--spec/ruby/library/set/keep_if_spec.rb38
-rw-r--r--spec/ruby/library/set/length_spec.rb7
-rw-r--r--spec/ruby/library/set/map_spec.rb7
-rw-r--r--spec/ruby/library/set/member_spec.rb7
-rw-r--r--spec/ruby/library/set/merge_spec.rb19
-rw-r--r--spec/ruby/library/set/minus_spec.rb7
-rw-r--r--spec/ruby/library/set/plus_spec.rb7
-rw-r--r--spec/ruby/library/set/pretty_print_cycle_spec.rb10
-rw-r--r--spec/ruby/library/set/pretty_print_spec.rb19
-rw-r--r--spec/ruby/library/set/proper_subset_spec.rb41
-rw-r--r--spec/ruby/library/set/proper_superset_spec.rb41
-rw-r--r--spec/ruby/library/set/reject_spec.rb42
-rw-r--r--spec/ruby/library/set/replace_spec.rb17
-rw-r--r--spec/ruby/library/set/shared/add.rb14
-rw-r--r--spec/ruby/library/set/shared/collect.rb20
-rw-r--r--spec/ruby/library/set/shared/difference.rb15
-rw-r--r--spec/ruby/library/set/shared/include.rb29
-rw-r--r--spec/ruby/library/set/shared/inspect.rb15
-rw-r--r--spec/ruby/library/set/shared/intersection.rb15
-rw-r--r--spec/ruby/library/set/shared/select.rb42
-rw-r--r--spec/ruby/library/set/shared/union.rb15
-rw-r--r--spec/ruby/library/set/size_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/add_spec.rb42
-rw-r--r--spec/ruby/library/set/sortedset/append_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/case_equality_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/classify_spec.rb30
-rw-r--r--spec/ruby/library/set/sortedset/clear_spec.rb20
-rw-r--r--spec/ruby/library/set/sortedset/collect_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/constructor_spec.rb18
-rw-r--r--spec/ruby/library/set/sortedset/delete_if_spec.rb41
-rw-r--r--spec/ruby/library/set/sortedset/delete_spec.rb40
-rw-r--r--spec/ruby/library/set/sortedset/difference_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/divide_spec.rb37
-rw-r--r--spec/ruby/library/set/sortedset/each_spec.rb29
-rw-r--r--spec/ruby/library/set/sortedset/empty_spec.rb13
-rw-r--r--spec/ruby/library/set/sortedset/eql_spec.rb19
-rw-r--r--spec/ruby/library/set/sortedset/equal_value_spec.rb16
-rw-r--r--spec/ruby/library/set/sortedset/exclusion_spec.rb21
-rw-r--r--spec/ruby/library/set/sortedset/filter_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/flatten_merge_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/flatten_spec.rb47
-rw-r--r--spec/ruby/library/set/sortedset/hash_spec.rb16
-rw-r--r--spec/ruby/library/set/sortedset/include_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/initialize_spec.rb33
-rw-r--r--spec/ruby/library/set/sortedset/inspect_spec.rb13
-rw-r--r--spec/ruby/library/set/sortedset/intersection_spec.rb14
-rw-r--r--spec/ruby/library/set/sortedset/keep_if_spec.rb34
-rw-r--r--spec/ruby/library/set/sortedset/length_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/map_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/member_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/merge_spec.rb22
-rw-r--r--spec/ruby/library/set/sortedset/minus_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/plus_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb13
-rw-r--r--spec/ruby/library/set/sortedset/pretty_print_spec.rb20
-rw-r--r--spec/ruby/library/set/sortedset/proper_subset_spec.rb36
-rw-r--r--spec/ruby/library/set/sortedset/proper_superset_spec.rb36
-rw-r--r--spec/ruby/library/set/sortedset/reject_spec.rb45
-rw-r--r--spec/ruby/library/set/sortedset/replace_spec.rb20
-rw-r--r--spec/ruby/library/set/sortedset/select_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/shared/add.rb14
-rw-r--r--spec/ruby/library/set/sortedset/shared/collect.rb20
-rw-r--r--spec/ruby/library/set/sortedset/shared/difference.rb15
-rw-r--r--spec/ruby/library/set/sortedset/shared/include.rb7
-rw-r--r--spec/ruby/library/set/sortedset/shared/intersection.rb15
-rw-r--r--spec/ruby/library/set/sortedset/shared/length.rb6
-rw-r--r--spec/ruby/library/set/sortedset/shared/select.rb35
-rw-r--r--spec/ruby/library/set/sortedset/shared/union.rb15
-rw-r--r--spec/ruby/library/set/sortedset/size_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/sortedset_spec.rb22
-rw-r--r--spec/ruby/library/set/sortedset/subset_spec.rb36
-rw-r--r--spec/ruby/library/set/sortedset/subtract_spec.rb20
-rw-r--r--spec/ruby/library/set/sortedset/superset_spec.rb36
-rw-r--r--spec/ruby/library/set/sortedset/to_a_spec.rb20
-rw-r--r--spec/ruby/library/set/sortedset/union_spec.rb14
-rw-r--r--spec/ruby/library/set/subset_spec.rb41
-rw-r--r--spec/ruby/library/set/subtract_spec.rb17
-rw-r--r--spec/ruby/library/set/superset_spec.rb41
-rw-r--r--spec/ruby/library/set/to_a_spec.rb8
-rw-r--r--spec/ruby/library/set/to_s_spec.rb11
-rw-r--r--spec/ruby/library/set/union_spec.rb11
-rw-r--r--spec/ruby/library/shellwords/shellwords_spec.rb15
-rw-r--r--spec/ruby/library/singleton/allocate_spec.rb2
-rw-r--r--spec/ruby/library/singleton/clone_spec.rb2
-rw-r--r--spec/ruby/library/singleton/dup_spec.rb2
-rw-r--r--spec/ruby/library/singleton/instance_spec.rb12
-rw-r--r--spec/ruby/library/singleton/load_spec.rb13
-rw-r--r--spec/ruby/library/singleton/new_spec.rb2
-rw-r--r--spec/ruby/library/socket/addrinfo/afamily_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/bind_spec.rb8
-rw-r--r--spec/ruby/library/socket/addrinfo/canonname_spec.rb4
-rw-r--r--spec/ruby/library/socket/addrinfo/connect_from_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/connect_spec.rb6
-rw-r--r--spec/ruby/library/socket/addrinfo/connect_to_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/family_addrinfo_spec.rb62
-rw-r--r--spec/ruby/library/socket/addrinfo/foreach_spec.rb2
-rw-r--r--spec/ruby/library/socket/addrinfo/getaddrinfo_spec.rb24
-rw-r--r--spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/initialize_spec.rb92
-rw-r--r--spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/inspect_spec.rb26
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_address_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_port_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_spec.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb22
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_spec.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_to_ipv4_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/listen_spec.rb4
-rw-r--r--spec/ruby/library/socket/addrinfo/marshal_dump_spec.rb58
-rw-r--r--spec/ruby/library/socket/addrinfo/marshal_load_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/pfamily_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/protocol_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/socktype_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/tcp_spec.rb2
-rw-r--r--spec/ruby/library/socket/addrinfo/udp_spec.rb8
-rw-r--r--spec/ruby/library/socket/addrinfo/unix_path_spec.rb46
-rw-r--r--spec/ruby/library/socket/addrinfo/unix_spec.rb52
-rw-r--r--spec/ruby/library/socket/ancillarydata/cmsg_is_spec.rb2
-rw-r--r--spec/ruby/library/socket/ancillarydata/initialize_spec.rb36
-rw-r--r--spec/ruby/library/socket/ancillarydata/int_spec.rb4
-rw-r--r--spec/ruby/library/socket/ancillarydata/ip_pktinfo_spec.rb16
-rw-r--r--spec/ruby/library/socket/ancillarydata/ipv6_pktinfo_addr_spec.rb2
-rw-r--r--spec/ruby/library/socket/ancillarydata/ipv6_pktinfo_spec.rb10
-rw-r--r--spec/ruby/library/socket/ancillarydata/unix_rights_spec.rb10
-rw-r--r--spec/ruby/library/socket/basicsocket/close_read_spec.rb12
-rw-r--r--spec/ruby/library/socket/basicsocket/close_write_spec.rb12
-rw-r--r--spec/ruby/library/socket/basicsocket/connect_address_spec.rb86
-rw-r--r--spec/ruby/library/socket/basicsocket/do_not_reverse_lookup_spec.rb2
-rw-r--r--spec/ruby/library/socket/basicsocket/for_fd_spec.rb6
-rw-r--r--spec/ruby/library/socket/basicsocket/getpeereid_spec.rb4
-rw-r--r--spec/ruby/library/socket/basicsocket/getpeername_spec.rb2
-rw-r--r--spec/ruby/library/socket/basicsocket/getsockname_spec.rb4
-rw-r--r--spec/ruby/library/socket/basicsocket/getsockopt_spec.rb12
-rw-r--r--spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb32
-rw-r--r--spec/ruby/library/socket/basicsocket/read_spec.rb47
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb71
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_spec.rb120
-rw-r--r--spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb69
-rw-r--r--spec/ruby/library/socket/basicsocket/recvmsg_spec.rb76
-rw-r--r--spec/ruby/library/socket/basicsocket/send_spec.rb94
-rw-r--r--spec/ruby/library/socket/basicsocket/sendmsg_nonblock_spec.rb6
-rw-r--r--spec/ruby/library/socket/basicsocket/sendmsg_spec.rb2
-rw-r--r--spec/ruby/library/socket/basicsocket/setsockopt_spec.rb58
-rw-r--r--spec/ruby/library/socket/basicsocket/shutdown_spec.rb44
-rw-r--r--spec/ruby/library/socket/constants/constants_spec.rb28
-rw-r--r--spec/ruby/library/socket/fixtures/classes.rb6
-rw-r--r--spec/ruby/library/socket/ipsocket/addr_spec.rb8
-rw-r--r--spec/ruby/library/socket/ipsocket/getaddress_spec.rb9
-rw-r--r--spec/ruby/library/socket/ipsocket/inspect_spec.rb24
-rw-r--r--spec/ruby/library/socket/ipsocket/peeraddr_spec.rb4
-rw-r--r--spec/ruby/library/socket/ipsocket/recvfrom_spec.rb60
-rw-r--r--spec/ruby/library/socket/option/bool_spec.rb4
-rw-r--r--spec/ruby/library/socket/option/initialize_spec.rb18
-rw-r--r--spec/ruby/library/socket/option/int_spec.rb6
-rw-r--r--spec/ruby/library/socket/option/linger_spec.rb18
-rw-r--r--spec/ruby/library/socket/option/new_spec.rb6
-rw-r--r--spec/ruby/library/socket/shared/address.rb92
-rw-r--r--spec/ruby/library/socket/shared/pack_sockaddr.rb69
-rw-r--r--spec/ruby/library/socket/shared/partially_closable_sockets.rb2
-rw-r--r--spec/ruby/library/socket/shared/socketpair.rb38
-rw-r--r--spec/ruby/library/socket/socket/accept_loop_spec.rb8
-rw-r--r--spec/ruby/library/socket/socket/accept_nonblock_spec.rb24
-rw-r--r--spec/ruby/library/socket/socket/accept_spec.rb12
-rw-r--r--spec/ruby/library/socket/socket/bind_spec.rb30
-rw-r--r--spec/ruby/library/socket/socket/connect_nonblock_spec.rb68
-rw-r--r--spec/ruby/library/socket/socket/connect_spec.rb24
-rw-r--r--spec/ruby/library/socket/socket/getaddrinfo_spec.rb70
-rw-r--r--spec/ruby/library/socket/socket/gethostbyaddr_spec.rb37
-rw-r--r--spec/ruby/library/socket/socket/gethostbyname_spec.rb12
-rw-r--r--spec/ruby/library/socket/socket/gethostname_spec.rb12
-rw-r--r--spec/ruby/library/socket/socket/getifaddrs_spec.rb42
-rw-r--r--spec/ruby/library/socket/socket/getnameinfo_spec.rb18
-rw-r--r--spec/ruby/library/socket/socket/getservbyname_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/getservbyport_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/initialize_spec.rb16
-rw-r--r--spec/ruby/library/socket/socket/ip_address_list_spec.rb10
-rw-r--r--spec/ruby/library/socket/socket/listen_spec.rb6
-rw-r--r--spec/ruby/library/socket/socket/local_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/new_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/pack_sockaddr_in_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/pair_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb78
-rw-r--r--spec/ruby/library/socket/socket/recvfrom_spec.rb69
-rw-r--r--spec/ruby/library/socket/socket/remote_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/socketpair_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/sysaccept_spec.rb10
-rw-r--r--spec/ruby/library/socket/socket/tcp_server_loop_spec.rb4
-rw-r--r--spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb8
-rw-r--r--spec/ruby/library/socket/socket/tcp_spec.rb30
-rw-r--r--spec/ruby/library/socket/socket/udp_server_loop_on_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/udp_server_loop_spec.rb6
-rw-r--r--spec/ruby/library/socket/socket/udp_server_recv_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/udp_server_sockets_spec.rb8
-rw-r--r--spec/ruby/library/socket/socket/unix_server_loop_spec.rb76
-rw-r--r--spec/ruby/library/socket/socket/unix_server_socket_spec.rb56
-rw-r--r--spec/ruby/library/socket/socket/unix_spec.rb56
-rw-r--r--spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb16
-rw-r--r--spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb34
-rw-r--r--spec/ruby/library/socket/spec_helper.rb21
-rw-r--r--spec/ruby/library/socket/tcpserver/accept_nonblock_spec.rb12
-rw-r--r--spec/ruby/library/socket/tcpserver/accept_spec.rb23
-rw-r--r--spec/ruby/library/socket/tcpserver/gets_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpserver/initialize_spec.rb12
-rw-r--r--spec/ruby/library/socket/tcpserver/listen_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpserver/new_spec.rb34
-rw-r--r--spec/ruby/library/socket/tcpserver/sysaccept_spec.rb4
-rw-r--r--spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb18
-rw-r--r--spec/ruby/library/socket/tcpsocket/initialize_spec.rb44
-rw-r--r--spec/ruby/library/socket/tcpsocket/local_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpsocket/open_spec.rb1
-rw-r--r--spec/ruby/library/socket/tcpsocket/partially_closable_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpsocket/remote_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpsocket/shared/new.rb70
-rw-r--r--spec/ruby/library/socket/udpsocket/bind_spec.rb4
-rw-r--r--spec/ruby/library/socket/udpsocket/initialize_spec.rb27
-rw-r--r--spec/ruby/library/socket/udpsocket/inspect_spec.rb17
-rw-r--r--spec/ruby/library/socket/udpsocket/local_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/udpsocket/new_spec.rb18
-rw-r--r--spec/ruby/library/socket/udpsocket/open_spec.rb2
-rw-r--r--spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb17
-rw-r--r--spec/ruby/library/socket/udpsocket/remote_address_spec.rb2
-rw-r--r--spec/ruby/library/socket/udpsocket/send_spec.rb14
-rw-r--r--spec/ruby/library/socket/udpsocket/write_spec.rb2
-rw-r--r--spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb113
-rw-r--r--spec/ruby/library/socket/unixserver/accept_spec.rb161
-rw-r--r--spec/ruby/library/socket/unixserver/for_fd_spec.rb28
-rw-r--r--spec/ruby/library/socket/unixserver/initialize_spec.rb36
-rw-r--r--spec/ruby/library/socket/unixserver/listen_spec.rb24
-rw-r--r--spec/ruby/library/socket/unixserver/new_spec.rb6
-rw-r--r--spec/ruby/library/socket/unixserver/open_spec.rb26
-rw-r--r--spec/ruby/library/socket/unixserver/shared/new.rb26
-rw-r--r--spec/ruby/library/socket/unixserver/sysaccept_spec.rb64
-rw-r--r--spec/ruby/library/socket/unixsocket/addr_spec.rb47
-rw-r--r--spec/ruby/library/socket/unixsocket/initialize_spec.rb62
-rw-r--r--spec/ruby/library/socket/unixsocket/inspect_spec.rb18
-rw-r--r--spec/ruby/library/socket/unixsocket/local_address_spec.rb132
-rw-r--r--spec/ruby/library/socket/unixsocket/new_spec.rb6
-rw-r--r--spec/ruby/library/socket/unixsocket/open_spec.rb26
-rw-r--r--spec/ruby/library/socket/unixsocket/pair_spec.rb41
-rw-r--r--spec/ruby/library/socket/unixsocket/partially_closable_spec.rb32
-rw-r--r--spec/ruby/library/socket/unixsocket/path_spec.rb34
-rw-r--r--spec/ruby/library/socket/unixsocket/peeraddr_spec.rb38
-rw-r--r--spec/ruby/library/socket/unixsocket/recv_io_spec.rb15
-rw-r--r--spec/ruby/library/socket/unixsocket/recvfrom_spec.rb138
-rw-r--r--spec/ruby/library/socket/unixsocket/remote_address_spec.rb60
-rw-r--r--spec/ruby/library/socket/unixsocket/send_io_spec.rb9
-rw-r--r--spec/ruby/library/socket/unixsocket/shared/new.rb28
-rw-r--r--spec/ruby/library/socket/unixsocket/shared/pair.rb47
-rw-r--r--spec/ruby/library/socket/unixsocket/socketpair_spec.rb46
-rw-r--r--spec/ruby/library/stringio/append_spec.rb25
-rw-r--r--spec/ruby/library/stringio/binmode_spec.rb4
-rw-r--r--spec/ruby/library/stringio/bytes_spec.rb29
-rw-r--r--spec/ruby/library/stringio/chars_spec.rb29
-rw-r--r--spec/ruby/library/stringio/close_read_spec.rb10
-rw-r--r--spec/ruby/library/stringio/close_spec.rb8
-rw-r--r--spec/ruby/library/stringio/close_write_spec.rb12
-rw-r--r--spec/ruby/library/stringio/closed_read_spec.rb6
-rw-r--r--spec/ruby/library/stringio/closed_spec.rb10
-rw-r--r--spec/ruby/library/stringio/closed_write_spec.rb6
-rw-r--r--spec/ruby/library/stringio/codepoints_spec.rb19
-rw-r--r--spec/ruby/library/stringio/each_line_spec.rb4
-rw-r--r--spec/ruby/library/stringio/each_spec.rb4
-rw-r--r--spec/ruby/library/stringio/fcntl_spec.rb2
-rw-r--r--spec/ruby/library/stringio/fileno_spec.rb5
-rw-r--r--spec/ruby/library/stringio/fixtures/classes.rb4
-rw-r--r--spec/ruby/library/stringio/flush_spec.rb4
-rw-r--r--spec/ruby/library/stringio/fsync_spec.rb4
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb263
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb278
-rw-r--r--spec/ruby/library/stringio/inspect_spec.rb2
-rw-r--r--spec/ruby/library/stringio/lineno_spec.rb8
-rw-r--r--spec/ruby/library/stringio/lines_spec.rb53
-rw-r--r--spec/ruby/library/stringio/new_spec.rb10
-rw-r--r--spec/ruby/library/stringio/open_spec.rb188
-rw-r--r--spec/ruby/library/stringio/path_spec.rb2
-rw-r--r--spec/ruby/library/stringio/pid_spec.rb2
-rw-r--r--spec/ruby/library/stringio/pos_spec.rb2
-rw-r--r--spec/ruby/library/stringio/print_spec.rb22
-rw-r--r--spec/ruby/library/stringio/printf_spec.rb45
-rw-r--r--spec/ruby/library/stringio/putc_spec.rb33
-rw-r--r--spec/ruby/library/stringio/puts_spec.rb30
-rw-r--r--spec/ruby/library/stringio/read_nonblock_spec.rb15
-rw-r--r--spec/ruby/library/stringio/read_spec.rb6
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb160
-rw-r--r--spec/ruby/library/stringio/readlines_spec.rb16
-rw-r--r--spec/ruby/library/stringio/readpartial_spec.rb50
-rw-r--r--spec/ruby/library/stringio/reopen_spec.rb142
-rw-r--r--spec/ruby/library/stringio/rewind_spec.rb2
-rw-r--r--spec/ruby/library/stringio/seek_spec.rb24
-rw-r--r--spec/ruby/library/stringio/set_encoding_by_bom_spec.rb237
-rw-r--r--spec/ruby/library/stringio/set_encoding_spec.rb8
-rw-r--r--spec/ruby/library/stringio/shared/codepoints.rb12
-rw-r--r--spec/ruby/library/stringio/shared/each.rb92
-rw-r--r--spec/ruby/library/stringio/shared/each_byte.rb12
-rw-r--r--spec/ruby/library/stringio/shared/each_char.rb10
-rw-r--r--spec/ruby/library/stringio/shared/eof.rb10
-rw-r--r--spec/ruby/library/stringio/shared/getc.rb22
-rw-r--r--spec/ruby/library/stringio/shared/gets.rb249
-rw-r--r--spec/ruby/library/stringio/shared/isatty.rb2
-rw-r--r--spec/ruby/library/stringio/shared/read.rb54
-rw-r--r--spec/ruby/library/stringio/shared/readchar.rb8
-rw-r--r--spec/ruby/library/stringio/shared/sysread.rb4
-rw-r--r--spec/ruby/library/stringio/shared/write.rb79
-rw-r--r--spec/ruby/library/stringio/string_spec.rb12
-rw-r--r--spec/ruby/library/stringio/stringio_spec.rb2
-rw-r--r--spec/ruby/library/stringio/sync_spec.rb4
-rw-r--r--spec/ruby/library/stringio/sysread_spec.rb7
-rw-r--r--spec/ruby/library/stringio/truncate_spec.rb24
-rw-r--r--spec/ruby/library/stringio/ungetc_spec.rb24
-rw-r--r--spec/ruby/library/stringio/write_nonblock_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/captures_spec.rb36
-rw-r--r--spec/ruby/library/stringscanner/charpos_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/check_spec.rb68
-rw-r--r--spec/ruby/library/stringscanner/check_until_spec.rb122
-rw-r--r--spec/ruby/library/stringscanner/clear_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/dup_spec.rb4
-rw-r--r--spec/ruby/library/stringscanner/element_reference_spec.rb19
-rw-r--r--spec/ruby/library/stringscanner/empty_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/eos_spec.rb17
-rw-r--r--spec/ruby/library/stringscanner/exist_spec.rb101
-rw-r--r--spec/ruby/library/stringscanner/fixed_anchor_spec.rb17
-rw-r--r--spec/ruby/library/stringscanner/get_byte_spec.rb81
-rw-r--r--spec/ruby/library/stringscanner/getbyte_spec.rb21
-rw-r--r--spec/ruby/library/stringscanner/getch_spec.rb65
-rw-r--r--spec/ruby/library/stringscanner/initialize_spec.rb11
-rw-r--r--spec/ruby/library/stringscanner/inspect_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/match_spec.rb23
-rw-r--r--spec/ruby/library/stringscanner/matched_spec.rb4
-rw-r--r--spec/ruby/library/stringscanner/must_C_version_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/named_captures_spec.rb28
-rw-r--r--spec/ruby/library/stringscanner/peek_byte_spec.rb35
-rw-r--r--spec/ruby/library/stringscanner/peek_spec.rb39
-rw-r--r--spec/ruby/library/stringscanner/peep_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/rest_size_spec.rb27
-rw-r--r--spec/ruby/library/stringscanner/rest_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/restsize_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/scan_byte_spec.rb98
-rw-r--r--spec/ruby/library/stringscanner/scan_full_spec.rb14
-rw-r--r--spec/ruby/library/stringscanner/scan_integer_spec.rb157
-rw-r--r--spec/ruby/library/stringscanner/scan_spec.rb34
-rw-r--r--spec/ruby/library/stringscanner/scan_until_spec.rb122
-rw-r--r--spec/ruby/library/stringscanner/search_full_spec.rb107
-rw-r--r--spec/ruby/library/stringscanner/shared/bol.rb16
-rw-r--r--spec/ruby/library/stringscanner/shared/concat.rb16
-rw-r--r--spec/ruby/library/stringscanner/shared/eos.rb17
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range.rb4
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range_matched.rb4
-rw-r--r--spec/ruby/library/stringscanner/shared/get_byte.rb29
-rw-r--r--spec/ruby/library/stringscanner/shared/peek.rb39
-rw-r--r--spec/ruby/library/stringscanner/shared/pos.rb11
-rw-r--r--spec/ruby/library/stringscanner/shared/rest_size.rb18
-rw-r--r--spec/ruby/library/stringscanner/shared/terminate.rb8
-rw-r--r--spec/ruby/library/stringscanner/skip_spec.rb14
-rw-r--r--spec/ruby/library/stringscanner/skip_until_spec.rb118
-rw-r--r--spec/ruby/library/stringscanner/string_spec.rb4
-rw-r--r--spec/ruby/library/stringscanner/terminate_spec.rb8
-rw-r--r--spec/ruby/library/stringscanner/unscan_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/values_at_spec.rb68
-rw-r--r--spec/ruby/library/syslog/close_spec.rb16
-rw-r--r--spec/ruby/library/syslog/constants_spec.rb4
-rw-r--r--spec/ruby/library/syslog/facility_spec.rb6
-rw-r--r--spec/ruby/library/syslog/ident_spec.rb4
-rw-r--r--spec/ruby/library/syslog/inspect_spec.rb4
-rw-r--r--spec/ruby/library/syslog/log_spec.rb10
-rw-r--r--spec/ruby/library/syslog/mask_spec.rb14
-rw-r--r--spec/ruby/library/syslog/open_spec.rb10
-rw-r--r--spec/ruby/library/syslog/opened_spec.rb16
-rw-r--r--spec/ruby/library/syslog/options_spec.rb6
-rw-r--r--spec/ruby/library/syslog/shared/log.rb6
-rw-r--r--spec/ruby/library/syslog/shared/reopen.rb14
-rw-r--r--spec/ruby/library/tempfile/_close_spec.rb4
-rw-r--r--spec/ruby/library/tempfile/callback_spec.rb6
-rw-r--r--spec/ruby/library/tempfile/close_spec.rb6
-rw-r--r--spec/ruby/library/tempfile/create_spec.rb176
-rw-r--r--spec/ruby/library/tempfile/initialize_spec.rb2
-rw-r--r--spec/ruby/library/tempfile/open_spec.rb18
-rw-r--r--spec/ruby/library/tempfile/path_spec.rb2
-rw-r--r--spec/ruby/library/tempfile/shared/length.rb6
-rw-r--r--spec/ruby/library/thread/queue_spec.rb4
-rw-r--r--spec/ruby/library/thread/sizedqueue_spec.rb4
-rw-r--r--spec/ruby/library/time/iso8601_spec.rb4
-rw-r--r--spec/ruby/library/time/shared/rfc2822.rb26
-rw-r--r--spec/ruby/library/time/shared/xmlschema.rb52
-rw-r--r--spec/ruby/library/time/to_date_spec.rb42
-rw-r--r--spec/ruby/library/time/to_datetime_spec.rb27
-rw-r--r--spec/ruby/library/time/to_time_spec.rb4
-rw-r--r--spec/ruby/library/time/xmlschema_spec.rb2
-rw-r--r--spec/ruby/library/timeout/error_spec.rb2
-rw-r--r--spec/ruby/library/timeout/timeout_spec.rb16
-rw-r--r--spec/ruby/library/tmpdir/dir/mktmpdir_spec.rb18
-rw-r--r--spec/ruby/library/tmpdir/dir/tmpdir_spec.rb4
-rw-r--r--spec/ruby/library/uri/generic/host_spec.rb5
-rw-r--r--spec/ruby/library/uri/generic/to_s_spec.rb5
-rw-r--r--spec/ruby/library/uri/join_spec.rb2
-rw-r--r--spec/ruby/library/uri/mailto/build_spec.rb2
-rw-r--r--spec/ruby/library/uri/parse_spec.rb24
-rw-r--r--spec/ruby/library/uri/plus_spec.rb170
-rw-r--r--spec/ruby/library/uri/select_spec.rb6
-rw-r--r--spec/ruby/library/uri/set_component_spec.rb60
-rw-r--r--spec/ruby/library/uri/shared/eql.rb6
-rw-r--r--spec/ruby/library/uri/shared/join.rb2
-rw-r--r--spec/ruby/library/uri/shared/parse.rb37
-rw-r--r--spec/ruby/library/uri/uri_spec.rb4
-rw-r--r--spec/ruby/library/weakref/__getobj___spec.rb4
-rw-r--r--spec/ruby/library/weakref/allocate_spec.rb2
-rw-r--r--spec/ruby/library/weakref/send_spec.rb4
-rw-r--r--spec/ruby/library/weakref/weakref_alive_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/fixtures/classes.rb17
-rw-r--r--spec/ruby/library/win32ole/win32ole/_getproperty_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/_invoke_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole/codepage_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/connect_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole/const_load_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole/constants_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/create_guid_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/invoke_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/locale_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole/new_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_method_help_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_method_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole/setproperty_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole/shared/ole_method.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole/shared/setproperty.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_event/new_spec.rb15
-rw-r--r--spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb13
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb15
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/event_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb13
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/name_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/new_spec.rb23
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/params_spec.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/shared/name.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/visible_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/default_spec.rb17
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/input_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/name_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/optional_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/retval_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/shared/name.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/guid_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/name_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/new_spec.rb35
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/progid_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/progids_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/shared/name.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb3
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb9
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/variables_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/visible_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/name_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb7
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/shared/name.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/to_s_spec.rb1
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/value_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb5
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb5
-rw-r--r--spec/ruby/library/yaml/dump_spec.rb20
-rw-r--r--spec/ruby/library/yaml/dump_stream_spec.rb3
-rw-r--r--spec/ruby/library/yaml/fixtures/common.rb4
-rw-r--r--spec/ruby/library/yaml/fixtures/strings.rb56
-rw-r--r--spec/ruby/library/yaml/load_file_spec.rb13
-rw-r--r--spec/ruby/library/yaml/load_stream_spec.rb3
-rw-r--r--spec/ruby/library/yaml/parse_file_spec.rb8
-rw-r--r--spec/ruby/library/yaml/parse_spec.rb9
-rw-r--r--spec/ruby/library/yaml/shared/each_document.rb5
-rw-r--r--spec/ruby/library/yaml/shared/load.rb24
-rw-r--r--spec/ruby/library/yaml/to_yaml_spec.rb40
-rw-r--r--spec/ruby/library/zlib/adler32_spec.rb2
-rw-r--r--spec/ruby/library/zlib/crc32_spec.rb2
-rw-r--r--spec/ruby/library/zlib/deflate/deflate_spec.rb9
-rw-r--r--spec/ruby/library/zlib/deflate/new_spec.rb1
-rw-r--r--spec/ruby/library/zlib/deflate/params_spec.rb2
-rw-r--r--spec/ruby/library/zlib/gzipfile/close_spec.rb6
-rw-r--r--spec/ruby/library/zlib/gzipfile/comment_spec.rb3
-rw-r--r--spec/ruby/library/zlib/gzipfile/orig_name_spec.rb3
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_char_spec.rb51
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_line_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/eof_spec.rb22
-rw-r--r--spec/ruby/library/zlib/gzipreader/getc_spec.rb2
-rw-r--r--spec/ruby/library/zlib/gzipreader/gets_spec.rb2
-rw-r--r--spec/ruby/library/zlib/gzipreader/mtime_spec.rb11
-rw-r--r--spec/ruby/library/zlib/gzipreader/new_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/read_spec.rb6
-rw-r--r--spec/ruby/library/zlib/gzipreader/ungetbyte_spec.rb4
-rw-r--r--spec/ruby/library/zlib/gzipreader/ungetc_spec.rb12
-rw-r--r--spec/ruby/library/zlib/gzipwriter/append_spec.rb2
-rw-r--r--spec/ruby/library/zlib/gzipwriter/mtime_spec.rb3
-rw-r--r--spec/ruby/library/zlib/inflate/append_spec.rb2
-rw-r--r--spec/ruby/library/zlib/inflate/finish_spec.rb3
-rw-r--r--spec/ruby/library/zlib/inflate/inflate_spec.rb19
-rw-r--r--spec/ruby/library/zlib/inflate/new_spec.rb1
-rw-r--r--spec/ruby/library/zlib/inflate/set_dictionary_spec.rb2
-rw-r--r--spec/ruby/library/zlib/zlib_version_spec.rb2
-rw-r--r--spec/ruby/optional/capi/array_spec.rb74
-rw-r--r--spec/ruby/optional/capi/bignum_spec.rb42
-rw-r--r--spec/ruby/optional/capi/binding_spec.rb18
-rw-r--r--spec/ruby/optional/capi/class_spec.rb183
-rw-r--r--spec/ruby/optional/capi/constants_spec.rb2
-rw-r--r--spec/ruby/optional/capi/data_spec.rb73
-rw-r--r--spec/ruby/optional/capi/debug_spec.rb24
-rw-r--r--spec/ruby/optional/capi/digest_spec.rb103
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb225
-rw-r--r--spec/ruby/optional/capi/exception_spec.rb72
-rw-r--r--spec/ruby/optional/capi/ext/array_spec.c36
-rw-r--r--spec/ruby/optional/capi/ext/class_spec.c17
-rw-r--r--spec/ruby/optional/capi/ext/constants_spec.c6
-rw-r--r--spec/ruby/optional/capi/ext/data_spec.c4
-rw-r--r--spec/ruby/optional/capi/ext/debug_spec.c2
-rw-r--r--spec/ruby/optional/capi/ext/digest_spec.c168
-rw-r--r--spec/ruby/optional/capi/ext/encoding_spec.c61
-rw-r--r--spec/ruby/optional/capi/ext/exception_spec.c27
-rw-r--r--spec/ruby/optional/capi/ext/fiber_spec.c5
-rw-r--r--spec/ruby/optional/capi/ext/finalizer_spec.c25
-rw-r--r--spec/ruby/optional/capi/ext/gc_spec.c118
-rw-r--r--spec/ruby/optional/capi/ext/globals_spec.c34
-rw-r--r--spec/ruby/optional/capi/ext/hash_spec.c20
-rw-r--r--spec/ruby/optional/capi/ext/integer_spec.c5
-rw-r--r--spec/ruby/optional/capi/ext/io_spec.c181
-rw-r--r--spec/ruby/optional/capi/ext/kernel_spec.c107
-rw-r--r--spec/ruby/optional/capi/ext/mutex_spec.c23
-rw-r--r--spec/ruby/optional/capi/ext/object_spec.c150
-rw-r--r--spec/ruby/optional/capi/ext/proc_spec.c15
-rw-r--r--spec/ruby/optional/capi/ext/range_spec.c50
-rw-r--r--spec/ruby/optional/capi/ext/rbasic_spec.c64
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h75
-rw-r--r--spec/ruby/optional/capi/ext/set_spec.c65
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c137
-rw-r--r--spec/ruby/optional/capi/ext/struct_spec.c42
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c23
-rw-r--r--spec/ruby/optional/capi/ext/tracepoint_spec.c2
-rw-r--r--spec/ruby/optional/capi/ext/typed_data_spec.c23
-rw-r--r--spec/ruby/optional/capi/ext/util_spec.c38
-rw-r--r--spec/ruby/optional/capi/fiber_spec.rb61
-rw-r--r--spec/ruby/optional/capi/file_spec.rb10
-rw-r--r--spec/ruby/optional/capi/finalizer_spec.rb40
-rw-r--r--spec/ruby/optional/capi/fixnum_spec.rb24
-rw-r--r--spec/ruby/optional/capi/fixtures/kernel.rb19
-rw-r--r--spec/ruby/optional/capi/fixtures/object.rb29
-rw-r--r--spec/ruby/optional/capi/float_spec.rb4
-rw-r--r--spec/ruby/optional/capi/gc_spec.rb97
-rw-r--r--spec/ruby/optional/capi/globals_spec.rb81
-rw-r--r--spec/ruby/optional/capi/hash_spec.rb107
-rw-r--r--spec/ruby/optional/capi/integer_spec.rb19
-rw-r--r--spec/ruby/optional/capi/io_spec.rb453
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb452
-rw-r--r--spec/ruby/optional/capi/module_spec.rb62
-rw-r--r--spec/ruby/optional/capi/mutex_spec.rb47
-rw-r--r--spec/ruby/optional/capi/numeric_spec.rb64
-rw-r--r--spec/ruby/optional/capi/object_spec.rb198
-rw-r--r--spec/ruby/optional/capi/proc_spec.rb73
-rw-r--r--spec/ruby/optional/capi/range_spec.rb158
-rw-r--r--spec/ruby/optional/capi/rbasic_spec.rb57
-rw-r--r--spec/ruby/optional/capi/regexp_spec.rb6
-rw-r--r--spec/ruby/optional/capi/set_spec.rb96
-rw-r--r--spec/ruby/optional/capi/shared/rbasic.rb4
-rw-r--r--spec/ruby/optional/capi/spec_helper.rb52
-rw-r--r--spec/ruby/optional/capi/string_spec.rb566
-rw-r--r--spec/ruby/optional/capi/struct_spec.rb133
-rw-r--r--spec/ruby/optional/capi/thread_spec.rb52
-rw-r--r--spec/ruby/optional/capi/time_spec.rb111
-rw-r--r--spec/ruby/optional/capi/tracepoint_spec.rb2
-rw-r--r--spec/ruby/optional/capi/typed_data_spec.rb20
-rw-r--r--spec/ruby/optional/capi/util_spec.rb117
-rw-r--r--spec/ruby/optional/thread_safety/fixtures/classes.rb39
-rw-r--r--spec/ruby/optional/thread_safety/hash_spec.rb210
-rw-r--r--spec/ruby/security/cve_2010_1330_spec.rb4
-rw-r--r--spec/ruby/security/cve_2014_8080_spec.rb34
-rw-r--r--spec/ruby/security/cve_2017_17742_spec.rb37
-rw-r--r--spec/ruby/security/cve_2018_8778_spec.rb2
-rw-r--r--spec/ruby/security/cve_2018_8779_spec.rb4
-rw-r--r--spec/ruby/security/cve_2018_8780_spec.rb12
-rw-r--r--spec/ruby/security/cve_2019_8322_spec.rb33
-rw-r--r--spec/ruby/security/cve_2019_8323_spec.rb14
-rw-r--r--spec/ruby/security/cve_2019_8325_spec.rb10
-rw-r--r--spec/ruby/security/cve_2020_10663_spec.rb64
-rw-r--r--spec/ruby/security/cve_2024_49761_spec.rb7
-rw-r--r--spec/ruby/shared/basicobject/method_missing.rb18
-rw-r--r--spec/ruby/shared/basicobject/send.rb18
-rw-r--r--spec/ruby/shared/enumerable/minmax.rb6
-rw-r--r--spec/ruby/shared/enumerator/enum_for.rb57
-rw-r--r--spec/ruby/shared/enumerator/with_index.rb33
-rw-r--r--spec/ruby/shared/enumerator/with_object.rb42
-rw-r--r--spec/ruby/shared/fiber/resume.rb58
-rw-r--r--spec/ruby/shared/file/directory.rb18
-rw-r--r--spec/ruby/shared/file/executable.rb8
-rw-r--r--spec/ruby/shared/file/executable_real.rb8
-rw-r--r--spec/ruby/shared/file/exist.rb11
-rw-r--r--spec/ruby/shared/file/file.rb8
-rw-r--r--spec/ruby/shared/file/grpowned.rb6
-rw-r--r--spec/ruby/shared/file/identical.rb18
-rw-r--r--spec/ruby/shared/file/size.rb4
-rw-r--r--spec/ruby/shared/file/socket.rb32
-rw-r--r--spec/ruby/shared/file/sticky.rb2
-rw-r--r--spec/ruby/shared/file/world_readable.rb10
-rw-r--r--spec/ruby/shared/file/world_writable.rb10
-rw-r--r--spec/ruby/shared/file/writable_real.rb8
-rw-r--r--spec/ruby/shared/file/zero.rb10
-rw-r--r--spec/ruby/shared/hash/key_error.rb8
-rw-r--r--spec/ruby/shared/io/putc.rb10
-rw-r--r--spec/ruby/shared/kernel/at_exit.rb73
-rw-r--r--spec/ruby/shared/kernel/complex.rb133
-rw-r--r--spec/ruby/shared/kernel/equal.rb4
-rw-r--r--spec/ruby/shared/kernel/fixtures/END.rb3
-rw-r--r--spec/ruby/shared/kernel/fixtures/at_exit.rb3
-rw-r--r--spec/ruby/shared/kernel/object_id.rb30
-rw-r--r--spec/ruby/shared/kernel/raise.rb363
-rw-r--r--spec/ruby/shared/math/atanh.rb44
-rw-r--r--spec/ruby/shared/process/abort.rb12
-rw-r--r--spec/ruby/shared/process/exit.rb28
-rw-r--r--spec/ruby/shared/process/fork.rb39
-rw-r--r--spec/ruby/shared/queue/clear.rb4
-rw-r--r--spec/ruby/shared/queue/close.rb4
-rw-r--r--spec/ruby/shared/queue/closed.rb4
-rw-r--r--spec/ruby/shared/queue/deque.rb130
-rw-r--r--spec/ruby/shared/queue/empty.rb4
-rw-r--r--spec/ruby/shared/queue/enque.rb2
-rw-r--r--spec/ruby/shared/queue/freeze.rb8
-rw-r--r--spec/ruby/shared/rational/Rational.rb141
-rw-r--r--spec/ruby/shared/rational/abs.rb11
-rw-r--r--spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb11
-rw-r--r--spec/ruby/shared/rational/ceil.rb45
-rw-r--r--spec/ruby/shared/rational/coerce.rb34
-rw-r--r--spec/ruby/shared/rational/comparison.rb95
-rw-r--r--spec/ruby/shared/rational/denominator.rb14
-rw-r--r--spec/ruby/shared/rational/div.rb54
-rw-r--r--spec/ruby/shared/rational/divide.rb71
-rw-r--r--spec/ruby/shared/rational/divmod.rb42
-rw-r--r--spec/ruby/shared/rational/equal_value.rb39
-rw-r--r--spec/ruby/shared/rational/exponent.rb196
-rw-r--r--spec/ruby/shared/rational/fdiv.rb5
-rw-r--r--spec/ruby/shared/rational/floor.rb45
-rw-r--r--spec/ruby/shared/rational/hash.rb9
-rw-r--r--spec/ruby/shared/rational/inspect.rb14
-rw-r--r--spec/ruby/shared/rational/marshal_dump.rb5
-rw-r--r--spec/ruby/shared/rational/marshal_load.rb5
-rw-r--r--spec/ruby/shared/rational/modulo.rb43
-rw-r--r--spec/ruby/shared/rational/multiply.rb62
-rw-r--r--spec/ruby/shared/rational/numerator.rb10
-rw-r--r--spec/ruby/shared/rational/plus.rb48
-rw-r--r--spec/ruby/shared/rational/quo.rb5
-rw-r--r--spec/ruby/shared/rational/remainder.rb5
-rw-r--r--spec/ruby/shared/rational/round.rb106
-rw-r--r--spec/ruby/shared/rational/to_f.rb16
-rw-r--r--spec/ruby/shared/rational/to_i.rb12
-rw-r--r--spec/ruby/shared/rational/to_r.rb11
-rw-r--r--spec/ruby/shared/rational/to_s.rb14
-rw-r--r--spec/ruby/shared/rational/truncate.rb45
-rw-r--r--spec/ruby/shared/sizedqueue/enque.rb83
-rw-r--r--spec/ruby/shared/sizedqueue/max.rb10
-rw-r--r--spec/ruby/shared/sizedqueue/new.rb17
-rw-r--r--spec/ruby/shared/string/end_with.rb12
-rw-r--r--spec/ruby/shared/string/start_with.rb20
-rw-r--r--spec/ruby/shared/string/times.rb40
-rw-r--r--spec/ruby/shared/time/yday.rb18
-rw-r--r--spec/ruby/shared/types/rb_num2dbl_fails.rb17
-rw-r--r--spec/ruby/spec_helper.rb5
3748 files changed, 73544 insertions, 48334 deletions
diff --git a/spec/ruby/.mspec.constants b/spec/ruby/.mspec.constants
index 5dd477eb66..4da3633715 100644
--- a/spec/ruby/.mspec.constants
+++ b/spec/ruby/.mspec.constants
@@ -146,6 +146,7 @@ Prime
Private
ProcFromMethod
Psych
+RactorLocalSingleton
REXML
RUBY_SIGNALS
RbReadline
@@ -204,6 +205,7 @@ UserArray
UserCustomConstructorString
UserDefined
UserDefinedImmediate
+UserDefinedString
UserDefinedWithIvar
UserHash
UserHashInitParams
diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml
index 1200e9d7ce..0b5dcb80a2 100644
--- a/spec/ruby/.rubocop.yml
+++ b/spec/ruby/.rubocop.yml
@@ -1,13 +1,17 @@
inherit_from: .rubocop_todo.yml
AllCops:
- TargetRubyVersion: 2.7
+ TargetRubyVersion: 3.2
DisplayCopNames: true
Exclude:
- command_line/fixtures/bad_syntax.rb
+ - core/exception/fixtures/syntax_error.rb
DisabledByDefault: true
NewCops: disable
+Layout/IndentationConsistency:
+ Enabled: true
+
Layout/TrailingWhitespace:
Enabled: true
@@ -33,18 +37,29 @@ Lint/AssignmentInCondition:
Lint/BooleanSymbol:
Enabled: false
+Lint/DeprecatedOpenSSLConstant:
+ Exclude:
+ - library/openssl/digest/**/*.rb
+
Lint/InterpolationCheck:
Enabled: false
Lint/LiteralAsCondition:
Enabled: false
+# Required to support Ruby 3.0
Lint/RedundantRequireStatement:
- Enabled: false
+ Exclude:
+ - core/fiber/**/*.rb
+ - library/fiber/**/*.rb
+ - optional/capi/fiber_spec.rb
Lint/RedundantSplatExpansion:
Enabled: false
+Lint/RescueException:
+ Enabled: false
+
Lint/UnifiedInteger:
Enabled: false
@@ -102,6 +117,9 @@ Lint/OutOfRangeRegexpRef:
Lint/InheritException:
Enabled: false
+Lint/SafeNavigationChain:
+ Enabled: false
+
Lint/ElseLayout:
Exclude:
- 'language/if_spec.rb'
@@ -115,6 +133,10 @@ Lint/EmptyWhen:
- language/case_spec.rb
- optional/capi/spec_helper.rb
+Lint/ErbNewArguments:
+ Exclude:
+ - 'library/erb/new_spec.rb'
+
Lint/FormatParameterMismatch:
Exclude:
- 'core/kernel/shared/sprintf.rb'
@@ -161,6 +183,9 @@ Lint/Debugger:
Lint/Loop:
Enabled: false
+Style/BlockComments:
+ Enabled: true
+
Style/Lambda:
Enabled: true
EnforcedStyle: literal
@@ -168,6 +193,7 @@ Style/Lambda:
- 'language/lambda_spec.rb'
- 'language/proc_spec.rb'
- 'language/numbered_parameters_spec.rb'
+ - 'language/it_parameter_spec.rb'
- 'core/kernel/lambda_spec.rb'
Style/EmptyLambdaParameter:
diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml
index ac9cfae2bf..f998002c6d 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 2019-12-12 22:16:26 +0900 using RuboCop version 0.77.0.
+# on 2026-05-29 08:10:07 UTC using RuboCop version 1.86.2.
# 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
@@ -11,14 +11,20 @@ Lint/DuplicateCaseCondition:
Exclude:
- 'language/case_spec.rb'
-# Offense count: 6
+# Offense count: 20
Lint/DuplicateMethods:
Exclude:
- 'core/array/fixtures/encoded_strings.rb'
- 'core/method/fixtures/classes.rb'
+ - 'core/module/const_added_spec.rb'
+ - 'core/module/define_method_spec.rb'
- 'core/module/fixtures/classes.rb'
+ - 'core/module/method_added_spec.rb'
+ - 'core/module/name_spec.rb'
+ - 'core/proc/new_spec.rb'
- 'core/unboundmethod/fixtures/classes.rb'
- 'fixtures/class.rb'
+ - 'language/assignments_spec.rb'
# Offense count: 8
Lint/EnsureReturn:
@@ -38,9 +44,11 @@ Lint/FloatOutOfRange:
Exclude:
- 'core/string/modulo_spec.rb'
-# Offense count: 2
+# Offense count: 3
+# This cop supports safe autocorrection (--autocorrect).
Lint/ImplicitStringConcatenation:
Exclude:
+ - 'core/string/chilled_string_spec.rb'
- 'language/string_spec.rb'
# Offense count: 4
@@ -50,12 +58,11 @@ Lint/IneffectiveAccessModifier:
- 'core/module/fixtures/classes.rb'
- 'language/fixtures/private.rb'
-# Offense count: 72
-# Cop supports --auto-correct.
+# Offense count: 12
+# This cop supports safe autocorrection (--autocorrect).
Lint/LiteralInInterpolation:
Exclude:
- 'core/module/refine_spec.rb'
- - 'core/regexp/shared/new.rb'
- 'core/string/shared/to_sym.rb'
- 'language/alias_spec.rb'
- 'language/defined_spec.rb'
@@ -63,49 +70,41 @@ Lint/LiteralInInterpolation:
- 'language/string_spec.rb'
- 'language/symbol_spec.rb'
- 'language/undef_spec.rb'
- - 'library/net/ftp/connect_spec.rb'
# Offense count: 8
-# Cop supports --auto-correct.
+# This cop supports safe autocorrection (--autocorrect).
Lint/MultipleComparison:
Exclude:
- 'language/precedence_spec.rb'
# Offense count: 9
+# This cop supports safe autocorrection (--autocorrect).
Lint/ParenthesesAsGroupedExpression:
Exclude:
- - 'core/string/fixtures/freeze_magic_comment.rb'
- 'language/block_spec.rb'
- - 'language/fixtures/send.rb'
- 'language/method_spec.rb'
+# Offense count: 1
+# This cop supports unsafe autocorrection (--autocorrect-all).
+# Configuration parameters: AllowedMethods, InferNonNilReceiver, AdditionalNilMethods.
+# AllowedMethods: instance_of?, kind_of?, is_a?, eql?, respond_to?, equal?
+# AdditionalNilMethods: present?, blank?, try, try!
+Lint/RedundantSafeNavigation:
+ Exclude:
+ - 'language/safe_navigator_spec.rb'
+ - 'language/fixtures/rescue_captures.rb'
+
# Offense count: 2
-# Cop supports --auto-correct.
+# This cop supports safe autocorrection (--autocorrect).
Lint/RedundantStringCoercion:
Exclude:
- 'core/io/print_spec.rb'
# Offense count: 1
-# Cop supports --auto-correct.
-Lint/RedundantWithIndex:
- Exclude:
- - 'core/enumerator/with_index_spec.rb'
-
-# Offense count: 22
-Lint/RescueException:
- Exclude:
- - 'command_line/fixtures/debug_info.rb'
- - 'core/dir/fileno_spec.rb'
- - 'core/exception/cause_spec.rb'
- - 'core/exception/no_method_error_spec.rb'
- - 'core/kernel/fixtures/autoload_frozen.rb'
- - 'core/kernel/raise_spec.rb'
- - 'core/module/autoload_spec.rb'
- - 'core/mutex/sleep_spec.rb'
- - 'core/thread/abort_on_exception_spec.rb'
- - 'core/thread/shared/exit.rb'
- - 'language/rescue_spec.rb'
- - 'library/erb/filename_spec.rb'
+# Configuration parameters: AllowRBSInlineAnnotation.
+Lint/SelfAssignment:
+ Exclude:
+ - 'core/gc/auto_compact_spec.rb'
# Offense count: 4
# Configuration parameters: IgnoreImplicitReferences.
@@ -113,8 +112,8 @@ Lint/ShadowedArgument:
Exclude:
- 'language/fixtures/super.rb'
-# Offense count: 39
-# Configuration parameters: AllowComments.
+# Offense count: 49
+# Configuration parameters: AllowComments, AllowNil.
Lint/SuppressedException:
Enabled: false
@@ -126,7 +125,8 @@ Lint/UnderscorePrefixedVariableName:
- 'core/io/popen_spec.rb'
- 'language/block_spec.rb'
-# Offense count: 7
+# Offense count: 9
+# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
Lint/UselessAccessModifier:
Exclude:
@@ -134,4 +134,5 @@ Lint/UselessAccessModifier:
- 'core/module/fixtures/classes.rb'
- 'core/module/module_function_spec.rb'
- 'core/module/private_class_method_spec.rb'
+ - 'language/fixtures/def.rb'
- 'language/fixtures/send.rb'
diff --git a/spec/ruby/CONTRIBUTING.md b/spec/ruby/CONTRIBUTING.md
index 20258e5c36..a474e205f0 100644
--- a/spec/ruby/CONTRIBUTING.md
+++ b/spec/ruby/CONTRIBUTING.md
@@ -55,6 +55,11 @@ which indicates the file was generated but the method unspecified.
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.
+The general idea is: add `.should` just before the predicate you expect to be truthy, and done!
+This works for most needs and provides a great error when it fails.
+It's immediately clear which method is used and there no need to remember a mapping like in RSpec between e.g. `eq` and `==`.
+See [this blog post](https://eregon.me/blog/2019/10/07/a-new-should-syntax.html) for the motivation behind that syntax.
+
#### Comparison matchers
```ruby
@@ -83,43 +88,37 @@ File.should.equal?(File) # Calls #equal? (tests identity)
(0.1 + 0.2).should be_close(0.3, TOLERANCE) # (0.2-0.1).abs < TOLERANCE
(0.0/0.0).should.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.instance_of?(Float) # Calls #instance_of?
+3.14.should.is_a?(Numeric) # Calls #is_a?
3.14.should.respond_to?(:to_i)
-Integer.should have_instance_method(:+)
-Array.should have_method(:new)
+Integer.should.method_defined?(:+, false)
```
-Also `have_constant`, `have_private_instance_method`, `have_singleton_method`, etc.
-
#### Exception matchers
```ruby
-> {
raise "oops"
-}.should raise_error(RuntimeError, /oops/)
+}.should.raise(RuntimeError, /oops/)
-> {
raise "oops"
-}.should raise_error(RuntimeError) { |e|
+}.should.raise(RuntimeError) { |e|
# Custom checks on the Exception object
e.message.should.include?("oops")
e.cause.should == nil
}
```
-##### should_not raise_error
+##### `should_not.raise`
-**To avoid!** Instead, use an expectation testing what the code in the lambda does.
+**Avoid this!** Instead, use an expectation testing what the code in the lambda does.
If an exception is raised, it will fail the example anyway.
```ruby
--> { ... }.should_not raise_error
+-> { ... }.should_not.raise
```
#### Warning matcher
@@ -138,12 +137,12 @@ Here is a list of the most commonly-used guards:
#### Version guards
```ruby
-ruby_version_is ""..."2.6" do
- # Specs for RUBY_VERSION < 2.6
+ruby_version_is ""..."3.2" do
+ # Specs for RUBY_VERSION < 3.2
end
-ruby_version_is "2.6" do
- # Specs for RUBY_VERSION >= 2.6
+ruby_version_is "3.2" do
+ # Specs for RUBY_VERSION >= 3.2
end
```
@@ -164,7 +163,7 @@ end
platform_is_not :linux, :darwin do # Not Linux and not Darwin
end
-platform_is wordsize: 64 do
+platform_is pointer_size: 64 do
# 64-bit platform
end
@@ -175,9 +174,13 @@ end
#### Guard for bug
-In case there is a bug in MRI but the expected behavior is obvious.
+In case there is a bug in MRI and the fix will be backported to previous versions.
+If it is not backported or not likely, use `ruby_version_is` instead.
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.
+The problem is `ruby_bug` would make non-MRI implementations fail this spec while MRI itself does not pass it, so it should only be used if the bug is/will be fixed and backported.
+Otherwise, non-MRI implementations would have to choose between being incompatible with the latest release of MRI (which has the bug) to pass the spec, or behave the same as the latest release of MRI (which has the bug) and fail the spec, both which make no sense.
+
+IOW, `ruby_bug '#NN', ''...'X.Y' do` is equivalent to `guard_not { RUBY_ENGINE == "ruby" && ruby_version_is ''...'X.Y' } do`. So it skips tests on MRI on specified versions (where a bug is present) and runs tests on alternative implementations only.
```ruby
ruby_bug '#13669', ''...'3.2' do
@@ -190,11 +193,11 @@ end
#### Combining guards
```ruby
-guard -> { platform_is :windows and ruby_version_is ""..."2.6" } do
- # Windows and RUBY_VERSION < 2.6
+guard -> { platform_is :windows and ruby_version_is ""..."3.2" } do
+ # Windows and RUBY_VERSION < 3.2
end
-guard_not -> { platform_is :windows and ruby_version_is ""..."2.6" } do
+guard_not -> { platform_is :windows and ruby_version_is ""..."3.2" } do
# The opposite
end
```
@@ -226,7 +229,7 @@ to avoid duplication of specs, we have shared specs that are re-used in other sp
bit tricky however, so let's go over it.
Commonly, if a shared spec is only reused within its own module, the shared spec will live within a
-shared directory inside that module's directory. For example, the `core/hash/shared/key.rb` spec is
+shared directory inside that module's directory. For example, the `core/hash/shared/iteration.rb` spec is
only used by `Hash` specs, and so it lives inside `core/hash/shared/`.
When a shared spec is used across multiple modules or classes, it lives within the `shared/` directory.
@@ -240,25 +243,25 @@ variables from the implementor spec: `@method` and `@object`, which the implemen
Here's an example of a snippet of a shared spec and two specs which integrates it:
```ruby
-# core/hash/shared/key.rb
-describe :hash_key_p, shared: true do
- it "returns true if the key's matching value was false" do
- { xyz: false }.send(@method, :xyz).should == true
+# core/hash/shared/iteration.rb
+describe :hash_iteration_no_block, shared: true do
+ it "returns an Enumerator if called on a non-empty hash without a block" do
+ { 1 => 2 }.send(@method).should.instance_of?(Enumerator)
end
end
-# core/hash/key_spec.rb
-describe "Hash#key?" do
- it_behaves_like :hash_key_p, :key?
+# core/hash/select_spec.rb
+describe "Hash#select" do
+ it_behaves_like :hash_iteration_no_block, :select
end
-# core/hash/include_spec.rb
-describe "Hash#include?" do
- it_behaves_like :hash_key_p, :include?
+# core/hash/reject_spec.rb
+describe "Hash#reject" do
+ it_behaves_like :hash_iteration_no_block, :reject
end
```
-In the example, the first `describe` defines the shared spec `:hash_key_p`, which defines a spec that
+In the example, the first `describe` defines the shared spec `:hash_iteration_no_block`, which defines a spec that
calls the `@method` method with an expectation. In the implementor spec, we use `it_behaves_like` to
integrate the shared spec. `it_behaves_like` takes 3 parameters: the key of the shared spec, a method,
and an object. These last two parameters are accessible via `@method` and `@object` in the shared spec.
@@ -270,18 +273,18 @@ how this is used currently:
```ruby
describe :kernel_sprintf, shared: true do
it "raises TypeError exception if cannot convert to Integer" do
- -> { @method.call("%b", Object.new) }.should raise_error(TypeError)
+ -> { @method.call("%b", Object.new) }.should.raise(TypeError)
end
end
describe "Kernel#sprintf" do
- it_behaves_like :kernel_sprintf, -> (format, *args) {
+ it_behaves_like :kernel_sprintf, -> format, *args {
sprintf(format, *args)
}
end
describe "Kernel.sprintf" do
- it_behaves_like :kernel_sprintf, -> (format, *args) {
+ it_behaves_like :kernel_sprintf, -> format, *args {
Kernel.sprintf(format, *args)
}
end
diff --git a/spec/ruby/README.md b/spec/ruby/README.md
index 55b248a6c3..b259a97e21 100644
--- a/spec/ruby/README.md
+++ b/spec/ruby/README.md
@@ -1,7 +1,6 @@
# The Ruby Spec Suite
[![Actions Build Status](https://github.com/ruby/spec/workflows/CI/badge.svg)](https://github.com/ruby/spec/actions)
-[![Gitter](https://badges.gitter.im/ruby/spec.svg)](https://gitter.im/ruby/spec)
The Ruby Spec Suite, abbreviated `ruby/spec`, is a test suite for the behavior of the Ruby programming language.
@@ -27,16 +26,16 @@ ruby/spec is known to be tested in these implementations for every commit:
* [MRI](https://rubyci.org/) on 30 platforms and 4 versions
* [JRuby](https://github.com/jruby/jruby/tree/master/spec/ruby) for both 1.7 and 9.x
-* [TruffleRuby](https://github.com/oracle/truffleruby/tree/master/spec/ruby)
+* [TruffleRuby](https://github.com/truffleruby/truffleruby/tree/master/spec/ruby)
* [Opal](https://github.com/opal/opal/tree/master/spec)
* [Artichoke](https://github.com/artichoke/spec/tree/artichoke-vendor)
-ruby/spec describes the behavior of Ruby 2.7 and more recent Ruby versions.
-More precisely, every latest stable MRI release should [pass](https://github.com/ruby/spec/actions/workflows/ci.yml) all specs of ruby/spec (2.7.x, 3.0.x, 3.1.x, etc), and those are tested in CI.
+ruby/spec describes the behavior of Ruby 3.3 and more recent Ruby versions.
+More precisely, every latest stable MRI release should [pass](https://github.com/ruby/spec/actions/workflows/ci.yml) all specs of ruby/spec (3.3.x, 3.4.x, etc), and those are tested in CI.
### Synchronization with Ruby Implementations
-The specs are synchronized both ways around once a month by @eregon between ruby/spec, MRI, JRuby and TruffleRuby,
+The specs are synchronized both ways around once a month by @andrykonchin between ruby/spec, MRI, JRuby and TruffleRuby,
using [this script](https://github.com/ruby/mspec/blob/master/tool/sync/sync-rubyspec.rb).
Each of these repositories has a full copy of the specs under `spec/ruby` to ease editing specs.
Any of these repositories can be used to add or edit specs, use what is most convenient for you.
@@ -45,7 +44,7 @@ For *testing* the development version of a Ruby implementation, one should alway
Also, this repository doesn't always contain the latest spec changes from MRI (it's synchronized monthly), and does not contain tags (specs marked as failing on that Ruby implementation).
Running specs on a Ruby implementation can be done with:
-```
+```console
$ cd ruby_implementation/spec/ruby
# Add ../ruby_implementation/bin in PATH, or pass -t /path/to/bin/ruby
$ ../mspec/bin/mspec
@@ -62,6 +61,10 @@ For older specs try these commits:
* Ruby 2.4.10 - [Suite](https://github.com/ruby/spec/commit/bce4f2b81d6c31db67cf4d023a0625ceadde59bd) using [MSpec](https://github.com/ruby/mspec/commit/e7eb8aa4c26495b7b461e687d950b96eb08b3ff2)
* Ruby 2.5.9 - [Suite](https://github.com/ruby/spec/commit/c503335d3d9f6ec6ef24de60a0716c34af69b64f) using [MSpec](https://github.com/ruby/mspec/commit/0091e8a62e954717cd54641f935eaf1403692041)
* Ruby 2.6.10 - [Suite](https://github.com/ruby/spec/commit/aaf998fb8c92c4e63ad423a2e7ca6e6921818c6e) using [MSpec](https://github.com/ruby/mspec/commit/5e36c684e9e2b92b1187589bba1df22c640a8661)
+* Ruby 2.7.8 - [Suite](https://github.com/ruby/spec/commit/93787e6035c925b593a9c0c6fb0e7e07a6f1df1f) using [MSpec](https://github.com/ruby/mspec/commit/1d8cf64722d8a7529f7cd205be5f16a89b7a67fd)
+* Ruby 3.0.7 - [Suite](https://github.com/ruby/spec/commit/affef93d9940f615e4836f64b011da211f570913) using [MSpec](https://github.com/ruby/mspec/commit/0aabb3e548eb5ea6cad0125f8f46cee34542b6b7)
+* Ruby 3.1.6 - [Suite](https://github.com/ruby/spec/commit/ec960f2389d1c2265d32397fa8afa6d462014efc) using [MSpec](https://github.com/ruby/mspec/commit/484310dbed35b84c74484fd674602f88c42d063a)
+* Ruby 3.2.9 - [Suite](https://github.com/ruby/spec/commit/97f076242b7fc6e60703e6a6053365065cd6fc30) using [MSpec](https://github.com/ruby/mspec/commit/54704795e21128a930af2021c72c49cb87065134)
### Running the specs
@@ -128,6 +131,12 @@ MSpec can automatically add new top-level constants in this file with:
$ CHECK_LEAKS=save mspec ../mspec/bin/mspec file
+### Running Specs on S390x CPU Architecture
+
+Run the specs with `DFLTCC=0` if you see failing specs related to the zlib library on s390x CPU architecture. The failures can happen with the zlib library applying the patch madler/zlib#410 to enable the deflate algorithm producing a different compressed byte stream.
+
+ $ DFLTCC=0 ../mspec/bin/mspec
+
### Contributing and Writing Specs
See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md) for documentation about contributing and writing specs (guards, matchers, etc).
@@ -144,10 +153,9 @@ The file `/etc/services` is required for socket specs (package `netbase` on Debi
### Socket specs from rubysl-socket
-Most specs under `library/socket` were imported from [the rubysl-socket project](https://github.com/rubysl/rubysl-socket).
+Most specs under `library/socket` were imported from the rubysl-socket project (which is no longer on GitHub).
The 3 copyright holders of rubysl-socket, Yorick Peterse, Chuck Remes and
-Brian Shirai, [agreed to relicense those specs](https://github.com/rubysl/rubysl-socket/issues/15)
-under the MIT license in ruby/spec.
+Brian Shirai, agreed to relicense those specs under the MIT license in ruby/spec.
### History and RubySpec
diff --git a/spec/ruby/bin/rubocop b/spec/ruby/bin/rubocop
new file mode 100755
index 0000000000..0937c47906
--- /dev/null
+++ b/spec/ruby/bin/rubocop
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'bundler/inline'
+
+gemfile do
+ source 'https://rubygems.org'
+
+ gem 'rubocop', '1.86.2'
+end
+
+exec(Gem.bin_path('rubocop', 'rubocop'), *ARGV)
diff --git a/spec/ruby/command_line/backtrace_limit_spec.rb b/spec/ruby/command_line/backtrace_limit_spec.rb
index 56afa8efef..4d57bc268b 100644
--- a/spec/ruby/command_line/backtrace_limit_spec.rb
+++ b/spec/ruby/command_line/backtrace_limit_spec.rb
@@ -1,7 +1,7 @@
require_relative '../spec_helper'
-ruby_version_is "3.0" do
- describe "The --backtrace-limit command line option" do
+describe "The --backtrace-limit command line option" do
+ ruby_version_is ""..."3.4" do
it "limits top-level backtraces to a given number of entries" do
file = fixture(__FILE__ , "backtrace.rb")
out = ruby_exe(file, options: "--backtrace-limit=2", args: "top 2>&1", exit_status: 1)
@@ -45,4 +45,49 @@ backtrace
MSG
end
end
+
+ ruby_version_is "3.4" do
+ it "limits top-level backtraces to a given number of entries" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "top 2>&1", exit_status: 1)
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+top
+/fixtures/backtrace.rb:2:in 'Object#a': oops (RuntimeError)
+\tfrom /fixtures/backtrace.rb:6:in 'Object#b'
+\tfrom /fixtures/backtrace.rb:10:in 'Object#c'
+\t ... 2 levels...
+ MSG
+ end
+
+ it "affects Exception#full_message" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "full_message 2>&1")
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+full_message
+/fixtures/backtrace.rb:2:in 'Object#a': oops (RuntimeError)
+\tfrom /fixtures/backtrace.rb:6:in 'Object#b'
+\tfrom /fixtures/backtrace.rb:10:in 'Object#c'
+\t ... 2 levels...
+ MSG
+ end
+
+ it "does not affect Exception#backtrace" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "backtrace 2>&1")
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+backtrace
+/fixtures/backtrace.rb:2:in 'Object#a'
+/fixtures/backtrace.rb:6:in 'Object#b'
+/fixtures/backtrace.rb:10:in 'Object#c'
+/fixtures/backtrace.rb:14:in 'Object#d'
+/fixtures/backtrace.rb:29:in '<main>'
+ MSG
+ end
+ end
end
diff --git a/spec/ruby/command_line/dash_0_spec.rb b/spec/ruby/command_line/dash_0_spec.rb
new file mode 100755
index 0000000000..2ce4f49b5e
--- /dev/null
+++ b/spec/ruby/command_line/dash_0_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../spec_helper'
+
+describe "The -0 command line option" do
+ it "sets $/ and $-0" do
+ ruby_exe("puts $/, $-0", options: "-072").should == ":\n:\n"
+ end
+
+ ruby_version_is "4.0" do
+ it "sets $/ and $-0 as a frozen string" do
+ ruby_exe("puts $/.frozen?, $-0.frozen?", options: "-072").should == "true\ntrue\n"
+ end
+ end
+end
diff --git a/spec/ruby/command_line/dash_a_spec.rb b/spec/ruby/command_line/dash_a_spec.rb
index 9ea135dc76..43d923ce16 100644
--- a/spec/ruby/command_line/dash_a_spec.rb
+++ b/spec/ruby/command_line/dash_a_spec.rb
@@ -6,13 +6,13 @@ describe "The -a command line option" do
end
it "runs the code in loop conditional on Kernel.gets()" do
- ruby_exe("puts $F.last", options: "-n -a", escape: true,
+ ruby_exe("puts $F.last", options: "-n -a",
args: " < #{@names}").should ==
"jones\nfield\ngrey\n"
end
it "sets $-a" do
- ruby_exe("puts $-a", options: "-n -a", escape: true,
+ ruby_exe("puts $-a", options: "-n -a",
args: " < #{@names}").should ==
"true\ntrue\ntrue\n"
end
diff --git a/spec/ruby/command_line/dash_l_spec.rb b/spec/ruby/command_line/dash_l_spec.rb
index 5c1d3cf4cd..44a98445f3 100644
--- a/spec/ruby/command_line/dash_l_spec.rb
+++ b/spec/ruby/command_line/dash_l_spec.rb
@@ -6,25 +6,25 @@ describe "The -l command line option" do
end
it "chomps lines with default separator" do
- ruby_exe('puts $_.end_with?("\n")', options: "-n -l", escape: true,
+ ruby_exe('puts $_.end_with?("\n")', options: "-n -l",
args: " < #{@names}").should ==
"false\nfalse\nfalse\n"
end
it "chomps last line based on $/" do
- ruby_exe('BEGIN { $/ = "ones\n" }; puts $_', options: "-W0 -n -l", escape: true,
+ ruby_exe('BEGIN { $/ = "ones\n" }; puts $_', options: "-W0 -n -l",
args: " < #{@names}").should ==
"alice j\nbob field\njames grey\n"
end
it "sets $\\ to the value of $/" do
- ruby_exe("puts $\\ == $/", options: "-W0 -n -l", escape: true,
+ ruby_exe("puts $\\ == $/", options: "-W0 -n -l",
args: " < #{@names}").should ==
"true\ntrue\ntrue\n"
end
it "sets $-l" do
- ruby_exe("puts $-l", options: "-n -l", escape: true,
+ ruby_exe("puts $-l", options: "-n -l",
args: " < #{@names}").should ==
"true\ntrue\ntrue\n"
end
diff --git a/spec/ruby/command_line/dash_n_spec.rb b/spec/ruby/command_line/dash_n_spec.rb
index 9d331d6065..1dd9379259 100644
--- a/spec/ruby/command_line/dash_n_spec.rb
+++ b/spec/ruby/command_line/dash_n_spec.rb
@@ -6,19 +6,19 @@ describe "The -n command line option" do
end
it "runs the code in loop conditional on Kernel.gets()" do
- ruby_exe("puts $_", options: "-n", escape: true,
+ ruby_exe("puts $_", options: "-n",
args: " < #{@names}").should ==
"alice\nbob\njames\n"
end
it "only evaluates BEGIN blocks once" do
- ruby_exe("BEGIN { puts \"hi\" }; puts $_", options: "-n", escape: true,
+ ruby_exe("BEGIN { puts \"hi\" }; puts $_", options: "-n",
args: " < #{@names}").should ==
"hi\nalice\nbob\njames\n"
end
it "only evaluates END blocks once" do
- ruby_exe("puts $_; END {puts \"bye\"}", options: "-n", escape: true,
+ ruby_exe("puts $_; END {puts \"bye\"}", options: "-n",
args: " < #{@names}").should ==
"alice\nbob\njames\nbye\n"
end
@@ -29,7 +29,7 @@ describe "The -n command line option" do
$total += 1
END { puts $total }
script
- ruby_exe(script, options: "-n", escape: true,
+ ruby_exe(script, options: "-n",
args: " < #{@names}").should ==
"3\n"
end
diff --git a/spec/ruby/command_line/dash_p_spec.rb b/spec/ruby/command_line/dash_p_spec.rb
index 39827c3868..967e3796de 100644
--- a/spec/ruby/command_line/dash_p_spec.rb
+++ b/spec/ruby/command_line/dash_p_spec.rb
@@ -6,13 +6,13 @@ describe "The -p command line option" do
end
it "runs the code in loop conditional on Kernel.gets() and prints $_" do
- ruby_exe("$_ = $_.upcase", options: "-p", escape: true,
+ ruby_exe("$_ = $_.upcase", options: "-p",
args: " < #{@names}").should ==
"ALICE\nBOB\nJAMES\n"
end
it "sets $-p" do
- ruby_exe("$_ = $-p", options: "-p", escape: true,
+ ruby_exe("$_ = $-p", options: "-p",
args: " < #{@names}").should ==
"truetruetrue"
end
diff --git a/spec/ruby/command_line/dash_r_spec.rb b/spec/ruby/command_line/dash_r_spec.rb
index ea5bde5adf..0de9ba2e24 100644
--- a/spec/ruby/command_line/dash_r_spec.rb
+++ b/spec/ruby/command_line/dash_r_spec.rb
@@ -8,15 +8,15 @@ describe "The -r command line option" do
it "requires the specified file" do
out = ruby_exe(@script, options: "-r #{@test_file}")
- out.should include("REQUIRED")
- out.should include(@test_file + ".rb")
+ out.should.include?("REQUIRED")
+ out.should.include?(@test_file + ".rb")
end
it "requires the file before parsing the main script" do
out = ruby_exe(fixture(__FILE__, "bad_syntax.rb"), options: "-r #{@test_file}", args: "2>&1", exit_status: 1)
$?.should_not.success?
- out.should include("REQUIRED")
- out.should include("syntax error")
+ out.should.include?("REQUIRED")
+ out.should.include?("SyntaxError")
end
it "does not require the file if the main script file does not exist" do
diff --git a/spec/ruby/command_line/dash_upper_f_spec.rb b/spec/ruby/command_line/dash_upper_f_spec.rb
index 967acc2ece..5c10a7140d 100644
--- a/spec/ruby/command_line/dash_upper_f_spec.rb
+++ b/spec/ruby/command_line/dash_upper_f_spec.rb
@@ -6,7 +6,7 @@ describe "the -F command line option" do
end
it "specifies the field separator pattern for -a" do
- ruby_exe("puts $F[0]", options: "-naF:", escape: true,
+ ruby_exe("puts $F[0]", options: "-naF:",
args: " < #{@passwd}").should ==
"nobody\nroot\ndaemon\n"
end
diff --git a/spec/ruby/command_line/dash_upper_i_spec.rb b/spec/ruby/command_line/dash_upper_i_spec.rb
index 4cafb724e3..4005a27d23 100644
--- a/spec/ruby/command_line/dash_upper_i_spec.rb
+++ b/spec/ruby/command_line/dash_upper_i_spec.rb
@@ -6,7 +6,7 @@ describe "The -I command line option" do
end
it "adds the path to the load path ($:)" do
- ruby_exe(@script, options: "-I fixtures").should include("fixtures")
+ ruby_exe(@script, options: "-I fixtures").should.include?("fixtures")
end
it "adds the path at the front of $LOAD_PATH" do
@@ -18,16 +18,16 @@ describe "The -I command line option" do
idx.should < 2
idx.should < lines.size-1
else
- lines[0].should include("fixtures")
+ lines[0].should.include?("fixtures")
end
end
it "adds the path expanded from CWD to $LOAD_PATH" do
- ruby_exe(@script, options: "-I fixtures").lines.should include "#{Dir.pwd}/fixtures\n"
+ ruby_exe(@script, options: "-I fixtures").lines.should.include? "#{Dir.pwd}/fixtures\n"
end
it "expands a path from CWD even if it does not exist" do
- ruby_exe(@script, options: "-I not_exist/not_exist").lines.should include "#{Dir.pwd}/not_exist/not_exist\n"
+ ruby_exe(@script, options: "-I not_exist/not_exist").lines.should.include? "#{Dir.pwd}/not_exist/not_exist\n"
end
end
@@ -45,7 +45,7 @@ platform_is_not :windows do
end
it "does not expand symlinks" do
- ruby_exe(@script, options: "-I #{@symlink}").lines.should include "#{@symlink}\n"
+ ruby_exe(@script, options: "-I #{@symlink}").lines.should.include? "#{@symlink}\n"
end
end
end
diff --git a/spec/ruby/command_line/dash_upper_s_spec.rb b/spec/ruby/command_line/dash_upper_s_spec.rb
index 17991503f1..71c6016659 100644
--- a/spec/ruby/command_line/dash_upper_s_spec.rb
+++ b/spec/ruby/command_line/dash_upper_s_spec.rb
@@ -2,7 +2,8 @@ require_relative '../spec_helper'
describe 'The -S command line option' do
before :each do
- @path = [ENV['PATH'], fixture(__FILE__, "bin")].join(':')
+ @bin = fixture(__FILE__, "bin")
+ @path = [ENV['PATH'], @bin].join(File::PATH_SEPARATOR)
end
platform_is_not :windows do
@@ -10,20 +11,57 @@ describe 'The -S command line option' do
# and MRI shows warning when including world writable path in ENV['PATH'].
# This is why we are using /success$/ matching in the following cases.
+ it "runs launcher found in RUBYPATH, but only code after the first /\#!.*ruby.*/-ish line in target file" do
+ result = ruby_exe(nil, options: '-S hybrid_launcher.sh', env: { 'RUBYPATH' => @bin }, args: '2>&1')
+ result.should =~ /success$/
+ end
+
it "runs launcher found in PATH, but only code after the first /\#!.*ruby.*/-ish line in target file" do
result = ruby_exe(nil, options: '-S hybrid_launcher.sh', env: { 'PATH' => @path }, args: '2>&1')
result.should =~ /success$/
end
+ it "runs launcher found in RUBYPATH" do
+ result = ruby_exe(nil, options: '-S launcher.rb', env: { 'RUBYPATH' => @bin }, args: '2>&1')
+ result.should =~ /success$/
+ end
+
it "runs launcher found in PATH" do
result = ruby_exe(nil, options: '-S launcher.rb', env: { 'PATH' => @path }, args: '2>&1')
result.should =~ /success$/
end
+ it "runs launcher found in RUBYPATH and sets the exit status to 1 if it fails" do
+ result = ruby_exe(nil, options: '-S dash_s_fail', env: { 'RUBYPATH' => @bin }, args: '2>&1', exit_status: 1)
+ result.should =~ /\bdie\b/
+ $?.exitstatus.should == 1
+ end
+
it "runs launcher found in PATH and sets the exit status to 1 if it fails" do
result = ruby_exe(nil, options: '-S dash_s_fail', env: { 'PATH' => @path }, args: '2>&1', exit_status: 1)
result.should =~ /\bdie\b/
$?.exitstatus.should == 1
end
+
+ ruby_version_is "4.1" do
+ describe "if the script name contains separator" do
+ before(:each) do
+ @bin = File.dirname(@bin)
+ @path = [ENV['PATH'], @bin].join(File::PATH_SEPARATOR)
+ end
+
+ it "does not search launcher in RUBYPATH" do
+ result = ruby_exe(nil, options: '-S bin/launcher.rb', env: { 'RUBYPATH' => @bin }, args: '2>&1', exit_status: 1)
+ result.should =~ /LoadError/
+ $?.should_not.success?
+ end
+
+ it "does not search launcher in PATH" do
+ result = ruby_exe(nil, options: '-S bin/launcher.rb', env: { 'PATH' => @path }, args: '2>&1', exit_status: 1)
+ result.should =~ /LoadError/
+ $?.should_not.success?
+ end
+ end
+ end
end
end
diff --git a/spec/ruby/command_line/dash_upper_u_spec.rb b/spec/ruby/command_line/dash_upper_u_spec.rb
index d62718b095..2c210eb603 100644
--- a/spec/ruby/command_line/dash_upper_u_spec.rb
+++ b/spec/ruby/command_line/dash_upper_u_spec.rb
@@ -2,30 +2,37 @@ require_relative '../spec_helper'
describe "ruby -U" do
it "sets Encoding.default_internal to UTF-8" do
- ruby_exe('print Encoding.default_internal.name',
- options: '-U').should == 'UTF-8'
+ ruby_exe('print Encoding.default_internal.name',
+ options: '-U').should == 'UTF-8'
+ end
+
+ it "sets Encoding.default_internal to UTF-8 when RUBYOPT is empty or only spaces" do
+ ruby_exe('p Encoding.default_internal',
+ options: '-U', env: { 'RUBYOPT' => '' }).should == "#<Encoding:UTF-8>\n"
+ ruby_exe('p Encoding.default_internal',
+ options: '-U', env: { 'RUBYOPT' => ' ' }).should == "#<Encoding:UTF-8>\n"
end
it "does nothing different if specified multiple times" do
- ruby_exe('print Encoding.default_internal.name',
- options: '-U -U').should == 'UTF-8'
+ ruby_exe('print Encoding.default_internal.name',
+ options: '-U -U').should == 'UTF-8'
end
it "is overruled by Encoding.default_internal=" do
- ruby_exe('Encoding.default_internal="ascii"; print Encoding.default_internal.name',
- options: '-U').should == 'US-ASCII'
+ ruby_exe('Encoding.default_internal="ascii"; print Encoding.default_internal.name',
+ options: '-U').should == 'US-ASCII'
end
it "does not affect the default external encoding" do
- ruby_exe('Encoding.default_external="ascii"; print Encoding.default_external.name',
- options: '-U').should == 'US-ASCII'
+ ruby_exe('Encoding.default_external="ascii"; print Encoding.default_external.name',
+ options: '-U').should == 'US-ASCII'
end
it "does not affect the source encoding" do
- ruby_exe("print __ENCODING__.name",
- options: '-U -KE').should == 'EUC-JP'
- ruby_exe("print __ENCODING__.name",
- options: '-KE -U').should == 'EUC-JP'
+ ruby_exe("print __ENCODING__.name",
+ options: '-U -KE').should == 'EUC-JP'
+ ruby_exe("print __ENCODING__.name",
+ options: '-KE -U').should == 'EUC-JP'
end
# I assume IO redirection will break on Windows...
diff --git a/spec/ruby/command_line/dash_v_spec.rb b/spec/ruby/command_line/dash_v_spec.rb
index a4f4dcd051..6a4f7d3a15 100644
--- a/spec/ruby/command_line/dash_v_spec.rb
+++ b/spec/ruby/command_line/dash_v_spec.rb
@@ -6,8 +6,10 @@ describe "The -v command line option" do
describe "when used alone" do
it "prints version and ends" do
- ruby_exe(nil, args: '-v').should include(RUBY_DESCRIPTION)
+ ruby_exe(nil, args: '-v').gsub("+PRISM ", "").should.include?(RUBY_DESCRIPTION.gsub("+PRISM ", ""))
end unless (defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?) ||
- (defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?)
+ (defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?) ||
+ (ENV['RUBY_GC_LIBRARY'] && ENV['RUBY_GC_LIBRARY'].length > 0) ||
+ (ENV['RUBY_MN_THREADS'] == '1')
end
end
diff --git a/spec/ruby/command_line/dash_x_spec.rb b/spec/ruby/command_line/dash_x_spec.rb
index ae14b61070..38f97a5ab1 100644
--- a/spec/ruby/command_line/dash_x_spec.rb
+++ b/spec/ruby/command_line/dash_x_spec.rb
@@ -10,7 +10,7 @@ describe "The -x command line option" do
it "fails when /\#!.*ruby.*/-ish line in target file is not found" do
bad_embedded_ruby = fixture __FILE__, "bin/bad_embedded_ruby.txt"
result = ruby_exe(bad_embedded_ruby, options: '-x', args: '2>&1', exit_status: 1)
- result.should include "no Ruby script found in input"
+ result.should.include? "no Ruby script found in input"
end
it "behaves as -x was set when non-ruby shebang is encountered on first line" do
diff --git a/spec/ruby/command_line/error_message_spec.rb b/spec/ruby/command_line/error_message_spec.rb
index 02150f30ce..157cb8969c 100644
--- a/spec/ruby/command_line/error_message_spec.rb
+++ b/spec/ruby/command_line/error_message_spec.rb
@@ -8,4 +8,9 @@ describe "The error message caused by an exception" do
out = ruby_exe("end #syntax error", args: "2> #{File::NULL}", exit_status: 1)
out.chomp.should.empty?
end
+
+ it "is not modified with extra escaping of control characters and backslashes" do
+ out = ruby_exe('raise "\e[31mRed\e[0m error\\\\message"', args: "2>&1", exit_status: 1)
+ out.chomp.should.include?("\e[31mRed\e[0m error\\message")
+ end
end
diff --git a/spec/ruby/command_line/feature_spec.rb b/spec/ruby/command_line/feature_spec.rb
index 4a24cc6795..0a3252b88d 100644
--- a/spec/ruby/command_line/feature_spec.rb
+++ b/spec/ruby/command_line/feature_spec.rb
@@ -51,7 +51,7 @@ describe "The --enable and --disable flags" do
env = {'RUBYOPT' => '-w'}
# Use a single variant here because it can be quite slow as it might enable jit, etc
ruby_exe(e, options: "--enable-all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]"
- end
+ end unless defined?(RubyVM::YJIT) && defined?(RubyVM::ZJIT) && RubyVM::ZJIT.enabled? # You're not supposed to enable YJIT with --enable-all when ZJIT options are passed.
end
it "can be used with all for disable" do
@@ -62,10 +62,10 @@ describe "The --enable and --disable flags" do
end
it "prints a warning for unknown features" do
- ruby_exe("p 14", options: "--enable=ruby-spec-feature-does-not-exist 2>&1").chomp.should include('warning: unknown argument for --enable')
- ruby_exe("p 14", options: "--disable=ruby-spec-feature-does-not-exist 2>&1").chomp.should include('warning: unknown argument for --disable')
- ruby_exe("p 14", options: "--enable-ruby-spec-feature-does-not-exist 2>&1").chomp.should include('warning: unknown argument for --enable')
- ruby_exe("p 14", options: "--disable-ruby-spec-feature-does-not-exist 2>&1").chomp.should include('warning: unknown argument for --disable')
+ ruby_exe("p 14", options: "--enable=ruby-spec-feature-does-not-exist 2>&1").chomp.should.include?('warning: unknown argument for --enable')
+ ruby_exe("p 14", options: "--disable=ruby-spec-feature-does-not-exist 2>&1").chomp.should.include?('warning: unknown argument for --disable')
+ ruby_exe("p 14", options: "--enable-ruby-spec-feature-does-not-exist 2>&1").chomp.should.include?('warning: unknown argument for --enable')
+ ruby_exe("p 14", options: "--disable-ruby-spec-feature-does-not-exist 2>&1").chomp.should.include?('warning: unknown argument for --disable')
end
end
diff --git a/spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt b/spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt
index a2b7ad085f..61b946977a 100644
--- a/spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt
+++ b/spec/ruby/command_line/fixtures/bin/bad_embedded_ruby.txt
@@ -1,3 +1,3 @@
-@@@This line is not value Ruby
+@@@This line is not valid Ruby
#!rub_y
puts 'success'
diff --git a/spec/ruby/command_line/fixtures/bin/embedded_ruby.txt b/spec/ruby/command_line/fixtures/bin/embedded_ruby.txt
index c556bf0b71..0ec0f358db 100644
--- a/spec/ruby/command_line/fixtures/bin/embedded_ruby.txt
+++ b/spec/ruby/command_line/fixtures/bin/embedded_ruby.txt
@@ -1,3 +1,3 @@
-@@@This line is not value Ruby
+@@@This line is not valid Ruby
#!ruby
-puts 'success' \ No newline at end of file
+puts 'success'
diff --git a/spec/ruby/command_line/fixtures/debug_info.rb b/spec/ruby/command_line/fixtures/debug_info.rb
index ee607910c0..f02b041920 100644
--- a/spec/ruby/command_line/fixtures/debug_info.rb
+++ b/spec/ruby/command_line/fixtures/debug_info.rb
@@ -1,4 +1,3 @@
-# frozen_string_literal: true
a = 'string'
b = a
c = b
diff --git a/spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rb b/spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rb
index fa348d59e7..df4b952c46 100644
--- a/spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rb
+++ b/spec/ruby/command_line/fixtures/freeze_flag_required_diff_enc.rb
Binary files differ
diff --git a/spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb b/spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb
new file mode 100644
index 0000000000..fb84b546c0
--- /dev/null
+++ b/spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+frozen = "test".frozen?
+interned = "test".equal?("test")
+puts "frozen:#{frozen} interned:#{interned}"
diff --git a/spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb b/spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb
new file mode 100644
index 0000000000..381a742001
--- /dev/null
+++ b/spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: false
+frozen = "test".frozen?
+interned = "test".equal?("test")
+puts "frozen:#{frozen} interned:#{interned}"
diff --git a/spec/ruby/command_line/fixtures/string_literal_raw.rb b/spec/ruby/command_line/fixtures/string_literal_raw.rb
new file mode 100644
index 0000000000..56b1841296
--- /dev/null
+++ b/spec/ruby/command_line/fixtures/string_literal_raw.rb
@@ -0,0 +1,3 @@
+frozen = "test".frozen?
+interned = "test".equal?("test")
+puts "frozen:#{frozen} interned:#{interned}"
diff --git a/spec/ruby/command_line/frozen_strings_spec.rb b/spec/ruby/command_line/frozen_strings_spec.rb
index 647b69daed..32ff7d0371 100644
--- a/spec/ruby/command_line/frozen_strings_spec.rb
+++ b/spec/ruby/command_line/frozen_strings_spec.rb
@@ -19,11 +19,76 @@ describe "The --enable-frozen-string-literal flag causes string literals to" do
end
end
+describe "The --disable-frozen-string-literal flag causes string literals to" do
+
+ it "produce a different object each time" do
+ ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb"), options: "--disable-frozen-string-literal").chomp.should == "false"
+ end
+
+end
+
+describe "With neither --enable-frozen-string-literal nor --disable-frozen-string-literal flag set" do
+ before do
+ # disable --enable-frozen-string-literal and --disable-frozen-string-literal passed in $RUBYOPT
+ @rubyopt = ENV["RUBYOPT"]
+ ENV["RUBYOPT"] = ""
+ end
+
+ after do
+ ENV["RUBYOPT"] = @rubyopt
+ end
+
+ it "produce a different object each time" do
+ ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb")).chomp.should == "false"
+ end
+
+ context "if file has no frozen_string_literal comment" do
+ it "produce different mutable strings each time" do
+ ruby_exe(fixture(__FILE__, "string_literal_raw.rb")).chomp.should == "frozen:false interned:false"
+ end
+
+ guard -> { ruby_version_is "3.4" and !"test".frozen? } do
+ it "complain about modification of produced mutable strings" do
+ -> { eval(<<~RUBY) }.should complain(/warning: literal string will be frozen in the future \(run with --debug-frozen-string-literal for more information\)/)
+ "test" << "!"
+ RUBY
+ end
+
+ it "does not complain about modification if Warning[:deprecated] is false" do
+ deprecated = Warning[:deprecated]
+ Warning[:deprecated] = false
+ -> { eval(<<~RUBY) }.should_not complain
+ "test" << "!"
+ RUBY
+ ensure
+ Warning[:deprecated] = deprecated
+ end
+ end
+ end
+
+ it "if file has frozen_string_literal:true comment produce same frozen strings each time" do
+ ruby_exe(fixture(__FILE__, "string_literal_frozen_comment.rb")).chomp.should == "frozen:true interned:true"
+ end
+
+ it "if file has frozen_string_literal:false comment produce different mutable strings each time" do
+ ruby_exe(fixture(__FILE__, "string_literal_mutable_comment.rb")).chomp.should == "frozen:false interned:false"
+ end
+end
+
describe "The --debug flag produces" do
it "debugging info on attempted frozen string modification" do
- error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '--debug', args: "2>&1")
- error_str.should include("can't modify frozen String")
- error_str.should include("created at")
- error_str.should include("command_line/fixtures/debug_info.rb:2")
+ error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '--enable-frozen-string-literal --debug', args: "2>&1")
+ error_str.should.include?("can't modify frozen String")
+ error_str.should.include?("created at")
+ error_str.should.include?("command_line/fixtures/debug_info.rb:1")
+ end
+
+ guard -> { ruby_version_is "3.4" and !"test".frozen? } do
+ it "debugging info on mutating chilled string" do
+ error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '-w --debug', args: "2>&1")
+ error_str.should.include?("literal string will be frozen in the future")
+ error_str.should.include?("the string was created here")
+ error_str.should.include?("command_line/fixtures/debug_info.rb:1")
+ end
end
end
diff --git a/spec/ruby/command_line/rubylib_spec.rb b/spec/ruby/command_line/rubylib_spec.rb
index b45919b997..1bedd146e3 100644
--- a/spec/ruby/command_line/rubylib_spec.rb
+++ b/spec/ruby/command_line/rubylib_spec.rb
@@ -14,15 +14,15 @@ describe "The RUBYLIB environment variable" do
dir = tmp("rubylib/incl")
ENV["RUBYLIB"] = @pre + dir
paths = ruby_exe("puts $LOAD_PATH").lines.map(&:chomp)
- paths.should include(dir)
+ paths.should.include?(dir)
end
it "adds a File::PATH_SEPARATOR-separated list of directories to $LOAD_PATH" do
dir1, dir2 = tmp("rubylib/incl1"), tmp("rubylib/incl2")
ENV["RUBYLIB"] = @pre + "#{dir1}#{File::PATH_SEPARATOR}#{dir2}"
paths = ruby_exe("puts $LOAD_PATH").lines.map(&:chomp)
- paths.should include(dir1)
- paths.should include(dir2)
+ paths.should.include?(dir1)
+ paths.should.include?(dir2)
paths.index(dir1).should < paths.index(dir2)
end
@@ -46,8 +46,8 @@ describe "The RUBYLIB environment variable" do
rubylib_dir = tmp("rubylib_include")
ENV["RUBYLIB"] = @pre + rubylib_dir
paths = ruby_exe("puts $LOAD_PATH", options: "-I #{dash_i_dir}").lines.map(&:chomp)
- paths.should include(dash_i_dir)
- paths.should include(rubylib_dir)
+ paths.should.include?(dash_i_dir)
+ paths.should.include?(rubylib_dir)
paths.index(dash_i_dir).should < paths.index(rubylib_dir)
end
@@ -56,14 +56,14 @@ describe "The RUBYLIB environment variable" do
rubylib_dir = tmp("rubylib_include")
ENV["RUBYLIB"] = @pre + rubylib_dir
paths = ruby_exe("puts $LOAD_PATH", env: { "RUBYOPT" => "-I#{rubyopt_dir}" }).lines.map(&:chomp)
- paths.should include(rubyopt_dir)
- paths.should include(rubylib_dir)
+ paths.should.include?(rubyopt_dir)
+ paths.should.include?(rubylib_dir)
paths.index(rubyopt_dir).should < paths.index(rubylib_dir)
end
it "keeps spaces in the value" do
ENV["RUBYLIB"] = @pre + " rubylib/incl "
out = ruby_exe("puts $LOAD_PATH")
- out.should include(" rubylib/incl ")
+ out.should.include?(" rubylib/incl ")
end
end
diff --git a/spec/ruby/command_line/rubyopt_spec.rb b/spec/ruby/command_line/rubyopt_spec.rb
index bbea4d557d..eb297cd6fe 100644
--- a/spec/ruby/command_line/rubyopt_spec.rb
+++ b/spec/ruby/command_line/rubyopt_spec.rb
@@ -11,52 +11,52 @@ describe "Processing RUBYOPT" do
it "adds the -I path to $LOAD_PATH" do
ENV["RUBYOPT"] = "-Ioptrubyspecincl"
- result = ruby_exe("puts $LOAD_PATH.grep(/byspecin/)", escape: true)
+ result = ruby_exe("puts $LOAD_PATH.grep(/byspecin/)")
result.chomp[-15..-1].should == "optrubyspecincl"
end
it "sets $DEBUG to true for '-d'" do
ENV["RUBYOPT"] = '-d'
command = %[puts "value of $DEBUG is \#{$DEBUG}"]
- result = ruby_exe(command, escape: true, args: "2>&1")
+ result = ruby_exe(command, args: "2>&1")
result.should =~ /value of \$DEBUG is true/
end
- guard -> { not CROSS_COMPILING } do
+ guard -> { RbConfig::CONFIG["CROSS_COMPILING"] != "yes" } do
it "prints the version number for '-v'" do
ENV["RUBYOPT"] = '-v'
- ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION
+ ruby_exe("")[/\A.*/].gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "")
end
it "ignores whitespace around the option" do
ENV["RUBYOPT"] = ' -v '
- ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION
+ ruby_exe("")[/\A.*/].gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "")
end
end
it "sets $VERBOSE to true for '-w'" do
ENV["RUBYOPT"] = '-w'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "true"
+ ruby_exe("p $VERBOSE").chomp.should == "true"
end
it "sets $VERBOSE to true for '-W'" do
ENV["RUBYOPT"] = '-W'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "true"
+ ruby_exe("p $VERBOSE").chomp.should == "true"
end
it "sets $VERBOSE to nil for '-W0'" do
ENV["RUBYOPT"] = '-W0'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "nil"
+ ruby_exe("p $VERBOSE").chomp.should == "nil"
end
it "sets $VERBOSE to false for '-W1'" do
ENV["RUBYOPT"] = '-W1'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "false"
+ ruby_exe("p $VERBOSE").chomp.should == "false"
end
it "sets $VERBOSE to true for '-W2'" do
ENV["RUBYOPT"] = '-W2'
- ruby_exe("p $VERBOSE", escape: true).chomp.should == "true"
+ ruby_exe("p $VERBOSE").chomp.should == "true"
end
it "suppresses deprecation warnings for '-W:no-deprecated'" do
diff --git a/spec/ruby/command_line/syntax_error_spec.rb b/spec/ruby/command_line/syntax_error_spec.rb
index 444ea9635c..88864c048e 100644
--- a/spec/ruby/command_line/syntax_error_spec.rb
+++ b/spec/ruby/command_line/syntax_error_spec.rb
@@ -3,11 +3,11 @@ require_relative '../spec_helper'
describe "The interpreter" do
it "prints an error when given a file with invalid syntax" do
out = ruby_exe(fixture(__FILE__, "bad_syntax.rb"), args: "2>&1", exit_status: 1)
- out.should include "syntax error"
+ out.should.include?("SyntaxError")
end
it "prints an error when given code via -e with invalid syntax" do
out = ruby_exe(nil, args: "-e 'a{' 2>&1", exit_status: 1)
- out.should include "syntax error"
+ out.should.include?("SyntaxError")
end
end
diff --git a/spec/ruby/core/argf/argf_spec.rb b/spec/ruby/core/argf/argf_spec.rb
index af67170b98..f9468539bb 100644
--- a/spec/ruby/core/argf/argf_spec.rb
+++ b/spec/ruby/core/argf/argf_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "ARGF" do
it "is extended by the Enumerable module" do
- ARGF.should be_kind_of(Enumerable)
+ ARGF.should.is_a?(Enumerable)
end
it "is an instance of ARGF.class" do
- ARGF.should be_an_instance_of(ARGF.class)
+ ARGF.should.instance_of?(ARGF.class)
end
end
diff --git a/spec/ruby/core/argf/argv_spec.rb b/spec/ruby/core/argf/argv_spec.rb
index eab03c450f..77dfe78c21 100644
--- a/spec/ruby/core/argf/argv_spec.rb
+++ b/spec/ruby/core/argf/argv_spec.rb
@@ -7,7 +7,7 @@ describe "ARGF.argv" do
end
it "returns ARGV for the initial ARGF" do
- ARGF.argv.should equal ARGV
+ ARGF.argv.should.equal? ARGV
end
it "returns the remaining arguments to treat" do
diff --git a/spec/ruby/core/argf/binmode_spec.rb b/spec/ruby/core/argf/binmode_spec.rb
index e083a30a27..5288e3199d 100644
--- a/spec/ruby/core/argf/binmode_spec.rb
+++ b/spec/ruby/core/argf/binmode_spec.rb
@@ -9,7 +9,7 @@ describe "ARGF.binmode" do
it "returns self" do
argf [@bin_file] do
- @argf.binmode.should equal @argf
+ @argf.binmode.should.equal? @argf
end
end
diff --git a/spec/ruby/core/argf/bytes_spec.rb b/spec/ruby/core/argf/bytes_spec.rb
deleted file mode 100644
index bf35ded1db..0000000000
--- a/spec/ruby/core/argf/bytes_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/each_byte'
-
-ruby_version_is ''...'3.0' do
- describe "ARGF.bytes" do
- before :each do
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- end
-
- it_behaves_like :argf_each_byte, :bytes
- end
-end
diff --git a/spec/ruby/core/argf/chars_spec.rb b/spec/ruby/core/argf/chars_spec.rb
deleted file mode 100644
index 6af73cdabb..0000000000
--- a/spec/ruby/core/argf/chars_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/each_char'
-
-ruby_version_is ''...'3.0' do
- describe "ARGF.chars" do
- before :each do
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- end
-
- it_behaves_like :argf_each_char, :chars
- end
-end
diff --git a/spec/ruby/core/argf/close_spec.rb b/spec/ruby/core/argf/close_spec.rb
index d4d6a51e72..8ca7d71dc2 100644
--- a/spec/ruby/core/argf/close_spec.rb
+++ b/spec/ruby/core/argf/close_spec.rb
@@ -10,20 +10,20 @@ describe "ARGF.close" do
argf [@file1_name, @file2_name] do
io = @argf.to_io
@argf.close
- io.closed?.should be_true
+ io.closed?.should == true
end
end
it "returns self" do
argf [@file1_name, @file2_name] do
- @argf.close.should equal(@argf)
+ @argf.close.should.equal?(@argf)
end
end
it "doesn't raise an IOError if called on a closed stream" do
argf [@file1_name] do
- -> { @argf.close }.should_not raise_error
- -> { @argf.close }.should_not raise_error
+ -> { @argf.close }.should_not.raise
+ -> { @argf.close }.should_not.raise
end
end
end
diff --git a/spec/ruby/core/argf/closed_spec.rb b/spec/ruby/core/argf/closed_spec.rb
index e2dd6134e5..769381e8c3 100644
--- a/spec/ruby/core/argf/closed_spec.rb
+++ b/spec/ruby/core/argf/closed_spec.rb
@@ -11,7 +11,7 @@ describe "ARGF.closed?" do
stream = @argf.to_io
stream.close
- @argf.closed?.should be_true
+ @argf.closed?.should == true
stream.reopen(@argf.filename, 'r')
end
end
diff --git a/spec/ruby/core/argf/codepoints_spec.rb b/spec/ruby/core/argf/codepoints_spec.rb
deleted file mode 100644
index bb28c17fbb..0000000000
--- a/spec/ruby/core/argf/codepoints_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/each_codepoint'
-
-ruby_version_is ''...'3.0' do
- describe "ARGF.codepoints" do
- before :each do
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- end
-
- it_behaves_like :argf_each_codepoint, :codepoints
- end
-end
diff --git a/spec/ruby/core/argf/each_byte_spec.rb b/spec/ruby/core/argf/each_byte_spec.rb
index c5cce9f250..d9e4e7fe5b 100644
--- a/spec/ruby/core/argf/each_byte_spec.rb
+++ b/spec/ruby/core/argf/each_byte_spec.rb
@@ -1,6 +1,60 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_byte'
describe "ARGF.each_byte" do
- it_behaves_like :argf_each_byte, :each_byte
+ before :each do
+ @file1_name = fixture __FILE__, "file1.txt"
+ @file2_name = fixture __FILE__, "file2.txt"
+
+ @bytes = []
+ File.read(@file1_name).each_byte { |b| @bytes << b }
+ File.read(@file2_name).each_byte { |b| @bytes << b }
+ end
+
+ it "yields each byte of all streams to the passed block" do
+ argf [@file1_name, @file2_name] do
+ bytes = []
+ @argf.each_byte { |b| bytes << b }
+ bytes.should == @bytes
+ end
+ end
+
+ it "returns self when passed a block" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_byte {}.should.equal?(@argf)
+ end
+ end
+
+ it "returns an Enumerator when passed no block" do
+ argf [@file1_name, @file2_name] do
+ enum = @argf.each_byte
+ enum.should.instance_of?(Enumerator)
+
+ bytes = []
+ enum.each { |b| bytes << b }
+ bytes.should == @bytes
+ end
+ end
+
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ argf [@file1_name, @file2_name] do
+ enum = @argf.each_byte
+ enum.should.instance_of?(Enumerator)
+
+ bytes = []
+ enum.each { |b| bytes << b }
+ bytes.should == @bytes
+ end
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_byte.size.should == nil
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/argf/each_char_spec.rb b/spec/ruby/core/argf/each_char_spec.rb
index 724e5e6e3e..62d19b6574 100644
--- a/spec/ruby/core/argf/each_char_spec.rb
+++ b/spec/ruby/core/argf/each_char_spec.rb
@@ -1,6 +1,60 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_char'
describe "ARGF.each_char" do
- it_behaves_like :argf_each_char, :each_char
+ before :each do
+ @file1_name = fixture __FILE__, "file1.txt"
+ @file2_name = fixture __FILE__, "file2.txt"
+
+ @chars = []
+ File.read(@file1_name).each_char { |c| @chars << c }
+ File.read(@file2_name).each_char { |c| @chars << c }
+ end
+
+ it "yields each char of all streams to the passed block" do
+ argf [@file1_name, @file2_name] do
+ chars = []
+ @argf.each_char { |c| chars << c }
+ chars.should == @chars
+ end
+ end
+
+ it "returns self when passed a block" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_char {}.should.equal?(@argf)
+ end
+ end
+
+ it "returns an Enumerator when passed no block" do
+ argf [@file1_name, @file2_name] do
+ enum = @argf.each_char
+ enum.should.instance_of?(Enumerator)
+
+ chars = []
+ enum.each { |c| chars << c }
+ chars.should == @chars
+ end
+ end
+
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ argf [@file1_name, @file2_name] do
+ enum = @argf.each_char
+ enum.should.instance_of?(Enumerator)
+
+ chars = []
+ enum.each { |c| chars << c }
+ chars.should == @chars
+ end
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_char.size.should == nil
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/argf/each_codepoint_spec.rb b/spec/ruby/core/argf/each_codepoint_spec.rb
index 0bf8bf9764..ad55785cba 100644
--- a/spec/ruby/core/argf/each_codepoint_spec.rb
+++ b/spec/ruby/core/argf/each_codepoint_spec.rb
@@ -1,6 +1,60 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_codepoint'
describe "ARGF.each_codepoint" do
- it_behaves_like :argf_each_codepoint, :each_codepoint
+ before :each do
+ file1_name = fixture __FILE__, "file1.txt"
+ file2_name = fixture __FILE__, "file2.txt"
+ @filenames = [file1_name, file2_name]
+
+ @codepoints = File.read(file1_name).codepoints
+ @codepoints.concat File.read(file2_name).codepoints
+ end
+
+ it "is a public method" do
+ argf @filenames do
+ @argf.public_methods(false).should.include?(:each_codepoint)
+ end
+ end
+
+ it "does not require arguments" do
+ argf @filenames do
+ @argf.method(:each_codepoint).arity.should == 0
+ end
+ end
+
+ it "returns self when passed a block" do
+ argf @filenames do
+ @argf.each_codepoint {}.should.equal?(@argf)
+ end
+ end
+
+ it "returns an Enumerator when passed no block" do
+ argf @filenames do
+ @argf.each_codepoint.should.instance_of?(Enumerator)
+ end
+ end
+
+ it "yields each codepoint of all streams" do
+ argf @filenames do
+ @argf.each_codepoint.to_a.should == @codepoints
+ end
+ end
+
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ argf @filenames do
+ @argf.each_codepoint.should.instance_of?(Enumerator)
+ end
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ argf @filenames do
+ @argf.each_codepoint.size.should == nil
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/argf/each_line_spec.rb b/spec/ruby/core/argf/each_line_spec.rb
index 52a7e5c411..fc4d6433b8 100644
--- a/spec/ruby/core/argf/each_line_spec.rb
+++ b/spec/ruby/core/argf/each_line_spec.rb
@@ -1,6 +1,64 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_line'
describe "ARGF.each_line" do
- it_behaves_like :argf_each_line, :each_line
+ before :each do
+ @file1_name = fixture __FILE__, "file1.txt"
+ @file2_name = fixture __FILE__, "file2.txt"
+
+ @lines = File.readlines @file1_name
+ @lines += File.readlines @file2_name
+ end
+
+ it "is a public method" do
+ argf [@file1_name, @file2_name] do
+ @argf.public_methods(false).should.include?(:each_line)
+ end
+ end
+
+ it "requires multiple arguments" do
+ argf [@file1_name, @file2_name] do
+ @argf.method(:each_line).arity.should < 0
+ end
+ end
+
+ it "reads each line of files" do
+ argf [@file1_name, @file2_name] do
+ lines = []
+ @argf.each_line { |b| lines << b }
+ lines.should == @lines
+ end
+ end
+
+ it "returns self when passed a block" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_line {}.should.equal?(@argf)
+ end
+ end
+
+ describe "with a separator" do
+ it "yields each separated section of all streams" do
+ argf [@file1_name, @file2_name] do
+ @argf.send(:each_line, '.').to_a.should ==
+ (File.readlines(@file1_name, '.') + File.readlines(@file2_name, '.'))
+ end
+ end
+ end
+
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_line.should.instance_of?(Enumerator)
+ end
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ argf [@file1_name, @file2_name] do
+ @argf.each_line.size.should == nil
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/argf/each_spec.rb b/spec/ruby/core/argf/each_spec.rb
index 5742ba43bd..25f60b31d2 100644
--- a/spec/ruby/core/argf/each_spec.rb
+++ b/spec/ruby/core/argf/each_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/each_line'
describe "ARGF.each" do
- it_behaves_like :argf_each_line, :each
+ it "is an alias of ARGF.each_line" do
+ ARGF.method(:each).should == ARGF.method(:each_line)
+ end
end
diff --git a/spec/ruby/core/argf/eof_spec.rb b/spec/ruby/core/argf/eof_spec.rb
index 518f6e566e..940d104d69 100644
--- a/spec/ruby/core/argf/eof_spec.rb
+++ b/spec/ruby/core/argf/eof_spec.rb
@@ -1,10 +1,32 @@
require_relative '../../spec_helper'
-require_relative 'shared/eof'
describe "ARGF.eof" do
- it_behaves_like :argf_eof, :eof
+ it "is an alias of ARGF.eof?" do
+ ARGF.method(:eof).should == ARGF.method(:eof?)
+ end
end
describe "ARGF.eof?" do
- it_behaves_like :argf_eof, :eof?
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+ end
+
+ # NOTE: this test assumes that fixtures files have two lines each
+ it "returns true when reaching the end of a file" do
+ argf [@file1, @file2] do
+ result = []
+ while @argf.gets
+ result << @argf.eof?
+ end
+ result.should == [false, true, false, true]
+ end
+ end
+
+ it "raises IOError when called on a closed stream" do
+ argf [@file1] do
+ @argf.read
+ -> { @argf.eof? }.should.raise(IOError)
+ end
+ end
end
diff --git a/spec/ruby/core/argf/filename_spec.rb b/spec/ruby/core/argf/filename_spec.rb
index 7c0446269d..f4b6e922c6 100644
--- a/spec/ruby/core/argf/filename_spec.rb
+++ b/spec/ruby/core/argf/filename_spec.rb
@@ -1,6 +1,30 @@
require_relative '../../spec_helper'
-require_relative 'shared/filename'
describe "ARGF.filename" do
- it_behaves_like :argf_filename, :filename
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+ end
+
+ # NOTE: this test assumes that fixtures files have two lines each
+ it "returns the current file name on each file" do
+ argf [@file1, @file2] do
+ result = []
+ # returns first current file even when not yet open
+ result << @argf.filename
+ result << @argf.filename while @argf.gets
+ # returns last current file even when closed
+ result << @argf.filename
+
+ result.map! { |f| File.expand_path(f) }
+ result.should == [@file1, @file1, @file1, @file2, @file2, @file2]
+ end
+ end
+
+ # NOTE: this test assumes that fixtures files have two lines each
+ it "sets the $FILENAME global variable with the current file name on each file" do
+ script = fixture __FILE__, "filename.rb"
+ out = ruby_exe(script, args: [@file1, @file2])
+ out.should == "#{@file1}\n#{@file1}\n#{@file2}\n#{@file2}\n#{@file2}\n"
+ end
end
diff --git a/spec/ruby/core/argf/fileno_spec.rb b/spec/ruby/core/argf/fileno_spec.rb
index 29d50c3582..99245f043c 100644
--- a/spec/ruby/core/argf/fileno_spec.rb
+++ b/spec/ruby/core/argf/fileno_spec.rb
@@ -1,6 +1,26 @@
require_relative '../../spec_helper'
-require_relative 'shared/fileno'
describe "ARGF.fileno" do
- it_behaves_like :argf_fileno, :fileno
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+ end
+
+ # NOTE: this test assumes that fixtures files have two lines each
+ it "returns the current file number on each file" do
+ argf [@file1, @file2] do
+ result = []
+ # returns first current file even when not yet open
+ result << @argf.fileno while @argf.gets
+ # returns last current file even when closed
+ result.map { |d| d.class }.should == [Integer, Integer, Integer, Integer]
+ end
+ end
+
+ it "raises an ArgumentError when called on a closed stream" do
+ argf [@file1] do
+ @argf.read
+ -> { @argf.fileno }.should.raise(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/argf/inspect_spec.rb b/spec/ruby/core/argf/inspect_spec.rb
new file mode 100644
index 0000000000..df0e3ba8dc
--- /dev/null
+++ b/spec/ruby/core/argf/inspect_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../../spec_helper'
+
+describe "ARGF.inspect" do
+ it "is an alias of ARGF.to_s" do
+ ARGF.method(:inspect).should == ARGF.method(:to_s)
+ end
+end
diff --git a/spec/ruby/core/argf/lines_spec.rb b/spec/ruby/core/argf/lines_spec.rb
deleted file mode 100644
index e964dbd0d3..0000000000
--- a/spec/ruby/core/argf/lines_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/each_line'
-
-ruby_version_is ''...'3.0' do
- describe "ARGF.lines" do
- before :each do
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- end
-
- it_behaves_like :argf_each_line, :lines
- end
-end
diff --git a/spec/ruby/core/argf/path_spec.rb b/spec/ruby/core/argf/path_spec.rb
index 7120f7d0e3..2f7b91999f 100644
--- a/spec/ruby/core/argf/path_spec.rb
+++ b/spec/ruby/core/argf/path_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/filename'
describe "ARGF.path" do
- it_behaves_like :argf_filename, :path
+ it "is an alias of ARGF.filename" do
+ ARGF.method(:path).should == ARGF.method(:filename)
+ end
end
diff --git a/spec/ruby/core/argf/pos_spec.rb b/spec/ruby/core/argf/pos_spec.rb
index fb3f25b945..1ff16e4f17 100644
--- a/spec/ruby/core/argf/pos_spec.rb
+++ b/spec/ruby/core/argf/pos_spec.rb
@@ -1,8 +1,35 @@
require_relative '../../spec_helper'
-require_relative 'shared/pos'
describe "ARGF.pos" do
- it_behaves_like :argf_pos, :pos
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+ end
+
+ it "gives the correct position for each read operation" do
+ argf [@file1, @file2] do
+ size1 = File.size(@file1)
+ size2 = File.size(@file2)
+
+ @argf.read(2)
+ @argf.pos.should == 2
+ @argf.read(size1-2)
+ @argf.pos.should == size1
+ @argf.read(6)
+ @argf.pos.should == 6
+ @argf.rewind
+ @argf.pos.should == 0
+ @argf.read(size2)
+ @argf.pos.should == size2
+ end
+ end
+
+ it "raises an ArgumentError when called on a closed stream" do
+ argf [@file1] do
+ @argf.read
+ -> { @argf.pos }.should.raise(ArgumentError)
+ end
+ end
end
describe "ARGF.pos=" do
diff --git a/spec/ruby/core/argf/read_nonblock_spec.rb b/spec/ruby/core/argf/read_nonblock_spec.rb
index 804a459a62..5c6bd52d80 100644
--- a/spec/ruby/core/argf/read_nonblock_spec.rb
+++ b/spec/ruby/core/argf/read_nonblock_spec.rb
@@ -66,7 +66,7 @@ platform_is_not :windows do
argf ['-'] do
-> {
@argf.read_nonblock(4)
- }.should raise_error(IO::EAGAINWaitReadable)
+ }.should.raise(IO::EAGAINWaitReadable)
end
end
diff --git a/spec/ruby/core/argf/readchar_spec.rb b/spec/ruby/core/argf/readchar_spec.rb
index 4eca2efcf7..63632721ec 100644
--- a/spec/ruby/core/argf/readchar_spec.rb
+++ b/spec/ruby/core/argf/readchar_spec.rb
@@ -13,7 +13,7 @@ describe "ARGF.readchar" do
it "raises EOFError when end of stream reached" do
argf [@file1, @file2] do
- -> { while @argf.readchar; end }.should raise_error(EOFError)
+ -> { while @argf.readchar; end }.should.raise(EOFError)
end
end
end
diff --git a/spec/ruby/core/argf/readline_spec.rb b/spec/ruby/core/argf/readline_spec.rb
index db53c499e9..8c23549b1b 100644
--- a/spec/ruby/core/argf/readline_spec.rb
+++ b/spec/ruby/core/argf/readline_spec.rb
@@ -17,7 +17,7 @@ describe "ARGF.readline" do
it "raises an EOFError when reaching end of files" do
argf [@file1, @file2] do
- -> { while @argf.readline; end }.should raise_error(EOFError)
+ -> { while @argf.readline; end }.should.raise(EOFError)
end
end
end
diff --git a/spec/ruby/core/argf/readlines_spec.rb b/spec/ruby/core/argf/readlines_spec.rb
index 30be936dab..156bb6a33f 100644
--- a/spec/ruby/core/argf/readlines_spec.rb
+++ b/spec/ruby/core/argf/readlines_spec.rb
@@ -1,6 +1,24 @@
require_relative '../../spec_helper'
-require_relative 'shared/readlines'
describe "ARGF.readlines" do
- it_behaves_like :argf_readlines, :readlines
+ before :each do
+ @file1 = fixture __FILE__, "file1.txt"
+ @file2 = fixture __FILE__, "file2.txt"
+
+ @lines = File.readlines(@file1)
+ @lines += File.readlines(@file2)
+ end
+
+ it "reads all lines of all files" do
+ argf [@file1, @file2] do
+ @argf.readlines.should == @lines
+ end
+ end
+
+ it "returns an empty Array when end of stream reached" do
+ argf [@file1, @file2] do
+ @argf.read
+ @argf.readlines.should == []
+ end
+ end
end
diff --git a/spec/ruby/core/argf/readpartial_spec.rb b/spec/ruby/core/argf/readpartial_spec.rb
index 5e284b3423..9f04e72cc2 100644
--- a/spec/ruby/core/argf/readpartial_spec.rb
+++ b/spec/ruby/core/argf/readpartial_spec.rb
@@ -16,7 +16,7 @@ describe "ARGF.readpartial" do
it "raises an ArgumentError if called without a maximum read length" do
argf [@file1_name] do
- -> { @argf.readpartial }.should raise_error(ArgumentError)
+ -> { @argf.readpartial }.should.raise(ArgumentError)
end
end
@@ -29,7 +29,7 @@ describe "ARGF.readpartial" do
it "clears output buffer even if EOFError is raised because @argf is at end" do
begin
- output = "to be cleared"
+ output = +"to be cleared"
argf [@file1_name] do
@argf.read
@@ -59,8 +59,8 @@ describe "ARGF.readpartial" do
@argf.readpartial(@file1.size)
@argf.readpartial(1)
@argf.readpartial(@file2.size)
- -> { @argf.readpartial(1) }.should raise_error(EOFError)
- -> { @argf.readpartial(1) }.should raise_error(EOFError)
+ -> { @argf.readpartial(1) }.should.raise(EOFError)
+ -> { @argf.readpartial(1) }.should.raise(EOFError)
end
end
@@ -69,7 +69,7 @@ describe "ARGF.readpartial" do
print ARGF.readpartial(#{@stdin.size})
ARGF.readpartial(1) rescue print $!.class
STR
- stdin = ruby_exe(ruby_str, args: "< #{@stdin_name}", escape: true)
+ stdin = ruby_exe(ruby_str, args: "< #{@stdin_name}")
stdin.should == @stdin + "EOFError"
end
end
diff --git a/spec/ruby/core/argf/rewind_spec.rb b/spec/ruby/core/argf/rewind_spec.rb
index b29f0b75b7..9255f790fe 100644
--- a/spec/ruby/core/argf/rewind_spec.rb
+++ b/spec/ruby/core/argf/rewind_spec.rb
@@ -33,7 +33,7 @@ describe "ARGF.rewind" do
it "raises an ArgumentError when end of stream reached" do
argf [@file1_name, @file2_name] do
@argf.read
- -> { @argf.rewind }.should raise_error(ArgumentError)
+ -> { @argf.rewind }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/argf/seek_spec.rb b/spec/ruby/core/argf/seek_spec.rb
index 2b73bd46fb..c1ea1ea438 100644
--- a/spec/ruby/core/argf/seek_spec.rb
+++ b/spec/ruby/core/argf/seek_spec.rb
@@ -57,7 +57,7 @@ describe "ARGF.seek" do
it "takes at least one argument (offset)" do
argf [@file1_name] do
- -> { @argf.seek }.should raise_error(ArgumentError)
+ -> { @argf.seek }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/argf/shared/each_byte.rb b/spec/ruby/core/argf/shared/each_byte.rb
deleted file mode 100644
index 6b1dc1dae2..0000000000
--- a/spec/ruby/core/argf/shared/each_byte.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-describe :argf_each_byte, shared: true do
- before :each do
- @file1_name = fixture __FILE__, "file1.txt"
- @file2_name = fixture __FILE__, "file2.txt"
-
- @bytes = []
- File.read(@file1_name).each_byte { |b| @bytes << b }
- File.read(@file2_name).each_byte { |b| @bytes << b }
- end
-
- it "yields each byte of all streams to the passed block" do
- argf [@file1_name, @file2_name] do
- bytes = []
- @argf.send(@method) { |b| bytes << b }
- bytes.should == @bytes
- end
- end
-
- it "returns self when passed a block" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method) {}.should equal(@argf)
- end
- end
-
- it "returns an Enumerator when passed no block" do
- argf [@file1_name, @file2_name] do
- enum = @argf.send(@method)
- enum.should be_an_instance_of(Enumerator)
-
- bytes = []
- enum.each { |b| bytes << b }
- bytes.should == @bytes
- end
- end
-
- describe "when no block is given" do
- it "returns an Enumerator" do
- argf [@file1_name, @file2_name] do
- enum = @argf.send(@method)
- enum.should be_an_instance_of(Enumerator)
-
- bytes = []
- enum.each { |b| bytes << b }
- bytes.should == @bytes
- end
- end
-
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method).size.should == nil
- end
- end
- end
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/each_char.rb b/spec/ruby/core/argf/shared/each_char.rb
deleted file mode 100644
index 9e333ecc5b..0000000000
--- a/spec/ruby/core/argf/shared/each_char.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-describe :argf_each_char, shared: true do
- before :each do
- @file1_name = fixture __FILE__, "file1.txt"
- @file2_name = fixture __FILE__, "file2.txt"
-
- @chars = []
- File.read(@file1_name).each_char { |c| @chars << c }
- File.read(@file2_name).each_char { |c| @chars << c }
- end
-
- it "yields each char of all streams to the passed block" do
- argf [@file1_name, @file2_name] do
- chars = []
- @argf.send(@method) { |c| chars << c }
- chars.should == @chars
- end
- end
-
- it "returns self when passed a block" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method) {}.should equal(@argf)
- end
- end
-
- it "returns an Enumerator when passed no block" do
- argf [@file1_name, @file2_name] do
- enum = @argf.send(@method)
- enum.should be_an_instance_of(Enumerator)
-
- chars = []
- enum.each { |c| chars << c }
- chars.should == @chars
- end
- end
-
- describe "when no block is given" do
- it "returns an Enumerator" do
- argf [@file1_name, @file2_name] do
- enum = @argf.send(@method)
- enum.should be_an_instance_of(Enumerator)
-
- chars = []
- enum.each { |c| chars << c }
- chars.should == @chars
- end
- end
-
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method).size.should == nil
- end
- end
- end
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/each_codepoint.rb b/spec/ruby/core/argf/shared/each_codepoint.rb
deleted file mode 100644
index e2a2dfff46..0000000000
--- a/spec/ruby/core/argf/shared/each_codepoint.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-describe :argf_each_codepoint, shared: true do
- before :each do
- file1_name = fixture __FILE__, "file1.txt"
- file2_name = fixture __FILE__, "file2.txt"
- @filenames = [file1_name, file2_name]
-
- @codepoints = File.read(file1_name).codepoints
- @codepoints.concat File.read(file2_name).codepoints
- end
-
- it "is a public method" do
- argf @filenames do
- @argf.public_methods(false).should include(@method)
- end
- end
-
- it "does not require arguments" do
- argf @filenames do
- @argf.method(@method).arity.should == 0
- end
- end
-
- it "returns self when passed a block" do
- argf @filenames do
- @argf.send(@method) {}.should equal(@argf)
- end
- end
-
- it "returns an Enumerator when passed no block" do
- argf @filenames do
- @argf.send(@method).should be_an_instance_of(Enumerator)
- end
- end
-
- it "yields each codepoint of all streams" do
- argf @filenames do
- @argf.send(@method).to_a.should == @codepoints
- end
- end
-
- describe "when no block is given" do
- it "returns an Enumerator" do
- argf @filenames do
- @argf.send(@method).should be_an_instance_of(Enumerator)
- end
- end
-
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- argf @filenames do
- @argf.send(@method).size.should == nil
- end
- end
- end
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/each_line.rb b/spec/ruby/core/argf/shared/each_line.rb
deleted file mode 100644
index c0ef77dc54..0000000000
--- a/spec/ruby/core/argf/shared/each_line.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-describe :argf_each_line, shared: true do
- before :each do
- @file1_name = fixture __FILE__, "file1.txt"
- @file2_name = fixture __FILE__, "file2.txt"
-
- @lines = File.readlines @file1_name
- @lines += File.readlines @file2_name
- end
-
- it "is a public method" do
- argf [@file1_name, @file2_name] do
- @argf.public_methods(false).should include(@method)
- end
- end
-
- it "requires multiple arguments" do
- argf [@file1_name, @file2_name] do
- @argf.method(@method).arity.should < 0
- end
- end
-
- it "reads each line of files" do
- argf [@file1_name, @file2_name] do
- lines = []
- @argf.send(@method) { |b| lines << b }
- lines.should == @lines
- end
- end
-
- it "returns self when passed a block" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method) {}.should equal(@argf)
- end
- end
-
- describe "with a separator" do
- it "yields each separated section of all streams" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method, '.').to_a.should ==
- (File.readlines(@file1_name, '.') + File.readlines(@file2_name, '.'))
- end
- end
- end
-
- describe "when no block is given" do
- it "returns an Enumerator" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method).should be_an_instance_of(Enumerator)
- end
- end
-
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- argf [@file1_name, @file2_name] do
- @argf.send(@method).size.should == nil
- end
- end
- end
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/eof.rb b/spec/ruby/core/argf/shared/eof.rb
deleted file mode 100644
index 0e684f943f..0000000000
--- a/spec/ruby/core/argf/shared/eof.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-describe :argf_eof, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
- end
-
- # NOTE: this test assumes that fixtures files have two lines each
- it "returns true when reaching the end of a file" do
- argf [@file1, @file2] do
- result = []
- while @argf.gets
- result << @argf.send(@method)
- end
- result.should == [false, true, false, true]
- end
- end
-
- it "raises IOError when called on a closed stream" do
- argf [@file1] do
- @argf.read
- -> { @argf.send(@method) }.should raise_error(IOError)
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/filename.rb b/spec/ruby/core/argf/shared/filename.rb
deleted file mode 100644
index f47c673dc0..0000000000
--- a/spec/ruby/core/argf/shared/filename.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-describe :argf_filename, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
- end
-
- # NOTE: this test assumes that fixtures files have two lines each
- it "returns the current file name on each file" do
- argf [@file1, @file2] do
- result = []
- # returns first current file even when not yet open
- result << @argf.send(@method)
- result << @argf.send(@method) while @argf.gets
- # returns last current file even when closed
- result << @argf.send(@method)
-
- result.map! { |f| File.expand_path(f) }
- result.should == [@file1, @file1, @file1, @file2, @file2, @file2]
- end
- end
-
- # NOTE: this test assumes that fixtures files have two lines each
- it "sets the $FILENAME global variable with the current file name on each file" do
- script = fixture __FILE__, "filename.rb"
- out = ruby_exe(script, args: [@file1, @file2])
- out.should == "#{@file1}\n#{@file1}\n#{@file2}\n#{@file2}\n#{@file2}\n"
- end
-end
diff --git a/spec/ruby/core/argf/shared/fileno.rb b/spec/ruby/core/argf/shared/fileno.rb
deleted file mode 100644
index 4350d43747..0000000000
--- a/spec/ruby/core/argf/shared/fileno.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-describe :argf_fileno, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
- end
-
- # NOTE: this test assumes that fixtures files have two lines each
- it "returns the current file number on each file" do
- argf [@file1, @file2] do
- result = []
- # returns first current file even when not yet open
- result << @argf.send(@method) while @argf.gets
- # returns last current file even when closed
- result.map { |d| d.class }.should == [Integer, Integer, Integer, Integer]
- end
- end
-
- it "raises an ArgumentError when called on a closed stream" do
- argf [@file1] do
- @argf.read
- -> { @argf.send(@method) }.should raise_error(ArgumentError)
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/getc.rb b/spec/ruby/core/argf/shared/getc.rb
index 8be39c60b6..d63372d9d7 100644
--- a/spec/ruby/core/argf/shared/getc.rb
+++ b/spec/ruby/core/argf/shared/getc.rb
@@ -9,7 +9,7 @@ describe :argf_getc, shared: true do
it "reads each char of files" do
argf [@file1, @file2] do
- chars = ""
+ chars = +""
@chars.size.times { chars << @argf.send(@method) }
chars.should == @chars
end
diff --git a/spec/ruby/core/argf/shared/pos.rb b/spec/ruby/core/argf/shared/pos.rb
deleted file mode 100644
index 9836d5f1e4..0000000000
--- a/spec/ruby/core/argf/shared/pos.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-describe :argf_pos, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
- end
-
- it "gives the correct position for each read operation" do
- argf [@file1, @file2] do
- size1 = File.size(@file1)
- size2 = File.size(@file2)
-
- @argf.read(2)
- @argf.send(@method).should == 2
- @argf.read(size1-2)
- @argf.send(@method).should == size1
- @argf.read(6)
- @argf.send(@method).should == 6
- @argf.rewind
- @argf.send(@method).should == 0
- @argf.read(size2)
- @argf.send(@method).should == size2
- end
- end
-
- it "raises an ArgumentError when called on a closed stream" do
- argf [@file1] do
- @argf.read
- -> { @argf.send(@method) }.should raise_error(ArgumentError)
- end
- end
-end
diff --git a/spec/ruby/core/argf/shared/read.rb b/spec/ruby/core/argf/shared/read.rb
index fe903983c0..e76d022139 100644
--- a/spec/ruby/core/argf/shared/read.rb
+++ b/spec/ruby/core/argf/shared/read.rb
@@ -15,7 +15,7 @@ describe :argf_read, shared: true do
it "treats second argument as an output buffer" do
argf [@file1_name] do
- buffer = ""
+ buffer = +""
@argf.send(@method, @file1.size, buffer)
buffer.should == @file1
end
@@ -23,7 +23,7 @@ describe :argf_read, shared: true do
it "clears output buffer before appending to it" do
argf [@file1_name] do
- buffer = "to be cleared"
+ buffer = +"to be cleared"
@argf.send(@method, @file1.size, buffer)
buffer.should == @file1
end
diff --git a/spec/ruby/core/argf/shared/readlines.rb b/spec/ruby/core/argf/shared/readlines.rb
deleted file mode 100644
index 505fa94acb..0000000000
--- a/spec/ruby/core/argf/shared/readlines.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-describe :argf_readlines, shared: true do
- before :each do
- @file1 = fixture __FILE__, "file1.txt"
- @file2 = fixture __FILE__, "file2.txt"
-
- @lines = File.readlines(@file1)
- @lines += File.readlines(@file2)
- end
-
- it "reads all lines of all files" do
- argf [@file1, @file2] do
- @argf.send(@method).should == @lines
- end
- end
-
- it "returns an empty Array when end of stream reached" do
- argf [@file1, @file2] do
- @argf.read
- @argf.send(@method).should == []
- end
- end
-end
diff --git a/spec/ruby/core/argf/skip_spec.rb b/spec/ruby/core/argf/skip_spec.rb
index 0181801c2d..bb1c0ae110 100644
--- a/spec/ruby/core/argf/skip_spec.rb
+++ b/spec/ruby/core/argf/skip_spec.rb
@@ -37,6 +37,6 @@ describe "ARGF.skip" do
# which as a side-effect calls argf.file which will initialize
# internals of ARGF enough for this to work.
it "has no effect when nothing has been processed yet" do
- -> { ARGF.class.new(@file1_name).skip }.should_not raise_error
+ -> { ARGF.class.new(@file1_name).skip }.should_not.raise
end
end
diff --git a/spec/ruby/core/argf/tell_spec.rb b/spec/ruby/core/argf/tell_spec.rb
index 16d9f29920..bb28df74a2 100644
--- a/spec/ruby/core/argf/tell_spec.rb
+++ b/spec/ruby/core/argf/tell_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/pos'
describe "ARGF.tell" do
- it_behaves_like :argf_pos, :tell
+ it "is an alias of ARGF.pos" do
+ ARGF.method(:tell).should == ARGF.method(:pos)
+ end
end
diff --git a/spec/ruby/core/argf/to_a_spec.rb b/spec/ruby/core/argf/to_a_spec.rb
index b17a93db33..d95dc732ec 100644
--- a/spec/ruby/core/argf/to_a_spec.rb
+++ b/spec/ruby/core/argf/to_a_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/readlines'
describe "ARGF.to_a" do
- it_behaves_like :argf_readlines, :to_a
+ it "is an alias of ARGF.readlines" do
+ ARGF.method(:to_a).should == ARGF.method(:readlines)
+ end
end
diff --git a/spec/ruby/core/argf/to_i_spec.rb b/spec/ruby/core/argf/to_i_spec.rb
index 2183de6cd4..e8df378f4e 100644
--- a/spec/ruby/core/argf/to_i_spec.rb
+++ b/spec/ruby/core/argf/to_i_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/fileno'
describe "ARGF.to_i" do
- it_behaves_like :argf_fileno, :to_i
+ it "is an alias of ARGF.fileno" do
+ ARGF.method(:to_i).should == ARGF.method(:fileno)
+ end
end
diff --git a/spec/ruby/core/argf/to_io_spec.rb b/spec/ruby/core/argf/to_io_spec.rb
index 062383d291..ab5de58bcf 100644
--- a/spec/ruby/core/argf/to_io_spec.rb
+++ b/spec/ruby/core/argf/to_io_spec.rb
@@ -15,7 +15,7 @@ describe "ARGF.to_io" do
result << @argf.to_io
end
- result.each { |io| io.should be_kind_of(IO) }
+ result.each { |io| io.should.is_a?(IO) }
result[0].should == result[1]
result[2].should == result[3]
end
diff --git a/spec/ruby/core/array/all_spec.rb b/spec/ruby/core/array/all_spec.rb
new file mode 100644
index 0000000000..680e8c26fa
--- /dev/null
+++ b/spec/ruby/core/array/all_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
+
+describe "Array#all?" do
+ @value_to_return = -> _ { true }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :all?
+
+ it "ignores the block if there is an argument" do
+ -> {
+ ['bar', 'foobar'].all?(/bar/) { false }.should == true
+ }.should complain(/given block not used/)
+ end
+end
diff --git a/spec/ruby/core/array/allocate_spec.rb b/spec/ruby/core/array/allocate_spec.rb
index 04f7c0d0ad..c9eceef590 100644
--- a/spec/ruby/core/array/allocate_spec.rb
+++ b/spec/ruby/core/array/allocate_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Array.allocate" do
it "returns an instance of Array" do
ary = Array.allocate
- ary.should be_an_instance_of(Array)
+ ary.should.instance_of?(Array)
end
it "returns a fully-formed instance of Array" do
@@ -14,6 +14,6 @@ describe "Array.allocate" do
end
it "does not accept any arguments" do
- -> { Array.allocate(1) }.should raise_error(ArgumentError)
+ -> { Array.allocate(1) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/any_spec.rb b/spec/ruby/core/array/any_spec.rb
index 09d949fe6e..b51ce62f0f 100644
--- a/spec/ruby/core/array/any_spec.rb
+++ b/spec/ruby/core/array/any_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#any?" do
describe 'with no block given (a default block of { |x| x } is implicit)' do
@@ -19,6 +20,9 @@ describe "Array#any?" do
end
describe 'with a block given' do
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :any?
+
it 'is false if the array is empty' do
empty_array = []
empty_array.any? {|v| 1 == 1 }.should == false
@@ -34,4 +38,12 @@ describe "Array#any?" do
array_with_members.any? {|v| v == 42 }.should == false
end
end
+
+ describe 'when given a pattern argument' do
+ it "ignores the block if there is an argument" do
+ -> {
+ ['bar', 'foobar'].any?(/bar/) { false }.should == true
+ }.should complain(/given block not used/)
+ end
+ end
end
diff --git a/spec/ruby/core/array/append_spec.rb b/spec/ruby/core/array/append_spec.rb
index c12473dc07..5480d9f65e 100644
--- a/spec/ruby/core/array/append_spec.rb
+++ b/spec/ruby/core/array/append_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/push'
describe "Array#<<" do
it "pushes the object onto the end of the array" do
@@ -10,8 +9,8 @@ describe "Array#<<" do
it "returns self to allow chaining" do
a = []
b = a
- (a << 1).should equal(b)
- (a << 2 << 3).should equal(b)
+ (a << 1).should.equal?(b)
+ (a << 2 << 3).should.equal?(b)
end
it "correctly resizes the Array" do
@@ -31,10 +30,12 @@ describe "Array#<<" do
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array << 5 }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array << 5 }.should.raise(FrozenError)
end
end
describe "Array#append" do
- it_behaves_like :array_push, :append
+ it "is an alias of Array#push" do
+ Array.instance_method(:append).should == Array.instance_method(:push)
+ end
end
diff --git a/spec/ruby/core/array/assoc_spec.rb b/spec/ruby/core/array/assoc_spec.rb
index f8479d763c..a5026cf5d4 100644
--- a/spec/ruby/core/array/assoc_spec.rb
+++ b/spec/ruby/core/array/assoc_spec.rb
@@ -6,18 +6,18 @@ describe "Array#assoc" do
s1 = ["colors", "red", "blue", "green"]
s2 = [:letters, "a", "b", "c"]
s3 = [4]
- s4 = ["colors", "cyan", "yellow", "magenda"]
+ s4 = ["colors", "cyan", "yellow", "magenta"]
s5 = [:letters, "a", "i", "u"]
s_nil = [nil, nil]
a = [s1, s2, s3, s4, s5, s_nil]
- a.assoc(s1.first).should equal(s1)
- a.assoc(s2.first).should equal(s2)
- a.assoc(s3.first).should equal(s3)
- a.assoc(s4.first).should equal(s1)
- a.assoc(s5.first).should equal(s2)
- a.assoc(s_nil.first).should equal(s_nil)
- a.assoc(4).should equal(s3)
- a.assoc("key not in array").should be_nil
+ a.assoc(s1.first).should.equal?(s1)
+ a.assoc(s2.first).should.equal?(s2)
+ a.assoc(s3.first).should.equal?(s3)
+ a.assoc(s4.first).should.equal?(s1)
+ a.assoc(s5.first).should.equal?(s2)
+ a.assoc(s_nil.first).should.equal?(s_nil)
+ a.assoc(4).should.equal?(s3)
+ a.assoc("key not in array").should == nil
end
it "calls == on first element of each array" do
@@ -25,16 +25,28 @@ describe "Array#assoc" do
key2 = mock('key2')
items = [['not it', 1], [ArraySpecs::AssocKey.new, 2], ['na', 3]]
- items.assoc(key1).should equal(items[1])
- items.assoc(key2).should be_nil
+ items.assoc(key1).should.equal?(items[1])
+ items.assoc(key2).should == nil
end
it "ignores any non-Array elements" do
- [1, 2, 3].assoc(2).should be_nil
+ [1, 2, 3].assoc(2).should == nil
s1 = [4]
s2 = [5, 4, 3]
a = ["foo", [], s1, s2, nil, []]
- a.assoc(s1.first).should equal(s1)
- a.assoc(s2.first).should equal(s2)
+ a.assoc(s1.first).should.equal?(s1)
+ a.assoc(s2.first).should.equal?(s2)
+ end
+
+ it "calls to_ary on non-array elements" do
+ s1 = [1, 2]
+ s2 = ArraySpecs::ArrayConvertible.new(2, 3)
+ a = [s1, s2]
+
+ s1.should_not_receive(:to_ary)
+ a.assoc(s1.first).should.equal?(s1)
+
+ a.assoc(2).should == [2, 3]
+ s2.called.should.equal?(:to_ary)
end
end
diff --git a/spec/ruby/core/array/at_spec.rb b/spec/ruby/core/array/at_spec.rb
index 8bc789fef7..3c7c99fdff 100644
--- a/spec/ruby/core/array/at_spec.rb
+++ b/spec/ruby/core/array/at_spec.rb
@@ -47,10 +47,10 @@ describe "Array#at" do
end
it "raises a TypeError when the passed argument can't be coerced to Integer" do
- -> { [].at("cat") }.should raise_error(TypeError)
+ -> { [].at("cat") }.should.raise(TypeError)
end
it "raises an ArgumentError when 2 or more arguments are passed" do
- -> { [:a, :b].at(0,1) }.should raise_error(ArgumentError)
+ -> { [:a, :b].at(0,1) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/bsearch_index_spec.rb b/spec/ruby/core/array/bsearch_index_spec.rb
index df2c7c098e..e1d5eb66bb 100644
--- a/spec/ruby/core/array/bsearch_index_spec.rb
+++ b/spec/ruby/core/array/bsearch_index_spec.rb
@@ -8,11 +8,11 @@ describe "Array#bsearch_index" do
end
it "returns an Enumerator" do
- @enum.should be_an_instance_of(Enumerator)
+ @enum.should.instance_of?(Enumerator)
end
it "returns an Enumerator with unknown size" do
- @enum.size.should be_nil
+ @enum.size.should == nil
end
it "returns index of element when block condition is satisfied" do
@@ -21,11 +21,11 @@ describe "Array#bsearch_index" do
end
it "raises a TypeError when block returns a String" do
- -> { [1, 2, 3].bsearch_index { "not ok" } }.should raise_error(TypeError)
+ -> { [1, 2, 3].bsearch_index { "not ok" } }.should.raise(TypeError)
end
it "returns nil when block is empty" do
- [1, 2, 3].bsearch_index {}.should be_nil
+ [1, 2, 3].bsearch_index {}.should == nil
end
context "minimum mode" do
@@ -40,8 +40,8 @@ describe "Array#bsearch_index" do
end
it "returns nil when block condition is never satisfied" do
- @array.bsearch_index { false }.should be_nil
- @array.bsearch_index { |x| x >= 100 }.should be_nil
+ @array.bsearch_index { false }.should == nil
+ @array.bsearch_index { |x| x >= 100 }.should == nil
end
end
@@ -51,34 +51,30 @@ describe "Array#bsearch_index" do
end
it "returns the index of any matched elements where element is between 4 <= x < 8" do
- [1, 2].should include(@array.bsearch_index { |x| 1 - x / 4 })
+ [1, 2].should.include?(@array.bsearch_index { |x| 1 - x / 4 })
end
it "returns the index of any matched elements where element is between 8 <= x < 10" do
- @array.bsearch_index { |x| 4 - x / 2 }.should be_nil
+ @array.bsearch_index { |x| 4 - x / 2 }.should == nil
end
it "returns nil when block never returns 0" do
- @array.bsearch_index { |x| 1 }.should be_nil
- @array.bsearch_index { |x| -1 }.should be_nil
- end
-
- it "returns the middle element when block always returns zero" do
- @array.bsearch_index { |x| 0 }.should == 2
+ @array.bsearch_index { |x| 1 }.should == nil
+ @array.bsearch_index { |x| -1 }.should == nil
end
context "magnitude does not effect the result" do
it "returns the index of any matched elements where element is between 4n <= xn < 8n" do
- [1, 2].should include(@array.bsearch_index { |x| (1 - x / 4) * (2**100) })
+ [1, 2].should.include?(@array.bsearch_index { |x| (1 - x / 4) * (2**100) })
end
it "returns nil when block never returns 0" do
- @array.bsearch_index { |x| 1 * (2**100) }.should be_nil
- @array.bsearch_index { |x| (-1) * (2**100) }.should be_nil
+ @array.bsearch_index { |x| 1 * (2**100) }.should == nil
+ @array.bsearch_index { |x| (-1) * (2**100) }.should == nil
end
it "handles values from Integer#coerce" do
- [1, 2].should include(@array.bsearch_index { |x| (2**100).coerce((1 - x / 4) * (2**100)).first })
+ [1, 2].should.include?(@array.bsearch_index { |x| (2**100).coerce((1 - x / 4) * (2**100)).first })
end
end
end
diff --git a/spec/ruby/core/array/bsearch_spec.rb b/spec/ruby/core/array/bsearch_spec.rb
index 8fa6245dbf..12aec60654 100644
--- a/spec/ruby/core/array/bsearch_spec.rb
+++ b/spec/ruby/core/array/bsearch_spec.rb
@@ -3,26 +3,26 @@ require_relative '../enumerable/shared/enumeratorized'
describe "Array#bsearch" do
it "returns an Enumerator when not passed a block" do
- [1].bsearch.should be_an_instance_of(Enumerator)
+ [1].bsearch.should.instance_of?(Enumerator)
end
it_behaves_like :enumeratorized_with_unknown_size, :bsearch, [1,2,3]
it "raises a TypeError if the block returns an Object" do
- -> { [1].bsearch { Object.new } }.should raise_error(TypeError)
+ -> { [1].bsearch { Object.new } }.should.raise(TypeError)
end
it "raises a TypeError if the block returns a String" do
- -> { [1].bsearch { "1" } }.should raise_error(TypeError)
+ -> { [1].bsearch { "1" } }.should.raise(TypeError)
end
context "with a block returning true or false" do
it "returns nil if the block returns false for every element" do
- [0, 1, 2, 3].bsearch { |x| x > 3 }.should be_nil
+ [0, 1, 2, 3].bsearch { |x| x > 3 }.should == nil
end
it "returns nil if the block returns nil for every element" do
- [0, 1, 2, 3].bsearch { |x| nil }.should be_nil
+ [0, 1, 2, 3].bsearch { |x| nil }.should == nil
end
it "returns element at zero if the block returns true for every element" do
@@ -38,21 +38,21 @@ describe "Array#bsearch" do
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
- [0, 1, 2, 3].bsearch { |x| x <=> 5 }.should be_nil
+ [0, 1, 2, 3].bsearch { |x| x <=> 5 }.should == nil
end
it "returns nil if the block returns greater than zero for every element" do
- [0, 1, 2, 3].bsearch { |x| x <=> -1 }.should be_nil
+ [0, 1, 2, 3].bsearch { |x| x <=> -1 }.should == nil
end
it "returns nil if the block never returns zero" do
- [0, 1, 3, 4].bsearch { |x| x <=> 2 }.should be_nil
+ [0, 1, 3, 4].bsearch { |x| x <=> 2 }.should == nil
end
it "accepts (+/-)Float::INFINITY from the block" do
- [0, 1, 3, 4].bsearch { |x| Float::INFINITY }.should be_nil
- [0, 1, 3, 4].bsearch { |x| -Float::INFINITY }.should be_nil
+ [0, 1, 3, 4].bsearch { |x| Float::INFINITY }.should == nil
+ [0, 1, 3, 4].bsearch { |x| -Float::INFINITY }.should == nil
end
it "returns an element at an index for which block returns 0.0" do
@@ -62,17 +62,17 @@ describe "Array#bsearch" do
it "returns an element at an index for which block returns 0" do
result = [0, 1, 2, 3, 4].bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
- [1, 2].should include(result)
+ [1, 2].should.include?(result)
end
end
context "with a block that calls break" do
it "returns nil if break is called without a value" do
- ['a', 'b', 'c'].bsearch { |v| break }.should be_nil
+ ['a', 'b', 'c'].bsearch { |v| break }.should == nil
end
it "returns nil if break is called with a nil value" do
- ['a', 'b', 'c'].bsearch { |v| break nil }.should be_nil
+ ['a', 'b', 'c'].bsearch { |v| break nil }.should == nil
end
it "returns object if break is called with an object" do
diff --git a/spec/ruby/core/array/clear_spec.rb b/spec/ruby/core/array/clear_spec.rb
index 81ba56e01e..15778f864f 100644
--- a/spec/ruby/core/array/clear_spec.rb
+++ b/spec/ruby/core/array/clear_spec.rb
@@ -4,13 +4,13 @@ require_relative 'fixtures/classes'
describe "Array#clear" do
it "removes all elements" do
a = [1, 2, 3, 4]
- a.clear.should equal(a)
+ a.clear.should.equal?(a)
a.should == []
end
it "returns self" do
a = [1]
- a.should equal a.clear
+ a.should.equal? a.clear
end
it "leaves the Array empty" do
@@ -21,12 +21,12 @@ describe "Array#clear" do
end
it "does not accept any arguments" do
- -> { [1].clear(true) }.should raise_error(ArgumentError)
+ -> { [1].clear(true) }.should.raise(ArgumentError)
end
it "raises a FrozenError on a frozen array" do
a = [1]
a.freeze
- -> { a.clear }.should raise_error(FrozenError)
+ -> { a.clear }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/clone_spec.rb b/spec/ruby/core/array/clone_spec.rb
index e22a6c6d53..7ce9d40a81 100644
--- a/spec/ruby/core/array/clone_spec.rb
+++ b/spec/ruby/core/array/clone_spec.rb
@@ -23,9 +23,9 @@ describe "Array#clone" do
aa = a.clone
bb = b.clone
- a.respond_to?(:a_singleton_method).should be_true
- b.respond_to?(:a_singleton_method).should be_false
- aa.respond_to?(:a_singleton_method).should be_true
- bb.respond_to?(:a_singleton_method).should be_false
+ a.respond_to?(:a_singleton_method).should == true
+ b.respond_to?(:a_singleton_method).should == false
+ aa.respond_to?(:a_singleton_method).should == true
+ bb.respond_to?(:a_singleton_method).should == false
end
end
diff --git a/spec/ruby/core/array/collect_spec.rb b/spec/ruby/core/array/collect_spec.rb
index 0ad4c283b1..43a539f805 100644
--- a/spec/ruby/core/array/collect_spec.rb
+++ b/spec/ruby/core/array/collect_spec.rb
@@ -1,11 +1,143 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/collect'
+require_relative '../enumerable/shared/enumeratorized'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#collect" do
- it_behaves_like :array_collect, :collect
+ it "returns a copy of array with each element replaced by the value returned by block" do
+ a = ['a', 'b', 'c', 'd']
+ b = a.collect { |i| i + '!' }
+ b.should == ["a!", "b!", "c!", "d!"]
+ b.should_not.equal? a
+ end
+
+ it "does not return subclass instance" do
+ ArraySpecs::MyArray[1, 2, 3].collect { |x| x + 1 }.should.instance_of?(Array)
+ end
+
+ it "does not change self" do
+ a = ['a', 'b', 'c', 'd']
+ a.collect { |i| i + '!' }
+ a.should == ['a', 'b', 'c', 'd']
+ end
+
+ it "returns the evaluated value of block if it broke in the block" do
+ a = ['a', 'b', 'c', 'd']
+ b = a.collect {|i|
+ if i == 'c'
+ break 0
+ else
+ i + '!'
+ end
+ }
+ b.should == 0
+ end
+
+ it "returns an Enumerator when no block given" do
+ a = [1, 2, 3]
+ a.collect.should.instance_of?(Enumerator)
+ end
+
+ it "raises an ArgumentError when no block and with arguments" do
+ a = [1, 2, 3]
+ -> {
+ a.collect(:foo)
+ }.should.raise(ArgumentError)
+ end
+
+ before :each do
+ @object = [1, 2, 3, 4]
+ end
+ it_behaves_like :enumeratorized_with_origin_size, :collect
+
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :collect
end
describe "Array#collect!" do
- it_behaves_like :array_collect_b, :collect!
+ it "replaces each element with the value returned by block" do
+ a = [7, 9, 3, 5]
+ a.collect! { |i| i - 1 }.should.equal?(a)
+ a.should == [6, 8, 2, 4]
+ end
+
+ it "returns self" do
+ a = [1, 2, 3, 4, 5]
+ b = a.collect! {|i| i+1 }
+ a.should.equal? b
+ end
+
+ it "returns the evaluated value of block but its contents is partially modified, if it broke in the block" do
+ a = ['a', 'b', 'c', 'd']
+ b = a.collect! {|i|
+ if i == 'c'
+ break 0
+ else
+ i + '!'
+ end
+ }
+ b.should == 0
+ a.should == ['a!', 'b!', 'c', 'd']
+ end
+
+ it "returns an Enumerator when no block given, and the enumerator can modify the original array" do
+ a = [1, 2, 3]
+ enum = a.collect!
+ enum.should.instance_of?(Enumerator)
+ enum.each{|i| "#{i}!" }
+ a.should == ["1!", "2!", "3!"]
+ end
+
+ describe "when frozen" do
+ it "raises a FrozenError" do
+ -> { ArraySpecs.frozen_array.collect! {} }.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError when empty" do
+ -> { ArraySpecs.empty_frozen_array.collect! {} }.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError when calling #each on the returned Enumerator" do
+ enumerator = ArraySpecs.frozen_array.collect!
+ -> { enumerator.each {|x| x } }.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError when calling #each on the returned Enumerator when empty" do
+ enumerator = ArraySpecs.empty_frozen_array.collect!
+ -> { enumerator.each {|x| x } }.should.raise(FrozenError)
+ end
+ end
+
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.collect! { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
+ end
+
+ it "only changes elements before error is raised, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.collect! do |e|
+ case e
+ when 1 then -1
+ when 2 then -2
+ when 3 then raise StandardError, 'Oops'
+ else 0
+ end
+ end
+ rescue StandardError
+ end
+
+ a.should == [-1, -2, 3, 4]
+ end
+
+ before :each do
+ @object = [1, 2, 3, 4]
+ end
+ it_behaves_like :enumeratorized_with_origin_size, :collect!
+
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :collect!
end
diff --git a/spec/ruby/core/array/combination_spec.rb b/spec/ruby/core/array/combination_spec.rb
index f16d6f98fc..ac570687ca 100644
--- a/spec/ruby/core/array/combination_spec.rb
+++ b/spec/ruby/core/array/combination_spec.rb
@@ -6,11 +6,11 @@ describe "Array#combination" do
end
it "returns an enumerator when no block is provided" do
- @array.combination(2).should be_an_instance_of(Enumerator)
+ @array.combination(2).should.instance_of?(Enumerator)
end
it "returns self when a block is given" do
- @array.combination(2){}.should equal(@array)
+ @array.combination(2){}.should.equal?(@array)
end
it "yields nothing for out of bounds length and return self" do
@@ -30,7 +30,7 @@ describe "Array#combination" do
it "yields a copy of self if the argument is the size of the receiver" do
r = @array.combination(4).to_a
r.should == [@array]
- r[0].should_not equal(@array)
+ r[0].should_not.equal?(@array)
end
it "yields [] when length is 0" do
diff --git a/spec/ruby/core/array/compact_spec.rb b/spec/ruby/core/array/compact_spec.rb
index 83b3fa2a89..dbcd16da35 100644
--- a/spec/ruby/core/array/compact_spec.rb
+++ b/spec/ruby/core/array/compact_spec.rb
@@ -15,30 +15,30 @@ describe "Array#compact" do
it "does not return self" do
a = [1, 2, 3]
- a.compact.should_not equal(a)
+ a.compact.should_not.equal?(a)
end
it "does not return subclass instance for Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3, nil].compact.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3, nil].compact.should.instance_of?(Array)
end
end
describe "Array#compact!" do
it "removes all nil elements" do
a = ['a', nil, 'b', false, 'c']
- a.compact!.should equal(a)
+ a.compact!.should.equal?(a)
a.should == ["a", "b", false, "c"]
a = [nil, 'a', 'b', false, 'c']
- a.compact!.should equal(a)
+ a.compact!.should.equal?(a)
a.should == ["a", "b", false, "c"]
a = ['a', 'b', false, 'c', nil]
- a.compact!.should equal(a)
+ a.compact!.should.equal?(a)
a.should == ["a", "b", false, "c"]
end
it "returns self if some nil elements are removed" do
a = ['a', nil, 'b', false, 'c']
- a.compact!.should equal a
+ a.compact!.should.equal? a
end
it "returns nil if there are no nil elements to remove" do
@@ -46,6 +46,6 @@ describe "Array#compact!" do
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.compact! }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.compact! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/comparison_spec.rb b/spec/ruby/core/array/comparison_spec.rb
index 5d1c3265f1..14e8931e5a 100644
--- a/spec/ruby/core/array/comparison_spec.rb
+++ b/spec/ruby/core/array/comparison_spec.rb
@@ -92,6 +92,6 @@ describe "Array#<=>" do
end
it "returns nil when the argument is not array-like" do
- ([] <=> false).should be_nil
+ ([] <=> false).should == nil
end
end
diff --git a/spec/ruby/core/array/concat_spec.rb b/spec/ruby/core/array/concat_spec.rb
index f3cab9c17c..1e8d20c36c 100644
--- a/spec/ruby/core/array/concat_spec.rb
+++ b/spec/ruby/core/array/concat_spec.rb
@@ -4,12 +4,12 @@ require_relative 'fixtures/classes'
describe "Array#concat" do
it "returns the array itself" do
ary = [1,2,3]
- ary.concat([4,5,6]).equal?(ary).should be_true
+ ary.concat([4,5,6]).equal?(ary).should == true
end
it "appends the elements in the other array" do
ary = [1, 2, 3]
- ary.concat([9, 10, 11]).should equal(ary)
+ ary.concat([9, 10, 11]).should.equal?(ary)
ary.should == [1, 2, 3, 9, 10, 11]
ary.concat([])
ary.should == [1, 2, 3, 9, 10, 11]
@@ -33,12 +33,12 @@ describe "Array#concat" do
end
it "raises a FrozenError when Array is frozen and modification occurs" do
- -> { ArraySpecs.frozen_array.concat [1] }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.concat [1] }.should.raise(FrozenError)
end
# see [ruby-core:23666]
it "raises a FrozenError when Array is frozen and no modification occurs" do
- -> { ArraySpecs.frozen_array.concat([]) }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.concat([]) }.should.raise(FrozenError)
end
it "appends elements to an Array with enough capacity that has been shifted" do
@@ -68,7 +68,7 @@ describe "Array#concat" do
it "returns self when given no arguments" do
ary = [1, 2]
- ary.concat.should equal(ary)
+ ary.concat.should.equal?(ary)
ary.should == [1, 2]
end
end
diff --git a/spec/ruby/core/array/constructor_spec.rb b/spec/ruby/core/array/constructor_spec.rb
index 6f36074c45..c4398c535d 100644
--- a/spec/ruby/core/array/constructor_spec.rb
+++ b/spec/ruby/core/array/constructor_spec.rb
@@ -7,7 +7,7 @@ describe "Array.[]" do
Array.[](5, true, nil, 'a', "Ruby", obj).should == [5, true, nil, "a", "Ruby", obj]
a = ArraySpecs::MyArray.[](5, true, nil, 'a', "Ruby", obj)
- a.should be_an_instance_of(ArraySpecs::MyArray)
+ a.should.instance_of?(ArraySpecs::MyArray)
a.inspect.should == [5, true, nil, "a", "Ruby", obj].inspect
end
end
@@ -18,7 +18,7 @@ describe "Array[]" do
Array[5, true, nil, 'a', "Ruby", obj].should == Array.[](5, true, nil, "a", "Ruby", obj)
a = ArraySpecs::MyArray[5, true, nil, 'a', "Ruby", obj]
- a.should be_an_instance_of(ArraySpecs::MyArray)
+ a.should.instance_of?(ArraySpecs::MyArray)
a.inspect.should == [5, true, nil, "a", "Ruby", obj].inspect
end
end
diff --git a/spec/ruby/core/array/count_spec.rb b/spec/ruby/core/array/count_spec.rb
index eaf275aeb7..e778233c16 100644
--- a/spec/ruby/core/array/count_spec.rb
+++ b/spec/ruby/core/array/count_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#count" do
it "returns the number of elements" do
@@ -12,4 +13,14 @@ describe "Array#count" do
it "returns the number of element for which the block evaluates to true" do
[:a, :b, :c].count { |s| s != :b }.should == 2
end
+
+ it "ignores the block if there is an argument" do
+ -> {
+ [:a, :b, :b, :c].count(:b) { |e| e.size > 10 }.should == 2
+ }.should complain(/given block not used/)
+ end
+
+ context "when a block argument given" do
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :count
+ end
end
diff --git a/spec/ruby/core/array/cycle_spec.rb b/spec/ruby/core/array/cycle_spec.rb
index 7219b49883..29284257e9 100644
--- a/spec/ruby/core/array/cycle_spec.rb
+++ b/spec/ruby/core/array/cycle_spec.rb
@@ -10,17 +10,17 @@ describe "Array#cycle" do
end
it "does not yield and returns nil when the array is empty and passed value is an integer" do
- [].cycle(6, &@prc).should be_nil
+ [].cycle(6, &@prc).should == nil
ScratchPad.recorded.should == []
end
it "does not yield and returns nil when the array is empty and passed value is nil" do
- [].cycle(nil, &@prc).should be_nil
+ [].cycle(nil, &@prc).should == nil
ScratchPad.recorded.should == []
end
it "does not yield and returns nil when passed 0" do
- @array.cycle(0, &@prc).should be_nil
+ @array.cycle(0, &@prc).should == nil
ScratchPad.recorded.should == []
end
@@ -48,13 +48,13 @@ describe "Array#cycle" do
it "does not rescue StopIteration when not passed a count" do
-> do
@array.cycle { raise StopIteration }
- end.should raise_error(StopIteration)
+ end.should.raise(StopIteration)
end
it "does not rescue StopIteration when passed a count" do
-> do
@array.cycle(3) { raise StopIteration }
- end.should raise_error(StopIteration)
+ end.should.raise(StopIteration)
end
it "iterates the array Integer(count) times when passed a Float count" do
@@ -74,23 +74,23 @@ describe "Array#cycle" do
count = mock("cycle count 2")
count.should_receive(:to_int).and_return("2")
- -> { @array.cycle(count, &@prc) }.should raise_error(TypeError)
+ -> { @array.cycle(count, &@prc) }.should.raise(TypeError)
end
it "raises a TypeError if passed a String" do
- -> { @array.cycle("4") { } }.should raise_error(TypeError)
+ -> { @array.cycle("4") { } }.should.raise(TypeError)
end
it "raises a TypeError if passed an Object" do
- -> { @array.cycle(mock("cycle count")) { } }.should raise_error(TypeError)
+ -> { @array.cycle(mock("cycle count")) { } }.should.raise(TypeError)
end
it "raises a TypeError if passed true" do
- -> { @array.cycle(true) { } }.should raise_error(TypeError)
+ -> { @array.cycle(true) { } }.should.raise(TypeError)
end
it "raises a TypeError if passed false" do
- -> { @array.cycle(false) { } }.should raise_error(TypeError)
+ -> { @array.cycle(false) { } }.should.raise(TypeError)
end
before :all do
diff --git a/spec/ruby/core/array/deconstruct_spec.rb b/spec/ruby/core/array/deconstruct_spec.rb
index ad67abe47b..11bb8e72c4 100644
--- a/spec/ruby/core/array/deconstruct_spec.rb
+++ b/spec/ruby/core/array/deconstruct_spec.rb
@@ -4,6 +4,6 @@ describe "Array#deconstruct" do
it "returns self" do
array = [1]
- array.deconstruct.should equal array
+ array.deconstruct.should.equal? array
end
end
diff --git a/spec/ruby/core/array/delete_at_spec.rb b/spec/ruby/core/array/delete_at_spec.rb
index 80ec643702..1e298b6730 100644
--- a/spec/ruby/core/array/delete_at_spec.rb
+++ b/spec/ruby/core/array/delete_at_spec.rb
@@ -36,6 +36,6 @@ describe "Array#delete_at" do
end
it "raises a FrozenError on a frozen array" do
- -> { [1,2,3].freeze.delete_at(0) }.should raise_error(FrozenError)
+ -> { [1,2,3].freeze.delete_at(0) }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/delete_if_spec.rb b/spec/ruby/core/array/delete_if_spec.rb
index 1459cc8d04..701a612395 100644
--- a/spec/ruby/core/array/delete_if_spec.rb
+++ b/spec/ruby/core/array/delete_if_spec.rb
@@ -2,6 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/enumeratorize'
require_relative 'shared/delete_if'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
require_relative '../enumerable/shared/enumeratorized'
describe "Array#delete_if" do
@@ -16,7 +17,7 @@ describe "Array#delete_if" do
end
it "returns self" do
- @a.delete_if{ true }.equal?(@a).should be_true
+ @a.delete_if{ true }.equal?(@a).should == true
end
it_behaves_like :enumeratorize, :delete_if
@@ -24,29 +25,58 @@ describe "Array#delete_if" do
it "returns self when called on an Array emptied with #shift" do
array = [1]
array.shift
- array.delete_if { |x| true }.should equal(array)
+ array.delete_if { |x| true }.should.equal?(array)
end
it "returns an Enumerator if no block given, and the enumerator can modify the original array" do
enum = @a.delete_if
- enum.should be_an_instance_of(Enumerator)
- @a.should_not be_empty
+ enum.should.instance_of?(Enumerator)
+ @a.should_not.empty?
enum.each { true }
- @a.should be_empty
+ @a.should.empty?
end
it "returns an Enumerator if no block given, and the array is frozen" do
- @a.freeze.delete_if.should be_an_instance_of(Enumerator)
+ @a.freeze.delete_if.should.instance_of?(Enumerator)
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.delete_if {} }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.delete_if {} }.should.raise(FrozenError)
end
it "raises a FrozenError on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.delete_if {} }.should raise_error(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.delete_if {} }.should.raise(FrozenError)
+ end
+
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.delete_if { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
+ end
+
+ it "only removes elements for which the block returns true, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.delete_if do |e|
+ case e
+ when 2 then true
+ when 3 then raise StandardError, 'Oops'
+ else false
+ end
+ end
+ rescue StandardError
+ end
+
+ a.should == [1, 3, 4]
end
it_behaves_like :enumeratorized_with_origin_size, :delete_if, [1,2,3]
it_behaves_like :delete_if, :delete_if
+
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :delete_if
end
diff --git a/spec/ruby/core/array/delete_spec.rb b/spec/ruby/core/array/delete_spec.rb
index dddbbe6bd3..0d80b2839d 100644
--- a/spec/ruby/core/array/delete_spec.rb
+++ b/spec/ruby/core/array/delete_spec.rb
@@ -41,6 +41,6 @@ describe "Array#delete" do
end
it "raises a FrozenError on a frozen array" do
- -> { [1, 2, 3].freeze.delete(1) }.should raise_error(FrozenError)
+ -> { [1, 2, 3].freeze.delete(1) }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/difference_spec.rb b/spec/ruby/core/array/difference_spec.rb
index 9f7d4c4a1a..63e32feca0 100644
--- a/spec/ruby/core/array/difference_spec.rb
+++ b/spec/ruby/core/array/difference_spec.rb
@@ -8,11 +8,11 @@ describe "Array#difference" do
it "returns a copy when called without any parameter" do
x = [1, 2, 3, 2]
x.difference.should == x
- x.difference.should_not equal x
+ x.difference.should_not.equal? x
end
it "does not return subclass instances for Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].difference.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].difference.should.instance_of?(Array)
end
it "accepts multiple arguments" do
diff --git a/spec/ruby/core/array/dig_spec.rb b/spec/ruby/core/array/dig_spec.rb
index f2d8ff47fd..4166ff9f1f 100644
--- a/spec/ruby/core/array/dig_spec.rb
+++ b/spec/ruby/core/array/dig_spec.rb
@@ -4,7 +4,7 @@ describe "Array#dig" do
it "returns #at with one arg" do
['a'].dig(0).should == 'a'
- ['a'].dig(1).should be_nil
+ ['a'].dig(1).should == nil
end
it "recurses array elements" do
@@ -22,20 +22,20 @@ describe "Array#dig" do
it "raises a TypeError for a non-numeric index" do
-> {
['a'].dig(:first)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises a TypeError if any intermediate step does not respond to #dig" do
a = [1, 2]
-> {
a.dig(0, 1)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises an ArgumentError if no arguments provided" do
-> {
[10].dig()
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "returns nil if any intermediate step is nil" do
diff --git a/spec/ruby/core/array/drop_spec.rb b/spec/ruby/core/array/drop_spec.rb
index f911fd9018..c0e1c9edce 100644
--- a/spec/ruby/core/array/drop_spec.rb
+++ b/spec/ruby/core/array/drop_spec.rb
@@ -7,7 +7,7 @@ describe "Array#drop" do
end
it "raises an ArgumentError if the number of elements specified is negative" do
- -> { [1, 2].drop(-3) }.should raise_error(ArgumentError)
+ -> { [1, 2].drop(-3) }.should.raise(ArgumentError)
end
it "returns an empty Array if all elements are dropped" do
@@ -40,25 +40,17 @@ describe "Array#drop" do
end
it "raises a TypeError when the passed argument can't be coerced to Integer" do
- -> { [1, 2].drop("cat") }.should raise_error(TypeError)
+ -> { [1, 2].drop("cat") }.should.raise(TypeError)
end
it "raises a TypeError when the passed argument isn't an integer and #to_int returns non-Integer" do
obj = mock("to_int")
obj.should_receive(:to_int).and_return("cat")
- -> { [1, 2].drop(obj) }.should raise_error(TypeError)
+ -> { [1, 2].drop(obj) }.should.raise(TypeError)
end
- ruby_version_is ''...'3.0' do
- it 'returns a subclass instance for Array subclasses' do
- ArraySpecs::MyArray[1, 2, 3, 4, 5].drop(1).should be_an_instance_of(ArraySpecs::MyArray)
- end
- end
-
- ruby_version_is '3.0' do
- it 'returns a Array instance for Array subclasses' do
- ArraySpecs::MyArray[1, 2, 3, 4, 5].drop(1).should be_an_instance_of(Array)
- end
+ it 'returns a Array instance for Array subclasses' do
+ ArraySpecs::MyArray[1, 2, 3, 4, 5].drop(1).should.instance_of?(Array)
end
end
diff --git a/spec/ruby/core/array/drop_while_spec.rb b/spec/ruby/core/array/drop_while_spec.rb
index bb783d22a5..4fead3ff06 100644
--- a/spec/ruby/core/array/drop_while_spec.rb
+++ b/spec/ruby/core/array/drop_while_spec.rb
@@ -1,7 +1,11 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#drop_while" do
+ @value_to_return = -> _ { true }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :drop_while
+
it "removes elements from the start of the array while the block evaluates to true" do
[1, 2, 3, 4].drop_while { |n| n < 4 }.should == [4]
end
@@ -14,15 +18,7 @@ describe "Array#drop_while" do
[1, 2, 3, false, 5].drop_while { |n| n }.should == [false, 5]
end
- ruby_version_is ''...'3.0' do
- it 'returns a subclass instance for Array subclasses' do
- ArraySpecs::MyArray[1, 2, 3, 4, 5].drop_while { |n| n < 4 }.should be_an_instance_of(ArraySpecs::MyArray)
- end
- end
-
- ruby_version_is '3.0' do
- it 'returns a Array instance for Array subclasses' do
- ArraySpecs::MyArray[1, 2, 3, 4, 5].drop_while { |n| n < 4 }.should be_an_instance_of(Array)
- end
+ it 'returns a Array instance for Array subclasses' do
+ ArraySpecs::MyArray[1, 2, 3, 4, 5].drop_while { |n| n < 4 }.should.instance_of?(Array)
end
end
diff --git a/spec/ruby/core/array/dup_spec.rb b/spec/ruby/core/array/dup_spec.rb
index 17f467d5fc..f14aeca3b5 100644
--- a/spec/ruby/core/array/dup_spec.rb
+++ b/spec/ruby/core/array/dup_spec.rb
@@ -12,8 +12,8 @@ describe "Array#dup" do
aa = a.dup
bb = b.dup
- aa.frozen?.should be_false
- bb.frozen?.should be_false
+ aa.frozen?.should == false
+ bb.frozen?.should == false
end
it "does not copy singleton methods" do
@@ -23,9 +23,9 @@ describe "Array#dup" do
aa = a.dup
bb = b.dup
- a.respond_to?(:a_singleton_method).should be_true
- b.respond_to?(:a_singleton_method).should be_false
- aa.respond_to?(:a_singleton_method).should be_false
- bb.respond_to?(:a_singleton_method).should be_false
+ a.respond_to?(:a_singleton_method).should == true
+ b.respond_to?(:a_singleton_method).should == false
+ aa.respond_to?(:a_singleton_method).should == false
+ bb.respond_to?(:a_singleton_method).should == false
end
end
diff --git a/spec/ruby/core/array/each_index_spec.rb b/spec/ruby/core/array/each_index_spec.rb
index 51af5842c4..b238a89d8a 100644
--- a/spec/ruby/core/array/each_index_spec.rb
+++ b/spec/ruby/core/array/each_index_spec.rb
@@ -5,7 +5,7 @@ require_relative '../enumerable/shared/enumeratorized'
# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
-# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
+# https://blade.ruby-lang.org/ruby-core/23633
describe "Array#each_index" do
before :each do
@@ -20,7 +20,7 @@ describe "Array#each_index" do
it "returns self" do
a = [:a, :b, :c]
- a.each_index { |i| }.should equal(a)
+ a.each_index { |i| }.should.equal?(a)
end
it "is not confused by removing elements from the front" do
@@ -40,3 +40,19 @@ describe "Array#each_index" do
it_behaves_like :enumeratorize, :each_index
it_behaves_like :enumeratorized_with_origin_size, :each_index, [1,2,3]
end
+
+describe "Array#each_index" do
+ it "tolerates increasing an array size during iteration" do
+ array = [:a, :b, :c]
+ ScratchPad.record []
+ i = 0
+
+ array.each_index do |index|
+ ScratchPad << index
+ array << i if i < 100
+ i += 1
+ end
+
+ ScratchPad.recorded.should == (0..102).to_a # element indices
+ end
+end
diff --git a/spec/ruby/core/array/each_spec.rb b/spec/ruby/core/array/each_spec.rb
index cf8e9da6d8..73a4c36b17 100644
--- a/spec/ruby/core/array/each_spec.rb
+++ b/spec/ruby/core/array/each_spec.rb
@@ -1,18 +1,19 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/enumeratorize'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
require_relative '../enumerable/shared/enumeratorized'
# Mutating the array while it is being iterated is discouraged as it can result in confusing behavior.
# Yet a Ruby implementation must not crash in such a case, and following the simple CRuby behavior makes sense.
# CRuby simply reads the array storage and checks the size for every iteration;
-# like `i = 0; while i < size; yield self[i]; end`
+# like `i = 0; while i < size; yield self[i]; i += 1; end`
describe "Array#each" do
it "yields each element to the block" do
a = []
x = [1, 2, 3]
- x.each { |item| a << item }.should equal(x)
+ x.each { |item| a << item }.should.equal?(x)
a.should == [1, 2, 3]
end
@@ -75,3 +76,7 @@ describe "Array#each" do
it_behaves_like :enumeratorize, :each
it_behaves_like :enumeratorized_with_origin_size, :each, [1,2,3]
end
+
+describe "Array#each" do
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :each
+end
diff --git a/spec/ruby/core/array/element_reference_spec.rb b/spec/ruby/core/array/element_reference_spec.rb
index 31e5578a09..d5f4b54961 100644
--- a/spec/ruby/core/array/element_reference_spec.rb
+++ b/spec/ruby/core/array/element_reference_spec.rb
@@ -1,9 +1,862 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/slice'
describe "Array#[]" do
- it_behaves_like :array_slice, :[]
+ it "returns the element at index with [index]" do
+ [ "a", "b", "c", "d", "e" ][1].should == "b"
+
+ a = [1, 2, 3, 4]
+
+ a[0].should == 1
+ a[1].should == 2
+ a[2].should == 3
+ a[3].should == 4
+ a[4].should == nil
+ a[10].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns the element at index from the end of the array with [-index]" do
+ [ "a", "b", "c", "d", "e" ][-2].should == "d"
+
+ a = [1, 2, 3, 4]
+
+ a[-1].should == 4
+ a[-2].should == 3
+ a[-3].should == 2
+ a[-4].should == 1
+ a[-5].should == nil
+ a[-10].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns count elements starting from index with [index, count]" do
+ [ "a", "b", "c", "d", "e" ][2, 3].should == ["c", "d", "e"]
+
+ a = [1, 2, 3, 4]
+
+ a[0, 0].should == []
+ a[0, 1].should == [1]
+ a[0, 2].should == [1, 2]
+ a[0, 4].should == [1, 2, 3, 4]
+ a[0, 6].should == [1, 2, 3, 4]
+ a[0, -1].should == nil
+ a[0, -2].should == nil
+ a[0, -4].should == nil
+
+ a[2, 0].should == []
+ a[2, 1].should == [3]
+ a[2, 2].should == [3, 4]
+ a[2, 4].should == [3, 4]
+ a[2, -1].should == nil
+
+ a[4, 0].should == []
+ a[4, 2].should == []
+ a[4, -1].should == nil
+
+ a[5, 0].should == nil
+ a[5, 2].should == nil
+ a[5, -1].should == nil
+
+ a[6, 0].should == nil
+ a[6, 2].should == nil
+ a[6, -1].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns count elements starting at index from the end of array with [-index, count]" do
+ [ "a", "b", "c", "d", "e" ][-2, 2].should == ["d", "e"]
+
+ a = [1, 2, 3, 4]
+
+ a[-1, 0].should == []
+ a[-1, 1].should == [4]
+ a[-1, 2].should == [4]
+ a[-1, -1].should == nil
+
+ a[-2, 0].should == []
+ a[-2, 1].should == [3]
+ a[-2, 2].should == [3, 4]
+ a[-2, 4].should == [3, 4]
+ a[-2, -1].should == nil
+
+ a[-4, 0].should == []
+ a[-4, 1].should == [1]
+ a[-4, 2].should == [1, 2]
+ a[-4, 4].should == [1, 2, 3, 4]
+ a[-4, 6].should == [1, 2, 3, 4]
+ a[-4, -1].should == nil
+
+ a[-5, 0].should == nil
+ a[-5, 1].should == nil
+ a[-5, 10].should == nil
+ a[-5, -1].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns the first count elements with [0, count]" do
+ [ "a", "b", "c", "d", "e" ][0, 3].should == ["a", "b", "c"]
+ end
+
+ it "returns the subarray which is independent to self with [index,count]" do
+ a = [1, 2, 3]
+ sub = a[1, 2]
+ sub.replace([:a, :b])
+ a.should == [1, 2, 3]
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.stub!(:to_int).and_return(2)
+
+ a = [1, 2, 3, 4]
+ a[obj].should == 3
+ a[obj, 1].should == [3]
+ a[obj, obj].should == [3, 4]
+ a[0, obj].should == [1, 2]
+ end
+
+ it "raises TypeError if to_int returns non-integer" do
+ from = mock('from')
+ to = mock('to')
+
+ # So we can construct a range out of them...
+ def from.<=>(o) 0 end
+ def to.<=>(o) 0 end
+
+ a = [1, 2, 3, 4, 5]
+
+ def from.to_int() 'cat' end
+ def to.to_int() -2 end
+
+ -> { a[from..to] }.should.raise(TypeError)
+
+ def from.to_int() 1 end
+ def to.to_int() 'cat' end
+
+ -> { a[from..to] }.should.raise(TypeError)
+ end
+
+ it "returns the elements specified by Range indexes with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][1..3].should == ["b", "c", "d"]
+ [ "a", "b", "c", "d", "e" ][4..-1].should == ['e']
+ [ "a", "b", "c", "d", "e" ][3..3].should == ['d']
+ [ "a", "b", "c", "d", "e" ][3..-2].should == ['d']
+ ['a'][0..-1].should == ['a']
+
+ a = [1, 2, 3, 4]
+
+ a[0..-10].should == []
+ a[0..0].should == [1]
+ a[0..1].should == [1, 2]
+ a[0..2].should == [1, 2, 3]
+ a[0..3].should == [1, 2, 3, 4]
+ a[0..4].should == [1, 2, 3, 4]
+ a[0..10].should == [1, 2, 3, 4]
+
+ a[2..-10].should == []
+ a[2..0].should == []
+ a[2..2].should == [3]
+ a[2..3].should == [3, 4]
+ a[2..4].should == [3, 4]
+
+ a[3..0].should == []
+ a[3..3].should == [4]
+ a[3..4].should == [4]
+
+ a[4..0].should == []
+ a[4..4].should == []
+ a[4..5].should == []
+
+ a[5..0].should == nil
+ a[5..5].should == nil
+ a[5..6].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns elements specified by Range indexes except the element at index n with [m...n]" do
+ [ "a", "b", "c", "d", "e" ][1...3].should == ["b", "c"]
+
+ a = [1, 2, 3, 4]
+
+ a[0...-10].should == []
+ a[0...0].should == []
+ a[0...1].should == [1]
+ a[0...2].should == [1, 2]
+ a[0...3].should == [1, 2, 3]
+ a[0...4].should == [1, 2, 3, 4]
+ a[0...10].should == [1, 2, 3, 4]
+
+ a[2...-10].should == []
+ a[2...0].should == []
+ a[2...2].should == []
+ a[2...3].should == [3]
+ a[2...4].should == [3, 4]
+
+ a[3...0].should == []
+ a[3...3].should == []
+ a[3...4].should == [4]
+
+ a[4...0].should == []
+ a[4...4].should == []
+ a[4...5].should == []
+
+ a[5...0].should == nil
+ a[5...5].should == nil
+ a[5...6].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns elements that exist if range start is in the array but range end is not with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][4..7].should == ["e"]
+ end
+
+ it "accepts Range instances having a negative m and both signs for n with [m..n] and [m...n]" do
+ a = [1, 2, 3, 4]
+
+ a[-1..-1].should == [4]
+ a[-1...-1].should == []
+ a[-1..3].should == [4]
+ a[-1...3].should == []
+ a[-1..4].should == [4]
+ a[-1...4].should == [4]
+ a[-1..10].should == [4]
+ a[-1...10].should == [4]
+ a[-1..0].should == []
+ a[-1..-4].should == []
+ a[-1...-4].should == []
+ a[-1..-6].should == []
+ a[-1...-6].should == []
+
+ a[-2..-2].should == [3]
+ a[-2...-2].should == []
+ a[-2..-1].should == [3, 4]
+ a[-2...-1].should == [3]
+ a[-2..10].should == [3, 4]
+ a[-2...10].should == [3, 4]
+
+ a[-4..-4].should == [1]
+ a[-4..-2].should == [1, 2, 3]
+ a[-4...-2].should == [1, 2]
+ a[-4..-1].should == [1, 2, 3, 4]
+ a[-4...-1].should == [1, 2, 3]
+ a[-4..3].should == [1, 2, 3, 4]
+ a[-4...3].should == [1, 2, 3]
+ a[-4..4].should == [1, 2, 3, 4]
+ a[-4...4].should == [1, 2, 3, 4]
+ a[-4...4].should == [1, 2, 3, 4]
+ a[-4..0].should == [1]
+ a[-4...0].should == []
+ a[-4..1].should == [1, 2]
+ a[-4...1].should == [1]
+
+ a[-5..-5].should == nil
+ a[-5...-5].should == nil
+ a[-5..-4].should == nil
+ a[-5..-1].should == nil
+ a[-5..10].should == nil
+
+ a.should == [1, 2, 3, 4]
+ end
+
+ it "returns the subarray which is independent to self with [m..n]" do
+ a = [1, 2, 3]
+ sub = a[1..2]
+ sub.replace([:a, :b])
+ a.should == [1, 2, 3]
+ end
+
+ it "tries to convert Range elements to Integers using #to_int with [m..n] and [m...n]" do
+ from = mock('from')
+ to = mock('to')
+
+ # So we can construct a range out of them...
+ def from.<=>(o) 0 end
+ def to.<=>(o) 0 end
+
+ def from.to_int() 1 end
+ def to.to_int() -2 end
+
+ a = [1, 2, 3, 4]
+
+ a[from..to].should == [2, 3]
+ a[from...to].should == [2]
+ a[1..0].should == []
+ a[1...0].should == []
+
+ -> { a["a" .. "b"] }.should.raise(TypeError)
+ -> { a["a" ... "b"] }.should.raise(TypeError)
+ -> { a[from .. "b"] }.should.raise(TypeError)
+ -> { a[from ... "b"] }.should.raise(TypeError)
+ end
+
+ it "returns the same elements as [m..n] and [m...n] with Range subclasses" do
+ a = [1, 2, 3, 4]
+ range_incl = ArraySpecs::MyRange.new(1, 2)
+ range_excl = ArraySpecs::MyRange.new(-3, -1, true)
+
+ a[range_incl].should == [2, 3]
+ a[range_excl].should == [2, 3]
+ end
+
+ it "returns nil for a requested index not in the array with [index]" do
+ [ "a", "b", "c", "d", "e" ][5].should == nil
+ end
+
+ it "returns [] if the index is valid but length is zero with [index, length]" do
+ [ "a", "b", "c", "d", "e" ][0, 0].should == []
+ [ "a", "b", "c", "d", "e" ][2, 0].should == []
+ end
+
+ it "returns nil if length is zero but index is invalid with [index, length]" do
+ [ "a", "b", "c", "d", "e" ][100, 0].should == nil
+ [ "a", "b", "c", "d", "e" ][-50, 0].should == nil
+ end
+
+ # This is by design. It is in the official documentation.
+ it "returns [] if index == array.size with [index, length]" do
+ %w|a b c d e|[5, 2].should == []
+ end
+
+ it "returns nil if index > array.size with [index, length]" do
+ %w|a b c d e|[6, 2].should == nil
+ end
+
+ it "returns nil if length is negative with [index, length]" do
+ %w|a b c d e|[3, -1].should == nil
+ %w|a b c d e|[2, -2].should == nil
+ %w|a b c d e|[1, -100].should == nil
+ end
+
+ it "returns nil if no requested index is in the array with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][6..10].should == nil
+ end
+
+ it "returns nil if range start is not in the array with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][-10..2].should == nil
+ [ "a", "b", "c", "d", "e" ][10..12].should == nil
+ end
+
+ it "returns an empty array when m == n with [m...n]" do
+ [1, 2, 3, 4, 5][1...1].should == []
+ end
+
+ it "returns an empty array with [0...0]" do
+ [1, 2, 3, 4, 5][0...0].should == []
+ end
+
+ it "returns a subarray where m, n negatives and m < n with [m..n]" do
+ [ "a", "b", "c", "d", "e" ][-3..-2].should == ["c", "d"]
+ end
+
+ it "returns an array containing the first element with [0..0]" do
+ [1, 2, 3, 4, 5][0..0].should == [1]
+ end
+
+ it "returns the entire array with [0..-1]" do
+ [1, 2, 3, 4, 5][0..-1].should == [1, 2, 3, 4, 5]
+ end
+
+ it "returns all but the last element with [0...-1]" do
+ [1, 2, 3, 4, 5][0...-1].should == [1, 2, 3, 4]
+ end
+
+ it "returns [3] for [2..-1] out of [1, 2, 3]" do
+ [1,2,3][2..-1].should == [3]
+ end
+
+ it "returns an empty array when m > n and m, n are positive with [m..n]" do
+ [1, 2, 3, 4, 5][3..2].should == []
+ end
+
+ it "returns an empty array when m > n and m, n are negative with [m..n]" do
+ [1, 2, 3, 4, 5][-2..-3].should == []
+ end
+
+ it "does not expand array when the indices are outside of the array bounds" do
+ a = [1, 2]
+ a[4].should == nil
+ a.should == [1, 2]
+ a[4, 0].should == nil
+ a.should == [1, 2]
+ a[6, 1].should == nil
+ a.should == [1, 2]
+ a[8...8].should == nil
+ a.should == [1, 2]
+ a[10..10].should == nil
+ a.should == [1, 2]
+ end
+
+ describe "with a subclass of Array" do
+ before :each do
+ ScratchPad.clear
+
+ @array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
+ end
+
+ it "returns a Array instance with [n, m]" do
+ @array[0, 2].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [-n, m]" do
+ @array[-3, 2].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [n..m]" do
+ @array[1..3].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [n...m]" do
+ @array[1...3].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [-n..-m]" do
+ @array[-3..-1].should.instance_of?(Array)
+ end
+
+ it "returns a Array instance with [-n...-m]" do
+ @array[-3...-1].should.instance_of?(Array)
+ end
+
+ it "returns an empty array when m == n with [m...n]" do
+ @array[1...1].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns an empty array with [0...0]" do
+ @array[0...0].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns an empty array when m > n and m, n are positive with [m..n]" do
+ @array[3..2].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns an empty array when m > n and m, n are negative with [m..n]" do
+ @array[-2..-3].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns [] if index == array.size with [index, length]" do
+ @array[5, 2].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "returns [] if the index is valid but length is zero with [index, length]" do
+ @array[0, 0].should == []
+ @array[2, 0].should == []
+ ScratchPad.recorded.should == nil
+ end
+
+ it "does not call #initialize on the subclass instance" do
+ @array[0, 3].should == [1, 2, 3]
+ ScratchPad.recorded.should == nil
+ end
+ end
+
+ it "raises a RangeError when the start index is out of range of Fixnum" do
+ array = [1, 2, 3, 4, 5, 6]
+ obj = mock('large value')
+ obj.should_receive(:to_int).and_return(bignum_value)
+ -> { array[obj] }.should.raise(RangeError)
+
+ obj = 8e19
+ -> { array[obj] }.should.raise(RangeError)
+
+ # boundary value when longs are 64 bits
+ -> { array[2.0**63] }.should.raise(RangeError)
+
+ # just under the boundary value when longs are 64 bits
+ array[max_long.to_f.prev_float].should == nil
+ end
+
+ it "raises a RangeError when the length is out of range of Fixnum" do
+ array = [1, 2, 3, 4, 5, 6]
+ obj = mock('large value')
+ obj.should_receive(:to_int).and_return(bignum_value)
+ -> { array[1, obj] }.should.raise(RangeError)
+
+ obj = 8e19
+ -> { array[1, obj] }.should.raise(RangeError)
+ end
+
+ it "raises a type error if a range is passed with a length" do
+ ->{ [1, 2, 3][1..2, 1] }.should.raise(TypeError)
+ end
+
+ it "raises a RangeError if passed a range with a bound that is too large" do
+ array = [1, 2, 3, 4, 5, 6]
+ -> { array[bignum_value..(bignum_value + 1)] }.should.raise(RangeError)
+ -> { array[0..bignum_value] }.should.raise(RangeError)
+ end
+
+ it "can accept endless ranges" do
+ a = [0, 1, 2, 3, 4, 5]
+ a[eval("(2..)")].should == [2, 3, 4, 5]
+ a[eval("(2...)")].should == [2, 3, 4, 5]
+ a[eval("(-2..)")].should == [4, 5]
+ a[eval("(-2...)")].should == [4, 5]
+ a[eval("(9..)")].should == nil
+ a[eval("(9...)")].should == nil
+ a[eval("(-9..)")].should == nil
+ a[eval("(-9...)")].should == nil
+ end
+
+ describe "can be sliced with Enumerator::ArithmeticSequence" do
+ before :each do
+ @array = [0, 1, 2, 3, 4, 5]
+ end
+
+ it "has endless range and positive steps" do
+ @array[eval("(0..).step(1)")].should == [0, 1, 2, 3, 4, 5]
+ @array[eval("(0..).step(2)")].should == [0, 2, 4]
+ @array[eval("(0..).step(10)")].should == [0]
+
+ @array[eval("(2..).step(1)")].should == [2, 3, 4, 5]
+ @array[eval("(2..).step(2)")].should == [2, 4]
+ @array[eval("(2..).step(10)")].should == [2]
+
+ @array[eval("(-3..).step(1)")].should == [3, 4, 5]
+ @array[eval("(-3..).step(2)")].should == [3, 5]
+ @array[eval("(-3..).step(10)")].should == [3]
+ end
+
+ it "has beginless range and positive steps" do
+ # end with zero index
+ @array[(..0).step(1)].should == [0]
+ @array[(...0).step(1)].should == []
+
+ @array[(..0).step(2)].should == [0]
+ @array[(...0).step(2)].should == []
+
+ @array[(..0).step(10)].should == [0]
+ @array[(...0).step(10)].should == []
+
+ # end with positive index
+ @array[(..3).step(1)].should == [0, 1, 2, 3]
+ @array[(...3).step(1)].should == [0, 1, 2]
+
+ @array[(..3).step(2)].should == [0, 2]
+ @array[(...3).step(2)].should == [0, 2]
+
+ @array[(..3).step(10)].should == [0]
+ @array[(...3).step(10)].should == [0]
+
+ # end with negative index
+ @array[(..-2).step(1)].should == [0, 1, 2, 3, 4,]
+ @array[(...-2).step(1)].should == [0, 1, 2, 3]
+
+ @array[(..-2).step(2)].should == [0, 2, 4]
+ @array[(...-2).step(2)].should == [0, 2]
+
+ @array[(..-2).step(10)].should == [0]
+ @array[(...-2).step(10)].should == [0]
+ end
+
+ it "has endless range and negative steps" do
+ @array[eval("(0..).step(-1)")].should == [0]
+ @array[eval("(0..).step(-2)")].should == [0]
+ @array[eval("(0..).step(-10)")].should == [0]
+
+ @array[eval("(2..).step(-1)")].should == [2, 1, 0]
+ @array[eval("(2..).step(-2)")].should == [2, 0]
+
+ @array[eval("(-3..).step(-1)")].should == [3, 2, 1, 0]
+ @array[eval("(-3..).step(-2)")].should == [3, 1]
+ end
+
+ it "has closed range and positive steps" do
+ # start and end with 0
+ @array[eval("(0..0).step(1)")].should == [0]
+ @array[eval("(0...0).step(1)")].should == []
+
+ @array[eval("(0..0).step(2)")].should == [0]
+ @array[eval("(0...0).step(2)")].should == []
+
+ @array[eval("(0..0).step(10)")].should == [0]
+ @array[eval("(0...0).step(10)")].should == []
+
+ # start and end with positive index
+ @array[eval("(1..3).step(1)")].should == [1, 2, 3]
+ @array[eval("(1...3).step(1)")].should == [1, 2]
+
+ @array[eval("(1..3).step(2)")].should == [1, 3]
+ @array[eval("(1...3).step(2)")].should == [1]
+
+ @array[eval("(1..3).step(10)")].should == [1]
+ @array[eval("(1...3).step(10)")].should == [1]
+
+ # start with positive index, end with negative index
+ @array[eval("(1..-2).step(1)")].should == [1, 2, 3, 4]
+ @array[eval("(1...-2).step(1)")].should == [1, 2, 3]
+
+ @array[eval("(1..-2).step(2)")].should == [1, 3]
+ @array[eval("(1...-2).step(2)")].should == [1, 3]
+
+ @array[eval("(1..-2).step(10)")].should == [1]
+ @array[eval("(1...-2).step(10)")].should == [1]
+
+ # start with negative index, end with positive index
+ @array[eval("(-4..4).step(1)")].should == [2, 3, 4]
+ @array[eval("(-4...4).step(1)")].should == [2, 3]
+
+ @array[eval("(-4..4).step(2)")].should == [2, 4]
+ @array[eval("(-4...4).step(2)")].should == [2]
+
+ @array[eval("(-4..4).step(10)")].should == [2]
+ @array[eval("(-4...4).step(10)")].should == [2]
+
+ # start with negative index, end with negative index
+ @array[eval("(-4..-2).step(1)")].should == [2, 3, 4]
+ @array[eval("(-4...-2).step(1)")].should == [2, 3]
+
+ @array[eval("(-4..-2).step(2)")].should == [2, 4]
+ @array[eval("(-4...-2).step(2)")].should == [2]
+
+ @array[eval("(-4..-2).step(10)")].should == [2]
+ @array[eval("(-4...-2).step(10)")].should == [2]
+ end
+
+ it "has closed range and negative steps" do
+ # start and end with 0
+ @array[eval("(0..0).step(-1)")].should == [0]
+ @array[eval("(0...0).step(-1)")].should == []
+
+ @array[eval("(0..0).step(-2)")].should == [0]
+ @array[eval("(0...0).step(-2)")].should == []
+
+ @array[eval("(0..0).step(-10)")].should == [0]
+ @array[eval("(0...0).step(-10)")].should == []
+
+ # start and end with positive index
+ @array[eval("(1..3).step(-1)")].should == []
+ @array[eval("(1...3).step(-1)")].should == []
+
+ @array[eval("(1..3).step(-2)")].should == []
+ @array[eval("(1...3).step(-2)")].should == []
+
+ @array[eval("(1..3).step(-10)")].should == []
+ @array[eval("(1...3).step(-10)")].should == []
+
+ # start with positive index, end with negative index
+ @array[eval("(1..-2).step(-1)")].should == []
+ @array[eval("(1...-2).step(-1)")].should == []
+
+ @array[eval("(1..-2).step(-2)")].should == []
+ @array[eval("(1...-2).step(-2)")].should == []
+
+ @array[eval("(1..-2).step(-10)")].should == []
+ @array[eval("(1...-2).step(-10)")].should == []
+
+ # start with negative index, end with positive index
+ @array[eval("(-4..4).step(-1)")].should == []
+ @array[eval("(-4...4).step(-1)")].should == []
+
+ @array[eval("(-4..4).step(-2)")].should == []
+ @array[eval("(-4...4).step(-2)")].should == []
+
+ @array[eval("(-4..4).step(-10)")].should == []
+ @array[eval("(-4...4).step(-10)")].should == []
+
+ # start with negative index, end with negative index
+ @array[eval("(-4..-2).step(-1)")].should == []
+ @array[eval("(-4...-2).step(-1)")].should == []
+
+ @array[eval("(-4..-2).step(-2)")].should == []
+ @array[eval("(-4...-2).step(-2)")].should == []
+
+ @array[eval("(-4..-2).step(-10)")].should == []
+ @array[eval("(-4...-2).step(-10)")].should == []
+ end
+
+ it "has inverted closed range and positive steps" do
+ # start and end with positive index
+ @array[eval("(3..1).step(1)")].should == []
+ @array[eval("(3...1).step(1)")].should == []
+
+ @array[eval("(3..1).step(2)")].should == []
+ @array[eval("(3...1).step(2)")].should == []
+
+ @array[eval("(3..1).step(10)")].should == []
+ @array[eval("(3...1).step(10)")].should == []
+
+ # start with negative index, end with positive index
+ @array[eval("(-2..1).step(1)")].should == []
+ @array[eval("(-2...1).step(1)")].should == []
+
+ @array[eval("(-2..1).step(2)")].should == []
+ @array[eval("(-2...1).step(2)")].should == []
+
+ @array[eval("(-2..1).step(10)")].should == []
+ @array[eval("(-2...1).step(10)")].should == []
+
+ # start with positive index, end with negative index
+ @array[eval("(4..-4).step(1)")].should == []
+ @array[eval("(4...-4).step(1)")].should == []
+
+ @array[eval("(4..-4).step(2)")].should == []
+ @array[eval("(4...-4).step(2)")].should == []
+
+ @array[eval("(4..-4).step(10)")].should == []
+ @array[eval("(4...-4).step(10)")].should == []
+
+ # start with negative index, end with negative index
+ @array[eval("(-2..-4).step(1)")].should == []
+ @array[eval("(-2...-4).step(1)")].should == []
+
+ @array[eval("(-2..-4).step(2)")].should == []
+ @array[eval("(-2...-4).step(2)")].should == []
+
+ @array[eval("(-2..-4).step(10)")].should == []
+ @array[eval("(-2...-4).step(10)")].should == []
+ end
+
+ it "has range with bounds outside of array" do
+ # end is equal to array's length
+ @array[(0..6).step(1)].should == [0, 1, 2, 3, 4, 5]
+ -> { @array[(0..6).step(2)] }.should.raise(RangeError)
+
+ # end is greater than length with positive steps
+ @array[(1..6).step(2)].should == [1, 3, 5]
+ @array[(2..7).step(2)].should == [2, 4]
+ -> { @array[(2..8).step(2)] }.should.raise(RangeError)
+
+ # begin is greater than length with negative steps
+ @array[(6..1).step(-2)].should == [5, 3, 1]
+ @array[(7..2).step(-2)].should == [5, 3]
+ -> { @array[(8..2).step(-2)] }.should.raise(RangeError)
+ end
+
+ it "has endless range with start outside of array's bounds" do
+ @array[eval("(6..).step(1)")].should == []
+ @array[eval("(7..).step(1)")].should == nil
+
+ @array[eval("(6..).step(2)")].should == []
+ -> { @array[eval("(7..).step(2)")] }.should.raise(RangeError)
+ end
+ end
+
+ it "can accept beginless ranges" do
+ a = [0, 1, 2, 3, 4, 5]
+ a[(..3)].should == [0, 1, 2, 3]
+ a[(...3)].should == [0, 1, 2]
+ a[(..-3)].should == [0, 1, 2, 3]
+ a[(...-3)].should == [0, 1, 2]
+ a[(..0)].should == [0]
+ a[(...0)].should == []
+ a[(..9)].should == [0, 1, 2, 3, 4, 5]
+ a[(...9)].should == [0, 1, 2, 3, 4, 5]
+ a[(..-9)].should == []
+ a[(...-9)].should == []
+ end
+
+ describe "can be sliced with Enumerator::ArithmeticSequence" do
+ it "with infinite/inverted ranges and negative steps" do
+ array = [0, 1, 2, 3, 4, 5]
+ array[(2..).step(-1)].should == [2, 1, 0]
+ array[(2..).step(-2)].should == [2, 0]
+ array[(2..).step(-3)].should == [2]
+ array[(2..).step(-4)].should == [2]
+
+ array[(-3..).step(-1)].should == [3, 2, 1, 0]
+ array[(-3..).step(-2)].should == [3, 1]
+ array[(-3..).step(-3)].should == [3, 0]
+ array[(-3..).step(-4)].should == [3]
+ array[(-3..).step(-5)].should == [3]
+
+ array[(..0).step(-1)].should == [5, 4, 3, 2, 1, 0]
+ array[(..0).step(-2)].should == [5, 3, 1]
+ array[(..0).step(-3)].should == [5, 2]
+ array[(..0).step(-4)].should == [5, 1]
+ array[(..0).step(-5)].should == [5, 0]
+ array[(..0).step(-6)].should == [5]
+ array[(..0).step(-7)].should == [5]
+
+ array[(...0).step(-1)].should == [5, 4, 3, 2, 1]
+ array[(...0).step(-2)].should == [5, 3, 1]
+ array[(...0).step(-3)].should == [5, 2]
+ array[(...0).step(-4)].should == [5, 1]
+ array[(...0).step(-5)].should == [5]
+ array[(...0).step(-6)].should == [5]
+
+ array[(...1).step(-1)].should == [5, 4, 3, 2]
+ array[(...1).step(-2)].should == [5, 3]
+ array[(...1).step(-3)].should == [5, 2]
+ array[(...1).step(-4)].should == [5]
+ array[(...1).step(-5)].should == [5]
+
+ array[(..-5).step(-1)].should == [5, 4, 3, 2, 1]
+ array[(..-5).step(-2)].should == [5, 3, 1]
+ array[(..-5).step(-3)].should == [5, 2]
+ array[(..-5).step(-4)].should == [5, 1]
+ array[(..-5).step(-5)].should == [5]
+ array[(..-5).step(-6)].should == [5]
+
+ array[(...-5).step(-1)].should == [5, 4, 3, 2]
+ array[(...-5).step(-2)].should == [5, 3]
+ array[(...-5).step(-3)].should == [5, 2]
+ array[(...-5).step(-4)].should == [5]
+ array[(...-5).step(-5)].should == [5]
+
+ array[(4..1).step(-1)].should == [4, 3, 2, 1]
+ array[(4..1).step(-2)].should == [4, 2]
+ array[(4..1).step(-3)].should == [4, 1]
+ array[(4..1).step(-4)].should == [4]
+ array[(4..1).step(-5)].should == [4]
+
+ array[(4...1).step(-1)].should == [4, 3, 2]
+ array[(4...1).step(-2)].should == [4, 2]
+ array[(4...1).step(-3)].should == [4]
+ array[(4...1).step(-4)].should == [4]
+
+ array[(-2..1).step(-1)].should == [4, 3, 2, 1]
+ array[(-2..1).step(-2)].should == [4, 2]
+ array[(-2..1).step(-3)].should == [4, 1]
+ array[(-2..1).step(-4)].should == [4]
+ array[(-2..1).step(-5)].should == [4]
+
+ array[(-2...1).step(-1)].should == [4, 3, 2]
+ array[(-2...1).step(-2)].should == [4, 2]
+ array[(-2...1).step(-3)].should == [4]
+ array[(-2...1).step(-4)].should == [4]
+
+ array[(4..-5).step(-1)].should == [4, 3, 2, 1]
+ array[(4..-5).step(-2)].should == [4, 2]
+ array[(4..-5).step(-3)].should == [4, 1]
+ array[(4..-5).step(-4)].should == [4]
+ array[(4..-5).step(-5)].should == [4]
+
+ array[(4...-5).step(-1)].should == [4, 3, 2]
+ array[(4...-5).step(-2)].should == [4, 2]
+ array[(4...-5).step(-3)].should == [4]
+ array[(4...-5).step(-4)].should == [4]
+
+ array[(-2..-5).step(-1)].should == [4, 3, 2, 1]
+ array[(-2..-5).step(-2)].should == [4, 2]
+ array[(-2..-5).step(-3)].should == [4, 1]
+ array[(-2..-5).step(-4)].should == [4]
+ array[(-2..-5).step(-5)].should == [4]
+
+ array[(-2...-5).step(-1)].should == [4, 3, 2]
+ array[(-2...-5).step(-2)].should == [4, 2]
+ array[(-2...-5).step(-3)].should == [4]
+ array[(-2...-5).step(-4)].should == [4]
+ end
+ end
+
+ it "can accept nil...nil ranges" do
+ a = [0, 1, 2, 3, 4, 5]
+ a[eval("(nil...nil)")].should == a
+ a[(...nil)].should == a
+ a[eval("(nil..)")].should == a
+ end
end
describe "Array.[]" do
@@ -39,12 +892,12 @@ describe "Array.[]" do
end
it "returns an instance of the subclass" do
- ArraySpecs::MyArray[1, 2, 3].should be_an_instance_of(ArraySpecs::MyArray)
+ ArraySpecs::MyArray[1, 2, 3].should.instance_of?(ArraySpecs::MyArray)
end
it "does not call #initialize on the subclass instance" do
ArraySpecs::MyArray[1, 2, 3].should == [1, 2, 3]
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
end
end
diff --git a/spec/ruby/core/array/element_set_spec.rb b/spec/ruby/core/array/element_set_spec.rb
index df5ca9582e..671e4338de 100644
--- a/spec/ruby/core/array/element_set_spec.rb
+++ b/spec/ruby/core/array/element_set_spec.rb
@@ -95,8 +95,8 @@ describe "Array#[]=" do
it "checks frozen before attempting to coerce arguments" do
a = [1,2,3,4].freeze
- -> {a[:foo] = 1}.should raise_error(FrozenError)
- -> {a[:foo, :bar] = 1}.should raise_error(FrozenError)
+ -> {a[:foo] = 1}.should.raise(FrozenError)
+ -> {a[:foo, :bar] = 1}.should.raise(FrozenError)
end
it "sets elements in the range arguments when passed ranges" do
@@ -197,25 +197,25 @@ describe "Array#[]=" do
a[to .. from] = ["x"]
a.should == [1, "a", "b", "x", "c", 4]
- -> { a["a" .. "b"] = [] }.should raise_error(TypeError)
- -> { a[from .. "b"] = [] }.should raise_error(TypeError)
+ -> { a["a" .. "b"] = [] }.should.raise(TypeError)
+ -> { a[from .. "b"] = [] }.should.raise(TypeError)
end
it "raises an IndexError when passed indexes out of bounds" do
a = [1, 2, 3, 4]
- -> { a[-5] = "" }.should raise_error(IndexError)
- -> { a[-5, -1] = "" }.should raise_error(IndexError)
- -> { a[-5, 0] = "" }.should raise_error(IndexError)
- -> { a[-5, 1] = "" }.should raise_error(IndexError)
- -> { a[-5, 2] = "" }.should raise_error(IndexError)
- -> { a[-5, 10] = "" }.should raise_error(IndexError)
-
- -> { a[-5..-5] = "" }.should raise_error(RangeError)
- -> { a[-5...-5] = "" }.should raise_error(RangeError)
- -> { a[-5..-4] = "" }.should raise_error(RangeError)
- -> { a[-5...-4] = "" }.should raise_error(RangeError)
- -> { a[-5..10] = "" }.should raise_error(RangeError)
- -> { a[-5...10] = "" }.should raise_error(RangeError)
+ -> { a[-5] = "" }.should.raise(IndexError)
+ -> { a[-5, -1] = "" }.should.raise(IndexError)
+ -> { a[-5, 0] = "" }.should.raise(IndexError)
+ -> { a[-5, 1] = "" }.should.raise(IndexError)
+ -> { a[-5, 2] = "" }.should.raise(IndexError)
+ -> { a[-5, 10] = "" }.should.raise(IndexError)
+
+ -> { a[-5..-5] = "" }.should.raise(RangeError)
+ -> { a[-5...-5] = "" }.should.raise(RangeError)
+ -> { a[-5..-4] = "" }.should.raise(RangeError)
+ -> { a[-5...-4] = "" }.should.raise(RangeError)
+ -> { a[-5..10] = "" }.should.raise(RangeError)
+ -> { a[-5...10] = "" }.should.raise(RangeError)
# ok
a[0..-9] = [1]
@@ -239,7 +239,7 @@ describe "Array#[]=" do
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array[0, 0] = [] }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array[0, 0] = [] }.should.raise(FrozenError)
end
end
@@ -349,12 +349,12 @@ describe "Array#[]= with [index, count]" do
it "raises an IndexError when passed start and negative length" do
a = [1, 2, 3, 4]
- -> { a[-2, -1] = "" }.should raise_error(IndexError)
- -> { a[0, -1] = "" }.should raise_error(IndexError)
- -> { a[2, -1] = "" }.should raise_error(IndexError)
- -> { a[4, -1] = "" }.should raise_error(IndexError)
- -> { a[10, -1] = "" }.should raise_error(IndexError)
- -> { [1, 2, 3, 4, 5][2, -1] = [7, 8] }.should raise_error(IndexError)
+ -> { a[-2, -1] = "" }.should.raise(IndexError)
+ -> { a[0, -1] = "" }.should.raise(IndexError)
+ -> { a[2, -1] = "" }.should.raise(IndexError)
+ -> { a[4, -1] = "" }.should.raise(IndexError)
+ -> { a[10, -1] = "" }.should.raise(IndexError)
+ -> { [1, 2, 3, 4, 5][2, -1] = [7, 8] }.should.raise(IndexError)
end
end
diff --git a/spec/ruby/core/array/eql_spec.rb b/spec/ruby/core/array/eql_spec.rb
index 8565b94c60..9a7447c2e8 100644
--- a/spec/ruby/core/array/eql_spec.rb
+++ b/spec/ruby/core/array/eql_spec.rb
@@ -6,7 +6,7 @@ describe "Array#eql?" do
it_behaves_like :array_eql, :eql?
it "returns false if any corresponding elements are not #eql?" do
- [1, 2, 3, 4].should_not eql([1, 2, 3, 4.0])
+ [1, 2, 3, 4].should_not.eql?([1, 2, 3, 4.0])
end
it "returns false if other is not a kind of Array" do
@@ -14,6 +14,6 @@ describe "Array#eql?" do
obj.should_not_receive(:to_ary)
obj.should_not_receive(:eql?)
- [1, 2, 3].should_not eql(obj)
+ [1, 2, 3].should_not.eql?(obj)
end
end
diff --git a/spec/ruby/core/array/equal_value_spec.rb b/spec/ruby/core/array/equal_value_spec.rb
index a82e07b218..4f7c0ce5e3 100644
--- a/spec/ruby/core/array/equal_value_spec.rb
+++ b/spec/ruby/core/array/equal_value_spec.rb
@@ -10,17 +10,17 @@ describe "Array#==" do
obj.should_receive(:respond_to?).at_least(1).with(:to_ary).and_return(true)
obj.should_receive(:==).with([1]).at_least(1).and_return(true)
- ([1] == obj).should be_true
- ([[1]] == [obj]).should be_true
- ([[[1], 3], 2] == [[obj, 3], 2]).should be_true
+ ([1] == obj).should == true
+ ([[1]] == [obj]).should == true
+ ([[[1], 3], 2] == [[obj, 3], 2]).should == true
# recursive arrays
arr1 = [[1]]
arr1 << arr1
arr2 = [obj]
arr2 << arr2
- (arr1 == arr2).should be_true
- (arr2 == arr1).should be_true
+ (arr1 == arr2).should == true
+ (arr2 == arr1).should == true
end
it "returns false if any corresponding elements are not #==" do
diff --git a/spec/ruby/core/array/fetch_spec.rb b/spec/ruby/core/array/fetch_spec.rb
index b81c0b48d7..ee94cfcbb2 100644
--- a/spec/ruby/core/array/fetch_spec.rb
+++ b/spec/ruby/core/array/fetch_spec.rb
@@ -12,9 +12,9 @@ describe "Array#fetch" do
end
it "raises an IndexError if there is no element at index" do
- -> { [1, 2, 3].fetch(3) }.should raise_error(IndexError)
- -> { [1, 2, 3].fetch(-4) }.should raise_error(IndexError)
- -> { [].fetch(0) }.should raise_error(IndexError)
+ -> { [1, 2, 3].fetch(3) }.should.raise(IndexError, "index 3 outside of array bounds: -3...3")
+ -> { [1, 2, 3].fetch(-4) }.should.raise(IndexError, "index -4 outside of array bounds: -3...3")
+ -> { [].fetch(0) }.should.raise(IndexError, "index 0 outside of array bounds: 0...0")
end
it "returns default if there is no element at index if passed a default value" do
@@ -33,7 +33,7 @@ describe "Array#fetch" do
o = mock('5')
def o.to_int(); 5; end
- [1, 2, 3].fetch(o) { |i| i }.should equal(o)
+ [1, 2, 3].fetch(o) { |i| i }.should.equal?(o)
end
it "gives precedence to the default block over the default argument" do
@@ -50,6 +50,6 @@ describe "Array#fetch" do
end
it "raises a TypeError when the passed argument can't be coerced to Integer" do
- -> { [].fetch("cat") }.should raise_error(TypeError)
+ -> { [].fetch("cat") }.should.raise(TypeError, "no implicit conversion of String into Integer")
end
end
diff --git a/spec/ruby/core/array/fetch_values_spec.rb b/spec/ruby/core/array/fetch_values_spec.rb
new file mode 100644
index 0000000000..237d6ad7f7
--- /dev/null
+++ b/spec/ruby/core/array/fetch_values_spec.rb
@@ -0,0 +1,55 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Array#fetch_values" do
+ before :each do
+ @array = [:a, :b, :c]
+ end
+
+ ruby_version_is "3.4" do
+ describe "with matched indexes" do
+ it "returns the values for indexes" do
+ @array.fetch_values(0).should == [:a]
+ @array.fetch_values(0, 2).should == [:a, :c]
+ @array.fetch_values(-1).should == [:c]
+ end
+
+ it "returns the values for indexes ordered in the order of the requested indexes" do
+ @array.fetch_values(2, 0).should == [:c, :a]
+ end
+ end
+
+ describe "with unmatched indexes" do
+ it "raises a index error if no block is provided" do
+ -> { @array.fetch_values(0, 1, 44) }.should.raise(IndexError, "index 44 outside of array bounds: -3...3")
+ end
+
+ it "returns the default value from block" do
+ @array.fetch_values(44) { |index| "`#{index}' is not found" }.should == ["`44' is not found"]
+ @array.fetch_values(0, 44) { |index| "`#{index}' is not found" }.should == [:a, "`44' is not found"]
+ end
+ end
+
+ describe "without keys" do
+ it "returns an empty Array" do
+ @array.fetch_values.should == []
+ end
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(2)
+ @array.fetch_values(obj).should == [:c]
+ end
+
+ it "does not support a Range object as argument" do
+ -> {
+ @array.fetch_values(1..2)
+ }.should.raise(TypeError, "no implicit conversion of Range into Integer")
+ end
+
+ it "raises a TypeError when the passed argument can't be coerced to Integer" do
+ -> { [].fetch_values("cat") }.should.raise(TypeError, "no implicit conversion of String into Integer")
+ end
+ end
+end
diff --git a/spec/ruby/core/array/fill_spec.rb b/spec/ruby/core/array/fill_spec.rb
index 23728414be..e4d51bd998 100644
--- a/spec/ruby/core/array/fill_spec.rb
+++ b/spec/ruby/core/array/fill_spec.rb
@@ -10,7 +10,7 @@ describe "Array#fill" do
it "returns self" do
ary = [1, 2, 3]
- ary.fill(:a).should equal(ary)
+ ary.fill(:a).should.equal?(ary)
end
it "is destructive" do
@@ -21,14 +21,14 @@ describe "Array#fill" do
it "does not replicate the filler" do
ary = [1, 2, 3, 4]
- str = "x"
+ str = +"x"
ary.fill(str).should == [str, str, str, str]
str << "y"
ary.should == [str, str, str, str]
- ary[0].should equal(str)
- ary[1].should equal(str)
- ary[2].should equal(str)
- ary[3].should equal(str)
+ ary[0].should.equal?(str)
+ ary[1].should.equal?(str)
+ ary[2].should.equal?(str)
+ ary[3].should.equal?(str)
end
it "replaces all elements in the array with the filler if not given a index nor a length" do
@@ -44,33 +44,71 @@ describe "Array#fill" do
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.fill('x') }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.fill('x') }.should.raise(FrozenError)
end
it "raises a FrozenError on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.fill('x') }.should raise_error(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.fill('x') }.should.raise(FrozenError)
end
it "raises an ArgumentError if 4 or more arguments are passed when no block given" do
- -> { [].fill('a') }.should_not raise_error(ArgumentError)
-
- -> { [].fill('a', 1) }.should_not raise_error(ArgumentError)
-
- -> { [].fill('a', 1, 2) }.should_not raise_error(ArgumentError)
- -> { [].fill('a', 1, 2, true) }.should raise_error(ArgumentError)
+ [].fill('a').should == []
+ [].fill('a', 1).should == []
+ [].fill('a', 1, 2).should == [nil, 'a', 'a']
+ -> { [].fill('a', 1, 2, true) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if no argument passed and no block given" do
- -> { [].fill }.should raise_error(ArgumentError)
+ -> { [].fill }.should.raise(ArgumentError)
end
it "raises an ArgumentError if 3 or more arguments are passed when a block given" do
- -> { [].fill() {|i|} }.should_not raise_error(ArgumentError)
+ [].fill() {|i|}.should == []
+ [].fill(1) {|i|}.should == []
+ [].fill(1, 2) {|i|}.should == [nil, nil, nil]
+ -> { [].fill(1, 2, true) {|i|} }.should.raise(ArgumentError)
+ end
+
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.fill { raise StandardError, 'Oops' }
+ rescue
+ end
- -> { [].fill(1) {|i|} }.should_not raise_error(ArgumentError)
+ a.should == [1, 2, 3]
+ end
+
+ it "only changes elements before error is raised, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.fill do |i|
+ case i
+ when 0 then -1
+ when 1 then -2
+ when 2 then raise StandardError, 'Oops'
+ else 0
+ end
+ end
+ rescue StandardError
+ end
+
+ a.should == [-1, -2, 3, 4]
+ end
+
+ it "tolerates increasing an array size during iteration" do
+ array = [:a, :b, :c]
+ ScratchPad.record []
+ i = 0
+
+ array.fill do |index|
+ ScratchPad << index
+ array << i if i < 100
+ i++
+ index
+ end
- -> { [].fill(1, 2) {|i|} }.should_not raise_error(ArgumentError)
- -> { [].fill(1, 2, true) {|i|} }.should raise_error(ArgumentError)
+ ScratchPad.recorded.should == [0, 1, 2]
end
end
@@ -169,25 +207,25 @@ describe "Array#fill with (filler, index, length)" do
[1, 2, 3, 4, 5].fill(-2, -2, &@never_passed).should == [1, 2, 3, 4, 5]
end
- # See: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/17481
+ # See: https://blade.ruby-lang.org/ruby-core/17481
it "does not raise an exception if the given length is negative and its absolute value does not exceed the index" do
- -> { [1, 2, 3, 4].fill('a', 3, -1)}.should_not raise_error(ArgumentError)
- -> { [1, 2, 3, 4].fill('a', 3, -2)}.should_not raise_error(ArgumentError)
- -> { [1, 2, 3, 4].fill('a', 3, -3)}.should_not raise_error(ArgumentError)
+ [1, 2, 3, 4].fill('a', 3, -1).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill('a', 3, -2).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill('a', 3, -3).should == [1, 2, 3, 4]
- -> { [1, 2, 3, 4].fill(3, -1, &@never_passed)}.should_not raise_error(ArgumentError)
- -> { [1, 2, 3, 4].fill(3, -2, &@never_passed)}.should_not raise_error(ArgumentError)
- -> { [1, 2, 3, 4].fill(3, -3, &@never_passed)}.should_not raise_error(ArgumentError)
+ [1, 2, 3, 4].fill(3, -1, &@never_passed).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill(3, -2, &@never_passed).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill(3, -3, &@never_passed).should == [1, 2, 3, 4]
end
it "does not raise an exception even if the given length is negative and its absolute value exceeds the index" do
- -> { [1, 2, 3, 4].fill('a', 3, -4)}.should_not raise_error(ArgumentError)
- -> { [1, 2, 3, 4].fill('a', 3, -5)}.should_not raise_error(ArgumentError)
- -> { [1, 2, 3, 4].fill('a', 3, -10000)}.should_not raise_error(ArgumentError)
+ [1, 2, 3, 4].fill('a', 3, -4).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill('a', 3, -5).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill('a', 3, -10000).should == [1, 2, 3, 4]
- -> { [1, 2, 3, 4].fill(3, -4, &@never_passed)}.should_not raise_error(ArgumentError)
- -> { [1, 2, 3, 4].fill(3, -5, &@never_passed)}.should_not raise_error(ArgumentError)
- -> { [1, 2, 3, 4].fill(3, -10000, &@never_passed)}.should_not raise_error(ArgumentError)
+ [1, 2, 3, 4].fill(3, -4, &@never_passed).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill(3, -5, &@never_passed).should == [1, 2, 3, 4]
+ [1, 2, 3, 4].fill(3, -10000, &@never_passed).should == [1, 2, 3, 4]
end
it "tries to convert the second and third arguments to Integers using #to_int" do
@@ -199,24 +237,24 @@ describe "Array#fill with (filler, index, length)" do
end
it "raises a TypeError if the index is not numeric" do
- -> { [].fill 'a', true }.should raise_error(TypeError)
+ -> { [].fill 'a', true }.should.raise(TypeError)
obj = mock('nonnumeric')
- -> { [].fill('a', obj) }.should raise_error(TypeError)
+ -> { [].fill('a', obj) }.should.raise(TypeError)
end
it "raises a TypeError when the length is not numeric" do
- -> { [1, 2, 3].fill("x", 1, "foo") }.should raise_error(TypeError, /no implicit conversion of String into Integer/)
- -> { [1, 2, 3].fill("x", 1, :"foo") }.should raise_error(TypeError, /no implicit conversion of Symbol into Integer/)
- -> { [1, 2, 3].fill("x", 1, Object.new) }.should raise_error(TypeError, /no implicit conversion of Object into Integer/)
+ -> { [1, 2, 3].fill("x", 1, "foo") }.should.raise(TypeError, /no implicit conversion of String into Integer/)
+ -> { [1, 2, 3].fill("x", 1, :"foo") }.should.raise(TypeError, /no implicit conversion of Symbol into Integer/)
+ -> { [1, 2, 3].fill("x", 1, Object.new) }.should.raise(TypeError, /no implicit conversion of Object into Integer/)
end
not_supported_on :opal do
it "raises an ArgumentError or RangeError for too-large sizes" do
error_types = [RangeError, ArgumentError]
arr = [1, 2, 3]
- -> { arr.fill(10, 1, fixnum_max) }.should raise_error { |err| error_types.should include(err.class) }
- -> { arr.fill(10, 1, bignum_value) }.should raise_error(RangeError)
+ -> { arr.fill(10, 1, fixnum_max) }.should.raise { |err| error_types.should.include?(err.class) }
+ -> { arr.fill(10, 1, bignum_value) }.should.raise(RangeError)
end
end
end
@@ -246,7 +284,7 @@ describe "Array#fill with (filler, range)" do
end
it "raises a TypeError with range and length argument" do
- -> { [].fill('x', 0 .. 2, 5) }.should raise_error(TypeError)
+ -> { [].fill('x', 0 .. 2, 5) }.should.raise(TypeError)
end
it "replaces elements between the (-m)th to the last and the (n+1)th from the first if given an range m..n where m < 0 and n >= 0" do
@@ -298,13 +336,13 @@ describe "Array#fill with (filler, range)" do
end
it "raises an exception if some of the given range lies before the first of the array" do
- -> { [1, 2, 3].fill('x', -5..-3) }.should raise_error(RangeError)
- -> { [1, 2, 3].fill('x', -5...-3) }.should raise_error(RangeError)
- -> { [1, 2, 3].fill('x', -5..-4) }.should raise_error(RangeError)
+ -> { [1, 2, 3].fill('x', -5..-3) }.should.raise(RangeError)
+ -> { [1, 2, 3].fill('x', -5...-3) }.should.raise(RangeError)
+ -> { [1, 2, 3].fill('x', -5..-4) }.should.raise(RangeError)
- -> { [1, 2, 3].fill(-5..-3, &@never_passed) }.should raise_error(RangeError)
- -> { [1, 2, 3].fill(-5...-3, &@never_passed) }.should raise_error(RangeError)
- -> { [1, 2, 3].fill(-5..-4, &@never_passed) }.should raise_error(RangeError)
+ -> { [1, 2, 3].fill(-5..-3, &@never_passed) }.should.raise(RangeError)
+ -> { [1, 2, 3].fill(-5...-3, &@never_passed) }.should.raise(RangeError)
+ -> { [1, 2, 3].fill(-5..-4, &@never_passed) }.should.raise(RangeError)
end
it "tries to convert the start and end of the passed range to Integers using #to_int" do
@@ -319,7 +357,7 @@ describe "Array#fill with (filler, range)" do
it "raises a TypeError if the start or end of the passed range is not numeric" do
obj = mock('nonnumeric')
def obj.<=>(rhs); rhs == self ? 0 : nil end
- -> { [].fill('a', obj..obj) }.should raise_error(TypeError)
+ -> { [].fill('a', obj..obj) }.should.raise(TypeError)
end
it "works with endless ranges" do
diff --git a/spec/ruby/core/array/filter_spec.rb b/spec/ruby/core/array/filter_spec.rb
index 156ad14f9c..6ebda61069 100644
--- a/spec/ruby/core/array/filter_spec.rb
+++ b/spec/ruby/core/array/filter_spec.rb
@@ -1,14 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'shared/select'
describe "Array#filter" do
- it_behaves_like :array_select, :filter
+ it "is an alias of Array#select" do
+ Array.instance_method(:filter).should == Array.instance_method(:select)
+ end
end
describe "Array#filter!" do
- it "returns nil if no changes were made in the array" do
- [1, 2, 3].filter! { true }.should be_nil
+ it "is an alias of Array#select!" do
+ Array.instance_method(:filter!).should == Array.instance_method(:select!)
end
-
- it_behaves_like :keep_if, :filter!
end
diff --git a/spec/ruby/core/array/find_index_spec.rb b/spec/ruby/core/array/find_index_spec.rb
index 759472024a..17ff6c04a7 100644
--- a/spec/ruby/core/array/find_index_spec.rb
+++ b/spec/ruby/core/array/find_index_spec.rb
@@ -1,6 +1,42 @@
require_relative '../../spec_helper'
-require_relative 'shared/index'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#find_index" do
- it_behaves_like :array_index, :find_index
+ it "returns the index of the first element == to object" do
+ x = mock('3')
+ def x.==(obj) 3 == obj; end
+
+ [2, x, 3, 1, 3, 1].find_index(3).should == 1
+ [2, 3.0, 3, x, 1, 3, 1].find_index(x).should == 1
+ end
+
+ it "returns 0 if first element == to object" do
+ [2, 1, 3, 2, 5].find_index(2).should == 0
+ end
+
+ it "returns size-1 if only last element == to object" do
+ [2, 1, 3, 1, 5].find_index(5).should == 4
+ end
+
+ it "returns nil if no element == to object" do
+ [2, 1, 1, 1, 1].find_index(3).should == nil
+ end
+
+ it "accepts a block instead of an argument" do
+ [4, 2, 1, 5, 1, 3].find_index {|x| x < 2}.should == 2
+ end
+
+ it "ignores the block if there is an argument" do
+ -> {
+ [4, 2, 1, 5, 1, 3].find_index(5) {|x| x < 2}.should == 3
+ }.should complain(/given block not used/)
+ end
+
+ describe "given no argument and no block" do
+ it "produces an Enumerator" do
+ [].find_index.should.instance_of?(Enumerator)
+ end
+ end
+
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :find_index
end
diff --git a/spec/ruby/core/array/first_spec.rb b/spec/ruby/core/array/first_spec.rb
index 66eeba6565..2c343ac8f6 100644
--- a/spec/ruby/core/array/first_spec.rb
+++ b/spec/ruby/core/array/first_spec.rb
@@ -30,11 +30,11 @@ describe "Array#first" do
end
it "raises an ArgumentError when count is negative" do
- -> { [1, 2].first(-1) }.should raise_error(ArgumentError)
+ -> { [1, 2].first(-1) }.should.raise(ArgumentError)
end
it "raises a RangeError when count is a Bignum" do
- -> { [].first(bignum_value) }.should raise_error(RangeError)
+ -> { [].first(bignum_value) }.should.raise(RangeError)
end
it "returns the entire array when count > length" do
@@ -53,10 +53,10 @@ describe "Array#first" do
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
- empty.first.should equal(empty)
+ empty.first.should.equal?(empty)
ary = ArraySpecs.head_recursive_array
- ary.first.should equal(ary)
+ ary.first.should.equal?(ary)
end
it "tries to convert the passed argument to an Integer using #to_int" do
@@ -66,19 +66,19 @@ describe "Array#first" do
end
it "raises a TypeError if the passed argument is not numeric" do
- -> { [1,2].first(nil) }.should raise_error(TypeError)
- -> { [1,2].first("a") }.should raise_error(TypeError)
+ -> { [1,2].first(nil) }.should.raise(TypeError)
+ -> { [1,2].first("a") }.should.raise(TypeError)
obj = mock("nonnumeric")
- -> { [1,2].first(obj) }.should raise_error(TypeError)
+ -> { [1,2].first(obj) }.should.raise(TypeError)
end
it "does not return subclass instance when passed count on Array subclasses" do
- ArraySpecs::MyArray[].first(0).should be_an_instance_of(Array)
- ArraySpecs::MyArray[].first(2).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].first(0).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].first(1).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].first(2).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[].first(0).should.instance_of?(Array)
+ ArraySpecs::MyArray[].first(2).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].first(0).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].first(1).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].first(2).should.instance_of?(Array)
end
it "is not destructive" do
diff --git a/spec/ruby/core/array/fixtures/classes.rb b/spec/ruby/core/array/fixtures/classes.rb
index aa5fecd96b..05283c0f74 100644
--- a/spec/ruby/core/array/fixtures/classes.rb
+++ b/spec/ruby/core/array/fixtures/classes.rb
@@ -56,23 +56,20 @@ module ArraySpecs
101.621, 102.816, 104.010, 105.202, 106.393, 107.583, 108.771, 109.958, 111.144, 112.329,
113.512, 114.695, 115.876, 117.057, 118.236, 119.414, 120.591, 121.767, 122.942, 124.116,
125.289, 126.462, 127.633, 128.803, 129.973, 131.141, 132.309, 133.476, 134.642, 135.807,
- ]
+ ]
def self.measure_sample_fairness(size, samples, iters)
ary = Array.new(size) { |x| x }
+ expected = iters.fdiv size
(samples).times do |i|
chi_results = []
3.times do
- counts = Array.new(size) { 0 }
- expected = iters / size
+ counts = Array.new(size, 0)
iters.times do
x = ary.sample(samples)[i]
counts[x] += 1
end
- chi_squared = 0.0
- counts.each do |count|
- chi_squared += (((count - expected) ** 2) * 1.0 / expected)
- end
+ chi_squared = counts.sum {|count| (count - expected) ** 2} / expected
chi_results << chi_squared
break if chi_squared <= CHI_SQUARED_CRITICAL_VALUES[size]
end
@@ -83,17 +80,14 @@ module ArraySpecs
def self.measure_sample_fairness_large_sample_size(size, samples, iters)
ary = Array.new(size) { |x| x }
- counts = Array.new(size) { 0 }
- expected = iters * samples / size
+ counts = Array.new(size, 0)
+ expected = (iters * samples).fdiv size
iters.times do
ary.sample(samples).each do |sample|
counts[sample] += 1
end
end
- chi_squared = 0.0
- counts.each do |count|
- chi_squared += (((count - expected) ** 2) * 1.0 / expected)
- end
+ chi_squared = counts.sum {|count| (count - expected) ** 2} / expected
# Chi squared critical values for tests with 4 degrees of freedom
# Values obtained from NIST Engineering Statistic Handbook at
@@ -160,6 +154,16 @@ module ArraySpecs
end
end
+ class ArrayMethodMissing
+ def initialize(*values, &block)
+ @values = values;
+ end
+
+ def method_missing(name, *args)
+ @values
+ end
+ end
+
class SortSame
def <=>(other); 0; end
def ==(other); true; end
@@ -213,366 +217,370 @@ module ArraySpecs
obj
end
- LargeArray = ["test_create_table_with_force_true_does_not_drop_nonexisting_table",
- "test_add_table",
- "assert_difference",
- "assert_operator",
- "instance_variables",
- "class",
- "instance_variable_get",
- "__class__",
- "expects",
- "assert_no_difference",
- "name",
- "assert_blank",
- "assert_not_same",
- "is_a?",
- "test_add_table_with_decimals",
- "test_create_table_with_timestamps_should_create_datetime_columns",
- "assert_present",
- "assert_no_match",
- "__instance_of__",
- "assert_deprecated",
- "assert",
- "assert_throws",
- "kind_of?",
- "try",
- "__instance_variable_get__",
- "object_id",
- "timeout",
- "instance_variable_set",
- "assert_nothing_thrown",
- "__instance_variable_set__",
- "copy_object",
- "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
- "assert_not_deprecated",
- "assert_in_delta",
- "id",
- "copy_metaclass",
- "test_create_table_without_a_block",
- "dup",
- "assert_not_nil",
- "send",
- "__instance_variables__",
- "to_sql",
- "mock",
- "assert_send",
- "instance_variable_defined?",
- "clone",
- "require",
- "test_migrator",
- "__instance_variable_defined_eh__",
- "frozen?",
- "test_add_column_not_null_with_default",
- "freeze",
- "test_migrator_one_up",
- "test_migrator_one_down",
- "singleton_methods",
- "method_exists?",
- "create_fixtures",
- "test_migrator_one_up_one_down",
- "test_native_decimal_insert_manual_vs_automatic",
- "instance_exec",
- "__is_a__",
- "test_migrator_double_up",
- "stub",
- "private_methods",
- "stubs",
- "test_migrator_double_down",
- "fixture_path",
- "private_singleton_methods",
- "stub_everything",
- "test_migrator_one_up_with_exception_and_rollback",
- "sequence",
- "protected_methods",
- "enum_for",
- "test_finds_migrations",
- "run_before_mocha",
- "states",
- "protected_singleton_methods",
- "to_json",
- "instance_values",
- "==",
- "mocha_setup",
- "public_methods",
- "test_finds_pending_migrations",
- "mocha_verify",
- "assert_kind_of",
- "===",
- "=~",
- "test_relative_migrations",
- "mocha_teardown",
- "gem",
- "mocha",
- "test_only_loads_pending_migrations",
- "test_add_column_with_precision_and_scale",
- "require_or_load",
- "eql?",
- "require_dependency",
- "test_native_types",
- "test_target_version_zero_should_run_only_once",
- "extend",
- "to_matcher",
- "unloadable",
- "require_association",
- "hash",
- "__id__",
- "load_dependency",
- "equals",
- "test_migrator_db_has_no_schema_migrations_table",
- "test_migrator_verbosity",
- "kind_of",
- "to_yaml",
- "to_bool",
- "test_migrator_verbosity_off",
- "taint",
- "test_migrator_going_down_due_to_version_target",
- "tainted?",
- "mocha_inspect",
- "test_migrator_rollback",
- "vim",
- "untaint",
- "taguri=",
- "test_migrator_forward",
- "test_schema_migrations_table_name",
- "test_proper_table_name",
- "all_of",
- "test_add_drop_table_with_prefix_and_suffix",
- "_setup_callbacks",
- "setup",
- "Not",
- "test_create_table_with_binary_column",
- "assert_not_equal",
- "enable_warnings",
- "acts_like?",
- "Rational",
- "_removed_setup_callbacks",
- "Table",
- "bind",
- "any_of",
- "__method__",
- "test_migrator_with_duplicates",
- "_teardown_callbacks",
- "method",
- "test_migrator_with_duplicate_names",
- "_removed_teardown_callbacks",
- "any_parameters",
- "test_migrator_with_missing_version_numbers",
- "test_add_remove_single_field_using_string_arguments",
- "test_create_table_with_custom_sequence_name",
- "test_add_remove_single_field_using_symbol_arguments",
- "_one_time_conditions_valid_14?",
- "_one_time_conditions_valid_16?",
- "run_callbacks",
- "anything",
- "silence_warnings",
- "instance_variable_names",
- "_fixture_path",
- "copy_instance_variables_from",
- "fixture_path?",
- "has_entry",
- "__marshal__",
- "_fixture_table_names",
- "__kind_of__",
- "fixture_table_names?",
- "test_add_rename",
- "assert_equal",
- "_fixture_class_names",
- "fixture_class_names?",
- "has_entries",
- "_use_transactional_fixtures",
- "people",
- "test_rename_column_using_symbol_arguments",
- "use_transactional_fixtures?",
- "instance_eval",
- "blank?",
- "with_warnings",
- "__nil__",
- "load",
- "metaclass",
- "_use_instantiated_fixtures",
- "has_key",
- "class_eval",
- "present?",
- "test_rename_column",
- "teardown",
- "use_instantiated_fixtures?",
- "method_name",
- "silence_stderr",
- "presence",
- "test_rename_column_preserves_default_value_not_null",
- "silence_stream",
- "_pre_loaded_fixtures",
- "__metaclass__",
- "__fixnum__",
- "pre_loaded_fixtures?",
- "has_value",
- "suppress",
- "to_yaml_properties",
- "test_rename_nonexistent_column",
- "test_add_index",
- "includes",
- "find_correlate_in",
- "equality_predicate_sql",
- "assert_nothing_raised",
- "let",
- "not_predicate_sql",
- "test_rename_column_with_sql_reserved_word",
- "singleton_class",
- "test_rename_column_with_an_index",
- "display",
- "taguri",
- "to_yaml_style",
- "test_remove_column_with_index",
- "size",
- "current_adapter?",
- "test_remove_column_with_multi_column_index",
- "respond_to?",
- "test_change_type_of_not_null_column",
- "is_a",
- "to_a",
- "test_rename_table_for_sqlite_should_work_with_reserved_words",
- "require_library_or_gem",
- "setup_fixtures",
- "equal?",
- "teardown_fixtures",
- "nil?",
- "fixture_table_names",
- "fixture_class_names",
- "test_create_table_without_id",
- "use_transactional_fixtures",
- "test_add_column_with_primary_key_attribute",
- "repair_validations",
- "use_instantiated_fixtures",
- "instance_of?",
- "test_create_table_adds_id",
- "test_rename_table",
- "pre_loaded_fixtures",
- "to_enum",
- "test_create_table_with_not_null_column",
- "instance_of",
- "test_change_column_nullability",
- "optionally",
- "test_rename_table_with_an_index",
- "run",
- "test_change_column",
- "default_test",
- "assert_raise",
- "test_create_table_with_defaults",
- "assert_nil",
- "flunk",
- "regexp_matches",
- "duplicable?",
- "reset_mocha",
- "stubba_method",
- "filter_backtrace",
- "test_create_table_with_limits",
- "responds_with",
- "stubba_object",
- "test_change_column_with_nil_default",
- "assert_block",
- "__show__",
- "assert_date_from_db",
- "__respond_to_eh__",
- "run_in_transaction?",
- "inspect",
- "assert_sql",
- "test_change_column_with_new_default",
- "yaml_equivalent",
- "build_message",
- "to_s",
- "test_change_column_default",
- "assert_queries",
- "pending",
- "as_json",
- "assert_no_queries",
- "test_change_column_quotes_column_names",
- "assert_match",
- "test_keeping_default_and_notnull_constraint_on_change",
- "methods",
- "connection_allow_concurrency_setup",
- "connection_allow_concurrency_teardown",
- "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
- "__send__",
- "make_connection",
- "assert_raises",
- "tap",
- "with_kcode",
- "assert_instance_of",
- "test_create_table_with_primary_key_prefix_as_table_name",
- "assert_respond_to",
- "test_change_column_default_to_null",
- "assert_same",
- "__extend__"]
-
- LargeTestArraySorted = ["test_add_column_not_null_with_default",
- "test_add_column_with_precision_and_scale",
- "test_add_column_with_primary_key_attribute",
- "test_add_drop_table_with_prefix_and_suffix",
- "test_add_index",
- "test_add_remove_single_field_using_string_arguments",
- "test_add_remove_single_field_using_symbol_arguments",
- "test_add_rename",
- "test_add_table",
- "test_add_table_with_decimals",
- "test_change_column",
- "test_change_column_default",
- "test_change_column_default_to_null",
- "test_change_column_nullability",
- "test_change_column_quotes_column_names",
- "test_change_column_with_new_default",
- "test_change_column_with_nil_default",
- "test_change_type_of_not_null_column",
- "test_create_table_adds_id",
- "test_create_table_with_binary_column",
- "test_create_table_with_custom_sequence_name",
- "test_create_table_with_defaults",
- "test_create_table_with_force_true_does_not_drop_nonexisting_table",
- "test_create_table_with_limits",
- "test_create_table_with_not_null_column",
- "test_create_table_with_primary_key_prefix_as_table_name",
- "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
- "test_create_table_with_timestamps_should_create_datetime_columns",
- "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
- "test_create_table_without_a_block",
- "test_create_table_without_id",
- "test_finds_migrations",
- "test_finds_pending_migrations",
- "test_keeping_default_and_notnull_constraint_on_change",
- "test_migrator",
- "test_migrator_db_has_no_schema_migrations_table",
- "test_migrator_double_down",
- "test_migrator_double_up",
- "test_migrator_forward",
- "test_migrator_going_down_due_to_version_target",
- "test_migrator_one_down",
- "test_migrator_one_up",
- "test_migrator_one_up_one_down",
- "test_migrator_one_up_with_exception_and_rollback",
- "test_migrator_rollback",
- "test_migrator_verbosity",
- "test_migrator_verbosity_off",
- "test_migrator_with_duplicate_names",
- "test_migrator_with_duplicates",
- "test_migrator_with_missing_version_numbers",
- "test_native_decimal_insert_manual_vs_automatic",
- "test_native_types",
- "test_only_loads_pending_migrations",
- "test_proper_table_name",
- "test_relative_migrations",
- "test_remove_column_with_index",
- "test_remove_column_with_multi_column_index",
- "test_rename_column",
- "test_rename_column_preserves_default_value_not_null",
- "test_rename_column_using_symbol_arguments",
- "test_rename_column_with_an_index",
- "test_rename_column_with_sql_reserved_word",
- "test_rename_nonexistent_column",
- "test_rename_table",
- "test_rename_table_for_sqlite_should_work_with_reserved_words",
- "test_rename_table_with_an_index",
- "test_schema_migrations_table_name",
- "test_target_version_zero_should_run_only_once"]
+ LargeArray = [
+ "test_create_table_with_force_true_does_not_drop_nonexisting_table",
+ "test_add_table",
+ "assert_difference",
+ "assert_operator",
+ "instance_variables",
+ "class",
+ "instance_variable_get",
+ "__class__",
+ "expects",
+ "assert_no_difference",
+ "name",
+ "assert_blank",
+ "assert_not_same",
+ "is_a?",
+ "test_add_table_with_decimals",
+ "test_create_table_with_timestamps_should_create_datetime_columns",
+ "assert_present",
+ "assert_no_match",
+ "__instance_of__",
+ "assert_deprecated",
+ "assert",
+ "assert_throws",
+ "kind_of?",
+ "try",
+ "__instance_variable_get__",
+ "object_id",
+ "timeout",
+ "instance_variable_set",
+ "assert_nothing_thrown",
+ "__instance_variable_set__",
+ "copy_object",
+ "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
+ "assert_not_deprecated",
+ "assert_in_delta",
+ "id",
+ "copy_metaclass",
+ "test_create_table_without_a_block",
+ "dup",
+ "assert_not_nil",
+ "send",
+ "__instance_variables__",
+ "to_sql",
+ "mock",
+ "assert_send",
+ "instance_variable_defined?",
+ "clone",
+ "require",
+ "test_migrator",
+ "__instance_variable_defined_eh__",
+ "frozen?",
+ "test_add_column_not_null_with_default",
+ "freeze",
+ "test_migrator_one_up",
+ "test_migrator_one_down",
+ "singleton_methods",
+ "method_exists?",
+ "create_fixtures",
+ "test_migrator_one_up_one_down",
+ "test_native_decimal_insert_manual_vs_automatic",
+ "instance_exec",
+ "__is_a__",
+ "test_migrator_double_up",
+ "stub",
+ "private_methods",
+ "stubs",
+ "test_migrator_double_down",
+ "fixture_path",
+ "private_singleton_methods",
+ "stub_everything",
+ "test_migrator_one_up_with_exception_and_rollback",
+ "sequence",
+ "protected_methods",
+ "enum_for",
+ "test_finds_migrations",
+ "run_before_mocha",
+ "states",
+ "protected_singleton_methods",
+ "to_json",
+ "instance_values",
+ "==",
+ "mocha_setup",
+ "public_methods",
+ "test_finds_pending_migrations",
+ "mocha_verify",
+ "assert_kind_of",
+ "===",
+ "=~",
+ "test_relative_migrations",
+ "mocha_teardown",
+ "gem",
+ "mocha",
+ "test_only_loads_pending_migrations",
+ "test_add_column_with_precision_and_scale",
+ "require_or_load",
+ "eql?",
+ "require_dependency",
+ "test_native_types",
+ "test_target_version_zero_should_run_only_once",
+ "extend",
+ "to_matcher",
+ "unloadable",
+ "require_association",
+ "hash",
+ "__id__",
+ "load_dependency",
+ "equals",
+ "test_migrator_db_has_no_schema_migrations_table",
+ "test_migrator_verbosity",
+ "kind_of",
+ "to_yaml",
+ "to_bool",
+ "test_migrator_verbosity_off",
+ "taint",
+ "test_migrator_going_down_due_to_version_target",
+ "tainted?",
+ "mocha_inspect",
+ "test_migrator_rollback",
+ "vim",
+ "untaint",
+ "taguri=",
+ "test_migrator_forward",
+ "test_schema_migrations_table_name",
+ "test_proper_table_name",
+ "all_of",
+ "test_add_drop_table_with_prefix_and_suffix",
+ "_setup_callbacks",
+ "setup",
+ "Not",
+ "test_create_table_with_binary_column",
+ "assert_not_equal",
+ "enable_warnings",
+ "acts_like?",
+ "Rational",
+ "_removed_setup_callbacks",
+ "Table",
+ "bind",
+ "any_of",
+ "__method__",
+ "test_migrator_with_duplicates",
+ "_teardown_callbacks",
+ "method",
+ "test_migrator_with_duplicate_names",
+ "_removed_teardown_callbacks",
+ "any_parameters",
+ "test_migrator_with_missing_version_numbers",
+ "test_add_remove_single_field_using_string_arguments",
+ "test_create_table_with_custom_sequence_name",
+ "test_add_remove_single_field_using_symbol_arguments",
+ "_one_time_conditions_valid_14?",
+ "_one_time_conditions_valid_16?",
+ "run_callbacks",
+ "anything",
+ "silence_warnings",
+ "instance_variable_names",
+ "_fixture_path",
+ "copy_instance_variables_from",
+ "fixture_path?",
+ "has_entry",
+ "__marshal__",
+ "_fixture_table_names",
+ "__kind_of__",
+ "fixture_table_names?",
+ "test_add_rename",
+ "assert_equal",
+ "_fixture_class_names",
+ "fixture_class_names?",
+ "has_entries",
+ "_use_transactional_fixtures",
+ "people",
+ "test_rename_column_using_symbol_arguments",
+ "use_transactional_fixtures?",
+ "instance_eval",
+ "blank?",
+ "with_warnings",
+ "__nil__",
+ "load",
+ "metaclass",
+ "_use_instantiated_fixtures",
+ "has_key",
+ "class_eval",
+ "present?",
+ "test_rename_column",
+ "teardown",
+ "use_instantiated_fixtures?",
+ "method_name",
+ "silence_stderr",
+ "presence",
+ "test_rename_column_preserves_default_value_not_null",
+ "silence_stream",
+ "_pre_loaded_fixtures",
+ "__metaclass__",
+ "__fixnum__",
+ "pre_loaded_fixtures?",
+ "has_value",
+ "suppress",
+ "to_yaml_properties",
+ "test_rename_nonexistent_column",
+ "test_add_index",
+ "includes",
+ "find_correlate_in",
+ "equality_predicate_sql",
+ "assert_nothing_raised",
+ "let",
+ "not_predicate_sql",
+ "test_rename_column_with_sql_reserved_word",
+ "singleton_class",
+ "test_rename_column_with_an_index",
+ "display",
+ "taguri",
+ "to_yaml_style",
+ "test_remove_column_with_index",
+ "size",
+ "current_adapter?",
+ "test_remove_column_with_multi_column_index",
+ "respond_to?",
+ "test_change_type_of_not_null_column",
+ "is_a",
+ "to_a",
+ "test_rename_table_for_sqlite_should_work_with_reserved_words",
+ "require_library_or_gem",
+ "setup_fixtures",
+ "equal?",
+ "teardown_fixtures",
+ "nil?",
+ "fixture_table_names",
+ "fixture_class_names",
+ "test_create_table_without_id",
+ "use_transactional_fixtures",
+ "test_add_column_with_primary_key_attribute",
+ "repair_validations",
+ "use_instantiated_fixtures",
+ "instance_of?",
+ "test_create_table_adds_id",
+ "test_rename_table",
+ "pre_loaded_fixtures",
+ "to_enum",
+ "test_create_table_with_not_null_column",
+ "instance_of",
+ "test_change_column_nullability",
+ "optionally",
+ "test_rename_table_with_an_index",
+ "run",
+ "test_change_column",
+ "default_test",
+ "assert_raise",
+ "test_create_table_with_defaults",
+ "assert_nil",
+ "flunk",
+ "regexp_matches",
+ "duplicable?",
+ "reset_mocha",
+ "stubba_method",
+ "filter_backtrace",
+ "test_create_table_with_limits",
+ "responds_with",
+ "stubba_object",
+ "test_change_column_with_nil_default",
+ "assert_block",
+ "__show__",
+ "assert_date_from_db",
+ "__respond_to_eh__",
+ "run_in_transaction?",
+ "inspect",
+ "assert_sql",
+ "test_change_column_with_new_default",
+ "yaml_equivalent",
+ "build_message",
+ "to_s",
+ "test_change_column_default",
+ "assert_queries",
+ "pending",
+ "as_json",
+ "assert_no_queries",
+ "test_change_column_quotes_column_names",
+ "assert_match",
+ "test_keeping_default_and_notnull_constraint_on_change",
+ "methods",
+ "connection_allow_concurrency_setup",
+ "connection_allow_concurrency_teardown",
+ "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
+ "__send__",
+ "make_connection",
+ "assert_raises",
+ "tap",
+ "with_kcode",
+ "assert_instance_of",
+ "test_create_table_with_primary_key_prefix_as_table_name",
+ "assert_respond_to",
+ "test_change_column_default_to_null",
+ "assert_same",
+ "__extend__",
+ ]
+
+ LargeTestArraySorted = [
+ "test_add_column_not_null_with_default",
+ "test_add_column_with_precision_and_scale",
+ "test_add_column_with_primary_key_attribute",
+ "test_add_drop_table_with_prefix_and_suffix",
+ "test_add_index",
+ "test_add_remove_single_field_using_string_arguments",
+ "test_add_remove_single_field_using_symbol_arguments",
+ "test_add_rename",
+ "test_add_table",
+ "test_add_table_with_decimals",
+ "test_change_column",
+ "test_change_column_default",
+ "test_change_column_default_to_null",
+ "test_change_column_nullability",
+ "test_change_column_quotes_column_names",
+ "test_change_column_with_new_default",
+ "test_change_column_with_nil_default",
+ "test_change_type_of_not_null_column",
+ "test_create_table_adds_id",
+ "test_create_table_with_binary_column",
+ "test_create_table_with_custom_sequence_name",
+ "test_create_table_with_defaults",
+ "test_create_table_with_force_true_does_not_drop_nonexisting_table",
+ "test_create_table_with_limits",
+ "test_create_table_with_not_null_column",
+ "test_create_table_with_primary_key_prefix_as_table_name",
+ "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
+ "test_create_table_with_timestamps_should_create_datetime_columns",
+ "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
+ "test_create_table_without_a_block",
+ "test_create_table_without_id",
+ "test_finds_migrations",
+ "test_finds_pending_migrations",
+ "test_keeping_default_and_notnull_constraint_on_change",
+ "test_migrator",
+ "test_migrator_db_has_no_schema_migrations_table",
+ "test_migrator_double_down",
+ "test_migrator_double_up",
+ "test_migrator_forward",
+ "test_migrator_going_down_due_to_version_target",
+ "test_migrator_one_down",
+ "test_migrator_one_up",
+ "test_migrator_one_up_one_down",
+ "test_migrator_one_up_with_exception_and_rollback",
+ "test_migrator_rollback",
+ "test_migrator_verbosity",
+ "test_migrator_verbosity_off",
+ "test_migrator_with_duplicate_names",
+ "test_migrator_with_duplicates",
+ "test_migrator_with_missing_version_numbers",
+ "test_native_decimal_insert_manual_vs_automatic",
+ "test_native_types",
+ "test_only_loads_pending_migrations",
+ "test_proper_table_name",
+ "test_relative_migrations",
+ "test_remove_column_with_index",
+ "test_remove_column_with_multi_column_index",
+ "test_rename_column",
+ "test_rename_column_preserves_default_value_not_null",
+ "test_rename_column_using_symbol_arguments",
+ "test_rename_column_with_an_index",
+ "test_rename_column_with_sql_reserved_word",
+ "test_rename_nonexistent_column",
+ "test_rename_table",
+ "test_rename_table_for_sqlite_should_work_with_reserved_words",
+ "test_rename_table_with_an_index",
+ "test_schema_migrations_table_name",
+ "test_target_version_zero_should_run_only_once",
+ ]
class PrivateToAry
private
diff --git a/spec/ruby/core/array/fixtures/encoded_strings.rb b/spec/ruby/core/array/fixtures/encoded_strings.rb
index 5b85bd0e06..b5888d86ae 100644
--- a/spec/ruby/core/array/fixtures/encoded_strings.rb
+++ b/spec/ruby/core/array/fixtures/encoded_strings.rb
@@ -2,14 +2,14 @@
module ArraySpecs
def self.array_with_usascii_and_7bit_utf8_strings
[
- 'foo'.force_encoding('US-ASCII'),
+ 'foo'.dup.force_encoding('US-ASCII'),
'bar'
]
end
def self.array_with_usascii_and_utf8_strings
[
- 'foo'.force_encoding('US-ASCII'),
+ 'foo'.dup.force_encoding('US-ASCII'),
'báz'
]
end
@@ -17,7 +17,7 @@ module ArraySpecs
def self.array_with_7bit_utf8_and_usascii_strings
[
'bar',
- 'foo'.force_encoding('US-ASCII')
+ 'foo'.dup.force_encoding('US-ASCII')
]
end
@@ -25,13 +25,13 @@ module ArraySpecs
[
'báz',
'bar',
- 'foo'.force_encoding('US-ASCII')
+ 'foo'.dup.force_encoding('US-ASCII')
]
end
def self.array_with_usascii_and_utf8_strings
[
- 'foo'.force_encoding('US-ASCII'),
+ 'foo'.dup.force_encoding('US-ASCII'),
'bar',
'báz'
]
@@ -41,7 +41,7 @@ module ArraySpecs
[
'bar',
'báz',
- 'foo'.force_encoding('BINARY')
+ 'foo'.dup.force_encoding('BINARY')
]
end
@@ -55,14 +55,14 @@ module ArraySpecs
def self.array_with_usascii_and_7bit_binary_strings
[
- 'bar'.force_encoding('US-ASCII'),
- 'foo'.force_encoding('BINARY')
+ 'bar'.dup.force_encoding('US-ASCII'),
+ 'foo'.dup.force_encoding('BINARY')
]
end
def self.array_with_usascii_and_binary_strings
[
- 'bar'.force_encoding('US-ASCII'),
+ 'bar'.dup.force_encoding('US-ASCII'),
[255].pack('C').force_encoding('BINARY')
]
end
diff --git a/spec/ruby/core/array/flatten_spec.rb b/spec/ruby/core/array/flatten_spec.rb
index 1770b5389a..272406b8f9 100644
--- a/spec/ruby/core/array/flatten_spec.rb
+++ b/spec/ruby/core/array/flatten_spec.rb
@@ -13,7 +13,7 @@ describe "Array#flatten" do
it "returns dup when the level of recursion is 0" do
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten(0).should == a
- a.flatten(0).should_not equal(a)
+ a.flatten(0).should_not.equal?(a)
end
it "ignores negative levels" do
@@ -30,7 +30,7 @@ describe "Array#flatten" do
it "raises a TypeError when the passed Object can't be converted to an Integer" do
obj = mock("Not converted")
- -> { [ 1, 2, [3, [4, 5] ] ].flatten(obj) }.should raise_error(TypeError)
+ -> { [ 1, 2, [3, [4, 5] ] ].flatten(obj) }.should.raise(TypeError)
end
it "does not call flatten on elements" do
@@ -46,13 +46,13 @@ describe "Array#flatten" do
it "raises an ArgumentError on recursive arrays" do
x = []
x << x
- -> { x.flatten }.should raise_error(ArgumentError)
+ -> { x.flatten }.should.raise(ArgumentError)
x = []
y = []
x << y
y << x
- -> { x.flatten }.should raise_error(ArgumentError)
+ -> { x.flatten }.should.raise(ArgumentError)
end
it "flattens any element which responds to #to_ary, using the return value of said method" do
@@ -75,24 +75,12 @@ describe "Array#flatten" do
[[obj]].flatten(1)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instance for Array subclasses" do
- ArraySpecs::MyArray[].flatten.should be_an_instance_of(ArraySpecs::MyArray)
- ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
- ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
- ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == ArraySpecs::MyArray[1, 2, 3, 4]
- [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns Array instance for Array subclasses" do
- ArraySpecs::MyArray[].flatten.should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == [1, 2, 3, 4]
- [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array)
- end
+ it "returns Array instance for Array subclasses" do
+ ArraySpecs::MyArray[].flatten.should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].flatten.should.instance_of?(Array)
+ ArraySpecs::MyArray[1, [2], 3].flatten.should.instance_of?(Array)
+ ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == [1, 2, 3, 4]
+ [ArraySpecs::MyArray[1, 2, 3]].flatten.should.instance_of?(Array)
end
it "is not destructive" do
@@ -118,7 +106,7 @@ describe "Array#flatten" do
it "raises a TypeError if #to_ary does not return an Array" do
@obj.should_receive(:to_ary).and_return(1)
- -> { [@obj].flatten }.should raise_error(TypeError)
+ -> { [@obj].flatten }.should.raise(TypeError)
end
it "calls respond_to_missing?(:to_ary, true) to try coercing" do
@@ -137,7 +125,7 @@ describe "Array#flatten" do
it "calls #to_ary if not defined when #respond_to_missing? returns true" do
def @obj.respond_to_missing?(name, priv) ScratchPad << name; true end
- -> { [@obj].flatten }.should raise_error(NoMethodError)
+ -> { [@obj].flatten }.should.raise(NoMethodError)
ScratchPad.recorded.should == [:to_ary]
end
@@ -180,7 +168,7 @@ describe "Array#flatten!" do
it "returns self if made some modifications" do
a = [[[1, [2, 3]],[2, 3, [4, [4, [5, 5]], [1, 2, 3]]], [4]], []]
- a.flatten!.should equal(a)
+ a.flatten!.should.equal?(a)
end
it "returns nil if no modifications took place" do
@@ -220,7 +208,7 @@ describe "Array#flatten!" do
it "raises a TypeError when the passed Object can't be converted to an Integer" do
obj = mock("Not converted")
- -> { [ 1, 2, [3, [4, 5] ] ].flatten!(obj) }.should raise_error(TypeError)
+ -> { [ 1, 2, [3, [4, 5] ] ].flatten!(obj) }.should.raise(TypeError)
end
it "does not call flatten! on elements" do
@@ -236,13 +224,13 @@ describe "Array#flatten!" do
it "raises an ArgumentError on recursive arrays" do
x = []
x << x
- -> { x.flatten! }.should raise_error(ArgumentError)
+ -> { x.flatten! }.should.raise(ArgumentError)
x = []
y = []
x << y
y << x
- -> { x.flatten! }.should raise_error(ArgumentError)
+ -> { x.flatten! }.should.raise(ArgumentError)
end
it "flattens any elements which responds to #to_ary, using the return value of said method" do
@@ -260,19 +248,19 @@ describe "Array#flatten!" do
ary = [ArraySpecs::MyArray[1, 2, 3]]
ary.flatten!
- ary.should be_an_instance_of(Array)
+ ary.should.instance_of?(Array)
ary.should == [1, 2, 3]
end
it "raises a FrozenError on frozen arrays when the array is modified" do
nested_ary = [1, 2, []]
nested_ary.freeze
- -> { nested_ary.flatten! }.should raise_error(FrozenError)
+ -> { nested_ary.flatten! }.should.raise(FrozenError)
end
# see [ruby-core:23663]
it "raises a FrozenError on frozen arrays when the array would not be modified" do
- -> { ArraySpecs.frozen_array.flatten! }.should raise_error(FrozenError)
- -> { ArraySpecs.empty_frozen_array.flatten! }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.flatten! }.should.raise(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.flatten! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/hash_spec.rb b/spec/ruby/core/array/hash_spec.rb
index f3bcc83fce..3b7b6d5bed 100644
--- a/spec/ruby/core/array/hash_spec.rb
+++ b/spec/ruby/core/array/hash_spec.rb
@@ -7,16 +7,16 @@ describe "Array#hash" do
[[], [1, 2, 3]].each do |ary|
ary.hash.should == ary.dup.hash
- ary.hash.should be_an_instance_of(Integer)
+ ary.hash.should.instance_of?(Integer)
end
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
- -> { empty.hash }.should_not raise_error
+ -> { empty.hash }.should_not.raise
array = ArraySpecs.recursive_array
- -> { array.hash }.should_not raise_error
+ -> { array.hash }.should_not.raise
end
it "returns the same hash for equal recursive arrays" do
@@ -74,7 +74,7 @@ describe "Array#hash" do
a.fill 'a', 0..3
b = %w|a a a a|
a.hash.should == b.hash
- a.should eql(b)
+ a.should.eql?(b)
end
it "produces different hashes for nested arrays with different values and empty terminator" do
diff --git a/spec/ruby/core/array/index_spec.rb b/spec/ruby/core/array/index_spec.rb
index 3acb7d0ef3..b66cb6eb53 100644
--- a/spec/ruby/core/array/index_spec.rb
+++ b/spec/ruby/core/array/index_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/index'
describe "Array#index" do
- it_behaves_like :array_index, :index
+ it "is an alias of Array#find_index" do
+ Array.instance_method(:index).should == Array.instance_method(:find_index)
+ end
end
diff --git a/spec/ruby/core/array/initialize_spec.rb b/spec/ruby/core/array/initialize_spec.rb
index a8deed2b84..19ee37825e 100644
--- a/spec/ruby/core/array/initialize_spec.rb
+++ b/spec/ruby/core/array/initialize_spec.rb
@@ -7,7 +7,7 @@ describe "Array#initialize" do
end
it "is private" do
- Array.should have_private_instance_method("initialize")
+ Array.private_instance_methods(false).should.include?(:initialize)
end
it "is called on subclasses" do
@@ -19,26 +19,26 @@ describe "Array#initialize" do
it "preserves the object's identity even when changing its value" do
a = [1, 2, 3]
- a.send(:initialize).should equal(a)
+ a.send(:initialize).should.equal?(a)
a.should_not == [1, 2, 3]
end
it "raises an ArgumentError if passed 3 or more arguments" do
-> do
[1, 2].send :initialize, 1, 'x', true
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
-> do
[1, 2].send(:initialize, 1, 'x', true) {}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "raises a FrozenError on frozen arrays" do
-> do
ArraySpecs.frozen_array.send :initialize
- end.should raise_error(FrozenError)
+ end.should.raise(FrozenError)
-> do
ArraySpecs.frozen_array.send :initialize, ArraySpecs.frozen_array
- end.should raise_error(FrozenError)
+ end.should.raise(FrozenError)
end
it "calls #to_ary to convert the value to an array, even if it's private" do
@@ -49,11 +49,13 @@ end
describe "Array#initialize with no arguments" do
it "makes the array empty" do
- [1, 2, 3].send(:initialize).should be_empty
+ [1, 2, 3].send(:initialize).should.empty?
end
it "does not use the given block" do
- ->{ [1, 2, 3].send(:initialize) { raise } }.should_not raise_error
+ -> {
+ -> { [1, 2, 3].send(:initialize) { raise } }.should_not.raise
+ }.should complain(/#{__FILE__}:#{__LINE__-1}: warning: given block not used/, verbose: true)
end
end
@@ -64,7 +66,7 @@ describe "Array#initialize with (array)" do
end
it "does not use the given block" do
- ->{ [1, 2, 3].send(:initialize) { raise } }.should_not raise_error
+ ->{ [1, 2, 3].send(:initialize) { raise } }.should_not.raise
end
it "calls #to_ary to convert the value to an array" do
@@ -81,7 +83,7 @@ describe "Array#initialize with (array)" do
end
it "raises a TypeError if an Array type argument and a default object" do
- -> { [].send(:initialize, [1, 2], 1) }.should raise_error(TypeError)
+ -> { [].send(:initialize, [1, 2], 1) }.should.raise(TypeError)
end
end
@@ -90,8 +92,8 @@ describe "Array#initialize with (size, object=nil)" do
a = []
obj = [3]
a.send(:initialize, 2, obj).should == [obj, obj]
- a[0].should equal(obj)
- a[1].should equal(obj)
+ a[0].should.equal?(obj)
+ a[1].should.equal?(obj)
b = []
b.send(:initialize, 3, 14).should == [14, 14, 14]
@@ -103,12 +105,12 @@ describe "Array#initialize with (size, object=nil)" do
end
it "raises an ArgumentError if size is negative" do
- -> { [].send(:initialize, -1, :a) }.should raise_error(ArgumentError)
- -> { [].send(:initialize, -1) }.should raise_error(ArgumentError)
+ -> { [].send(:initialize, -1, :a) }.should.raise(ArgumentError)
+ -> { [].send(:initialize, -1) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if size is too large" do
- -> { [].send(:initialize, fixnum_max+1) }.should raise_error(ArgumentError)
+ -> { [].send(:initialize, fixnum_max+1) }.should.raise(ArgumentError)
end
it "calls #to_int to convert the size argument to an Integer when object is given" do
@@ -126,7 +128,7 @@ describe "Array#initialize with (size, object=nil)" do
it "raises a TypeError if the size argument is not an Integer type" do
obj = mock('nonnumeric')
obj.stub!(:to_ary).and_return([1, 2])
- ->{ [].send(:initialize, obj, :a) }.should raise_error(TypeError)
+ ->{ [].send(:initialize, obj, :a) }.should.raise(TypeError)
end
it "yields the index of the element and sets the element to the value of the block" do
diff --git a/spec/ruby/core/array/insert_spec.rb b/spec/ruby/core/array/insert_spec.rb
index 9e1757f68b..38e132fd25 100644
--- a/spec/ruby/core/array/insert_spec.rb
+++ b/spec/ruby/core/array/insert_spec.rb
@@ -4,8 +4,8 @@ require_relative 'fixtures/classes'
describe "Array#insert" do
it "returns self" do
ary = []
- ary.insert(0).should equal(ary)
- ary.insert(0, :a).should equal(ary)
+ ary.insert(0).should.equal?(ary)
+ ary.insert(0, :a).should.equal?(ary)
end
it "inserts objects before the element at index for non-negative index" do
@@ -46,8 +46,8 @@ describe "Array#insert" do
end
it "raises an IndexError if the negative index is out of bounds" do
- -> { [].insert(-2, 1) }.should raise_error(IndexError)
- -> { [1].insert(-3, 2) }.should raise_error(IndexError)
+ -> { [].insert(-2, 1) }.should.raise(IndexError)
+ -> { [1].insert(-3, 2) }.should.raise(IndexError)
end
it "does nothing of no object is passed" do
@@ -64,15 +64,15 @@ describe "Array#insert" do
end
it "raises an ArgumentError if no argument passed" do
- -> { [].insert() }.should raise_error(ArgumentError)
+ -> { [].insert() }.should.raise(ArgumentError)
end
it "raises a FrozenError on frozen arrays when the array is modified" do
- -> { ArraySpecs.frozen_array.insert(0, 'x') }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.insert(0, 'x') }.should.raise(FrozenError)
end
# see [ruby-core:23666]
it "raises a FrozenError on frozen arrays when the array would not be modified" do
- -> { ArraySpecs.frozen_array.insert(0) }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.insert(0) }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/inspect_spec.rb b/spec/ruby/core/array/inspect_spec.rb
index 0832224f5a..e5dca82889 100644
--- a/spec/ruby/core/array/inspect_spec.rb
+++ b/spec/ruby/core/array/inspect_spec.rb
@@ -1,7 +1,108 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/inspect'
describe "Array#inspect" do
- it_behaves_like :array_inspect, :inspect
+ it "returns a string" do
+ [1, 2, 3].inspect.should.instance_of?(String)
+ end
+
+ it "returns '[]' for an empty Array" do
+ [].inspect.should == "[]"
+ end
+
+ it "calls inspect on its elements and joins the results with commas" do
+ items = Array.new(3) do |i|
+ obj = mock(i.to_s)
+ obj.should_receive(:inspect).and_return(i.to_s)
+ obj
+ end
+ items.inspect.should == "[0, 1, 2]"
+ end
+
+ it "does not call #to_s on a String returned from #inspect" do
+ str = +"abc"
+ str.should_not_receive(:to_s)
+
+ [str].inspect.should == '["abc"]'
+ end
+
+ it "calls #to_s on the object returned from #inspect if the Object isn't a String" do
+ obj = mock("Array#inspect/to_s calls #to_s")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_receive(:to_s).and_return("abc")
+
+ [obj].inspect.should == "[abc]"
+ end
+
+ it "does not call #to_str on the object returned from #inspect when it is not a String" do
+ obj = mock("Array#inspect/to_s does not call #to_str")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_not_receive(:to_str)
+
+ [obj].inspect.should =~ /^\[#<MockObject:0x[0-9a-f]+>\]$/
+ end
+
+ it "does not call #to_str on the object returned from #to_s when it is not a String" do
+ obj = mock("Array#inspect/to_s does not call #to_str on #to_s result")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_receive(:to_s).and_return(obj)
+ obj.should_not_receive(:to_str)
+
+ [obj].inspect.should =~ /^\[#<MockObject:0x[0-9a-f]+>\]$/
+ end
+
+ it "does not swallow exceptions raised by #to_s" do
+ obj = mock("Array#inspect/to_s does not swallow #to_s exceptions")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_receive(:to_s).and_raise(Exception)
+
+ -> { [obj].inspect }.should.raise(Exception)
+ end
+
+ it "represents a recursive element with '[...]'" do
+ ArraySpecs.recursive_array.inspect.should == "[1, \"two\", 3.0, [...], [...], [...], [...], [...]]"
+ ArraySpecs.head_recursive_array.inspect.should == "[[...], [...], [...], [...], [...], 1, \"two\", 3.0]"
+ ArraySpecs.empty_recursive_array.inspect.should == "[[...]]"
+ end
+
+ describe "with encoding" do
+ before :each do
+ @default_external_encoding = Encoding.default_external
+ end
+
+ after :each do
+ Encoding.default_external = @default_external_encoding
+ end
+
+ it "returns a US-ASCII string for an empty Array" do
+ [].inspect.encoding.should == Encoding::US_ASCII
+ end
+
+ it "use the default external encoding if it is ascii compatible" do
+ Encoding.default_external = Encoding.find('UTF-8')
+
+ utf8 = "utf8".encode("UTF-8")
+ jp = "jp".encode("EUC-JP")
+ array = [jp, utf8]
+
+ array.inspect.encoding.name.should == "UTF-8"
+ end
+
+ it "use US-ASCII encoding if the default external encoding is not ascii compatible" do
+ Encoding.default_external = Encoding.find('UTF-32')
+
+ utf8 = "utf8".encode("UTF-8")
+ jp = "jp".encode("EUC-JP")
+ array = [jp, utf8]
+
+ array.inspect.encoding.name.should == "US-ASCII"
+ end
+
+ it "does not raise if inspected result is not default external encoding" do
+ utf_16be = mock(+"utf_16be")
+ utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode(Encoding::UTF_16BE))
+
+ [utf_16be].inspect.should == '["utf_16be \u3042"]'
+ end
+ end
end
diff --git a/spec/ruby/core/array/intersect_spec.rb b/spec/ruby/core/array/intersect_spec.rb
index b8c5b1e69a..456aa26c6e 100644
--- a/spec/ruby/core/array/intersect_spec.rb
+++ b/spec/ruby/core/array/intersect_spec.rb
@@ -1,17 +1,64 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'Array#intersect?' do
- ruby_version_is '3.1' do # https://bugs.ruby-lang.org/issues/15198
- describe 'when at least one element in two Arrays is the same' do
- it 'returns true' do
- [1, 2].intersect?([2, 3]).should == true
- end
+ describe 'when at least one element in two Arrays is the same' do
+ it 'returns true' do
+ [1, 2].intersect?([2, 3, 4]).should == true
+ [2, 3, 4].intersect?([1, 2]).should == true
end
+ end
- describe 'when there are no elements in common between two Arrays' do
- it 'returns false' do
- [1, 2].intersect?([3, 4]).should == false
- end
+ describe 'when there are no elements in common between two Arrays' do
+ it 'returns false' do
+ [0, 1, 2].intersect?([3, 4]).should == false
+ [3, 4].intersect?([0, 1, 2]).should == false
+ [3, 4].intersect?([]).should == false
+ [].intersect?([0, 1, 2]).should == false
end
end
+
+ it "tries to convert the passed argument to an Array using #to_ary" do
+ obj = mock('[1,2,3]')
+ obj.should_receive(:to_ary).and_return([1, 2, 3])
+
+ [1, 2].intersect?(obj).should == true
+ end
+
+ it "determines equivalence between elements in the sense of eql?" do
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.stub!(:eql?).and_return(true)
+ obj2.stub!(:eql?).and_return(true)
+
+ [obj1].intersect?([obj2]).should == true
+
+ obj1 = mock('3')
+ obj2 = mock('4')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.stub!(:eql?).and_return(false)
+ obj2.stub!(:eql?).and_return(false)
+
+ [obj1].intersect?([obj2]).should == false
+ end
+
+ it "does not call to_ary on array subclasses" do
+ [5, 6].intersect?(ArraySpecs::ToAryArray[1, 2, 5, 6]).should == true
+ end
+
+ it "properly handles an identical item even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.stub!(:hash).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ [x].intersect?([x]).should == true
+ end
+
+ it "has semantic of !(a & b).empty?" do
+ [].intersect?([]).should == false
+ [nil].intersect?([nil]).should == true
+ end
end
diff --git a/spec/ruby/core/array/join_spec.rb b/spec/ruby/core/array/join_spec.rb
index e78ea6f9e1..3b4946a99f 100644
--- a/spec/ruby/core/array/join_spec.rb
+++ b/spec/ruby/core/array/join_spec.rb
@@ -4,7 +4,6 @@ require_relative 'shared/join'
describe "Array#join" do
it_behaves_like :array_join_with_string_separator, :join
- it_behaves_like :array_join_with_default_separator, :join
it "does not separate elements when the passed separator is nil" do
[1, 2, 3].join(nil).should == '123'
@@ -24,11 +23,108 @@ describe "Array#join" do
it "raises a TypeError if the separator cannot be coerced to a String by calling #to_str" do
obj = mock("not a string")
- -> { [1, 2].join(obj) }.should raise_error(TypeError)
+ -> { [1, 2].join(obj) }.should.raise(TypeError)
end
it "raises a TypeError if passed false as the separator" do
- -> { [1, 2].join(false) }.should raise_error(TypeError)
+ -> { [1, 2].join(false) }.should.raise(TypeError)
+ end
+end
+
+describe "Array#join with default separator" do
+ before :each do
+ @separator = $,
+ end
+
+ after :each do
+ $, = @separator
+ end
+
+ it "returns an empty string if the Array is empty" do
+ [].join.should == ''
+ end
+
+ it "returns a US-ASCII string for an empty Array" do
+ [].join.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a string formed by concatenating each String element separated by $," do
+ suppress_warning {
+ $, = " | "
+ ["1", "2", "3"].join.should == "1 | 2 | 3"
+ }
+ end
+
+ it "attempts coercion via #to_str first" do
+ obj = mock('foo')
+ obj.should_receive(:to_str).any_number_of_times.and_return("foo")
+ [obj].join.should == "foo"
+ end
+
+ it "attempts coercion via #to_ary second" do
+ obj = mock('foo')
+ obj.should_receive(:to_str).any_number_of_times.and_return(nil)
+ obj.should_receive(:to_ary).any_number_of_times.and_return(["foo"])
+ [obj].join.should == "foo"
+ end
+
+ it "attempts coercion via #to_s third" do
+ obj = mock('foo')
+ obj.should_receive(:to_str).any_number_of_times.and_return(nil)
+ obj.should_receive(:to_ary).any_number_of_times.and_return(nil)
+ obj.should_receive(:to_s).any_number_of_times.and_return("foo")
+ [obj].join.should == "foo"
+ end
+
+ it "raises a NoMethodError if an element does not respond to #to_str, #to_ary, or #to_s" do
+ obj = mock('o')
+ class << obj; undef :to_s; end
+ -> { [1, obj].join }.should.raise(NoMethodError)
+ end
+
+ it "raises an ArgumentError when the Array is recursive" do
+ -> { ArraySpecs.recursive_array.join }.should.raise(ArgumentError)
+ -> { ArraySpecs.head_recursive_array.join }.should.raise(ArgumentError)
+ -> { ArraySpecs.empty_recursive_array.join }.should.raise(ArgumentError)
+ end
+
+ it "uses the first encoding when other strings are compatible" do
+ ary1 = ArraySpecs.array_with_7bit_utf8_and_usascii_strings
+ ary2 = ArraySpecs.array_with_usascii_and_7bit_utf8_strings
+ ary3 = ArraySpecs.array_with_utf8_and_7bit_binary_strings
+ ary4 = ArraySpecs.array_with_usascii_and_7bit_binary_strings
+
+ ary1.join.encoding.should == Encoding::UTF_8
+ ary2.join.encoding.should == Encoding::US_ASCII
+ ary3.join.encoding.should == Encoding::UTF_8
+ ary4.join.encoding.should == Encoding::US_ASCII
+ end
+
+ it "uses the widest common encoding when other strings are incompatible" do
+ ary1 = ArraySpecs.array_with_utf8_and_usascii_strings
+ ary2 = ArraySpecs.array_with_usascii_and_utf8_strings
+
+ ary1.join.encoding.should == Encoding::UTF_8
+ ary2.join.encoding.should == Encoding::UTF_8
+ end
+
+ it "fails for arrays with incompatibly-encoded strings" do
+ ary_utf8_bad_binary = ArraySpecs.array_with_utf8_and_binary_strings
+
+ -> { ary_utf8_bad_binary.join }.should.raise(EncodingError)
+ end
+
+ context "when $, is not nil" do
+ before do
+ suppress_warning do
+ $, = '*'
+ end
+ end
+
+ it "warns" do
+ -> { [].join }.should complain(/warning: \$, is set to non-nil value/)
+ -> { [].join(nil) }.should complain(/warning: \$, is set to non-nil value/)
+ end
end
end
diff --git a/spec/ruby/core/array/keep_if_spec.rb b/spec/ruby/core/array/keep_if_spec.rb
index bf2bdeaf91..62a65a04e8 100644
--- a/spec/ruby/core/array/keep_if_spec.rb
+++ b/spec/ruby/core/array/keep_if_spec.rb
@@ -1,9 +1,10 @@
+require_relative '../../spec_helper'
require_relative 'shared/keep_if'
describe "Array#keep_if" do
it "returns the same array if no changes were made" do
array = [1, 2, 3]
- array.keep_if { true }.should equal(array)
+ array.keep_if { true }.should.equal?(array)
end
it_behaves_like :keep_if, :keep_if
diff --git a/spec/ruby/core/array/last_spec.rb b/spec/ruby/core/array/last_spec.rb
index d6fefada09..ed417bcd2a 100644
--- a/spec/ruby/core/array/last_spec.rb
+++ b/spec/ruby/core/array/last_spec.rb
@@ -28,7 +28,7 @@ describe "Array#last" do
end
it "raises an ArgumentError when count is negative" do
- -> { [1, 2].last(-1) }.should raise_error(ArgumentError)
+ -> { [1, 2].last(-1) }.should.raise(ArgumentError)
end
it "returns the entire array when count > length" do
@@ -47,10 +47,10 @@ describe "Array#last" do
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
- empty.last.should equal(empty)
+ empty.last.should.equal?(empty)
array = ArraySpecs.recursive_array
- array.last.should equal(array)
+ array.last.should.equal?(array)
end
it "tries to convert the passed argument to an Integer using #to_int" do
@@ -60,19 +60,19 @@ describe "Array#last" do
end
it "raises a TypeError if the passed argument is not numeric" do
- -> { [1,2].last(nil) }.should raise_error(TypeError)
- -> { [1,2].last("a") }.should raise_error(TypeError)
+ -> { [1,2].last(nil) }.should.raise(TypeError)
+ -> { [1,2].last("a") }.should.raise(TypeError)
obj = mock("nonnumeric")
- -> { [1,2].last(obj) }.should raise_error(TypeError)
+ -> { [1,2].last(obj) }.should.raise(TypeError)
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[].last(0).should be_an_instance_of(Array)
- ArraySpecs::MyArray[].last(2).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].last(0).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].last(1).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].last(2).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[].last(0).should.instance_of?(Array)
+ ArraySpecs::MyArray[].last(2).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].last(0).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].last(1).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].last(2).should.instance_of?(Array)
end
it "is not destructive" do
diff --git a/spec/ruby/core/array/length_spec.rb b/spec/ruby/core/array/length_spec.rb
index a90c001300..74b2eb3a08 100644
--- a/spec/ruby/core/array/length_spec.rb
+++ b/spec/ruby/core/array/length_spec.rb
@@ -1,7 +1,14 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/length'
describe "Array#length" do
- it_behaves_like :array_length, :length
+ it "returns the number of elements" do
+ [].length.should == 0
+ [1, 2, 3].length.should == 3
+ end
+
+ it "properly handles recursive arrays" do
+ ArraySpecs.empty_recursive_array.length.should == 1
+ ArraySpecs.recursive_array.length.should == 8
+ end
end
diff --git a/spec/ruby/core/array/map_spec.rb b/spec/ruby/core/array/map_spec.rb
index 0c7f3afa8c..f5e88c8624 100644
--- a/spec/ruby/core/array/map_spec.rb
+++ b/spec/ruby/core/array/map_spec.rb
@@ -1,11 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/collect'
describe "Array#map" do
- it_behaves_like :array_collect, :map
+ it "is an alias of Array#collect" do
+ Array.instance_method(:map).should == Array.instance_method(:collect)
+ end
end
describe "Array#map!" do
- it_behaves_like :array_collect_b, :map!
+ it "is an alias of Array#collect!" do
+ Array.instance_method(:map!).should == Array.instance_method(:collect!)
+ end
end
diff --git a/spec/ruby/core/array/max_spec.rb b/spec/ruby/core/array/max_spec.rb
index d1c64519d0..868275a748 100644
--- a/spec/ruby/core/array/max_spec.rb
+++ b/spec/ruby/core/array/max_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Array#max" do
it "is defined on Array" do
- [1].method(:max).owner.should equal Array
+ [1].method(:max).owner.should.equal? Array
end
it "returns nil with no values" do
@@ -70,16 +70,16 @@ describe "Array#max" do
it "raises a NoMethodError for elements without #<=>" do
-> do
[BasicObject.new, BasicObject.new].max
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
it "raises an ArgumentError for incomparable elements" do
-> do
[11,"22"].max
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
-> do
[11,12,22,33].max{|a, b| nil}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "returns the maximum element (with block)" do
diff --git a/spec/ruby/core/array/min_spec.rb b/spec/ruby/core/array/min_spec.rb
index 3bdef0dd00..5913e08cf8 100644
--- a/spec/ruby/core/array/min_spec.rb
+++ b/spec/ruby/core/array/min_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Array#min" do
it "is defined on Array" do
- [1].method(:max).owner.should equal Array
+ [1].method(:max).owner.should.equal? Array
end
it "returns nil with no values" do
@@ -64,22 +64,22 @@ describe "Array#min" do
end
it "returns nil for an empty Enumerable" do
- [].min.should be_nil
+ [].min.should == nil
end
it "raises a NoMethodError for elements without #<=>" do
-> do
[BasicObject.new, BasicObject.new].min
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
it "raises an ArgumentError for incomparable elements" do
-> do
[11,"22"].min
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
-> do
[11,12,22,33].min{|a, b| nil}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "returns the minimum when using a block rule" do
diff --git a/spec/ruby/core/array/multiply_spec.rb b/spec/ruby/core/array/multiply_spec.rb
index 23d5c99f3a..1ac14e1b09 100644
--- a/spec/ruby/core/array/multiply_spec.rb
+++ b/spec/ruby/core/array/multiply_spec.rb
@@ -17,7 +17,7 @@ describe "Array#*" do
it "raises a TypeError if the argument can neither be converted to a string nor an integer" do
obj = mock('not a string or integer')
- ->{ [1,2] * obj }.should raise_error(TypeError)
+ ->{ [1,2] * obj }.should.raise(TypeError)
end
it "converts the passed argument to a String rather than an Integer" do
@@ -28,15 +28,15 @@ describe "Array#*" do
end
it "raises a TypeError is the passed argument is nil" do
- ->{ [1,2] * nil }.should raise_error(TypeError)
+ ->{ [1,2] * nil }.should.raise(TypeError)
end
it "raises an ArgumentError when passed 2 or more arguments" do
- ->{ [1,2].send(:*, 1, 2) }.should raise_error(ArgumentError)
+ ->{ [1,2].send(:*, 1, 2) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed no arguments" do
- ->{ [1,2].send(:*) }.should raise_error(ArgumentError)
+ ->{ [1,2].send(:*) }.should.raise(ArgumentError)
end
end
@@ -50,7 +50,7 @@ describe "Array#* with an integer" do
it "does not return self even if the passed integer is 1" do
ary = [1, 2, 3]
- (ary * 1).should_not equal(ary)
+ (ary * 1).should_not.equal?(ary)
end
it "properly handles recursive arrays" do
@@ -65,8 +65,8 @@ describe "Array#* with an integer" do
end
it "raises an ArgumentError when passed a negative integer" do
- -> { [ 1, 2, 3 ] * -1 }.should raise_error(ArgumentError)
- -> { [] * -1 }.should raise_error(ArgumentError)
+ -> { [ 1, 2, 3 ] * -1 }.should.raise(ArgumentError)
+ -> { [] * -1 }.should.raise(ArgumentError)
end
describe "with a subclass of Array" do
@@ -76,25 +76,15 @@ describe "Array#* with an integer" do
@array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
end
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance" do
- (@array * 0).should be_an_instance_of(ArraySpecs::MyArray)
- (@array * 1).should be_an_instance_of(ArraySpecs::MyArray)
- (@array * 2).should be_an_instance_of(ArraySpecs::MyArray)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns an Array instance" do
- (@array * 0).should be_an_instance_of(Array)
- (@array * 1).should be_an_instance_of(Array)
- (@array * 2).should be_an_instance_of(Array)
- end
+ it "returns an Array instance" do
+ (@array * 0).should.instance_of?(Array)
+ (@array * 1).should.instance_of?(Array)
+ (@array * 2).should.instance_of?(Array)
end
it "does not call #initialize on the subclass instance" do
(@array * 2).should == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
end
end
diff --git a/spec/ruby/core/array/new_spec.rb b/spec/ruby/core/array/new_spec.rb
index 96ec6b8198..b2f23e2f6b 100644
--- a/spec/ruby/core/array/new_spec.rb
+++ b/spec/ruby/core/array/new_spec.rb
@@ -3,30 +3,32 @@ require_relative 'fixtures/classes'
describe "Array.new" do
it "returns an instance of Array" do
- Array.new.should be_an_instance_of(Array)
+ Array.new.should.instance_of?(Array)
end
it "returns an instance of a subclass" do
- ArraySpecs::MyArray.new(1, 2).should be_an_instance_of(ArraySpecs::MyArray)
+ ArraySpecs::MyArray.new(1, 2).should.instance_of?(ArraySpecs::MyArray)
end
it "raises an ArgumentError if passed 3 or more arguments" do
-> do
[1, 2].send :initialize, 1, 'x', true
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
-> do
[1, 2].send(:initialize, 1, 'x', true) {}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
end
describe "Array.new with no arguments" do
it "returns an empty array" do
- Array.new.should be_empty
+ Array.new.should.empty?
end
it "does not use the given block" do
- ->{ Array.new { raise } }.should_not raise_error
+ -> {
+ -> { Array.new { raise } }.should_not.raise
+ }.should complain(/warning: given block not used/, verbose: true)
end
end
@@ -37,7 +39,7 @@ describe "Array.new with (array)" do
end
it "does not use the given block" do
- ->{ Array.new([1, 2]) { raise } }.should_not raise_error
+ ->{ Array.new([1, 2]) { raise } }.should_not.raise
end
it "calls #to_ary to convert the value to an array" do
@@ -54,7 +56,7 @@ describe "Array.new with (array)" do
end
it "raises a TypeError if an Array type argument and a default object" do
- -> { Array.new([1, 2], 1) }.should raise_error(TypeError)
+ -> { Array.new([1, 2], 1) }.should.raise(TypeError)
end
end
@@ -63,8 +65,8 @@ describe "Array.new with (size, object=nil)" do
obj = [3]
a = Array.new(2, obj)
a.should == [obj, obj]
- a[0].should equal(obj)
- a[1].should equal(obj)
+ a[0].should.equal?(obj)
+ a[1].should.equal?(obj)
Array.new(3, 14).should == [14, 14, 14]
end
@@ -74,12 +76,12 @@ describe "Array.new with (size, object=nil)" do
end
it "raises an ArgumentError if size is negative" do
- -> { Array.new(-1, :a) }.should raise_error(ArgumentError)
- -> { Array.new(-1) }.should raise_error(ArgumentError)
+ -> { Array.new(-1, :a) }.should.raise(ArgumentError)
+ -> { Array.new(-1) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if size is too large" do
- -> { Array.new(fixnum_max+1) }.should raise_error(ArgumentError)
+ -> { Array.new(fixnum_max+1) }.should.raise(ArgumentError)
end
it "calls #to_int to convert the size argument to an Integer when object is given" do
@@ -97,7 +99,7 @@ describe "Array.new with (size, object=nil)" do
it "raises a TypeError if the size argument is not an Integer type" do
obj = mock('nonnumeric')
obj.stub!(:to_ary).and_return([1, 2])
- ->{ Array.new(obj, :a) }.should raise_error(TypeError)
+ ->{ Array.new(obj, :a) }.should.raise(TypeError)
end
it "yields the index of the element and sets the element to the value of the block" do
diff --git a/spec/ruby/core/array/none_spec.rb b/spec/ruby/core/array/none_spec.rb
new file mode 100644
index 0000000000..31cd8c46d6
--- /dev/null
+++ b/spec/ruby/core/array/none_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
+
+describe "Array#none?" do
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :none?
+
+ it "ignores the block if there is an argument" do
+ -> {
+ ['bar', 'foobar'].none?(/baz/) { true }.should == true
+ }.should complain(/given block not used/)
+ end
+end
diff --git a/spec/ruby/core/array/one_spec.rb b/spec/ruby/core/array/one_spec.rb
new file mode 100644
index 0000000000..0c61907881
--- /dev/null
+++ b/spec/ruby/core/array/one_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
+
+describe "Array#one?" do
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :one?
+
+ it "ignores the block if there is an argument" do
+ -> {
+ ['bar', 'foobar'].one?(/foo/) { false }.should == true
+ }.should complain(/given block not used/)
+ end
+end
diff --git a/spec/ruby/core/array/pack/a_spec.rb b/spec/ruby/core/array/pack/a_spec.rb
index f4a40502c2..03bfd8214c 100644
--- a/spec/ruby/core/array/pack/a_spec.rb
+++ b/spec/ruby/core/array/pack/a_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -19,15 +19,15 @@ describe "Array#pack with format 'A'" do
end
it "will not implicitly convert a number to a string" do
- -> { [0].pack('A') }.should raise_error(TypeError)
- -> { [0].pack('a') }.should raise_error(TypeError)
+ -> { [0].pack('A') }.should.raise(TypeError)
+ -> { [0].pack('a') }.should.raise(TypeError)
end
it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("A*").should == "abc"
end
- it "padds the output with spaces when the count exceeds the size of the String" do
+ it "pads the output with spaces when the count exceeds the size of the String" do
["abc"].pack("A6").should == "abc "
end
@@ -55,7 +55,7 @@ describe "Array#pack with format 'a'" do
["abc"].pack("a*").should == "abc"
end
- it "padds the output with NULL bytes when the count exceeds the size of the String" do
+ it "pads the output with NULL bytes when the count exceeds the size of the String" do
["abc"].pack("a6").should == "abc\x00\x00\x00"
end
diff --git a/spec/ruby/core/array/pack/at_spec.rb b/spec/ruby/core/array/pack/at_spec.rb
index 3942677913..bb9801440a 100644
--- a/spec/ruby/core/array/pack/at_spec.rb
+++ b/spec/ruby/core/array/pack/at_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/array/pack/b_spec.rb b/spec/ruby/core/array/pack/b_spec.rb
index ec82b7d1ab..f7576846ef 100644
--- a/spec/ruby/core/array/pack/b_spec.rb
+++ b/spec/ruby/core/array/pack/b_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -19,8 +19,8 @@ describe "Array#pack with format 'B'" do
end
it "will not implicitly convert a number to a string" do
- -> { [0].pack('B') }.should raise_error(TypeError)
- -> { [0].pack('b') }.should raise_error(TypeError)
+ -> { [0].pack('B') }.should.raise(TypeError)
+ -> { [0].pack('b') }.should.raise(TypeError)
end
it "encodes one bit for each character starting with the most significant bit" do
diff --git a/spec/ruby/core/array/pack/buffer_spec.rb b/spec/ruby/core/array/pack/buffer_spec.rb
index ecb40bfd06..d104c80186 100644
--- a/spec/ruby/core/array/pack/buffer_spec.rb
+++ b/spec/ruby/core/array/pack/buffer_spec.rb
@@ -7,43 +7,53 @@ describe "Array#pack with :buffer option" do
n = [ 65, 66, 67 ]
buffer = " "*3
result = n.pack("ccc", buffer: buffer) #=> "ABC"
- result.should equal(buffer)
+ 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 = ""
+ buffer = +""
n.pack("ccc", buffer: buffer).should == "ABC"
- buffer = "123"
+ buffer = +"123"
n.pack("ccc", buffer: buffer).should == "123ABC"
- buffer = "12345"
+ buffer = +"12345"
n.pack("ccc", buffer: buffer).should == "12345ABC"
end
it "raises TypeError exception if buffer is not String" do
- -> { [65].pack("ccc", buffer: []) }.should raise_error(
+ -> { [65].pack("ccc", buffer: []) }.should.raise(
TypeError, "buffer must be String, not Array")
end
+ it "raise FrozenError if buffer is frozen" do
+ -> { [65].pack("c", buffer: "frozen-string".freeze) }.should.raise(FrozenError)
+ end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ [65, 66, 67].pack("ccc", buffer: buffer)
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
+
context "offset (@) is specified" do
it 'keeps buffer content if it is longer than offset' do
n = [ 65, 66, 67 ]
- buffer = "123456"
+ 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"
+ 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"
+ buffer = +"1234567890"
n.pack("@3ccc", buffer: buffer).should == "123ABC"
end
end
diff --git a/spec/ruby/core/array/pack/c_spec.rb b/spec/ruby/core/array/pack/c_spec.rb
index 7200830331..de06207a23 100644
--- a/spec/ruby/core/array/pack/c_spec.rb
+++ b/spec/ruby/core/array/pack/c_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
@@ -45,8 +45,10 @@ describe :array_pack_8bit, shared: true do
[1, 2, 3, 4, 5].pack(pack_format('*')).should == "\x01\x02\x03\x04\x05"
end
- it "ignores NULL bytes between directives" do
- [1, 2, 3].pack(pack_format("\000", 2)).should == "\x01\x02"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [1, 2, 3].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/array/pack/comment_spec.rb b/spec/ruby/core/array/pack/comment_spec.rb
index 254c827ccc..daf1cff06a 100644
--- a/spec/ruby/core/array/pack/comment_spec.rb
+++ b/spec/ruby/core/array/pack/comment_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/array/pack/h_spec.rb b/spec/ruby/core/array/pack/h_spec.rb
index 2c1dac8d4a..1492d02b1f 100644
--- a/spec/ruby/core/array/pack/h_spec.rb
+++ b/spec/ruby/core/array/pack/h_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -19,8 +19,8 @@ describe "Array#pack with format 'H'" do
end
it "will not implicitly convert a number to a string" do
- -> { [0].pack('H') }.should raise_error(TypeError)
- -> { [0].pack('h') }.should raise_error(TypeError)
+ -> { [0].pack('H') }.should.raise(TypeError)
+ -> { [0].pack('h') }.should.raise(TypeError)
end
it "encodes the first character as the most significant nibble when passed no count modifier" do
diff --git a/spec/ruby/core/array/pack/l_spec.rb b/spec/ruby/core/array/pack/l_spec.rb
index b446a7a36a..f6dfb1da83 100644
--- a/spec/ruby/core/array/pack/l_spec.rb
+++ b/spec/ruby/core/array/pack/l_spec.rb
@@ -29,7 +29,7 @@ describe "Array#pack with format 'L'" do
it_behaves_like :array_pack_32bit_be, 'L>'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'L<_'
it_behaves_like :array_pack_32bit_le, 'L_<'
@@ -51,7 +51,7 @@ describe "Array#pack with format 'L'" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'L<_'
it_behaves_like :array_pack_64bit_le, 'L_<'
@@ -83,7 +83,7 @@ describe "Array#pack with format 'l'" do
it_behaves_like :array_pack_32bit_be, 'l>'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'l<_'
it_behaves_like :array_pack_32bit_le, 'l_<'
@@ -105,7 +105,7 @@ describe "Array#pack with format 'l'" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'l<_'
it_behaves_like :array_pack_64bit_le, 'l_<'
@@ -137,7 +137,7 @@ little_endian do
it_behaves_like :array_pack_32bit_le, 'l'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'L_'
end
@@ -155,7 +155,7 @@ little_endian do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'L_'
end
@@ -183,7 +183,7 @@ big_endian do
it_behaves_like :array_pack_32bit_be, 'l'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'L_'
end
@@ -201,7 +201,7 @@ big_endian do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'L_'
end
diff --git a/spec/ruby/core/array/pack/m_spec.rb b/spec/ruby/core/array/pack/m_spec.rb
index 2b1a84abca..fb670d120e 100644
--- a/spec/ruby/core/array/pack/m_spec.rb
+++ b/spec/ruby/core/array/pack/m_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -80,8 +80,16 @@ describe "Array#pack with format 'M'" do
].should be_computed_by(:pack, "M")
end
- it "encodes a tab followed by a newline with an encoded newline" do
+ it "encodes a tab at the end of a line with an encoded newline" do
+ ["\t"].pack("M").should == "\t=\n"
["\t\n"].pack("M").should == "\t=\n\n"
+ ["abc\t\nxyz"].pack("M").should == "abc\t=\n\nxyz=\n"
+ end
+
+ it "encodes a space at the end of a line with an encoded newline" do
+ [" "].pack("M").should == " =\n"
+ [" \n"].pack("M").should == " =\n\n"
+ ["abc \nxyz"].pack("M").should == "abc =\n\nxyz=\n"
end
it "encodes 127..255 in hex format" do
@@ -147,7 +155,7 @@ describe "Array#pack with format 'M'" do
it "encodes a recursive array" do
empty = ArraySpecs.empty_recursive_array
- empty.pack('M').should be_an_instance_of(String)
+ empty.pack('M').should.instance_of?(String)
array = ArraySpecs.recursive_array
array.pack('M').should == "1=\n"
@@ -164,7 +172,7 @@ describe "Array#pack with format 'M'" do
obj = mock("pack M non-string")
obj.should_receive(:to_s).and_return(2)
- [obj].pack("M").should be_an_instance_of(String)
+ [obj].pack("M").should.instance_of?(String)
end
it "encodes a Symbol as a String" do
@@ -285,16 +293,16 @@ describe "Array#pack with format 'm'" do
it "raises a TypeError if #to_str does not return a String" do
obj = mock("pack m non-string")
- -> { [obj].pack("m") }.should raise_error(TypeError)
+ -> { [obj].pack("m") }.should.raise(TypeError)
end
it "raises a TypeError if passed nil" do
- -> { [nil].pack("m") }.should raise_error(TypeError)
+ -> { [nil].pack("m") }.should.raise(TypeError)
end
it "raises a TypeError if passed an Integer" do
- -> { [0].pack("m") }.should raise_error(TypeError)
- -> { [bignum_value].pack("m") }.should raise_error(TypeError)
+ -> { [0].pack("m") }.should.raise(TypeError)
+ -> { [bignum_value].pack("m") }.should.raise(TypeError)
end
it "does not emit a newline if passed zero as the count modifier" do
diff --git a/spec/ruby/core/array/pack/percent_spec.rb b/spec/ruby/core/array/pack/percent_spec.rb
index 5d56dea5fe..29b119732a 100644
--- a/spec/ruby/core/array/pack/percent_spec.rb
+++ b/spec/ruby/core/array/pack/percent_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../../spec_helper'
describe "Array#pack with format '%'" do
it "raises an Argument Error" do
- -> { [1].pack("%") }.should raise_error(ArgumentError)
+ -> { [1].pack("%") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/pack/r_spec.rb b/spec/ruby/core/array/pack/r_spec.rb
new file mode 100644
index 0000000000..cefe1388d2
--- /dev/null
+++ b/spec/ruby/core/array/pack/r_spec.rb
@@ -0,0 +1,89 @@
+# encoding: binary
+require_relative '../../../spec_helper'
+require_relative '../fixtures/classes'
+require_relative 'shared/basic'
+require_relative 'shared/numeric_basic'
+require_relative 'shared/integer'
+
+ruby_version_is "4.1" do
+ describe "Array#pack with format 'R'" do
+ it_behaves_like :array_pack_basic, 'R'
+ it_behaves_like :array_pack_basic_non_float, 'R'
+ it_behaves_like :array_pack_arguments, 'R'
+ it_behaves_like :array_pack_numeric_basic, 'R'
+ it_behaves_like :array_pack_integer, 'R'
+
+ it "encodes a ULEB128 integer" do
+ [ [[0], "\x00"],
+ [[1], "\x01"],
+ [[127], "\x7f"],
+ [[128], "\x80\x01"],
+ [[0x3fff], "\xff\x7f"],
+ [[0x4000], "\x80\x80\x01"],
+ [[0xffffffff], "\xff\xff\xff\xff\x0f"],
+ [[0x100000000], "\x80\x80\x80\x80\x10"],
+ [[0xffff_ffff_ffff_ffff], "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01"],
+ [[0xffff_ffff_ffff_ffff_ffff_ffff], "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1f"],
+ ].should be_computed_by(:pack, "R")
+ end
+
+ it "encodes multiple values with '*' modifier" do
+ [1, 2].pack("R*").should == "\x01\x02"
+ [127, 128].pack("R*").should == "\x7f\x80\x01"
+ end
+
+ it "raises an ArgumentError when passed a negative value" do
+ -> { [-1].pack("R") }.should.raise(ArgumentError)
+ -> { [-100].pack("R") }.should.raise(ArgumentError)
+ end
+
+ it "round-trips values through pack and unpack" do
+ values = [0, 1, 127, 128, 0x3fff, 0x4000, 0xffffffff, 0x100000000]
+ values.pack("R*").unpack("R*").should == values
+ end
+ end
+
+ describe "Array#pack with format 'r'" do
+ it_behaves_like :array_pack_basic, 'r'
+ it_behaves_like :array_pack_basic_non_float, 'r'
+ it_behaves_like :array_pack_arguments, 'r'
+ it_behaves_like :array_pack_numeric_basic, 'r'
+ it_behaves_like :array_pack_integer, 'r'
+
+ it "encodes a SLEB128 integer" do
+ [ [[0], "\x00"],
+ [[1], "\x01"],
+ [[-1], "\x7f"],
+ [[-2], "\x7e"],
+ [[127], "\xff\x00"],
+ [[128], "\x80\x01"],
+ [[-127], "\x81\x7f"],
+ [[-128], "\x80\x7f"],
+ ].should be_computed_by(:pack, "r")
+ end
+
+ it "encodes larger positive numbers" do
+ [0x3fff].pack("r").should == "\xff\xff\x00"
+ [0x4000].pack("r").should == "\x80\x80\x01"
+ end
+
+ it "encodes larger negative numbers" do
+ [-0x3fff].pack("r").should == "\x81\x80\x7f"
+ [-0x4000].pack("r").should == "\x80\x80\x7f"
+ end
+
+ it "encodes very large numbers" do
+ [0xffff_ffff_ffff_ffff_ffff_ffff].pack("r").should == "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1F"
+ [-0xffff_ffff_ffff_ffff_ffff_ffff].pack("r").should == "\x81\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x60"
+ end
+
+ it "encodes multiple values with '*' modifier" do
+ [0, 1, -1].pack("r*").should == "\x00\x01\x7f"
+ end
+
+ it "round-trips values through pack and unpack" do
+ values = [0, 1, -1, 127, -127, 128, -128, 0x3fff, -0x3fff, 0x4000, -0x4000]
+ values.pack("r*").unpack("r*").should == values
+ end
+ end
+end
diff --git a/spec/ruby/core/array/pack/shared/basic.rb b/spec/ruby/core/array/pack/shared/basic.rb
index 23e239d3de..2894369c71 100644
--- a/spec/ruby/core/array/pack/shared/basic.rb
+++ b/spec/ruby/core/array/pack/shared/basic.rb
@@ -1,6 +1,6 @@
describe :array_pack_arguments, shared: true do
it "raises an ArgumentError if there are fewer elements than the format requires" do
- -> { [].pack(pack_format(1)) }.should raise_error(ArgumentError)
+ -> { [].pack(pack_format(1)) }.should.raise(ArgumentError)
end
end
@@ -10,11 +10,11 @@ describe :array_pack_basic, shared: true do
end
it "raises a TypeError when passed nil" do
- -> { [@obj].pack(nil) }.should raise_error(TypeError)
+ -> { [@obj].pack(nil) }.should.raise(TypeError)
end
it "raises a TypeError when passed an Integer" do
- -> { [@obj].pack(1) }.should raise_error(TypeError)
+ -> { [@obj].pack(1) }.should.raise(TypeError)
end
end
@@ -24,34 +24,50 @@ describe :array_pack_basic_non_float, shared: true do
end
it "ignores whitespace in the format string" do
- [@obj, @obj].pack("a \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
+ [@obj, @obj].pack("a \t\n\v\f\r"+pack_format).should.instance_of?(String)
+ end
+
+ it "ignores comments in the format string" do
+ # 2 additional directives ('a') are required for the X directive
+ [@obj, @obj, @obj, @obj].pack("aa #{pack_format} # some comment \n#{pack_format}").should.instance_of?(String)
+ end
+
+ it "raise ArgumentError when a directive is unknown" do
+ # additional directive ('a') is required for the X directive
+ -> { [@obj, @obj].pack("a K" + pack_format) }.should.raise(ArgumentError, /unknown pack directive 'K'/)
+ -> { [@obj, @obj].pack("a 0" + pack_format) }.should.raise(ArgumentError, /unknown pack directive '0'/)
+ -> { [@obj, @obj].pack("a :" + pack_format) }.should.raise(ArgumentError, /unknown pack directive ':'/)
end
it "calls #to_str to coerce the directives string" do
d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format)
- [@obj, @obj].pack(d).should be_an_instance_of(String)
+ [@obj, @obj].pack(d).should.instance_of?(String)
end
end
describe :array_pack_basic_float, shared: true do
it "ignores whitespace in the format string" do
- [9.3, 4.7].pack(" \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
+ [9.3, 4.7].pack(" \t\n\v\f\r"+pack_format).should.instance_of?(String)
+ end
+
+ it "ignores comments in the format string" do
+ [9.3, 4.7].pack(pack_format + "# some comment \n" + pack_format).should.instance_of?(String)
end
it "calls #to_str to coerce the directives string" do
d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format)
- [1.2, 4.7].pack(d).should be_an_instance_of(String)
+ [1.2, 4.7].pack(d).should.instance_of?(String)
end
end
describe :array_pack_no_platform, shared: true do
it "raises ArgumentError when the format modifier is '_'" do
- ->{ [1].pack(pack_format("_")) }.should raise_error(ArgumentError)
+ ->{ [1].pack(pack_format("_")) }.should.raise(ArgumentError)
end
it "raises ArgumentError when the format modifier is '!'" do
- ->{ [1].pack(pack_format("!")) }.should raise_error(ArgumentError)
+ ->{ [1].pack(pack_format("!")) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/pack/shared/encodings.rb b/spec/ruby/core/array/pack/shared/encodings.rb
index 6b7ffac764..0b5a5cc8a0 100644
--- a/spec/ruby/core/array/pack/shared/encodings.rb
+++ b/spec/ruby/core/array/pack/shared/encodings.rb
@@ -5,12 +5,12 @@ describe :array_pack_hex, shared: true do
it "raises a TypeError if the object does not respond to #to_str" do
obj = mock("pack hex non-string")
- -> { [obj].pack(pack_format) }.should raise_error(TypeError)
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
it "raises a TypeError if #to_str does not return a String" do
obj = mock("pack hex non-string")
obj.should_receive(:to_str).and_return(1)
- -> { [obj].pack(pack_format) }.should raise_error(TypeError)
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/array/pack/shared/float.rb b/spec/ruby/core/array/pack/shared/float.rb
index ba174a071a..c1efcd7677 100644
--- a/spec/ruby/core/array/pack/shared/float.rb
+++ b/spec/ruby/core/array/pack/shared/float.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :array_pack_float_le, shared: true do
it "encodes a positive Float" do
@@ -14,7 +14,7 @@ describe :array_pack_float_le, shared: true do
end
it "raises a TypeError if passed a String representation of a floating point number" do
- -> { ["13"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["13"].pack(pack_format) }.should.raise(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
@@ -25,8 +25,10 @@ describe :array_pack_float_le, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "\x9a\x999@33\xb3?33\x03A"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "\x9a\x99\xa9@33\x13A"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -43,7 +45,7 @@ describe :array_pack_float_le, shared: true do
it "encodes NaN" do
nans = ["\x00\x00\xc0\xff", "\x00\x00\xc0\x7f", "\xFF\xFF\xFF\x7F"]
- nans.should include([nan_value].pack(pack_format))
+ nans.should.include?([nan_value].pack(pack_format))
end
it "encodes a positive Float outside the range of a single precision float" do
@@ -74,10 +76,15 @@ describe :array_pack_float_be, shared: true do
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "A\x00\x00\x00"
+ [bignum_value].pack(pack_format).should == "_\x80\x00\x00"
+ end
+
+ it "converts a Rational to a Float" do
+ [Rational(8)].pack(pack_format).should == "A\x00\x00\x00"
end
it "raises a TypeError if passed a String representation of a floating point number" do
- -> { ["13"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["13"].pack(pack_format) }.should.raise(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
@@ -88,8 +95,10 @@ describe :array_pack_float_be, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@9\x99\x9a?\xb333A\x0333"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\xa9\x99\x9aA\x1333"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -106,7 +115,7 @@ describe :array_pack_float_be, shared: true do
it "encodes NaN" do
nans = ["\xff\xc0\x00\x00", "\x7f\xc0\x00\x00", "\x7F\xFF\xFF\xFF"]
- nans.should include([nan_value].pack(pack_format))
+ nans.should.include?([nan_value].pack(pack_format))
end
it "encodes a positive Float outside the range of a single precision float" do
@@ -129,10 +138,15 @@ describe :array_pack_double_le, shared: true do
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\x20@"
+ [bignum_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xF0C"
+ end
+
+ it "converts a Rational to a Float" do
+ [Rational(8)].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00 @"
end
it "raises a TypeError if passed a String representation of a floating point number" do
- -> { ["13"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["13"].pack(pack_format) }.should.raise(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
@@ -143,8 +157,10 @@ describe :array_pack_double_le, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "333333\x07@ffffff\xf6?ffffff\x20@"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "333333\x15@ffffff\x22@"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -165,7 +181,7 @@ describe :array_pack_double_le, shared: true do
"\x00\x00\x00\x00\x00\x00\xf8\x7f",
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F"
]
- nans.should include([nan_value].pack(pack_format))
+ nans.should.include?([nan_value].pack(pack_format))
end
it "encodes a positive Float outside the range of a single precision float" do
@@ -191,7 +207,7 @@ describe :array_pack_double_be, shared: true do
end
it "raises a TypeError if passed a String representation of a floating point number" do
- -> { ["13"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["13"].pack(pack_format) }.should.raise(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
@@ -202,8 +218,10 @@ describe :array_pack_double_be, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@\x07333333?\xf6ffffff@\x20ffffff"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\x15333333@\x22ffffff"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -224,7 +242,7 @@ describe :array_pack_double_be, shared: true do
"\x7f\xf8\x00\x00\x00\x00\x00\x00",
"\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
]
- nans.should include([nan_value].pack(pack_format))
+ nans.should.include?([nan_value].pack(pack_format))
end
it "encodes a positive Float outside the range of a single precision float" do
diff --git a/spec/ruby/core/array/pack/shared/integer.rb b/spec/ruby/core/array/pack/shared/integer.rb
index 6592f85022..1cdd386cc1 100644
--- a/spec/ruby/core/array/pack/shared/integer.rb
+++ b/spec/ruby/core/array/pack/shared/integer.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :array_pack_16bit_le, shared: true do
it "encodes the least significant 16 bits of a positive number" do
@@ -41,9 +41,10 @@ describe :array_pack_16bit_le, shared: true do
str.should == "\x78\x65\xcd\xab\x21\x43"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x78\x65\xcd\xab"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -93,9 +94,10 @@ describe :array_pack_16bit_be, shared: true do
str.should == "\x65\x78\xab\xcd\x43\x21"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x65\x78\xab\xcd"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -145,9 +147,10 @@ describe :array_pack_32bit_le, shared: true do
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -197,9 +200,10 @@ describe :array_pack_32bit_be, shared: true do
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -225,7 +229,7 @@ describe :array_pack_32bit_le_platform, shared: true do
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x21\x43\x65\x78"],
[[-0xff_7865_4321], "\xdf\xbc\x9a\x87"]
@@ -251,7 +255,7 @@ describe :array_pack_32bit_be_platform, shared: true do
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x78\x65\x43\x21"],
[[-0xff_7865_4321], "\x87\x9a\xbc\xdf"]
@@ -309,9 +313,10 @@ describe :array_pack_64bit_le, shared: true do
str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
end
- it "ignores NULL bytes between directives" do
- str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
- str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -369,9 +374,10 @@ describe :array_pack_64bit_be, shared: true do
str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
end
- it "ignores NULL bytes between directives" do
- str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
- str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/array/pack/shared/numeric_basic.rb b/spec/ruby/core/array/pack/shared/numeric_basic.rb
index 7c36ba4a32..6594914933 100644
--- a/spec/ruby/core/array/pack/shared/numeric_basic.rb
+++ b/spec/ruby/core/array/pack/shared/numeric_basic.rb
@@ -4,15 +4,15 @@ describe :array_pack_numeric_basic, shared: true do
end
it "raises a TypeError when passed nil" do
- -> { [nil].pack(pack_format) }.should raise_error(TypeError)
+ -> { [nil].pack(pack_format) }.should.raise(TypeError)
end
it "raises a TypeError when passed true" do
- -> { [true].pack(pack_format) }.should raise_error(TypeError)
+ -> { [true].pack(pack_format) }.should.raise(TypeError)
end
it "raises a TypeError when passed false" do
- -> { [false].pack(pack_format) }.should raise_error(TypeError)
+ -> { [false].pack(pack_format) }.should.raise(TypeError)
end
it "returns a binary string" do
@@ -24,21 +24,27 @@ end
describe :array_pack_integer, shared: true do
it "raises a TypeError when the object does not respond to #to_int" do
obj = mock('not an integer')
- -> { [obj].pack(pack_format) }.should raise_error(TypeError)
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- -> { ["5"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["5"].pack(pack_format) }.should.raise(TypeError)
end
end
describe :array_pack_float, shared: true do
it "raises a TypeError if a String does not represent a floating point number" do
- -> { ["a"].pack(pack_format) }.should raise_error(TypeError)
+ -> { ["a"].pack(pack_format) }.should.raise(TypeError)
end
- it "raises a TypeError when the object does not respond to #to_f" do
- obj = mock('not an float')
- -> { [obj].pack(pack_format) }.should raise_error(TypeError)
+ it "raises a TypeError when the object is not Numeric" do
+ obj = Object.new
+ -> { [obj].pack(pack_format) }.should.raise(TypeError, /can't convert Object into Float/)
+ end
+
+ it "raises a TypeError when the Numeric object does not respond to #to_f" do
+ klass = Class.new(Numeric)
+ obj = klass.new
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/array/pack/shared/string.rb b/spec/ruby/core/array/pack/shared/string.rb
index 8c82e8c617..b02257059f 100644
--- a/spec/ruby/core/array/pack/shared/string.rb
+++ b/spec/ruby/core/array/pack/shared/string.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :array_pack_string, shared: true do
it "adds count bytes of a String to the output" do
["abc"].pack(pack_format(2)).should == "ab"
@@ -17,11 +17,11 @@ describe :array_pack_string, shared: true do
end
it "raises an ArgumentError when the Array is empty" do
- -> { [].pack(pack_format) }.should raise_error(ArgumentError)
+ -> { [].pack(pack_format) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the Array has too few elements" do
- -> { ["a"].pack(pack_format(nil, 2)) }.should raise_error(ArgumentError)
+ -> { ["a"].pack(pack_format(nil, 2)) }.should.raise(ArgumentError)
end
it "calls #to_str to convert the element to a String" do
@@ -33,14 +33,14 @@ describe :array_pack_string, shared: true do
it "raises a TypeError when the object does not respond to #to_str" do
obj = mock("not a string")
- -> { [obj].pack(pack_format) }.should raise_error(TypeError)
+ -> { [obj].pack(pack_format) }.should.raise(TypeError)
end
it "returns a string in encoding of common to the concatenated results" do
f = pack_format("*")
[ [["\u{3042 3044 3046 3048}", 0x2000B].pack(f+"U"), Encoding::BINARY],
[["abcde\xd1", "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::BINARY],
- [["a".force_encoding("ascii"), "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::BINARY],
+ [["a".dup.force_encoding("ascii"), "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::BINARY],
# under discussion [ruby-dev:37294]
[["\u{3042 3044 3046 3048}", 1].pack(f+"N"), Encoding::BINARY]
].should be_computed_by(:encoding)
diff --git a/spec/ruby/core/array/pack/shared/unicode.rb b/spec/ruby/core/array/pack/shared/unicode.rb
index dd0f8b38aa..58ba8a8b23 100644
--- a/spec/ruby/core/array/pack/shared/unicode.rb
+++ b/spec/ruby/core/array/pack/shared/unicode.rb
@@ -26,7 +26,7 @@ describe :array_pack_unicode, shared: true do
it "constructs strings with valid encodings" do
str = [0x85].pack("U*")
str.should == "\xc2\x85"
- str.valid_encoding?.should be_true
+ str.valid_encoding?.should == true
end
it "encodes values larger than UTF-8 max codepoints" do
@@ -64,11 +64,13 @@ describe :array_pack_unicode, shared: true do
it "raises a TypeError if #to_int does not return an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return("5")
- -> { [obj].pack("U") }.should raise_error(TypeError)
+ -> { [obj].pack("U") }.should.raise(TypeError)
end
- it "ignores NULL bytes between directives" do
- [1, 2, 3].pack("U\x00U").should == "\x01\x02"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [1, 2, 3].pack("U\x00U")
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -76,11 +78,11 @@ describe :array_pack_unicode, shared: true do
end
it "raises a RangeError if passed a negative number" do
- -> { [-1].pack("U") }.should raise_error(RangeError)
+ -> { [-1].pack("U") }.should.raise(RangeError)
end
it "raises a RangeError if passed a number larger than an unsigned 32-bit integer" do
- -> { [2**32].pack("U") }.should raise_error(RangeError)
+ -> { [2**32].pack("U") }.should.raise(RangeError)
end
it "sets the output string to UTF-8 encoding" do
diff --git a/spec/ruby/core/array/pack/u_spec.rb b/spec/ruby/core/array/pack/u_spec.rb
index b20093a647..c6a0d77eb2 100644
--- a/spec/ruby/core/array/pack/u_spec.rb
+++ b/spec/ruby/core/array/pack/u_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -25,7 +25,7 @@ describe "Array#pack with format 'u'" do
end
it "will not implicitly convert a number to a string" do
- -> { [0].pack('u') }.should raise_error(TypeError)
+ -> { [0].pack('u') }.should.raise(TypeError)
end
it "encodes an empty string as an empty string" do
@@ -122,16 +122,16 @@ describe "Array#pack with format 'u'" do
it "raises a TypeError if #to_str does not return a String" do
obj = mock("pack m non-string")
- -> { [obj].pack("u") }.should raise_error(TypeError)
+ -> { [obj].pack("u") }.should.raise(TypeError)
end
it "raises a TypeError if passed nil" do
- -> { [nil].pack("u") }.should raise_error(TypeError)
+ -> { [nil].pack("u") }.should.raise(TypeError)
end
it "raises a TypeError if passed an Integer" do
- -> { [0].pack("u") }.should raise_error(TypeError)
- -> { [bignum_value].pack("u") }.should raise_error(TypeError)
+ -> { [0].pack("u") }.should.raise(TypeError)
+ -> { [bignum_value].pack("u") }.should.raise(TypeError)
end
it "sets the output string to US-ASCII encoding" do
diff --git a/spec/ruby/core/array/pack/w_spec.rb b/spec/ruby/core/array/pack/w_spec.rb
index 439fa02198..263e2a2288 100644
--- a/spec/ruby/core/array/pack/w_spec.rb
+++ b/spec/ruby/core/array/pack/w_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -24,8 +24,10 @@ describe "Array#pack with format 'w'" do
[obj].pack("w").should == "\x05"
end
- it "ignores NULL bytes between directives" do
- [1, 2, 3].pack("w\x00w").should == "\x01\x02"
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [1, 2, 3].pack("w\x00w")
+ }.should.raise(ArgumentError, /unknown pack directive/)
end
it "ignores spaces between directives" do
@@ -33,7 +35,7 @@ describe "Array#pack with format 'w'" do
end
it "raises an ArgumentError when passed a negative value" do
- -> { [-1].pack("w") }.should raise_error(ArgumentError)
+ -> { [-1].pack("w") }.should.raise(ArgumentError)
end
it "returns a binary string" do
diff --git a/spec/ruby/core/array/pack/x_spec.rb b/spec/ruby/core/array/pack/x_spec.rb
index 86c3ad1aa4..7ff587a01e 100644
--- a/spec/ruby/core/array/pack/x_spec.rb
+++ b/spec/ruby/core/array/pack/x_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -56,10 +56,10 @@ describe "Array#pack with format 'X'" do
end
it "raises an ArgumentError if the output string is empty" do
- -> { [1, 2, 3].pack("XC") }.should raise_error(ArgumentError)
+ -> { [1, 2, 3].pack("XC") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the count modifier is greater than the bytes in the string" do
- -> { [1, 2, 3].pack("C2X3") }.should raise_error(ArgumentError)
+ -> { [1, 2, 3].pack("C2X3") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/pack/z_spec.rb b/spec/ruby/core/array/pack/z_spec.rb
index 5ad3afd69e..5cd084c825 100644
--- a/spec/ruby/core/array/pack/z_spec.rb
+++ b/spec/ruby/core/array/pack/z_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -19,14 +19,14 @@ describe "Array#pack with format 'Z'" do
end
it "will not implicitly convert a number to a string" do
- -> { [0].pack('Z') }.should raise_error(TypeError)
+ -> { [0].pack('Z') }.should.raise(TypeError)
end
it "adds all the bytes and appends a NULL byte when passed the '*' modifier" do
["abc"].pack("Z*").should == "abc\x00"
end
- it "padds the output with NULL bytes when the count exceeds the size of the String" do
+ it "pads the output with NULL bytes when the count exceeds the size of the String" do
["abc"].pack("Z6").should == "abc\x00\x00\x00"
end
diff --git a/spec/ruby/core/array/partition_spec.rb b/spec/ruby/core/array/partition_spec.rb
index be36fffcab..bd3f3a6b6f 100644
--- a/spec/ruby/core/array/partition_spec.rb
+++ b/spec/ruby/core/array/partition_spec.rb
@@ -36,8 +36,8 @@ describe "Array#partition" do
it "does not return subclass instances on Array subclasses" do
result = ArraySpecs::MyArray[1, 2, 3].partition { |x| x % 2 == 0 }
- result.should be_an_instance_of(Array)
- result[0].should be_an_instance_of(Array)
- result[1].should be_an_instance_of(Array)
+ result.should.instance_of?(Array)
+ result[0].should.instance_of?(Array)
+ result[1].should.instance_of?(Array)
end
end
diff --git a/spec/ruby/core/array/permutation_spec.rb b/spec/ruby/core/array/permutation_spec.rb
index f15bd76639..b5df84b52b 100644
--- a/spec/ruby/core/array/permutation_spec.rb
+++ b/spec/ruby/core/array/permutation_spec.rb
@@ -11,7 +11,7 @@ describe "Array#permutation" do
it "returns an Enumerator of all permutations when called without a block or arguments" do
enum = @numbers.permutation
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.sort.should == [
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]
].sort
@@ -19,13 +19,13 @@ describe "Array#permutation" do
it "returns an Enumerator of permutations of given length when called with an argument but no block" do
enum = @numbers.permutation(1)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.sort.should == [[1],[2],[3]]
end
it "yields all permutations to the block then returns self when called with block but no arguments" do
array = @numbers.permutation {|n| @yielded << n}
- array.should be_an_instance_of(Array)
+ array.should.instance_of?(Array)
array.sort.should == @numbers.sort
@yielded.sort.should == [
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]
@@ -34,7 +34,7 @@ describe "Array#permutation" do
it "yields all permutations of given length to the block then returns self when called with block and argument" do
array = @numbers.permutation(2) {|n| @yielded << n}
- array.should be_an_instance_of(Array)
+ array.should.instance_of?(Array)
array.sort.should == @numbers.sort
@yielded.sort.should == [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]].sort
end
@@ -78,7 +78,7 @@ describe "Array#permutation" do
[3, 1], [3, 2], [3, [4, 5]],
[[4, 5], 1], [[4, 5], 2], [[4, 5], 3]
]
- expected.each {|e| got.include?(e).should be_true}
+ expected.each {|e| got.include?(e).should == true}
got.size.should == expected.size
end
diff --git a/spec/ruby/core/array/plus_spec.rb b/spec/ruby/core/array/plus_spec.rb
index 3962b05c39..7ead927fc0 100644
--- a/spec/ruby/core/array/plus_spec.rb
+++ b/spec/ruby/core/array/plus_spec.rb
@@ -14,10 +14,23 @@ describe "Array#+" do
(ary + ary).should == [1, 2, 3, 1, 2, 3]
end
- it "tries to convert the passed argument to an Array using #to_ary" do
- obj = mock('["x", "y"]')
- obj.should_receive(:to_ary).and_return(["x", "y"])
- ([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
+ describe "converts the passed argument to an Array using #to_ary" do
+ it "successfully concatenates the resulting array from the #to_ary call" do
+ obj = mock('["x", "y"]')
+ obj.should_receive(:to_ary).and_return(["x", "y"])
+ ([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
+ end
+
+ it "raises a TypeError if the given argument can't be converted to an array" do
+ -> { [1, 2, 3] + nil }.should.raise(TypeError)
+ -> { [1, 2, 3] + "abc" }.should.raise(TypeError)
+ end
+
+ it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to an Array" do
+ obj = mock("hello")
+ obj.should_receive(:to_ary).and_raise(NoMethodError)
+ -> { [1, 2, 3] + obj }.should.raise(NoMethodError)
+ end
end
it "properly handles recursive arrays" do
@@ -32,9 +45,9 @@ describe "Array#+" do
end
it "does return subclass instances with Array subclasses" do
- (ArraySpecs::MyArray[1, 2, 3] + []).should be_an_instance_of(Array)
- (ArraySpecs::MyArray[1, 2, 3] + ArraySpecs::MyArray[]).should be_an_instance_of(Array)
- ([1, 2, 3] + ArraySpecs::MyArray[]).should be_an_instance_of(Array)
+ (ArraySpecs::MyArray[1, 2, 3] + []).should.instance_of?(Array)
+ (ArraySpecs::MyArray[1, 2, 3] + ArraySpecs::MyArray[]).should.instance_of?(Array)
+ ([1, 2, 3] + ArraySpecs::MyArray[]).should.instance_of?(Array)
end
it "does not call to_ary on array subclasses" do
diff --git a/spec/ruby/core/array/pop_spec.rb b/spec/ruby/core/array/pop_spec.rb
index 2a19408660..069083331c 100644
--- a/spec/ruby/core/array/pop_spec.rb
+++ b/spec/ruby/core/array/pop_spec.rb
@@ -31,11 +31,11 @@ describe "Array#pop" do
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.pop }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.pop }.should.raise(FrozenError)
end
it "raises a FrozenError on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.pop }.should raise_error(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.pop }.should.raise(FrozenError)
end
describe "passed a number n as an argument" do
@@ -71,7 +71,7 @@ describe "Array#pop" do
popped2.should == []
a.should == []
- popped1.should_not equal(popped2)
+ popped1.should_not.equal?(popped2)
end
it "returns whole elements if n exceeds size of the array" do
@@ -82,14 +82,14 @@ describe "Array#pop" do
it "does not return self even when it returns whole elements" do
a = [1, 2, 3, 4, 5]
- a.pop(5).should_not equal(a)
+ a.pop(5).should_not.equal?(a)
a = [1, 2, 3, 4, 5]
- a.pop(6).should_not equal(a)
+ a.pop(6).should_not.equal?(a)
end
it "raises an ArgumentError if n is negative" do
- ->{ [1, 2, 3].pop(-1) }.should raise_error(ArgumentError)
+ ->{ [1, 2, 3].pop(-1) }.should.raise(ArgumentError)
end
it "tries to convert n to an Integer using #to_int" do
@@ -104,21 +104,21 @@ describe "Array#pop" do
end
it "raises a TypeError when the passed n cannot be coerced to Integer" do
- ->{ [1, 2].pop("cat") }.should raise_error(TypeError)
- ->{ [1, 2].pop(nil) }.should raise_error(TypeError)
+ ->{ [1, 2].pop("cat") }.should.raise(TypeError)
+ ->{ [1, 2].pop(nil) }.should.raise(TypeError)
end
it "raises an ArgumentError if more arguments are passed" do
- ->{ [1, 2].pop(1, 2) }.should raise_error(ArgumentError)
+ ->{ [1, 2].pop(1, 2) }.should.raise(ArgumentError)
end
it "does not return subclass instances with Array subclass" do
- ArraySpecs::MyArray[1, 2, 3].pop(2).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].pop(2).should.instance_of?(Array)
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.pop(2) }.should raise_error(FrozenError)
- -> { ArraySpecs.frozen_array.pop(0) }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.pop(2) }.should.raise(FrozenError)
+ -> { ArraySpecs.frozen_array.pop(0) }.should.raise(FrozenError)
end
end
end
diff --git a/spec/ruby/core/array/prepend_spec.rb b/spec/ruby/core/array/prepend_spec.rb
index 368b8dcfcd..2d0ce31c71 100644
--- a/spec/ruby/core/array/prepend_spec.rb
+++ b/spec/ruby/core/array/prepend_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/unshift'
describe "Array#prepend" do
- it_behaves_like :array_unshift, :prepend
+ it "is an alias of Array#unshift" do
+ Array.instance_method(:prepend).should == Array.instance_method(:unshift)
+ end
end
diff --git a/spec/ruby/core/array/product_spec.rb b/spec/ruby/core/array/product_spec.rb
index 07d2880a96..837f0eaf34 100644
--- a/spec/ruby/core/array/product_spec.rb
+++ b/spec/ruby/core/array/product_spec.rb
@@ -3,12 +3,17 @@ require_relative 'fixtures/classes'
describe "Array#product" do
it "returns converted arguments using :to_ary" do
- ->{ [1].product(2..3) }.should raise_error(TypeError)
+ ->{ [1].product(2..3) }.should.raise(TypeError)
ar = ArraySpecs::ArrayConvertible.new(2,3)
[1].product(ar).should == [[1,2],[1,3]]
ar.called.should == :to_ary
end
+ it "returns converted arguments using :method_missing" do
+ ar = ArraySpecs::ArrayMethodMissing.new(2,3)
+ [1].product(ar).should == [[1,2],[1,3]]
+ end
+
it "returns the expected result" do
[1,2].product([3,4,5],[6,8]).should == [[1, 3, 6], [1, 3, 8], [1, 4, 6], [1, 4, 8], [1, 5, 6], [1, 5, 8],
[2, 3, 6], [2, 3, 8], [2, 4, 6], [2, 4, 8], [2, 5, 6], [2, 5, 8]]
@@ -26,7 +31,7 @@ describe "Array#product" do
a = (0..100).to_a
-> do
a.product(a, a, a, a, a, a, a, a, a, a)
- end.should raise_error(RangeError)
+ end.should.raise(RangeError)
end
describe "when given a block" do
@@ -38,7 +43,7 @@ describe "Array#product" do
acc = []
[1,2].product([3,4,5],[],[6,8]){|array| acc << array}
- acc.should be_empty
+ acc.should.empty?
end
it "returns self" do
@@ -51,18 +56,18 @@ describe "Array#product" do
a = (0..100).to_a
-> do
a.product(a, a, a, a, a, a, a, a, a, a)
- end.should raise_error(RangeError)
+ end.should.raise(RangeError)
end
end
describe "when given an empty block" do
it "returns self" do
arr = [1,2]
- arr.product([3,4,5],[6,8]){}.should equal(arr)
+ arr.product([3,4,5],[6,8]){}.should.equal?(arr)
arr = []
- arr.product([3,4,5],[6,8]){}.should equal(arr)
+ arr.product([3,4,5],[6,8]){}.should.equal?(arr)
arr = [1,2]
- arr.product([]){}.should equal(arr)
+ arr.product([]){}.should.equal?(arr)
end
end
end
diff --git a/spec/ruby/core/array/push_spec.rb b/spec/ruby/core/array/push_spec.rb
index 607cbc7b4d..6255a84371 100644
--- a/spec/ruby/core/array/push_spec.rb
+++ b/spec/ruby/core/array/push_spec.rb
@@ -1,7 +1,36 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/push'
describe "Array#push" do
- it_behaves_like :array_push, :push
+ it "appends the arguments to the array" do
+ a = [ "a", "b", "c" ]
+ a.push("d", "e", "f").should.equal?(a)
+ a.push.should == ["a", "b", "c", "d", "e", "f"]
+ a.push(5)
+ a.should == ["a", "b", "c", "d", "e", "f", 5]
+
+ a = [0, 1]
+ a.push(2)
+ a.should == [0, 1, 2]
+ end
+
+ it "isn't confused by previous shift" do
+ a = [ "a", "b", "c" ]
+ a.shift
+ a.push("foo")
+ a.should == ["b", "c", "foo"]
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.push(:last).should == [empty, :last]
+
+ array = ArraySpecs.recursive_array
+ array.push(:last).should == [1, 'two', 3.0, array, array, array, array, array, :last]
+ end
+
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.push(1) }.should.raise(FrozenError)
+ -> { ArraySpecs.frozen_array.push }.should.raise(FrozenError)
+ end
end
diff --git a/spec/ruby/core/array/rassoc_spec.rb b/spec/ruby/core/array/rassoc_spec.rb
index 62fbd40611..95e4ed1892 100644
--- a/spec/ruby/core/array/rassoc_spec.rb
+++ b/spec/ruby/core/array/rassoc_spec.rb
@@ -12,11 +12,11 @@ describe "Array#rassoc" do
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
- empty.rassoc([]).should be_nil
+ empty.rassoc([]).should == nil
[[empty, empty]].rassoc(empty).should == [empty, empty]
array = ArraySpecs.recursive_array
- array.rassoc(array).should be_nil
+ array.rassoc(array).should == nil
[[empty, array]].rassoc(array).should == [empty, array]
end
@@ -35,4 +35,16 @@ describe "Array#rassoc" do
[[1, :foobar, o], [2, o, 1], [3, mock('foo')]].rassoc(key).should == [2, o, 1]
end
+
+ it "calls to_ary on non-array elements" do
+ s1 = [1, 2]
+ s2 = ArraySpecs::ArrayConvertible.new(2, 3)
+ a = [s1, s2]
+
+ s1.should_not_receive(:to_ary)
+ a.rassoc(2).should.equal?(s1)
+
+ a.rassoc(3).should == [2, 3]
+ s2.called.should.equal?(:to_ary)
+ end
end
diff --git a/spec/ruby/core/array/reject_spec.rb b/spec/ruby/core/array/reject_spec.rb
index fcf43fabde..8d237b3a75 100644
--- a/spec/ruby/core/array/reject_spec.rb
+++ b/spec/ruby/core/array/reject_spec.rb
@@ -2,6 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/enumeratorize'
require_relative 'shared/delete_if'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
require_relative '../enumerable/shared/enumeratorized'
describe "Array#reject" do
@@ -9,9 +10,9 @@ describe "Array#reject" do
ary = [1, 2, 3, 4, 5]
ary.reject { true }.should == []
ary.reject { false }.should == ary
- ary.reject { false }.should_not equal ary
+ ary.reject { false }.should_not.equal? ary
ary.reject { nil }.should == ary
- ary.reject { nil }.should_not equal ary
+ ary.reject { nil }.should_not.equal? ary
ary.reject { 5 }.should == []
ary.reject { |i| i < 3 }.should == [3, 4, 5]
ary.reject { |i| i % 2 == 0 }.should == [1, 3, 5]
@@ -34,7 +35,7 @@ describe "Array#reject" do
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].reject { |x| x % 2 == 0 }.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].reject { |x| x % 2 == 0 }.should.instance_of?(Array)
end
it "does not retain instance variables" do
@@ -47,10 +48,14 @@ describe "Array#reject" do
it_behaves_like :enumeratorized_with_origin_size, :reject, [1,2,3]
end
+describe "Array#reject" do
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :reject
+end
+
describe "Array#reject!" do
it "removes elements for which block is true" do
a = [3, 4, 5, 6, 7, 8, 9, 10, 11]
- a.reject! { |i| i % 2 == 0 }.should equal(a)
+ a.reject! { |i| i % 2 == 0 }.should.equal?(a)
a.should == [3, 5, 7, 9, 11]
a.reject! { |i| i > 8 }
a.should == [3, 5, 7]
@@ -100,15 +105,20 @@ describe "Array#reject!" do
end
it "returns an Enumerator if no block given, and the array is frozen" do
- ArraySpecs.frozen_array.reject!.should be_an_instance_of(Enumerator)
+ ArraySpecs.frozen_array.reject!.should.instance_of?(Enumerator)
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.reject! {} }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.reject! {} }.should.raise(FrozenError)
end
it "raises a FrozenError on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.reject! {} }.should raise_error(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.reject! {} }.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError on a frozen array only during iteration if called without a block" do
+ enum = ArraySpecs.frozen_array.reject!
+ -> { enum.each {} }.should.raise(FrozenError)
end
it "does not truncate the array is the block raises an exception" do
@@ -141,3 +151,8 @@ describe "Array#reject!" do
it_behaves_like :enumeratorized_with_origin_size, :reject!, [1,2,3]
it_behaves_like :delete_if, :reject!
end
+
+describe "Array#reject!" do
+ @value_to_return = -> _ { false }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :reject!
+end
diff --git a/spec/ruby/core/array/repeated_combination_spec.rb b/spec/ruby/core/array/repeated_combination_spec.rb
index b62382024a..a714f05f54 100644
--- a/spec/ruby/core/array/repeated_combination_spec.rb
+++ b/spec/ruby/core/array/repeated_combination_spec.rb
@@ -6,16 +6,16 @@ describe "Array#repeated_combination" do
end
it "returns an enumerator when no block is provided" do
- @array.repeated_combination(2).should be_an_instance_of(Enumerator)
+ @array.repeated_combination(2).should.instance_of?(Enumerator)
end
it "returns self when a block is given" do
- @array.repeated_combination(2){}.should equal(@array)
+ @array.repeated_combination(2){}.should.equal?(@array)
end
it "yields nothing for negative length and return self" do
- @array.repeated_combination(-1){ fail }.should equal(@array)
- @array.repeated_combination(-10){ fail }.should equal(@array)
+ @array.repeated_combination(-1){ fail }.should.equal?(@array)
+ @array.repeated_combination(-10){ fail }.should.equal?(@array)
end
it "yields the expected repeated_combinations" do
diff --git a/spec/ruby/core/array/repeated_permutation_spec.rb b/spec/ruby/core/array/repeated_permutation_spec.rb
index a165fda09e..c54a8c0c2b 100644
--- a/spec/ruby/core/array/repeated_permutation_spec.rb
+++ b/spec/ruby/core/array/repeated_permutation_spec.rb
@@ -10,13 +10,13 @@ describe "Array#repeated_permutation" do
it "returns an Enumerator of all repeated permutations of given length when called without a block" do
enum = @numbers.repeated_permutation(2)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.sort.should == @permutations
end
it "yields all repeated_permutations to the block then returns self when called with block but no arguments" do
yielded = []
- @numbers.repeated_permutation(2) {|n| yielded << n}.should equal(@numbers)
+ @numbers.repeated_permutation(2) {|n| yielded << n}.should.equal?(@numbers)
yielded.sort.should == @permutations
end
diff --git a/spec/ruby/core/array/replace_spec.rb b/spec/ruby/core/array/replace_spec.rb
index 2f53338f5e..ee6a98a646 100644
--- a/spec/ruby/core/array/replace_spec.rb
+++ b/spec/ruby/core/array/replace_spec.rb
@@ -1,7 +1,63 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/replace'
describe "Array#replace" do
- it_behaves_like :array_replace, :replace
+ it "replaces the elements with elements from other array" do
+ a = [1, 2, 3, 4, 5]
+ b = ['a', 'b', 'c']
+ a.replace(b).should.equal?(a)
+ a.should == b
+ a.should_not.equal?(b)
+
+ a.replace([4] * 10)
+ a.should == [4] * 10
+
+ a.replace([])
+ a.should == []
+ end
+
+ it "properly handles recursive arrays" do
+ orig = [1, 2, 3]
+ empty = ArraySpecs.empty_recursive_array
+ orig.replace(empty)
+ orig.should == empty
+
+ array = ArraySpecs.recursive_array
+ orig.replace(array)
+ orig.should == array
+ end
+
+ it "returns self" do
+ ary = [1, 2, 3]
+ other = [:a, :b, :c]
+ ary.replace(other).should.equal?(ary)
+ end
+
+ it "does not make self dependent to the original array" do
+ ary = [1, 2, 3]
+ other = [:a, :b, :c]
+ ary.replace(other)
+ ary.should == [:a, :b, :c]
+ ary << :d
+ ary.should == [:a, :b, :c, :d]
+ other.should == [:a, :b, :c]
+ end
+
+ it "tries to convert the passed argument to an Array using #to_ary" do
+ obj = mock('to_ary')
+ obj.stub!(:to_ary).and_return([1, 2, 3])
+ [].replace(obj).should == [1, 2, 3]
+ end
+
+ it "does not call #to_ary on Array subclasses" do
+ obj = ArraySpecs::ToAryArray[5, 6, 7]
+ obj.should_not_receive(:to_ary)
+ [].replace(ArraySpecs::ToAryArray[5, 6, 7]).should == [5, 6, 7]
+ end
+
+ it "raises a FrozenError on a frozen array" do
+ -> {
+ ArraySpecs.frozen_array.replace(ArraySpecs.frozen_array)
+ }.should.raise(FrozenError)
+ end
end
diff --git a/spec/ruby/core/array/reverse_each_spec.rb b/spec/ruby/core/array/reverse_each_spec.rb
index 28b8bfcb34..8fa5ce6da1 100644
--- a/spec/ruby/core/array/reverse_each_spec.rb
+++ b/spec/ruby/core/array/reverse_each_spec.rb
@@ -5,7 +5,7 @@ require_relative '../enumerable/shared/enumeratorized'
# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
-# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
+# https://blade.ruby-lang.org/ruby-core/23633
describe "Array#reverse_each" do
before :each do
@@ -19,7 +19,7 @@ describe "Array#reverse_each" do
it "returns self" do
a = [:a, :b, :c]
- a.reverse_each { |x| }.should equal(a)
+ a.reverse_each { |x| }.should.equal?(a)
end
it "yields only the top level element of an empty recursive arrays" do
@@ -38,6 +38,20 @@ describe "Array#reverse_each" do
[1, 2, 3].reverse_each.size.should == 3
end
+ it "tolerates increasing an array size during iteration" do
+ array = [:a, :b, :c]
+ ScratchPad.record []
+ i = 0
+
+ array.reverse_each do |e|
+ ScratchPad << e
+ array.prepend i if i < 100
+ i += 1
+ end
+
+ ScratchPad.recorded.should == [:c, :a, 1]
+ end
+
it_behaves_like :enumeratorize, :reverse_each
it_behaves_like :enumeratorized_with_origin_size, :reverse_each, [1,2,3]
end
diff --git a/spec/ruby/core/array/reverse_spec.rb b/spec/ruby/core/array/reverse_spec.rb
index 05dbd2efcf..f25a484be8 100644
--- a/spec/ruby/core/array/reverse_spec.rb
+++ b/spec/ruby/core/array/reverse_spec.rb
@@ -16,14 +16,14 @@ describe "Array#reverse" do
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].reverse.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].reverse.should.instance_of?(Array)
end
end
describe "Array#reverse!" do
it "reverses the elements in place" do
a = [6, 3, 4, 2, 1]
- a.reverse!.should equal(a)
+ a.reverse!.should.equal?(a)
a.should == [1, 2, 4, 3, 6]
[].reverse!.should == []
end
@@ -37,6 +37,6 @@ describe "Array#reverse!" do
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.reverse! }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.reverse! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/rindex_spec.rb b/spec/ruby/core/array/rindex_spec.rb
index 175c7bcfe2..858c39dc92 100644
--- a/spec/ruby/core/array/rindex_spec.rb
+++ b/spec/ruby/core/array/rindex_spec.rb
@@ -4,7 +4,7 @@ require_relative '../enumerable/shared/enumeratorized'
# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
-# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
+# https://blade.ruby-lang.org/ruby-core/23633
describe "Array#rindex" do
it "returns the first index backwards from the end where element == to object" do
@@ -41,7 +41,7 @@ describe "Array#rindex" do
it "properly handles empty recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty.rindex(empty).should == 0
- empty.rindex(1).should be_nil
+ empty.rindex(1).should == nil
end
it "properly handles recursive arrays" do
@@ -68,10 +68,25 @@ describe "Array#rindex" do
seen.should == [3]
end
+ it "tolerates increasing an array size during iteration" do
+ array = [:a, :b, :c]
+ ScratchPad.record []
+ i = 0
+
+ array.rindex do |e|
+ ScratchPad << e
+ array.prepend i if i < 100
+ i += 1
+ false
+ end
+
+ ScratchPad.recorded.should == [:c, :a, 1]
+ end
+
describe "given no argument and no block" do
it "produces an Enumerator" do
enum = [4, 2, 1, 5, 1, 3].rindex
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.each { |x| x < 2 }.should == 4
end
end
diff --git a/spec/ruby/core/array/rotate_spec.rb b/spec/ruby/core/array/rotate_spec.rb
index 60dcc8b113..009ce5ed49 100644
--- a/spec/ruby/core/array/rotate_spec.rb
+++ b/spec/ruby/core/array/rotate_spec.rb
@@ -29,10 +29,10 @@ describe "Array#rotate" do
it "raises a TypeError if not passed an integer-like argument" do
-> {
[1, 2].rotate(nil)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
-> {
[1, 2].rotate("4")
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
@@ -50,18 +50,18 @@ describe "Array#rotate" do
[].freeze.rotate
[2].freeze.rotate(2)
[1,2,3].freeze.rotate(-3)
- }.should_not raise_error
+ }.should_not.raise
end
it "does not return self" do
a = [1, 2, 3]
- a.rotate.should_not equal(a)
+ a.rotate.should_not.equal?(a)
a = []
- a.rotate(0).should_not equal(a)
+ a.rotate(0).should_not.equal?(a)
end
it "does not return subclass instance for Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].rotate.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].rotate.should.instance_of?(Array)
end
end
@@ -69,7 +69,7 @@ describe "Array#rotate!" do
describe "when passed no argument" do
it "moves the first element to the end and returns self" do
a = [1, 2, 3, 4, 5]
- a.rotate!.should equal(a)
+ a.rotate!.should.equal?(a)
a.should == [2, 3, 4, 5, 1]
end
end
@@ -77,11 +77,11 @@ describe "Array#rotate!" do
describe "with an argument n" do
it "moves the first (n % size) elements at the end and returns self" do
a = [1, 2, 3, 4, 5]
- a.rotate!(2).should equal(a)
+ a.rotate!(2).should.equal?(a)
a.should == [3, 4, 5, 1, 2]
- a.rotate!(-12).should equal(a)
+ a.rotate!(-12).should.equal?(a)
a.should == [1, 2, 3, 4, 5]
- a.rotate!(13).should equal(a)
+ a.rotate!(13).should.equal?(a)
a.should == [4, 5, 1, 2, 3]
end
@@ -96,34 +96,34 @@ describe "Array#rotate!" do
it "raises a TypeError if not passed an integer-like argument" do
-> {
[1, 2].rotate!(nil)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
-> {
[1, 2].rotate!("4")
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
it "does nothing and returns self when the length is zero or one" do
a = [1]
- a.rotate!.should equal(a)
+ a.rotate!.should.equal?(a)
a.should == [1]
- a.rotate!(2).should equal(a)
+ a.rotate!(2).should.equal?(a)
a.should == [1]
- a.rotate!(-21).should equal(a)
+ a.rotate!(-21).should.equal?(a)
a.should == [1]
a = []
- a.rotate!.should equal(a)
+ a.rotate!.should.equal?(a)
a.should == []
- a.rotate!(2).should equal(a)
+ a.rotate!(2).should.equal?(a)
a.should == []
- a.rotate!(-21).should equal(a)
+ a.rotate!(-21).should.equal?(a)
a.should == []
end
it "raises a FrozenError on a frozen array" do
- -> { [1, 2, 3].freeze.rotate!(0) }.should raise_error(FrozenError)
- -> { [1].freeze.rotate!(42) }.should raise_error(FrozenError)
- -> { [].freeze.rotate! }.should raise_error(FrozenError)
+ -> { [1, 2, 3].freeze.rotate!(0) }.should.raise(FrozenError)
+ -> { [1].freeze.rotate!(42) }.should.raise(FrozenError)
+ -> { [].freeze.rotate! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/array/sample_spec.rb b/spec/ruby/core/array/sample_spec.rb
index 5b3aac9aed..fd443b47de 100644
--- a/spec/ruby/core/array/sample_spec.rb
+++ b/spec/ruby/core/array/sample_spec.rb
@@ -14,19 +14,23 @@ describe "Array#sample" do
end
it "returns nil for an empty Array" do
- [].sample.should be_nil
+ [].sample.should == nil
end
it "returns nil for an empty array when called without n and a Random is given" do
- [].sample(random: Random.new(42)).should be_nil
+ [].sample(random: Random.new(42)).should == nil
end
it "returns a single value when not passed a count" do
- [4].sample.should equal(4)
+ [4].sample.should.equal?(4)
end
it "returns a single value when not passed a count and a Random is given" do
- [4].sample(random: Random.new(42)).should equal(4)
+ [4].sample(random: Random.new(42)).should.equal?(4)
+ end
+
+ it "returns a single value when not passed a count and a Random class is given" do
+ [4].sample(random: Random).should.equal?(4)
end
it "returns an empty Array when passed zero" do
@@ -34,12 +38,12 @@ describe "Array#sample" do
end
it "returns an Array of elements when passed a count" do
- [1, 2, 3, 4].sample(3).should be_an_instance_of(Array)
+ [1, 2, 3, 4].sample(3).should.instance_of?(Array)
end
it "returns elements from the Array" do
array = [1, 2, 3, 4]
- array.sample(3).all? { |x| array.should include(x) }
+ array.sample(3).all? { |x| array.should.include?(x) }
end
it "returns at most the number of elements in the Array" do
@@ -63,11 +67,11 @@ describe "Array#sample" do
end
it "raises ArgumentError when passed a negative count" do
- -> { [1, 2].sample(-1) }.should raise_error(ArgumentError)
+ -> { [1, 2].sample(-1) }.should.raise(ArgumentError)
end
it "does not return subclass instances with Array subclass" do
- ArraySpecs::MyArray[1, 2, 3].sample(2).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].sample(2).should.instance_of?(Array)
end
describe "with options" do
@@ -75,13 +79,13 @@ describe "Array#sample" do
obj = mock("array_sample_random")
obj.should_receive(:rand).and_return(0.5)
- [1, 2].sample(random: obj).should be_an_instance_of(Integer)
+ [1, 2].sample(random: obj).should.instance_of?(Integer)
end
it "raises a NoMethodError if an object passed for the RNG does not define #rand" do
obj = BasicObject.new
- -> { [1, 2].sample(random: obj) }.should raise_error(NoMethodError)
+ -> { [1, 2].sample(random: obj) }.should.raise(NoMethodError)
end
describe "when the object returned by #rand is an Integer" do
@@ -101,14 +105,21 @@ describe "Array#sample" do
random = mock("array_sample_random")
random.should_receive(:rand).and_return(-1)
- -> { [1, 2].sample(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
end
it "raises a RangeError if the value is equal to the Array size" do
random = mock("array_sample_random")
random.should_receive(:rand).and_return(2)
- -> { [1, 2].sample(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
+ end
+
+ it "raises a RangeError if the value is greater than the Array size" do
+ random = mock("array_sample_random")
+ random.should_receive(:rand).and_return(3)
+
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
end
end
end
@@ -129,7 +140,7 @@ describe "Array#sample" do
random = mock("array_sample_random")
random.should_receive(:rand).and_return(value)
- -> { [1, 2].sample(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
end
it "raises a RangeError if the value is equal to the Array size" do
@@ -138,7 +149,7 @@ describe "Array#sample" do
random = mock("array_sample_random")
random.should_receive(:rand).and_return(value)
- -> { [1, 2].sample(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].sample(random: random) }.should.raise(RangeError)
end
end
end
diff --git a/spec/ruby/core/array/select_spec.rb b/spec/ruby/core/array/select_spec.rb
index 298b591744..57ec0b2540 100644
--- a/spec/ruby/core/array/select_spec.rb
+++ b/spec/ruby/core/array/select_spec.rb
@@ -1,13 +1,42 @@
require_relative '../../spec_helper'
-require_relative 'shared/select'
+require_relative '../enumerable/shared/enumeratorized'
+require_relative 'fixtures/classes'
+require_relative 'shared/enumeratorize'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
+require_relative 'shared/keep_if'
describe "Array#select" do
- it_behaves_like :array_select, :select
+ it_behaves_like :enumeratorize, :select
+
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :select
+
+ before :each do
+ @object = [1,2,3]
+ end
+ it_behaves_like :enumeratorized_with_origin_size, :select
+
+ it "returns a new array of elements for which block is true" do
+ [1, 3, 4, 5, 6, 9].select { |i| i % ((i + 1) / 2) == 0}.should == [1, 4, 6]
+ end
+
+ it "does not return subclass instance on Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].select { true }.should.instance_of?(Array)
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.select { true }.should == empty
+ empty.select { false }.should == []
+
+ array = ArraySpecs.recursive_array
+ array.select { true }.should == [1, 'two', 3.0, array, array, array, array, array]
+ array.select { false }.should == []
+ end
end
describe "Array#select!" do
it "returns nil if no changes were made in the array" do
- [1, 2, 3].select! { true }.should be_nil
+ [1, 2, 3].select! { true }.should == nil
end
it_behaves_like :keep_if, :select!
diff --git a/spec/ruby/core/array/shared/clone.rb b/spec/ruby/core/array/shared/clone.rb
index 035b45ec99..1a45c2fe2c 100644
--- a/spec/ruby/core/array/shared/clone.rb
+++ b/spec/ruby/core/array/shared/clone.rb
@@ -1,14 +1,14 @@
describe :array_clone, shared: true do
it "returns an Array or a subclass instance" do
- [].send(@method).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2].send(@method).should be_an_instance_of(ArraySpecs::MyArray)
+ [].send(@method).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2].send(@method).should.instance_of?(ArraySpecs::MyArray)
end
it "produces a shallow copy where the references are directly copied" do
a = [mock('1'), mock('2')]
b = a.send @method
- b.first.should equal a.first
- b.last.should equal a.last
+ b.first.should.equal? a.first
+ b.last.should.equal? a.last
end
it "creates a new array containing all elements or the original" do
diff --git a/spec/ruby/core/array/shared/collect.rb b/spec/ruby/core/array/shared/collect.rb
deleted file mode 100644
index 8d75f7db9a..0000000000
--- a/spec/ruby/core/array/shared/collect.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-require_relative '../../enumerable/shared/enumeratorized'
-
-describe :array_collect, shared: true do
- it "returns a copy of array with each element replaced by the value returned by block" do
- a = ['a', 'b', 'c', 'd']
- b = a.send(@method) { |i| i + '!' }
- b.should == ["a!", "b!", "c!", "d!"]
- b.should_not equal a
- end
-
- it "does not return subclass instance" do
- ArraySpecs::MyArray[1, 2, 3].send(@method) { |x| x + 1 }.should be_an_instance_of(Array)
- end
-
- it "does not change self" do
- a = ['a', 'b', 'c', 'd']
- a.send(@method) { |i| i + '!' }
- a.should == ['a', 'b', 'c', 'd']
- end
-
- it "returns the evaluated value of block if it broke in the block" do
- a = ['a', 'b', 'c', 'd']
- b = a.send(@method) {|i|
- if i == 'c'
- break 0
- else
- i + '!'
- end
- }
- b.should == 0
- end
-
- it "returns an Enumerator when no block given" do
- a = [1, 2, 3]
- a.send(@method).should be_an_instance_of(Enumerator)
- end
-
- it "raises an ArgumentError when no block and with arguments" do
- a = [1, 2, 3]
- -> {
- a.send(@method, :foo)
- }.should raise_error(ArgumentError)
- end
-
- before :all do
- @object = [1, 2, 3, 4]
- end
- it_should_behave_like :enumeratorized_with_origin_size
-end
-
-describe :array_collect_b, shared: true do
- it "replaces each element with the value returned by block" do
- a = [7, 9, 3, 5]
- a.send(@method) { |i| i - 1 }.should equal(a)
- a.should == [6, 8, 2, 4]
- end
-
- it "returns self" do
- a = [1, 2, 3, 4, 5]
- b = a.send(@method) {|i| i+1 }
- a.should equal b
- end
-
- it "returns the evaluated value of block but its contents is partially modified, if it broke in the block" do
- a = ['a', 'b', 'c', 'd']
- b = a.send(@method) {|i|
- if i == 'c'
- break 0
- else
- i + '!'
- end
- }
- b.should == 0
- a.should == ['a!', 'b!', 'c', 'd']
- end
-
- it "returns an Enumerator when no block given, and the enumerator can modify the original array" do
- a = [1, 2, 3]
- enum = a.send(@method)
- enum.should be_an_instance_of(Enumerator)
- enum.each{|i| "#{i}!" }
- a.should == ["1!", "2!", "3!"]
- end
-
- describe "when frozen" do
- it "raises a FrozenError" do
- -> { ArraySpecs.frozen_array.send(@method) {} }.should raise_error(FrozenError)
- end
-
- it "raises a FrozenError when empty" do
- -> { ArraySpecs.empty_frozen_array.send(@method) {} }.should raise_error(FrozenError)
- end
-
- it "raises a FrozenError when calling #each on the returned Enumerator" do
- enumerator = ArraySpecs.frozen_array.send(@method)
- -> { enumerator.each {|x| x } }.should raise_error(FrozenError)
- end
-
- it "raises a FrozenError when calling #each on the returned Enumerator when empty" do
- enumerator = ArraySpecs.empty_frozen_array.send(@method)
- -> { enumerator.each {|x| x } }.should raise_error(FrozenError)
- end
- end
-
- before :all do
- @object = [1, 2, 3, 4]
- end
- it_should_behave_like :enumeratorized_with_origin_size
-end
diff --git a/spec/ruby/core/array/shared/difference.rb b/spec/ruby/core/array/shared/difference.rb
index 3e69050d82..3fe22331bd 100644
--- a/spec/ruby/core/array/shared/difference.rb
+++ b/spec/ruby/core/array/shared/difference.rb
@@ -27,13 +27,13 @@ describe :array_binary_difference, shared: true do
it "raises a TypeError if the argument cannot be coerced to an Array by calling #to_ary" do
obj = mock('not an array')
- -> { [1, 2, 3].send(@method, obj) }.should raise_error(TypeError)
+ -> { [1, 2, 3].send(@method, obj) }.should.raise(TypeError)
end
it "does not return subclass instance for Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].send(@method, []).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[]).should be_an_instance_of(Array)
- [1, 2, 3].send(@method, ArraySpecs::MyArray[]).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, []).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[]).should.instance_of?(Array)
+ [1, 2, 3].send(@method, ArraySpecs::MyArray[]).should.instance_of?(Array)
end
it "does not call to_ary on array subclasses" do
diff --git a/spec/ruby/core/array/shared/enumeratorize.rb b/spec/ruby/core/array/shared/enumeratorize.rb
index a19a5d3b9b..5beab5c4c4 100644
--- a/spec/ruby/core/array/shared/enumeratorize.rb
+++ b/spec/ruby/core/array/shared/enumeratorize.rb
@@ -1,5 +1,5 @@
describe :enumeratorize, shared: true do
it "returns an Enumerator if no block given" do
- [1,2].send(@method).should be_an_instance_of(Enumerator)
+ [1,2].send(@method).should.instance_of?(Enumerator)
end
end
diff --git a/spec/ruby/core/array/shared/eql.rb b/spec/ruby/core/array/shared/eql.rb
index b5d9128434..5e770bf167 100644
--- a/spec/ruby/core/array/shared/eql.rb
+++ b/spec/ruby/core/array/shared/eql.rb
@@ -1,59 +1,59 @@
describe :array_eql, shared: true do
it "returns true if other is the same array" do
a = [1]
- a.send(@method, a).should be_true
+ a.send(@method, a).should == true
end
it "returns true if corresponding elements are #eql?" do
- [].send(@method, []).should be_true
- [1, 2, 3, 4].send(@method, [1, 2, 3, 4]).should be_true
+ [].send(@method, []).should == true
+ [1, 2, 3, 4].send(@method, [1, 2, 3, 4]).should == true
end
it "returns false if other is shorter than self" do
- [1, 2, 3, 4].send(@method, [1, 2, 3]).should be_false
+ [1, 2, 3, 4].send(@method, [1, 2, 3]).should == false
end
it "returns false if other is longer than self" do
- [1, 2, 3, 4].send(@method, [1, 2, 3, 4, 5]).should be_false
+ [1, 2, 3, 4].send(@method, [1, 2, 3, 4, 5]).should == false
end
it "returns false immediately when sizes of the arrays differ" do
obj = mock('1')
obj.should_not_receive(@method)
- [] .send(@method, [obj] ).should be_false
- [obj] .send(@method, [] ).should be_false
+ [] .send(@method, [obj] ).should == false
+ [obj] .send(@method, [] ).should == false
end
it "handles well recursive arrays" do
a = ArraySpecs.empty_recursive_array
- a .send(@method, [a] ).should be_true
- a .send(@method, [[a]] ).should be_true
- [a] .send(@method, a ).should be_true
- [[a]] .send(@method, a ).should be_true
+ a .send(@method, [a] ).should == true
+ a .send(@method, [[a]] ).should == true
+ [a] .send(@method, a ).should == true
+ [[a]] .send(@method, a ).should == true
# These may be surprising, but no difference can be
# found between these arrays, so they are ==.
# There is no "path" that will lead to a difference
# (contrary to other examples below)
a2 = ArraySpecs.empty_recursive_array
- a .send(@method, a2 ).should be_true
- a .send(@method, [a2] ).should be_true
- a .send(@method, [[a2]] ).should be_true
- [a] .send(@method, a2 ).should be_true
- [[a]] .send(@method, a2 ).should be_true
+ a .send(@method, a2 ).should == true
+ a .send(@method, [a2] ).should == true
+ a .send(@method, [[a2]] ).should == true
+ [a] .send(@method, a2 ).should == true
+ [[a]] .send(@method, a2 ).should == true
back = []
forth = [back]; back << forth;
- back .send(@method, a ).should be_true
+ back .send(@method, a ).should == true
x = []; x << x << x
- x .send(@method, a ).should be_false # since x.size != a.size
- x .send(@method, [a, a] ).should be_false # since x[0].size != [a, a][0].size
- x .send(@method, [x, a] ).should be_false # since x[1].size != [x, a][1].size
- [x, a] .send(@method, [a, x] ).should be_false # etc...
- x .send(@method, [x, x] ).should be_true
- x .send(@method, [[x, x], [x, x]] ).should be_true
+ x .send(@method, a ).should == false # since x.size != a.size
+ x .send(@method, [a, a] ).should == false # since x[0].size != [a, a][0].size
+ x .send(@method, [x, a] ).should == false # since x[1].size != [x, a][1].size
+ [x, a] .send(@method, [a, x] ).should == false # etc...
+ x .send(@method, [x, x] ).should == true
+ x .send(@method, [[x, x], [x, x]] ).should == true
tree = [];
branch = []; branch << tree << tree; tree << branch
@@ -62,31 +62,31 @@ describe :array_eql, shared: true do
forest = [tree, branch, :bird, a]; forest << forest
forest2 = [tree2, branch2, :bird, a2]; forest2 << forest2
- forest .send(@method, forest2 ).should be_true
- forest .send(@method, [tree2, branch, :bird, a, forest2]).should be_true
+ forest .send(@method, forest2 ).should == true
+ forest .send(@method, [tree2, branch, :bird, a, forest2]).should == true
diffforest = [branch2, tree2, :bird, a2]; diffforest << forest2
- forest .send(@method, diffforest ).should be_false # since forest[0].size == 1 != 3 == diffforest[0]
- forest .send(@method, [nil] ).should be_false
- forest .send(@method, [forest] ).should be_false
+ forest .send(@method, diffforest ).should == false # since forest[0].size == 1 != 3 == diffforest[0]
+ forest .send(@method, [nil] ).should == false
+ forest .send(@method, [forest] ).should == false
end
it "does not call #to_ary on its argument" do
obj = mock('to_ary')
obj.should_not_receive(:to_ary)
- [1, 2, 3].send(@method, obj).should be_false
+ [1, 2, 3].send(@method, obj).should == false
end
it "does not call #to_ary on Array subclasses" do
ary = ArraySpecs::ToAryArray[5, 6, 7]
ary.should_not_receive(:to_ary)
- [5, 6, 7].send(@method, ary).should be_true
+ [5, 6, 7].send(@method, ary).should == true
end
it "ignores array class differences" do
- ArraySpecs::MyArray[1, 2, 3].send(@method, [1, 2, 3]).should be_true
- ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_true
- [1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_true
+ ArraySpecs::MyArray[1, 2, 3].send(@method, [1, 2, 3]).should == true
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should == true
+ [1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should == true
end
end
diff --git a/spec/ruby/core/array/shared/index.rb b/spec/ruby/core/array/shared/index.rb
deleted file mode 100644
index a9896554f2..0000000000
--- a/spec/ruby/core/array/shared/index.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-describe :array_index, shared: true do
- it "returns the index of the first element == to object" do
- x = mock('3')
- def x.==(obj) 3 == obj; end
-
- [2, x, 3, 1, 3, 1].send(@method, 3).should == 1
- [2, 3.0, 3, x, 1, 3, 1].send(@method, x).should == 1
- end
-
- it "returns 0 if first element == to object" do
- [2, 1, 3, 2, 5].send(@method, 2).should == 0
- end
-
- it "returns size-1 if only last element == to object" do
- [2, 1, 3, 1, 5].send(@method, 5).should == 4
- end
-
- it "returns nil if no element == to object" do
- [2, 1, 1, 1, 1].send(@method, 3).should == nil
- end
-
- it "accepts a block instead of an argument" do
- [4, 2, 1, 5, 1, 3].send(@method) {|x| x < 2}.should == 2
- end
-
- it "ignores the block if there is an argument" do
- -> {
- [4, 2, 1, 5, 1, 3].send(@method, 5) {|x| x < 2}.should == 3
- }.should complain(/given block not used/)
- end
-
- describe "given no argument and no block" do
- it "produces an Enumerator" do
- [].send(@method).should be_an_instance_of(Enumerator)
- end
- end
-end
diff --git a/spec/ruby/core/array/shared/inspect.rb b/spec/ruby/core/array/shared/inspect.rb
deleted file mode 100644
index a2b43d4959..0000000000
--- a/spec/ruby/core/array/shared/inspect.rb
+++ /dev/null
@@ -1,107 +0,0 @@
-require_relative '../fixtures/encoded_strings'
-
-describe :array_inspect, shared: true do
- it "returns a string" do
- [1, 2, 3].send(@method).should be_an_instance_of(String)
- end
-
- it "returns '[]' for an empty Array" do
- [].send(@method).should == "[]"
- end
-
- it "calls inspect on its elements and joins the results with commas" do
- items = Array.new(3) do |i|
- obj = mock(i.to_s)
- obj.should_receive(:inspect).and_return(i.to_s)
- obj
- end
- items.send(@method).should == "[0, 1, 2]"
- end
-
- it "does not call #to_s on a String returned from #inspect" do
- str = "abc"
- str.should_not_receive(:to_s)
-
- [str].send(@method).should == '["abc"]'
- end
-
- it "calls #to_s on the object returned from #inspect if the Object isn't a String" do
- obj = mock("Array#inspect/to_s calls #to_s")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_receive(:to_s).and_return("abc")
-
- [obj].send(@method).should == "[abc]"
- end
-
- it "does not call #to_str on the object returned from #inspect when it is not a String" do
- obj = mock("Array#inspect/to_s does not call #to_str")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_not_receive(:to_str)
-
- [obj].send(@method).should =~ /^\[#<MockObject:0x[0-9a-f]+>\]$/
- end
-
- it "does not call #to_str on the object returned from #to_s when it is not a String" do
- obj = mock("Array#inspect/to_s does not call #to_str on #to_s result")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_receive(:to_s).and_return(obj)
- obj.should_not_receive(:to_str)
-
- [obj].send(@method).should =~ /^\[#<MockObject:0x[0-9a-f]+>\]$/
- end
-
- it "does not swallow exceptions raised by #to_s" do
- obj = mock("Array#inspect/to_s does not swallow #to_s exceptions")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_receive(:to_s).and_raise(Exception)
-
- -> { [obj].send(@method) }.should raise_error(Exception)
- end
-
- it "represents a recursive element with '[...]'" do
- ArraySpecs.recursive_array.send(@method).should == "[1, \"two\", 3.0, [...], [...], [...], [...], [...]]"
- ArraySpecs.head_recursive_array.send(@method).should == "[[...], [...], [...], [...], [...], 1, \"two\", 3.0]"
- ArraySpecs.empty_recursive_array.send(@method).should == "[[...]]"
- end
-
- describe "with encoding" do
- before :each do
- @default_external_encoding = Encoding.default_external
- end
-
- after :each do
- Encoding.default_external = @default_external_encoding
- end
-
- it "returns a US-ASCII string for an empty Array" do
- [].send(@method).encoding.should == Encoding::US_ASCII
- end
-
- it "use the default external encoding if it is ascii compatible" do
- Encoding.default_external = Encoding.find('UTF-8')
-
- utf8 = "utf8".encode("UTF-8")
- jp = "jp".encode("EUC-JP")
- array = [jp, utf8]
-
- array.send(@method).encoding.name.should == "UTF-8"
- end
-
- it "use US-ASCII encoding if the default external encoding is not ascii compatible" do
- Encoding.default_external = Encoding.find('UTF-32')
-
- utf8 = "utf8".encode("UTF-8")
- jp = "jp".encode("EUC-JP")
- array = [jp, utf8]
-
- array.send(@method).encoding.name.should == "US-ASCII"
- end
-
- it "does not raise if inspected result is not default external encoding" do
- utf_16be = mock("utf_16be")
- utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
-
- [utf_16be].send(@method).should == '["utf_16be \u3042"]'
- end
- end
-end
diff --git a/spec/ruby/core/array/shared/intersection.rb b/spec/ruby/core/array/shared/intersection.rb
index 49849b08c2..dda72e8bd7 100644
--- a/spec/ruby/core/array/shared/intersection.rb
+++ b/spec/ruby/core/array/shared/intersection.rb
@@ -11,7 +11,8 @@ describe :array_intersection, shared: true do
end
it "creates an array with elements in order they are first encountered" do
- [ 1, 2, 3, 2, 5 ].send(@method, [ 5, 2, 3, 4 ]).should == [2, 3, 5]
+ [ 1, 2, 3, 2, 5, 6, 7, 8 ].send(@method, [ 5, 2, 3, 4 ]).should == [2, 3, 5] # array > other
+ [ 5, 2, 3, 4 ].send(@method, [ 1, 2, 3, 2, 5, 6, 7, 8 ]).should == [5, 2, 3] # array < other
end
it "does not modify the original Array" do
@@ -65,9 +66,9 @@ describe :array_intersection, shared: true do
end
it "does return subclass instances for Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].send(@method, []).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
- [].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, []).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should.instance_of?(Array)
+ [].send(@method, ArraySpecs::MyArray[1, 2, 3]).should.instance_of?(Array)
end
it "does not call to_ary on array subclasses" do
diff --git a/spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb b/spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb
new file mode 100644
index 0000000000..3e73bad44b
--- /dev/null
+++ b/spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb
@@ -0,0 +1,25 @@
+describe :array_iterable_and_tolerating_size_increasing, shared: true do
+ before do
+ @value_to_return ||= -> _ { nil }
+ end
+
+ it "tolerates increasing an array size during iteration" do
+ # The goal is to trigger potential reallocation of internal array storage, so we:
+ # - use elements of different types, starting with the less generic (Integer)
+ # - add reasonably big number of new elements (~ 100)
+ array = [1, 2, 3] # to test some methods we need several uniq elements
+ array_to_join = [:a, :b, :c] + (4..100).to_a
+
+ ScratchPad.record []
+ i = 0
+
+ array.send(@method) do |e|
+ ScratchPad << e
+ array << array_to_join[i] if i < array_to_join.size
+ i += 1
+ @value_to_return.call(e)
+ end
+
+ ScratchPad.recorded.should == [1, 2, 3] + array_to_join
+ end
+end
diff --git a/spec/ruby/core/array/shared/join.rb b/spec/ruby/core/array/shared/join.rb
index 507b13e3c8..93d5329ee3 100644
--- a/spec/ruby/core/array/shared/join.rb
+++ b/spec/ruby/core/array/shared/join.rb
@@ -1,103 +1,6 @@
require_relative '../fixtures/classes'
require_relative '../fixtures/encoded_strings'
-describe :array_join_with_default_separator, shared: true do
- before :each do
- @separator = $,
- end
-
- after :each do
- $, = @separator
- end
-
- it "returns an empty string if the Array is empty" do
- [].send(@method).should == ''
- end
-
- it "returns a US-ASCII string for an empty Array" do
- [].send(@method).encoding.should == Encoding::US_ASCII
- end
-
- it "returns a string formed by concatenating each String element separated by $," do
- suppress_warning {
- $, = " | "
- ["1", "2", "3"].send(@method).should == "1 | 2 | 3"
- }
- end
-
- it "attempts coercion via #to_str first" do
- obj = mock('foo')
- obj.should_receive(:to_str).any_number_of_times.and_return("foo")
- [obj].send(@method).should == "foo"
- end
-
- it "attempts coercion via #to_ary second" do
- obj = mock('foo')
- obj.should_receive(:to_str).any_number_of_times.and_return(nil)
- obj.should_receive(:to_ary).any_number_of_times.and_return(["foo"])
- [obj].send(@method).should == "foo"
- end
-
- it "attempts coercion via #to_s third" do
- obj = mock('foo')
- obj.should_receive(:to_str).any_number_of_times.and_return(nil)
- obj.should_receive(:to_ary).any_number_of_times.and_return(nil)
- obj.should_receive(:to_s).any_number_of_times.and_return("foo")
- [obj].send(@method).should == "foo"
- end
-
- it "raises a NoMethodError if an element does not respond to #to_str, #to_ary, or #to_s" do
- obj = mock('o')
- class << obj; undef :to_s; end
- -> { [1, obj].send(@method) }.should raise_error(NoMethodError)
- end
-
- it "raises an ArgumentError when the Array is recursive" do
- -> { ArraySpecs.recursive_array.send(@method) }.should raise_error(ArgumentError)
- -> { ArraySpecs.head_recursive_array.send(@method) }.should raise_error(ArgumentError)
- -> { ArraySpecs.empty_recursive_array.send(@method) }.should raise_error(ArgumentError)
- end
-
- it "uses the first encoding when other strings are compatible" do
- ary1 = ArraySpecs.array_with_7bit_utf8_and_usascii_strings
- ary2 = ArraySpecs.array_with_usascii_and_7bit_utf8_strings
- ary3 = ArraySpecs.array_with_utf8_and_7bit_binary_strings
- ary4 = ArraySpecs.array_with_usascii_and_7bit_binary_strings
-
- ary1.send(@method).encoding.should == Encoding::UTF_8
- ary2.send(@method).encoding.should == Encoding::US_ASCII
- ary3.send(@method).encoding.should == Encoding::UTF_8
- ary4.send(@method).encoding.should == Encoding::US_ASCII
- end
-
- it "uses the widest common encoding when other strings are incompatible" do
- ary1 = ArraySpecs.array_with_utf8_and_usascii_strings
- ary2 = ArraySpecs.array_with_usascii_and_utf8_strings
-
- ary1.send(@method).encoding.should == Encoding::UTF_8
- ary2.send(@method).encoding.should == Encoding::UTF_8
- end
-
- it "fails for arrays with incompatibly-encoded strings" do
- ary_utf8_bad_binary = ArraySpecs.array_with_utf8_and_binary_strings
-
- -> { ary_utf8_bad_binary.send(@method) }.should raise_error(EncodingError)
- end
-
- context "when $, is not nil" do
- before do
- suppress_warning do
- $, = '*'
- end
- end
-
- it "warns" do
- -> { [].join }.should complain(/warning: \$, is set to non-nil value/)
- -> { [].join(nil) }.should complain(/warning: \$, is set to non-nil value/)
- end
- end
-end
-
describe :array_join_with_string_separator, shared: true do
it "returns a string formed by concatenating each element.to_str separated by separator" do
obj = mock('foo')
diff --git a/spec/ruby/core/array/shared/keep_if.rb b/spec/ruby/core/array/shared/keep_if.rb
index f26aff028c..44625eebd1 100644
--- a/spec/ruby/core/array/shared/keep_if.rb
+++ b/spec/ruby/core/array/shared/keep_if.rb
@@ -1,14 +1,15 @@
require_relative '../../enumerable/shared/enumeratorized'
+require_relative '../shared/iterable_and_tolerating_size_increasing'
describe :keep_if, shared: true do
it "deletes elements for which the block returns a false value" do
array = [1, 2, 3, 4, 5]
- array.send(@method) {|item| item > 3 }.should equal(array)
+ array.send(@method) {|item| item > 3 }.should.equal?(array)
array.should == [4, 5]
end
it "returns an enumerator if no block is given" do
- [1, 2, 3].send(@method).should be_an_instance_of(Enumerator)
+ [1, 2, 3].send(@method).should.instance_of?(Enumerator)
end
it "updates the receiver after all blocks" do
@@ -32,29 +33,63 @@ describe :keep_if, shared: true do
end
it "returns an Enumerator if no block is given" do
- @frozen.send(@method).should be_an_instance_of(Enumerator)
+ @frozen.send(@method).should.instance_of?(Enumerator)
end
describe "with truthy block" do
it "keeps elements after any exception" do
- -> { @frozen.send(@method) { true } }.should raise_error(Exception)
+ -> { @frozen.send(@method) { true } }.should.raise(Exception)
@frozen.should == @origin
end
it "raises a FrozenError" do
- -> { @frozen.send(@method) { true } }.should raise_error(FrozenError)
+ -> { @frozen.send(@method) { true } }.should.raise(FrozenError)
end
end
describe "with falsy block" do
it "keeps elements after any exception" do
- -> { @frozen.send(@method) { false } }.should raise_error(Exception)
+ -> { @frozen.send(@method) { false } }.should.raise(Exception)
@frozen.should == @origin
end
it "raises a FrozenError" do
- -> { @frozen.send(@method) { false } }.should raise_error(FrozenError)
+ -> { @frozen.send(@method) { false } }.should.raise(FrozenError)
end
end
+
+ it "raises a FrozenError on a frozen array only during iteration if called without a block" do
+ enum = @frozen.send(@method)
+ -> { enum.each {} }.should.raise(FrozenError)
+ end
+ end
+
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.send(@method) { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
end
+
+ it "only changes elements before error is raised, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.send(@method) do |e|
+ case e
+ when 2 then false
+ when 3 then raise StandardError, 'Oops'
+ else true
+ end
+ end
+ rescue StandardError
+ end
+
+ a.should == [1, 3, 4]
+ end
+
+ @value_to_return = -> _ { true }
+ it_should_behave_like :array_iterable_and_tolerating_size_increasing
end
diff --git a/spec/ruby/core/array/shared/length.rb b/spec/ruby/core/array/shared/length.rb
deleted file mode 100644
index f84966d0ba..0000000000
--- a/spec/ruby/core/array/shared/length.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-describe :array_length, shared: true do
- it "returns the number of elements" do
- [].send(@method).should == 0
- [1, 2, 3].send(@method).should == 3
- end
-
- it "properly handles recursive arrays" do
- ArraySpecs.empty_recursive_array.send(@method).should == 1
- ArraySpecs.recursive_array.send(@method).should == 8
- end
-end
diff --git a/spec/ruby/core/array/shared/push.rb b/spec/ruby/core/array/shared/push.rb
deleted file mode 100644
index ac790fb6a4..0000000000
--- a/spec/ruby/core/array/shared/push.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-describe :array_push, shared: true do
- it "appends the arguments to the array" do
- a = [ "a", "b", "c" ]
- a.send(@method, "d", "e", "f").should equal(a)
- a.send(@method).should == ["a", "b", "c", "d", "e", "f"]
- a.send(@method, 5)
- a.should == ["a", "b", "c", "d", "e", "f", 5]
-
- a = [0, 1]
- a.send(@method, 2)
- a.should == [0, 1, 2]
- end
-
- it "isn't confused by previous shift" do
- a = [ "a", "b", "c" ]
- a.shift
- a.send(@method, "foo")
- a.should == ["b", "c", "foo"]
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- empty.send(@method, :last).should == [empty, :last]
-
- array = ArraySpecs.recursive_array
- array.send(@method, :last).should == [1, 'two', 3.0, array, array, array, array, array, :last]
- end
-
- it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(FrozenError)
- -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError)
- end
-end
diff --git a/spec/ruby/core/array/shared/replace.rb b/spec/ruby/core/array/shared/replace.rb
deleted file mode 100644
index 9a6e60c1b0..0000000000
--- a/spec/ruby/core/array/shared/replace.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-describe :array_replace, shared: true do
- it "replaces the elements with elements from other array" do
- a = [1, 2, 3, 4, 5]
- b = ['a', 'b', 'c']
- a.send(@method, b).should equal(a)
- a.should == b
- a.should_not equal(b)
-
- a.send(@method, [4] * 10)
- a.should == [4] * 10
-
- a.send(@method, [])
- a.should == []
- end
-
- it "properly handles recursive arrays" do
- orig = [1, 2, 3]
- empty = ArraySpecs.empty_recursive_array
- orig.send(@method, empty)
- orig.should == empty
-
- array = ArraySpecs.recursive_array
- orig.send(@method, array)
- orig.should == array
- end
-
- it "returns self" do
- ary = [1, 2, 3]
- other = [:a, :b, :c]
- ary.send(@method, other).should equal(ary)
- end
-
- it "does not make self dependent to the original array" do
- ary = [1, 2, 3]
- other = [:a, :b, :c]
- ary.send(@method, other)
- ary.should == [:a, :b, :c]
- ary << :d
- ary.should == [:a, :b, :c, :d]
- other.should == [:a, :b, :c]
- end
-
- it "tries to convert the passed argument to an Array using #to_ary" do
- obj = mock('to_ary')
- obj.stub!(:to_ary).and_return([1, 2, 3])
- [].send(@method, obj).should == [1, 2, 3]
- end
-
- it "does not call #to_ary on Array subclasses" do
- obj = ArraySpecs::ToAryArray[5, 6, 7]
- obj.should_not_receive(:to_ary)
- [].send(@method, ArraySpecs::ToAryArray[5, 6, 7]).should == [5, 6, 7]
- end
-
- it "raises a FrozenError on a frozen array" do
- -> {
- ArraySpecs.frozen_array.send(@method, ArraySpecs.frozen_array)
- }.should raise_error(FrozenError)
- end
-end
diff --git a/spec/ruby/core/array/shared/select.rb b/spec/ruby/core/array/shared/select.rb
deleted file mode 100644
index 09101e8ab5..0000000000
--- a/spec/ruby/core/array/shared/select.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require_relative '../../../spec_helper'
-require_relative '../fixtures/classes'
-require_relative '../shared/enumeratorize'
-require_relative '../shared/keep_if'
-require_relative '../../enumerable/shared/enumeratorized'
-
-describe :array_select, shared: true do
- it_should_behave_like :enumeratorize
-
- before :each do
- @object = [1,2,3]
- end
- it_should_behave_like :enumeratorized_with_origin_size
-
- it "returns a new array of elements for which block is true" do
- [1, 3, 4, 5, 6, 9].send(@method) { |i| i % ((i + 1) / 2) == 0}.should == [1, 4, 6]
- end
-
- it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].send(@method) { true }.should be_an_instance_of(Array)
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- empty.send(@method) { true }.should == empty
- empty.send(@method) { false }.should == []
-
- array = ArraySpecs.recursive_array
- array.send(@method) { true }.should == [1, 'two', 3.0, array, array, array, array, array]
- array.send(@method) { false }.should == []
- end
-end
diff --git a/spec/ruby/core/array/shared/slice.rb b/spec/ruby/core/array/shared/slice.rb
deleted file mode 100644
index 3b09fdcbc6..0000000000
--- a/spec/ruby/core/array/shared/slice.rb
+++ /dev/null
@@ -1,793 +0,0 @@
-describe :array_slice, shared: true do
- it "returns the element at index with [index]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 1).should == "b"
-
- a = [1, 2, 3, 4]
-
- a.send(@method, 0).should == 1
- a.send(@method, 1).should == 2
- a.send(@method, 2).should == 3
- a.send(@method, 3).should == 4
- a.send(@method, 4).should == nil
- a.send(@method, 10).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns the element at index from the end of the array with [-index]" do
- [ "a", "b", "c", "d", "e" ].send(@method, -2).should == "d"
-
- a = [1, 2, 3, 4]
-
- a.send(@method, -1).should == 4
- a.send(@method, -2).should == 3
- a.send(@method, -3).should == 2
- a.send(@method, -4).should == 1
- a.send(@method, -5).should == nil
- a.send(@method, -10).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns count elements starting from index with [index, count]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 2, 3).should == ["c", "d", "e"]
-
- a = [1, 2, 3, 4]
-
- a.send(@method, 0, 0).should == []
- a.send(@method, 0, 1).should == [1]
- a.send(@method, 0, 2).should == [1, 2]
- a.send(@method, 0, 4).should == [1, 2, 3, 4]
- a.send(@method, 0, 6).should == [1, 2, 3, 4]
- a.send(@method, 0, -1).should == nil
- a.send(@method, 0, -2).should == nil
- a.send(@method, 0, -4).should == nil
-
- a.send(@method, 2, 0).should == []
- a.send(@method, 2, 1).should == [3]
- a.send(@method, 2, 2).should == [3, 4]
- a.send(@method, 2, 4).should == [3, 4]
- a.send(@method, 2, -1).should == nil
-
- a.send(@method, 4, 0).should == []
- a.send(@method, 4, 2).should == []
- a.send(@method, 4, -1).should == nil
-
- a.send(@method, 5, 0).should == nil
- a.send(@method, 5, 2).should == nil
- a.send(@method, 5, -1).should == nil
-
- a.send(@method, 6, 0).should == nil
- a.send(@method, 6, 2).should == nil
- a.send(@method, 6, -1).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns count elements starting at index from the end of array with [-index, count]" do
- [ "a", "b", "c", "d", "e" ].send(@method, -2, 2).should == ["d", "e"]
-
- a = [1, 2, 3, 4]
-
- a.send(@method, -1, 0).should == []
- a.send(@method, -1, 1).should == [4]
- a.send(@method, -1, 2).should == [4]
- a.send(@method, -1, -1).should == nil
-
- a.send(@method, -2, 0).should == []
- a.send(@method, -2, 1).should == [3]
- a.send(@method, -2, 2).should == [3, 4]
- a.send(@method, -2, 4).should == [3, 4]
- a.send(@method, -2, -1).should == nil
-
- a.send(@method, -4, 0).should == []
- a.send(@method, -4, 1).should == [1]
- a.send(@method, -4, 2).should == [1, 2]
- a.send(@method, -4, 4).should == [1, 2, 3, 4]
- a.send(@method, -4, 6).should == [1, 2, 3, 4]
- a.send(@method, -4, -1).should == nil
-
- a.send(@method, -5, 0).should == nil
- a.send(@method, -5, 1).should == nil
- a.send(@method, -5, 10).should == nil
- a.send(@method, -5, -1).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns the first count elements with [0, count]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 0, 3).should == ["a", "b", "c"]
- end
-
- it "returns the subarray which is independent to self with [index,count]" do
- a = [1, 2, 3]
- sub = a.send(@method, 1,2)
- sub.replace([:a, :b])
- a.should == [1, 2, 3]
- end
-
- it "tries to convert the passed argument to an Integer using #to_int" do
- obj = mock('to_int')
- obj.stub!(:to_int).and_return(2)
-
- a = [1, 2, 3, 4]
- a.send(@method, obj).should == 3
- a.send(@method, obj, 1).should == [3]
- a.send(@method, obj, obj).should == [3, 4]
- a.send(@method, 0, obj).should == [1, 2]
- end
-
- it "raises TypeError if to_int returns non-integer" do
- from = mock('from')
- to = mock('to')
-
- # So we can construct a range out of them...
- def from.<=>(o) 0 end
- def to.<=>(o) 0 end
-
- a = [1, 2, 3, 4, 5]
-
- def from.to_int() 'cat' end
- def to.to_int() -2 end
-
- -> { a.send(@method, from..to) }.should raise_error(TypeError)
-
- def from.to_int() 1 end
- def to.to_int() 'cat' end
-
- -> { a.send(@method, from..to) }.should raise_error(TypeError)
- end
-
- it "returns the elements specified by Range indexes with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 1..3).should == ["b", "c", "d"]
- [ "a", "b", "c", "d", "e" ].send(@method, 4..-1).should == ['e']
- [ "a", "b", "c", "d", "e" ].send(@method, 3..3).should == ['d']
- [ "a", "b", "c", "d", "e" ].send(@method, 3..-2).should == ['d']
- ['a'].send(@method, 0..-1).should == ['a']
-
- a = [1, 2, 3, 4]
-
- a.send(@method, 0..-10).should == []
- a.send(@method, 0..0).should == [1]
- a.send(@method, 0..1).should == [1, 2]
- a.send(@method, 0..2).should == [1, 2, 3]
- a.send(@method, 0..3).should == [1, 2, 3, 4]
- a.send(@method, 0..4).should == [1, 2, 3, 4]
- a.send(@method, 0..10).should == [1, 2, 3, 4]
-
- a.send(@method, 2..-10).should == []
- a.send(@method, 2..0).should == []
- a.send(@method, 2..2).should == [3]
- a.send(@method, 2..3).should == [3, 4]
- a.send(@method, 2..4).should == [3, 4]
-
- a.send(@method, 3..0).should == []
- a.send(@method, 3..3).should == [4]
- a.send(@method, 3..4).should == [4]
-
- a.send(@method, 4..0).should == []
- a.send(@method, 4..4).should == []
- a.send(@method, 4..5).should == []
-
- a.send(@method, 5..0).should == nil
- a.send(@method, 5..5).should == nil
- a.send(@method, 5..6).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns elements specified by Range indexes except the element at index n with [m...n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 1...3).should == ["b", "c"]
-
- a = [1, 2, 3, 4]
-
- a.send(@method, 0...-10).should == []
- a.send(@method, 0...0).should == []
- a.send(@method, 0...1).should == [1]
- a.send(@method, 0...2).should == [1, 2]
- a.send(@method, 0...3).should == [1, 2, 3]
- a.send(@method, 0...4).should == [1, 2, 3, 4]
- a.send(@method, 0...10).should == [1, 2, 3, 4]
-
- a.send(@method, 2...-10).should == []
- a.send(@method, 2...0).should == []
- a.send(@method, 2...2).should == []
- a.send(@method, 2...3).should == [3]
- a.send(@method, 2...4).should == [3, 4]
-
- a.send(@method, 3...0).should == []
- a.send(@method, 3...3).should == []
- a.send(@method, 3...4).should == [4]
-
- a.send(@method, 4...0).should == []
- a.send(@method, 4...4).should == []
- a.send(@method, 4...5).should == []
-
- a.send(@method, 5...0).should == nil
- a.send(@method, 5...5).should == nil
- a.send(@method, 5...6).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns elements that exist if range start is in the array but range end is not with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 4..7).should == ["e"]
- end
-
- it "accepts Range instances having a negative m and both signs for n with [m..n] and [m...n]" do
- a = [1, 2, 3, 4]
-
- a.send(@method, -1..-1).should == [4]
- a.send(@method, -1...-1).should == []
- a.send(@method, -1..3).should == [4]
- a.send(@method, -1...3).should == []
- a.send(@method, -1..4).should == [4]
- a.send(@method, -1...4).should == [4]
- a.send(@method, -1..10).should == [4]
- a.send(@method, -1...10).should == [4]
- a.send(@method, -1..0).should == []
- a.send(@method, -1..-4).should == []
- a.send(@method, -1...-4).should == []
- a.send(@method, -1..-6).should == []
- a.send(@method, -1...-6).should == []
-
- a.send(@method, -2..-2).should == [3]
- a.send(@method, -2...-2).should == []
- a.send(@method, -2..-1).should == [3, 4]
- a.send(@method, -2...-1).should == [3]
- a.send(@method, -2..10).should == [3, 4]
- a.send(@method, -2...10).should == [3, 4]
-
- a.send(@method, -4..-4).should == [1]
- a.send(@method, -4..-2).should == [1, 2, 3]
- a.send(@method, -4...-2).should == [1, 2]
- a.send(@method, -4..-1).should == [1, 2, 3, 4]
- a.send(@method, -4...-1).should == [1, 2, 3]
- a.send(@method, -4..3).should == [1, 2, 3, 4]
- a.send(@method, -4...3).should == [1, 2, 3]
- a.send(@method, -4..4).should == [1, 2, 3, 4]
- a.send(@method, -4...4).should == [1, 2, 3, 4]
- a.send(@method, -4...4).should == [1, 2, 3, 4]
- a.send(@method, -4..0).should == [1]
- a.send(@method, -4...0).should == []
- a.send(@method, -4..1).should == [1, 2]
- a.send(@method, -4...1).should == [1]
-
- a.send(@method, -5..-5).should == nil
- a.send(@method, -5...-5).should == nil
- a.send(@method, -5..-4).should == nil
- a.send(@method, -5..-1).should == nil
- a.send(@method, -5..10).should == nil
-
- a.should == [1, 2, 3, 4]
- end
-
- it "returns the subarray which is independent to self with [m..n]" do
- a = [1, 2, 3]
- sub = a.send(@method, 1..2)
- sub.replace([:a, :b])
- a.should == [1, 2, 3]
- end
-
- it "tries to convert Range elements to Integers using #to_int with [m..n] and [m...n]" do
- from = mock('from')
- to = mock('to')
-
- # So we can construct a range out of them...
- def from.<=>(o) 0 end
- def to.<=>(o) 0 end
-
- def from.to_int() 1 end
- def to.to_int() -2 end
-
- a = [1, 2, 3, 4]
-
- a.send(@method, from..to).should == [2, 3]
- a.send(@method, from...to).should == [2]
- a.send(@method, 1..0).should == []
- a.send(@method, 1...0).should == []
-
- -> { a.send(@method, "a" .. "b") }.should raise_error(TypeError)
- -> { a.send(@method, "a" ... "b") }.should raise_error(TypeError)
- -> { a.send(@method, from .. "b") }.should raise_error(TypeError)
- -> { a.send(@method, from ... "b") }.should raise_error(TypeError)
- end
-
- it "returns the same elements as [m..n] and [m...n] with Range subclasses" do
- a = [1, 2, 3, 4]
- range_incl = ArraySpecs::MyRange.new(1, 2)
- range_excl = ArraySpecs::MyRange.new(-3, -1, true)
-
- a.send(@method, range_incl).should == [2, 3]
- a.send(@method, range_excl).should == [2, 3]
- end
-
- it "returns nil for a requested index not in the array with [index]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 5).should == nil
- end
-
- it "returns [] if the index is valid but length is zero with [index, length]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 0, 0).should == []
- [ "a", "b", "c", "d", "e" ].send(@method, 2, 0).should == []
- end
-
- it "returns nil if length is zero but index is invalid with [index, length]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 100, 0).should == nil
- [ "a", "b", "c", "d", "e" ].send(@method, -50, 0).should == nil
- end
-
- # This is by design. It is in the official documentation.
- it "returns [] if index == array.size with [index, length]" do
- %w|a b c d e|.send(@method, 5, 2).should == []
- end
-
- it "returns nil if index > array.size with [index, length]" do
- %w|a b c d e|.send(@method, 6, 2).should == nil
- end
-
- it "returns nil if length is negative with [index, length]" do
- %w|a b c d e|.send(@method, 3, -1).should == nil
- %w|a b c d e|.send(@method, 2, -2).should == nil
- %w|a b c d e|.send(@method, 1, -100).should == nil
- end
-
- it "returns nil if no requested index is in the array with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, 6..10).should == nil
- end
-
- it "returns nil if range start is not in the array with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, -10..2).should == nil
- [ "a", "b", "c", "d", "e" ].send(@method, 10..12).should == nil
- end
-
- it "returns an empty array when m == n with [m...n]" do
- [1, 2, 3, 4, 5].send(@method, 1...1).should == []
- end
-
- it "returns an empty array with [0...0]" do
- [1, 2, 3, 4, 5].send(@method, 0...0).should == []
- end
-
- it "returns a subarray where m, n negatives and m < n with [m..n]" do
- [ "a", "b", "c", "d", "e" ].send(@method, -3..-2).should == ["c", "d"]
- end
-
- it "returns an array containing the first element with [0..0]" do
- [1, 2, 3, 4, 5].send(@method, 0..0).should == [1]
- end
-
- it "returns the entire array with [0..-1]" do
- [1, 2, 3, 4, 5].send(@method, 0..-1).should == [1, 2, 3, 4, 5]
- end
-
- it "returns all but the last element with [0...-1]" do
- [1, 2, 3, 4, 5].send(@method, 0...-1).should == [1, 2, 3, 4]
- end
-
- it "returns [3] for [2..-1] out of [1, 2, 3]" do
- [1,2,3].send(@method, 2..-1).should == [3]
- end
-
- it "returns an empty array when m > n and m, n are positive with [m..n]" do
- [1, 2, 3, 4, 5].send(@method, 3..2).should == []
- end
-
- it "returns an empty array when m > n and m, n are negative with [m..n]" do
- [1, 2, 3, 4, 5].send(@method, -2..-3).should == []
- end
-
- it "does not expand array when the indices are outside of the array bounds" do
- a = [1, 2]
- a.send(@method, 4).should == nil
- a.should == [1, 2]
- a.send(@method, 4, 0).should == nil
- a.should == [1, 2]
- a.send(@method, 6, 1).should == nil
- a.should == [1, 2]
- a.send(@method, 8...8).should == nil
- a.should == [1, 2]
- a.send(@method, 10..10).should == nil
- a.should == [1, 2]
- end
-
- describe "with a subclass of Array" do
- before :each do
- ScratchPad.clear
-
- @array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
- end
-
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance with [n, m]" do
- @array.send(@method, 0, 2).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [-n, m]" do
- @array.send(@method, -3, 2).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [n..m]" do
- @array.send(@method, 1..3).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [n...m]" do
- @array.send(@method, 1...3).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [-n..-m]" do
- @array.send(@method, -3..-1).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [-n...-m]" do
- @array.send(@method, -3...-1).should be_an_instance_of(ArraySpecs::MyArray)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns a Array instance with [n, m]" do
- @array.send(@method, 0, 2).should be_an_instance_of(Array)
- end
-
- it "returns a Array instance with [-n, m]" do
- @array.send(@method, -3, 2).should be_an_instance_of(Array)
- end
-
- it "returns a Array instance with [n..m]" do
- @array.send(@method, 1..3).should be_an_instance_of(Array)
- end
-
- it "returns a Array instance with [n...m]" do
- @array.send(@method, 1...3).should be_an_instance_of(Array)
- end
-
- it "returns a Array instance with [-n..-m]" do
- @array.send(@method, -3..-1).should be_an_instance_of(Array)
- end
-
- it "returns a Array instance with [-n...-m]" do
- @array.send(@method, -3...-1).should be_an_instance_of(Array)
- end
- end
-
- it "returns an empty array when m == n with [m...n]" do
- @array.send(@method, 1...1).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns an empty array with [0...0]" do
- @array.send(@method, 0...0).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns an empty array when m > n and m, n are positive with [m..n]" do
- @array.send(@method, 3..2).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns an empty array when m > n and m, n are negative with [m..n]" do
- @array.send(@method, -2..-3).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns [] if index == array.size with [index, length]" do
- @array.send(@method, 5, 2).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "returns [] if the index is valid but length is zero with [index, length]" do
- @array.send(@method, 0, 0).should == []
- @array.send(@method, 2, 0).should == []
- ScratchPad.recorded.should be_nil
- end
-
- it "does not call #initialize on the subclass instance" do
- @array.send(@method, 0, 3).should == [1, 2, 3]
- ScratchPad.recorded.should be_nil
- end
- end
-
- it "raises a RangeError when the start index is out of range of Fixnum" do
- array = [1, 2, 3, 4, 5, 6]
- obj = mock('large value')
- obj.should_receive(:to_int).and_return(bignum_value)
- -> { array.send(@method, obj) }.should raise_error(RangeError)
-
- obj = 8e19
- -> { array.send(@method, obj) }.should raise_error(RangeError)
-
- # boundary value when longs are 64 bits
- -> { array.send(@method, 2.0**63) }.should raise_error(RangeError)
-
- # just under the boundary value when longs are 64 bits
- array.send(@method, max_long.to_f.prev_float).should == nil
- end
-
- it "raises a RangeError when the length is out of range of Fixnum" do
- array = [1, 2, 3, 4, 5, 6]
- obj = mock('large value')
- obj.should_receive(:to_int).and_return(bignum_value)
- -> { array.send(@method, 1, obj) }.should raise_error(RangeError)
-
- obj = 8e19
- -> { array.send(@method, 1, obj) }.should raise_error(RangeError)
- end
-
- it "raises a type error if a range is passed with a length" do
- ->{ [1, 2, 3].send(@method, 1..2, 1) }.should raise_error(TypeError)
- end
-
- it "raises a RangeError if passed a range with a bound that is too large" do
- array = [1, 2, 3, 4, 5, 6]
- -> { array.send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError)
- -> { array.send(@method, 0..bignum_value) }.should raise_error(RangeError)
- end
-
- it "can accept endless ranges" do
- a = [0, 1, 2, 3, 4, 5]
- a.send(@method, eval("(2..)")).should == [2, 3, 4, 5]
- a.send(@method, eval("(2...)")).should == [2, 3, 4, 5]
- a.send(@method, eval("(-2..)")).should == [4, 5]
- a.send(@method, eval("(-2...)")).should == [4, 5]
- a.send(@method, eval("(9..)")).should == nil
- a.send(@method, eval("(9...)")).should == nil
- a.send(@method, eval("(-9..)")).should == nil
- a.send(@method, eval("(-9...)")).should == nil
- end
-
- ruby_version_is "3.0" do
- describe "can be sliced with Enumerator::ArithmeticSequence" do
- before :each do
- @array = [0, 1, 2, 3, 4, 5]
- end
-
- it "has endless range and positive steps" do
- @array.send(@method, eval("(0..).step(1)")).should == [0, 1, 2, 3, 4, 5]
- @array.send(@method, eval("(0..).step(2)")).should == [0, 2, 4]
- @array.send(@method, eval("(0..).step(10)")).should == [0]
-
- @array.send(@method, eval("(2..).step(1)")).should == [2, 3, 4, 5]
- @array.send(@method, eval("(2..).step(2)")).should == [2, 4]
- @array.send(@method, eval("(2..).step(10)")).should == [2]
-
- @array.send(@method, eval("(-3..).step(1)")).should == [3, 4, 5]
- @array.send(@method, eval("(-3..).step(2)")).should == [3, 5]
- @array.send(@method, eval("(-3..).step(10)")).should == [3]
- end
-
- it "has beginless range and positive steps" do
- # end with zero index
- @array.send(@method, (..0).step(1)).should == [0]
- @array.send(@method, (...0).step(1)).should == []
-
- @array.send(@method, (..0).step(2)).should == [0]
- @array.send(@method, (...0).step(2)).should == []
-
- @array.send(@method, (..0).step(10)).should == [0]
- @array.send(@method, (...0).step(10)).should == []
-
- # end with positive index
- @array.send(@method, (..3).step(1)).should == [0, 1, 2, 3]
- @array.send(@method, (...3).step(1)).should == [0, 1, 2]
-
- @array.send(@method, (..3).step(2)).should == [0, 2]
- @array.send(@method, (...3).step(2)).should == [0, 2]
-
- @array.send(@method, (..3).step(10)).should == [0]
- @array.send(@method, (...3).step(10)).should == [0]
-
- # end with negative index
- @array.send(@method, (..-2).step(1)).should == [0, 1, 2, 3, 4,]
- @array.send(@method, (...-2).step(1)).should == [0, 1, 2, 3]
-
- @array.send(@method, (..-2).step(2)).should == [0, 2, 4]
- @array.send(@method, (...-2).step(2)).should == [0, 2]
-
- @array.send(@method, (..-2).step(10)).should == [0]
- @array.send(@method, (...-2).step(10)).should == [0]
- end
-
- it "has endless range and negative steps" do
- @array.send(@method, eval("(0..).step(-1)")).should == [0]
- @array.send(@method, eval("(0..).step(-2)")).should == [0]
- @array.send(@method, eval("(0..).step(-10)")).should == [0]
-
- @array.send(@method, eval("(2..).step(-1)")).should == [2, 1, 0]
- @array.send(@method, eval("(2..).step(-2)")).should == [2, 0]
-
- @array.send(@method, eval("(-3..).step(-1)")).should == [3, 2, 1, 0]
- @array.send(@method, eval("(-3..).step(-2)")).should == [3, 1]
- end
-
- it "has closed range and positive steps" do
- # start and end with 0
- @array.send(@method, eval("(0..0).step(1)")).should == [0]
- @array.send(@method, eval("(0...0).step(1)")).should == []
-
- @array.send(@method, eval("(0..0).step(2)")).should == [0]
- @array.send(@method, eval("(0...0).step(2)")).should == []
-
- @array.send(@method, eval("(0..0).step(10)")).should == [0]
- @array.send(@method, eval("(0...0).step(10)")).should == []
-
- # start and end with positive index
- @array.send(@method, eval("(1..3).step(1)")).should == [1, 2, 3]
- @array.send(@method, eval("(1...3).step(1)")).should == [1, 2]
-
- @array.send(@method, eval("(1..3).step(2)")).should == [1, 3]
- @array.send(@method, eval("(1...3).step(2)")).should == [1]
-
- @array.send(@method, eval("(1..3).step(10)")).should == [1]
- @array.send(@method, eval("(1...3).step(10)")).should == [1]
-
- # start with positive index, end with negative index
- @array.send(@method, eval("(1..-2).step(1)")).should == [1, 2, 3, 4]
- @array.send(@method, eval("(1...-2).step(1)")).should == [1, 2, 3]
-
- @array.send(@method, eval("(1..-2).step(2)")).should == [1, 3]
- @array.send(@method, eval("(1...-2).step(2)")).should == [1, 3]
-
- @array.send(@method, eval("(1..-2).step(10)")).should == [1]
- @array.send(@method, eval("(1...-2).step(10)")).should == [1]
-
- # start with negative index, end with positive index
- @array.send(@method, eval("(-4..4).step(1)")).should == [2, 3, 4]
- @array.send(@method, eval("(-4...4).step(1)")).should == [2, 3]
-
- @array.send(@method, eval("(-4..4).step(2)")).should == [2, 4]
- @array.send(@method, eval("(-4...4).step(2)")).should == [2]
-
- @array.send(@method, eval("(-4..4).step(10)")).should == [2]
- @array.send(@method, eval("(-4...4).step(10)")).should == [2]
-
- # start with negative index, end with negative index
- @array.send(@method, eval("(-4..-2).step(1)")).should == [2, 3, 4]
- @array.send(@method, eval("(-4...-2).step(1)")).should == [2, 3]
-
- @array.send(@method, eval("(-4..-2).step(2)")).should == [2, 4]
- @array.send(@method, eval("(-4...-2).step(2)")).should == [2]
-
- @array.send(@method, eval("(-4..-2).step(10)")).should == [2]
- @array.send(@method, eval("(-4...-2).step(10)")).should == [2]
- end
-
- it "has closed range and negative steps" do
- # start and end with 0
- @array.send(@method, eval("(0..0).step(-1)")).should == [0]
- @array.send(@method, eval("(0...0).step(-1)")).should == []
-
- @array.send(@method, eval("(0..0).step(-2)")).should == [0]
- @array.send(@method, eval("(0...0).step(-2)")).should == []
-
- @array.send(@method, eval("(0..0).step(-10)")).should == [0]
- @array.send(@method, eval("(0...0).step(-10)")).should == []
-
- # start and end with positive index
- @array.send(@method, eval("(1..3).step(-1)")).should == []
- @array.send(@method, eval("(1...3).step(-1)")).should == []
-
- @array.send(@method, eval("(1..3).step(-2)")).should == []
- @array.send(@method, eval("(1...3).step(-2)")).should == []
-
- @array.send(@method, eval("(1..3).step(-10)")).should == []
- @array.send(@method, eval("(1...3).step(-10)")).should == []
-
- # start with positive index, end with negative index
- @array.send(@method, eval("(1..-2).step(-1)")).should == []
- @array.send(@method, eval("(1...-2).step(-1)")).should == []
-
- @array.send(@method, eval("(1..-2).step(-2)")).should == []
- @array.send(@method, eval("(1...-2).step(-2)")).should == []
-
- @array.send(@method, eval("(1..-2).step(-10)")).should == []
- @array.send(@method, eval("(1...-2).step(-10)")).should == []
-
- # start with negative index, end with positive index
- @array.send(@method, eval("(-4..4).step(-1)")).should == []
- @array.send(@method, eval("(-4...4).step(-1)")).should == []
-
- @array.send(@method, eval("(-4..4).step(-2)")).should == []
- @array.send(@method, eval("(-4...4).step(-2)")).should == []
-
- @array.send(@method, eval("(-4..4).step(-10)")).should == []
- @array.send(@method, eval("(-4...4).step(-10)")).should == []
-
- # start with negative index, end with negative index
- @array.send(@method, eval("(-4..-2).step(-1)")).should == []
- @array.send(@method, eval("(-4...-2).step(-1)")).should == []
-
- @array.send(@method, eval("(-4..-2).step(-2)")).should == []
- @array.send(@method, eval("(-4...-2).step(-2)")).should == []
-
- @array.send(@method, eval("(-4..-2).step(-10)")).should == []
- @array.send(@method, eval("(-4...-2).step(-10)")).should == []
- end
-
- it "has inverted closed range and positive steps" do
- # start and end with positive index
- @array.send(@method, eval("(3..1).step(1)")).should == []
- @array.send(@method, eval("(3...1).step(1)")).should == []
-
- @array.send(@method, eval("(3..1).step(2)")).should == []
- @array.send(@method, eval("(3...1).step(2)")).should == []
-
- @array.send(@method, eval("(3..1).step(10)")).should == []
- @array.send(@method, eval("(3...1).step(10)")).should == []
-
- # start with negative index, end with positive index
- @array.send(@method, eval("(-2..1).step(1)")).should == []
- @array.send(@method, eval("(-2...1).step(1)")).should == []
-
- @array.send(@method, eval("(-2..1).step(2)")).should == []
- @array.send(@method, eval("(-2...1).step(2)")).should == []
-
- @array.send(@method, eval("(-2..1).step(10)")).should == []
- @array.send(@method, eval("(-2...1).step(10)")).should == []
-
- # start with positive index, end with negative index
- @array.send(@method, eval("(4..-4).step(1)")).should == []
- @array.send(@method, eval("(4...-4).step(1)")).should == []
-
- @array.send(@method, eval("(4..-4).step(2)")).should == []
- @array.send(@method, eval("(4...-4).step(2)")).should == []
-
- @array.send(@method, eval("(4..-4).step(10)")).should == []
- @array.send(@method, eval("(4...-4).step(10)")).should == []
-
- # start with negative index, end with negative index
- @array.send(@method, eval("(-2..-4).step(1)")).should == []
- @array.send(@method, eval("(-2...-4).step(1)")).should == []
-
- @array.send(@method, eval("(-2..-4).step(2)")).should == []
- @array.send(@method, eval("(-2...-4).step(2)")).should == []
-
- @array.send(@method, eval("(-2..-4).step(10)")).should == []
- @array.send(@method, eval("(-2...-4).step(10)")).should == []
- end
-
- it "has range with bounds outside of array" do
- # end is equal to array's length
- @array.send(@method, (0..6).step(1)).should == [0, 1, 2, 3, 4, 5]
- -> { @array.send(@method, (0..6).step(2)) }.should raise_error(RangeError)
-
- # end is greater than length with positive steps
- @array.send(@method, (1..6).step(2)).should == [1, 3, 5]
- @array.send(@method, (2..7).step(2)).should == [2, 4]
- -> { @array.send(@method, (2..8).step(2)) }.should raise_error(RangeError)
-
- # begin is greater than length with negative steps
- @array.send(@method, (6..1).step(-2)).should == [5, 3, 1]
- @array.send(@method, (7..2).step(-2)).should == [5, 3]
- -> { @array.send(@method, (8..2).step(-2)) }.should raise_error(RangeError)
- end
-
- it "has endless range with start outside of array's bounds" do
- @array.send(@method, eval("(6..).step(1)")).should == []
- @array.send(@method, eval("(7..).step(1)")).should == nil
-
- @array.send(@method, eval("(6..).step(2)")).should == []
- -> { @array.send(@method, eval("(7..).step(2)")) }.should raise_error(RangeError)
- end
- end
- end
-
- it "can accept beginless ranges" do
- a = [0, 1, 2, 3, 4, 5]
- a.send(@method, (..3)).should == [0, 1, 2, 3]
- a.send(@method, (...3)).should == [0, 1, 2]
- a.send(@method, (..-3)).should == [0, 1, 2, 3]
- a.send(@method, (...-3)).should == [0, 1, 2]
- a.send(@method, (..0)).should == [0]
- a.send(@method, (...0)).should == []
- a.send(@method, (..9)).should == [0, 1, 2, 3, 4, 5]
- a.send(@method, (...9)).should == [0, 1, 2, 3, 4, 5]
- a.send(@method, (..-9)).should == []
- a.send(@method, (...-9)).should == []
- end
-
- it "can accept nil...nil ranges" do
- a = [0, 1, 2, 3, 4, 5]
- a.send(@method, eval("(nil...nil)")).should == a
- a.send(@method, (...nil)).should == a
- a.send(@method, eval("(nil..)")).should == a
- end
-end
diff --git a/spec/ruby/core/array/shared/union.rb b/spec/ruby/core/array/shared/union.rb
index 0b60df9ca4..0b225b9a31 100644
--- a/spec/ruby/core/array/shared/union.rb
+++ b/spec/ruby/core/array/shared/union.rb
@@ -60,9 +60,9 @@ describe :array_binary_union, shared: true do
end
it "does not return subclass instances for Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].send(@method, []).should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
- [].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, []).should.instance_of?(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should.instance_of?(Array)
+ [].send(@method, ArraySpecs::MyArray[1, 2, 3]).should.instance_of?(Array)
end
it "does not call to_ary on array subclasses" do
diff --git a/spec/ruby/core/array/shared/unshift.rb b/spec/ruby/core/array/shared/unshift.rb
deleted file mode 100644
index fc82e19e2a..0000000000
--- a/spec/ruby/core/array/shared/unshift.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-describe :array_unshift, shared: true do
- it "prepends object to the original array" do
- a = [1, 2, 3]
- a.send(@method, "a").should equal(a)
- a.should == ['a', 1, 2, 3]
- a.send(@method).should equal(a)
- a.should == ['a', 1, 2, 3]
- a.send(@method, 5, 4, 3)
- a.should == [5, 4, 3, 'a', 1, 2, 3]
-
- # shift all but one element
- a = [1, 2]
- a.shift
- a.send(@method, 3, 4)
- a.should == [3, 4, 2]
-
- # now shift all elements
- a.shift
- a.shift
- a.shift
- a.send(@method, 3, 4)
- a.should == [3, 4]
- end
-
- it "quietly ignores unshifting nothing" do
- [].send(@method).should == []
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- empty.send(@method, :new).should == [:new, empty]
-
- array = ArraySpecs.recursive_array
- array.send(@method, :new)
- array[0..5].should == [:new, 1, 'two', 3.0, array, array]
- end
-
- it "raises a FrozenError on a frozen array when the array is modified" do
- -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(FrozenError)
- end
-
- # see [ruby-core:23666]
- it "raises a FrozenError on a frozen array when the array would not be modified" do
- -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError)
- end
-end
diff --git a/spec/ruby/core/array/shift_spec.rb b/spec/ruby/core/array/shift_spec.rb
index 6b4ef39f77..09dfa79c45 100644
--- a/spec/ruby/core/array/shift_spec.rb
+++ b/spec/ruby/core/array/shift_spec.rb
@@ -31,10 +31,10 @@ describe "Array#shift" do
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.shift }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.shift }.should.raise(FrozenError)
end
it "raises a FrozenError on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.shift }.should raise_error(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.shift }.should.raise(FrozenError)
end
describe "passed a number n as an argument" do
@@ -72,7 +72,7 @@ describe "Array#shift" do
popped2.should == []
a.should == []
- popped1.should_not equal(popped2)
+ popped1.should_not.equal?(popped2)
end
it "returns whole elements if n exceeds size of the array" do
@@ -83,14 +83,14 @@ describe "Array#shift" do
it "does not return self even when it returns whole elements" do
a = [1, 2, 3, 4, 5]
- a.shift(5).should_not equal(a)
+ a.shift(5).should_not.equal?(a)
a = [1, 2, 3, 4, 5]
- a.shift(6).should_not equal(a)
+ a.shift(6).should_not.equal?(a)
end
it "raises an ArgumentError if n is negative" do
- ->{ [1, 2, 3].shift(-1) }.should raise_error(ArgumentError)
+ ->{ [1, 2, 3].shift(-1) }.should.raise(ArgumentError)
end
it "tries to convert n to an Integer using #to_int" do
@@ -105,16 +105,16 @@ describe "Array#shift" do
end
it "raises a TypeError when the passed n cannot be coerced to Integer" do
- ->{ [1, 2].shift("cat") }.should raise_error(TypeError)
- ->{ [1, 2].shift(nil) }.should raise_error(TypeError)
+ ->{ [1, 2].shift("cat") }.should.raise(TypeError)
+ ->{ [1, 2].shift(nil) }.should.raise(TypeError)
end
it "raises an ArgumentError if more arguments are passed" do
- ->{ [1, 2].shift(1, 2) }.should raise_error(ArgumentError)
+ ->{ [1, 2].shift(1, 2) }.should.raise(ArgumentError)
end
it "does not return subclass instances with Array subclass" do
- ArraySpecs::MyArray[1, 2, 3].shift(2).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].shift(2).should.instance_of?(Array)
end
end
end
diff --git a/spec/ruby/core/array/shuffle_spec.rb b/spec/ruby/core/array/shuffle_spec.rb
index b255147c75..9bc9df73ac 100644
--- a/spec/ruby/core/array/shuffle_spec.rb
+++ b/spec/ruby/core/array/shuffle_spec.rb
@@ -10,7 +10,7 @@ describe "Array#shuffle" do
s.sort.should == a
different ||= (a != s)
end
- different.should be_true # Will fail once in a blue moon (4!^10)
+ different.should == true # Will fail once in a blue moon (4!^10)
end
it "is not destructive" do
@@ -22,7 +22,7 @@ describe "Array#shuffle" do
end
it "does not return subclass instances with Array subclass" do
- ArraySpecs::MyArray[1, 2, 3].shuffle.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].shuffle.should.instance_of?(Array)
end
it "calls #rand on the Object passed by the :random key in the arguments Hash" do
@@ -31,20 +31,24 @@ describe "Array#shuffle" do
result = [1, 2].shuffle(random: obj)
result.size.should == 2
- result.should include(1, 2)
+ result.sort.should == [1, 2]
end
it "raises a NoMethodError if an object passed for the RNG does not define #rand" do
obj = BasicObject.new
- -> { [1, 2].shuffle(random: obj) }.should raise_error(NoMethodError)
+ -> { [1, 2].shuffle(random: obj) }.should.raise(NoMethodError)
end
it "accepts a Float for the value returned by #rand" do
random = mock("array_shuffle_random")
random.should_receive(:rand).at_least(1).times.and_return(0.3)
- [1, 2].shuffle(random: random).should be_an_instance_of(Array)
+ [1, 2].shuffle(random: random).should.instance_of?(Array)
+ end
+
+ it "accepts a Random class for the value for random: argument" do
+ [1, 2].shuffle(random: Random).should.instance_of?(Array)
end
it "calls #to_int on the Object returned by #rand" do
@@ -53,7 +57,7 @@ describe "Array#shuffle" do
random = mock("array_shuffle_random")
random.should_receive(:rand).at_least(1).times.and_return(value)
- [1, 2].shuffle(random: random).should be_an_instance_of(Array)
+ [1, 2].shuffle(random: random).should.instance_of?(Array)
end
it "raises a RangeError if the value is less than zero" do
@@ -62,16 +66,25 @@ describe "Array#shuffle" do
random = mock("array_shuffle_random")
random.should_receive(:rand).and_return(value)
- -> { [1, 2].shuffle(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].shuffle(random: random) }.should.raise(RangeError)
+ end
+
+ it "raises a RangeError if the value is equal to the Array size" do
+ value = mock("array_shuffle_random_value")
+ value.should_receive(:to_int).at_least(1).times.and_return(2)
+ random = mock("array_shuffle_random")
+ random.should_receive(:rand).at_least(1).times.and_return(value)
+
+ -> { [1, 2].shuffle(random: random) }.should.raise(RangeError)
end
- it "raises a RangeError if the value is equal to one" do
+ it "raises a RangeError if the value is greater than the Array size" do
value = mock("array_shuffle_random_value")
- value.should_receive(:to_int).at_least(1).times.and_return(1)
+ value.should_receive(:to_int).at_least(1).times.and_return(3)
random = mock("array_shuffle_random")
random.should_receive(:rand).at_least(1).times.and_return(value)
- -> { [1, 2].shuffle(random: random) }.should raise_error(RangeError)
+ -> { [1, 2].shuffle(random: random) }.should.raise(RangeError)
end
end
@@ -85,12 +98,22 @@ describe "Array#shuffle!" do
a.sort.should == [1, 2, 3, 4]
different ||= (a != [1, 2, 3, 4])
end
- different.should be_true # Will fail once in a blue moon (4!^10)
- a.should equal(original)
+ different.should == true # Will fail once in a blue moon (4!^10)
+ a.should.equal?(original)
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.shuffle! }.should raise_error(FrozenError)
- -> { ArraySpecs.empty_frozen_array.shuffle! }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.shuffle! }.should.raise(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.shuffle! }.should.raise(FrozenError)
+ end
+
+ it "matches CRuby with random:" do
+ %w[a b c].shuffle(random: Random.new(1)).should == %w[a c b]
+ (0..10).to_a.shuffle(random: Random.new(10)).should == [2, 6, 8, 5, 7, 10, 3, 1, 0, 4, 9]
+ end
+
+ it "matches CRuby with srand" do
+ srand(123)
+ %w[a b c d e f g h i j k].shuffle.should == %w[a e f h i j d b g k c]
end
end
diff --git a/spec/ruby/core/array/size_spec.rb b/spec/ruby/core/array/size_spec.rb
index d68f956a83..83e8969012 100644
--- a/spec/ruby/core/array/size_spec.rb
+++ b/spec/ruby/core/array/size_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/length'
describe "Array#size" do
- it_behaves_like :array_length, :size
+ it "is an alias of Array#length" do
+ Array.instance_method(:size).should == Array.instance_method(:length)
+ end
end
diff --git a/spec/ruby/core/array/slice_spec.rb b/spec/ruby/core/array/slice_spec.rb
index 8e1499855a..230d1dc5d1 100644
--- a/spec/ruby/core/array/slice_spec.rb
+++ b/spec/ruby/core/array/slice_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/slice'
describe "Array#slice!" do
it "removes and return the element at index" do
@@ -116,8 +115,8 @@ describe "Array#slice!" do
a.slice!(from .. to).should == [2, 3, 4]
a.should == [1, 5]
- -> { a.slice!("a" .. "b") }.should raise_error(TypeError)
- -> { a.slice!(from .. "b") }.should raise_error(TypeError)
+ -> { a.slice!("a" .. "b") }.should.raise(TypeError)
+ -> { a.slice!(from .. "b") }.should.raise(TypeError)
end
it "returns last element for consecutive calls at zero index" do
@@ -151,7 +150,7 @@ describe "Array#slice!" do
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.slice!(0, 0) }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.slice!(0, 0) }.should.raise(FrozenError)
end
it "works with endless ranges" do
@@ -187,60 +186,34 @@ describe "Array#slice!" do
@array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
end
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance with [n, m]" do
- @array.slice!(0, 2).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [-n, m]" do
- @array.slice!(-3, 2).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [n..m]" do
- @array.slice!(1..3).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [n...m]" do
- @array.slice!(1...3).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [-n..-m]" do
- @array.slice!(-3..-1).should be_an_instance_of(ArraySpecs::MyArray)
- end
-
- it "returns a subclass instance with [-n...-m]" do
- @array.slice!(-3...-1).should be_an_instance_of(ArraySpecs::MyArray)
- end
+ it "returns a Array instance with [n, m]" do
+ @array.slice!(0, 2).should.instance_of?(Array)
end
- ruby_version_is '3.0' do
- it "returns a Array instance with [n, m]" do
- @array.slice!(0, 2).should be_an_instance_of(Array)
- end
-
- it "returns a Array instance with [-n, m]" do
- @array.slice!(-3, 2).should be_an_instance_of(Array)
- end
+ it "returns a Array instance with [-n, m]" do
+ @array.slice!(-3, 2).should.instance_of?(Array)
+ end
- it "returns a Array instance with [n..m]" do
- @array.slice!(1..3).should be_an_instance_of(Array)
- end
+ it "returns a Array instance with [n..m]" do
+ @array.slice!(1..3).should.instance_of?(Array)
+ end
- it "returns a Array instance with [n...m]" do
- @array.slice!(1...3).should be_an_instance_of(Array)
- end
+ it "returns a Array instance with [n...m]" do
+ @array.slice!(1...3).should.instance_of?(Array)
+ end
- it "returns a Array instance with [-n..-m]" do
- @array.slice!(-3..-1).should be_an_instance_of(Array)
- end
+ it "returns a Array instance with [-n..-m]" do
+ @array.slice!(-3..-1).should.instance_of?(Array)
+ end
- it "returns a Array instance with [-n...-m]" do
- @array.slice!(-3...-1).should be_an_instance_of(Array)
- end
+ it "returns a Array instance with [-n...-m]" do
+ @array.slice!(-3...-1).should.instance_of?(Array)
end
end
end
describe "Array#slice" do
- it_behaves_like :array_slice, :slice
+ it "is an alias of Array#[]" do
+ Array.instance_method(:slice).should == Array.instance_method(:[])
+ end
end
diff --git a/spec/ruby/core/array/sort_by_spec.rb b/spec/ruby/core/array/sort_by_spec.rb
index 7cea6ec6d3..132abb028a 100644
--- a/spec/ruby/core/array/sort_by_spec.rb
+++ b/spec/ruby/core/array/sort_by_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
require_relative '../enumerable/shared/enumeratorized'
describe "Array#sort_by!" do
@@ -10,25 +11,30 @@ describe "Array#sort_by!" do
end
it "returns an Enumerator if not given a block" do
- (1..10).to_a.sort_by!.should be_an_instance_of(Enumerator)
+ (1..10).to_a.sort_by!.should.instance_of?(Enumerator)
end
it "completes when supplied a block that always returns the same result" do
a = [2, 3, 5, 1, 4]
a.sort_by!{ 1 }
- a.should be_an_instance_of(Array)
+ a.should.instance_of?(Array)
a.sort_by!{ 0 }
- a.should be_an_instance_of(Array)
+ a.should.instance_of?(Array)
a.sort_by!{ -1 }
- a.should be_an_instance_of(Array)
+ a.should.instance_of?(Array)
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.sort_by! {}}.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.sort_by! {}}.should.raise(FrozenError)
end
it "raises a FrozenError on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.sort_by! {}}.should raise_error(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.sort_by! {}}.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError on a frozen array only during iteration if called without a block" do
+ enum = ArraySpecs.frozen_array.sort_by!
+ -> { enum.each {} }.should.raise(FrozenError)
end
it "returns the specified value when it would break in the given block" do
@@ -41,12 +47,39 @@ describe "Array#sort_by!" do
ary.sort_by!{|x,y| break if x==i; x<=>y}
ary
}
- partially_sorted.any?{|ary| ary != [1, 2, 3, 4, 5]}.should be_true
+ partially_sorted.any?{|ary| ary != [1, 2, 3, 4, 5]}.should == true
end
it "changes nothing when called on a single element array" do
[1].sort_by!(&:to_s).should == [1]
end
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.sort_by! { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
+ end
+
+ it "doesn't change array if error is raised" do
+ a = [4, 3, 2, 1]
+ begin
+ a.sort_by! do |e|
+ raise StandardError, 'Oops' if e == 1
+ e
+ end
+ rescue StandardError
+ end
+
+ a.should == [4, 3, 2, 1]
+ end
+
it_behaves_like :enumeratorized_with_origin_size, :sort_by!, [1,2,3]
end
+
+describe "Array#sort_by!" do
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :sort_by!
+end
diff --git a/spec/ruby/core/array/sort_spec.rb b/spec/ruby/core/array/sort_spec.rb
index e20b650516..27300c3385 100644
--- a/spec/ruby/core/array/sort_spec.rb
+++ b/spec/ruby/core/array/sort_spec.rb
@@ -42,7 +42,7 @@ describe "Array#sort" do
a = [1, 2, 3]
sorted = a.sort
sorted.should == a
- sorted.should_not equal(a)
+ sorted.should_not.equal?(a)
end
it "properly handles recursive arrays" do
@@ -68,7 +68,7 @@ describe "Array#sort" do
-> {
[o, 1].sort
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "may take a block which is used to determine the order of objects a and b described as -1, 0 or +1" do
@@ -78,28 +78,28 @@ describe "Array#sort" do
end
it "raises an error when a given block returns nil" do
- -> { [1, 2].sort {} }.should raise_error(ArgumentError)
+ -> { [1, 2].sort {} }.should.raise(ArgumentError)
end
it "does not call #<=> on contained objects when invoked with a block" do
a = Array.new(25)
(0...25).each {|i| a[i] = ArraySpecs::UFOSceptic.new }
- a.sort { -1 }.should be_an_instance_of(Array)
+ a.sort { -1 }.should.instance_of?(Array)
end
it "does not call #<=> on elements when invoked with a block even if Array is large (Rubinius #412)" do
a = Array.new(1500)
(0...1500).each {|i| a[i] = ArraySpecs::UFOSceptic.new }
- a.sort { -1 }.should be_an_instance_of(Array)
+ a.sort { -1 }.should.instance_of?(Array)
end
it "completes when supplied a block that always returns the same result" do
a = [2, 3, 5, 1, 4]
- a.sort { 1 }.should be_an_instance_of(Array)
- a.sort { 0 }.should be_an_instance_of(Array)
- a.sort { -1 }.should be_an_instance_of(Array)
+ a.sort { 1 }.should.instance_of?(Array)
+ a.sort { 0 }.should.instance_of?(Array)
+ a.sort { -1 }.should.instance_of?(Array)
end
it "does not freezes self during being sorted" do
@@ -136,7 +136,7 @@ describe "Array#sort" do
}.should == [-4, 1, 2, 5, 7, 10, 12]
-> {
a.sort { |n, m| (n - m).to_s }
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "sorts an array that has a value shifted off without a block" do
@@ -155,7 +155,7 @@ describe "Array#sort" do
it "raises an error if objects can't be compared" do
a=[ArraySpecs::Uncomparable.new, ArraySpecs::Uncomparable.new]
- -> {a.sort}.should raise_error(ArgumentError)
+ -> {a.sort}.should.raise(ArgumentError)
end
# From a strange Rubinius bug
@@ -166,7 +166,7 @@ describe "Array#sort" do
it "does not return subclass instance on Array subclasses" do
ary = ArraySpecs::MyArray[1, 2, 3]
- ary.sort.should be_an_instance_of(Array)
+ ary.sort.should.instance_of?(Array)
end
end
@@ -184,13 +184,13 @@ describe "Array#sort!" do
it "returns self if the order of elements changed" do
a = [6, 7, 2, 3, 7]
- a.sort!.should equal(a)
+ a.sort!.should.equal?(a)
a.should == [2, 3, 6, 7, 7]
end
it "returns self even if makes no modification" do
a = [1, 2, 3, 4, 5]
- a.sort!.should equal(a)
+ a.sort!.should.equal?(a)
a.should == [1, 2, 3, 4, 5]
end
@@ -216,25 +216,25 @@ describe "Array#sort!" do
a = Array.new(25)
(0...25).each {|i| a[i] = ArraySpecs::UFOSceptic.new }
- a.sort! { -1 }.should be_an_instance_of(Array)
+ a.sort! { -1 }.should.instance_of?(Array)
end
it "does not call #<=> on elements when invoked with a block even if Array is large (Rubinius #412)" do
a = Array.new(1500)
(0...1500).each {|i| a[i] = ArraySpecs::UFOSceptic.new }
- a.sort! { -1 }.should be_an_instance_of(Array)
+ a.sort! { -1 }.should.instance_of?(Array)
end
it "completes when supplied a block that always returns the same result" do
a = [2, 3, 5, 1, 4]
- a.sort!{ 1 }.should be_an_instance_of(Array)
- a.sort!{ 0 }.should be_an_instance_of(Array)
- a.sort!{ -1 }.should be_an_instance_of(Array)
+ a.sort!{ 1 }.should.instance_of?(Array)
+ a.sort!{ 0 }.should.instance_of?(Array)
+ a.sort!{ -1 }.should.instance_of?(Array)
end
it "raises a FrozenError on a frozen array" do
- -> { ArraySpecs.frozen_array.sort! }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.sort! }.should.raise(FrozenError)
end
it "returns the specified value when it would break in the given block" do
@@ -247,6 +247,6 @@ describe "Array#sort!" do
ary.sort!{|x,y| break if x==i; x<=>y}
ary
}
- partially_sorted.any?{|ary| ary != [1, 2, 3, 4, 5]}.should be_true
+ partially_sorted.any?{|ary| ary != [1, 2, 3, 4, 5]}.should == true
end
end
diff --git a/spec/ruby/core/array/sum_spec.rb b/spec/ruby/core/array/sum_spec.rb
index 8ca8353a67..cd4ba4c2d8 100644
--- a/spec/ruby/core/array/sum_spec.rb
+++ b/spec/ruby/core/array/sum_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#sum" do
it "returns the sum of elements" do
@@ -9,8 +10,12 @@ describe "Array#sum" do
[1, 2, 3].sum { |i| i * 10 }.should == 60
end
+ it "doesn't apply the block init" do
+ [1, 2, 3].sum(1) { |i| i * 10 }.should == 61
+ end
+
# https://bugs.ruby-lang.org/issues/12217
- # https://github.com/ruby/ruby/blob/master/doc/ChangeLog-2.4.0#L6208-L6214
+ # https://github.com/ruby/ruby/blob/master/doc/ChangeLog/ChangeLog-2.4.0#L6208-L6214
it "uses Kahan's compensated summation algorithm for precise sum of float numbers" do
floats = [2.7800000000000002, 5.0, 2.5, 4.44, 3.89, 3.89, 4.44, 7.78, 5.0, 2.7800000000000002, 5.0, 2.5]
naive_sum = floats.reduce { |sum, e| sum + e }
@@ -55,11 +60,11 @@ describe "Array#sum" do
end
it 'raises TypeError if any element are not numeric' do
- -> { ["a"].sum }.should raise_error(TypeError)
+ -> { ["a"].sum }.should.raise(TypeError)
end
it 'raises TypeError if any element cannot be added to init value' do
- -> { [1].sum([]) }.should raise_error(TypeError)
+ -> { [1].sum([]) }.should.raise(TypeError)
end
it "calls + to sum the elements" do
@@ -68,4 +73,16 @@ describe "Array#sum" do
a.should_receive(:+).with(b).and_return(42)
[b].sum(a).should == 42
end
+
+ it "calls + on the init value" do
+ a = mock("a")
+ b = mock("b")
+ a.should_receive(:+).with(42).and_return(b)
+ [42].sum(a).should == b
+ end
+end
+
+describe "Array#sum" do
+ @value_to_return = -> _ { 1 }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :sum
end
diff --git a/spec/ruby/core/array/take_spec.rb b/spec/ruby/core/array/take_spec.rb
index 4fb6f0ce75..837c734b77 100644
--- a/spec/ruby/core/array/take_spec.rb
+++ b/spec/ruby/core/array/take_spec.rb
@@ -23,18 +23,10 @@ describe "Array#take" do
end
it "raises an ArgumentError when the argument is negative" do
- ->{ [1].take(-3) }.should raise_error(ArgumentError)
+ ->{ [1].take(-3) }.should.raise(ArgumentError)
end
- ruby_version_is ''...'3.0' do
- it 'returns a subclass instance for Array subclasses' do
- ArraySpecs::MyArray[1, 2, 3, 4, 5].take(1).should be_an_instance_of(ArraySpecs::MyArray)
- end
- end
-
- ruby_version_is '3.0' do
- it 'returns a Array instance for Array subclasses' do
- ArraySpecs::MyArray[1, 2, 3, 4, 5].take(1).should be_an_instance_of(Array)
- end
+ it 'returns a Array instance for Array subclasses' do
+ ArraySpecs::MyArray[1, 2, 3, 4, 5].take(1).should.instance_of?(Array)
end
end
diff --git a/spec/ruby/core/array/take_while_spec.rb b/spec/ruby/core/array/take_while_spec.rb
index 363419b265..7811edab9e 100644
--- a/spec/ruby/core/array/take_while_spec.rb
+++ b/spec/ruby/core/array/take_while_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#take_while" do
it "returns all elements until the block returns false" do
@@ -14,15 +15,12 @@ describe "Array#take_while" do
[1, 2, false, 4].take_while{ |element| element }.should == [1, 2]
end
- ruby_version_is ''...'3.0' do
- it 'returns a subclass instance for Array subclasses' do
- ArraySpecs::MyArray[1, 2, 3, 4, 5].take_while { |n| n < 4 }.should be_an_instance_of(ArraySpecs::MyArray)
- end
+ it 'returns a Array instance for Array subclasses' do
+ ArraySpecs::MyArray[1, 2, 3, 4, 5].take_while { |n| n < 4 }.should.instance_of?(Array)
end
+end
- ruby_version_is '3.0' do
- it 'returns a Array instance for Array subclasses' do
- ArraySpecs::MyArray[1, 2, 3, 4, 5].take_while { |n| n < 4 }.should be_an_instance_of(Array)
- end
- end
+describe "Array#take_while" do
+ @value_to_return = -> _ { true }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :take_while
end
diff --git a/spec/ruby/core/array/to_a_spec.rb b/spec/ruby/core/array/to_a_spec.rb
index 49d0a4782e..078de1638a 100644
--- a/spec/ruby/core/array/to_a_spec.rb
+++ b/spec/ruby/core/array/to_a_spec.rb
@@ -5,12 +5,12 @@ describe "Array#to_a" do
it "returns self" do
a = [1, 2, 3]
a.to_a.should == [1, 2, 3]
- a.should equal(a.to_a)
+ a.should.equal?(a.to_a)
end
it "does not return subclass instance on Array subclasses" do
e = ArraySpecs::MyArray.new(1, 2)
- e.to_a.should be_an_instance_of(Array)
+ e.to_a.should.instance_of?(Array)
e.to_a.should == [1, 2]
end
diff --git a/spec/ruby/core/array/to_ary_spec.rb b/spec/ruby/core/array/to_ary_spec.rb
index 314699b709..dc5193158d 100644
--- a/spec/ruby/core/array/to_ary_spec.rb
+++ b/spec/ruby/core/array/to_ary_spec.rb
@@ -4,9 +4,9 @@ require_relative 'fixtures/classes'
describe "Array#to_ary" do
it "returns self" do
a = [1, 2, 3]
- a.should equal(a.to_ary)
+ a.should.equal?(a.to_ary)
a = ArraySpecs::MyArray[1, 2, 3]
- a.should equal(a.to_ary)
+ a.should.equal?(a.to_ary)
end
it "properly handles recursive arrays" do
diff --git a/spec/ruby/core/array/to_h_spec.rb b/spec/ruby/core/array/to_h_spec.rb
index f5a7e546e6..1d626763c2 100644
--- a/spec/ruby/core/array/to_h_spec.rb
+++ b/spec/ruby/core/array/to_h_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#to_h" do
it "converts empty array to empty hash" do
@@ -24,19 +25,19 @@ describe "Array#to_h" do
end
it "raises TypeError if an element is not an array" do
- -> { [:x].to_h }.should raise_error(TypeError)
+ -> { [:x].to_h }.should.raise(TypeError)
end
it "raises ArgumentError if an element is not a [key, value] pair" do
- -> { [[:x]].to_h }.should raise_error(ArgumentError)
+ -> { [[:x]].to_h }.should.raise(ArgumentError)
end
it "does not accept arguments" do
- -> { [].to_h(:a, :b) }.should raise_error(ArgumentError)
+ -> { [].to_h(:a, :b) }.should.raise(ArgumentError)
end
it "produces a hash that returns nil for a missing element" do
- [[:a, 1], [:b, 2]].to_h[:c].should be_nil
+ [[:a, 1], [:b, 2]].to_h[:c].should == nil
end
context "with block" do
@@ -44,20 +45,26 @@ describe "Array#to_h" do
[:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
end
+ it "passes to a block each element as a single argument" do
+ ScratchPad.record []
+ [[:a, 1], [:b, 2]].to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
+ end
+
it "raises ArgumentError if block returns longer or shorter array" do
-> do
[:a, :b].to_h { |k| [k, k.to_s, 1] }
- end.should raise_error(ArgumentError, /wrong array length at 0/)
+ end.should.raise(ArgumentError, /wrong array length at 0/)
-> do
[:a, :b].to_h { |k| [k] }
- end.should raise_error(ArgumentError, /wrong array length at 0/)
+ end.should.raise(ArgumentError, /wrong array length at 0/)
end
it "raises TypeError if block returns something other than Array" do
-> do
[:a, :b].to_h { |k| "not-array" }
- end.should raise_error(TypeError, /wrong element type String at 0/)
+ end.should.raise(TypeError, /wrong element type String at 0/)
end
it "coerces returned pair to Array with #to_ary" do
@@ -73,7 +80,12 @@ describe "Array#to_h" do
-> do
[:a].to_h { |k| x }
- end.should raise_error(TypeError, /wrong element type MockObject at 0/)
+ end.should.raise(TypeError, /wrong element type MockObject at 0/)
end
end
end
+
+describe "Array#to_h" do
+ @value_to_return = -> e { [e, e.to_s] }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :to_h
+end
diff --git a/spec/ruby/core/array/to_s_spec.rb b/spec/ruby/core/array/to_s_spec.rb
index e8476702ec..483e14f902 100644
--- a/spec/ruby/core/array/to_s_spec.rb
+++ b/spec/ruby/core/array/to_s_spec.rb
@@ -1,8 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/join'
-require_relative 'shared/inspect'
describe "Array#to_s" do
- it_behaves_like :array_inspect, :to_s
+ it "is an alias of Array#inspect" do
+ Array.instance_method(:to_s).should == Array.instance_method(:inspect)
+ end
end
diff --git a/spec/ruby/core/array/transpose_spec.rb b/spec/ruby/core/array/transpose_spec.rb
index b39077f4c9..d45e9c351c 100644
--- a/spec/ruby/core/array/transpose_spec.rb
+++ b/spec/ruby/core/array/transpose_spec.rb
@@ -32,7 +32,7 @@ describe "Array#transpose" do
end
it "raises a TypeError if the passed Argument does not respond to #to_ary" do
- -> { [Object.new, [:a, :b]].transpose }.should raise_error(TypeError)
+ -> { [Object.new, [:a, :b]].transpose }.should.raise(TypeError)
end
it "does not call to_ary on array subclass elements" do
@@ -41,13 +41,13 @@ describe "Array#transpose" do
end
it "raises an IndexError if the arrays are not of the same length" do
- -> { [[1, 2], [:a]].transpose }.should raise_error(IndexError)
+ -> { [[1, 2], [:a]].transpose }.should.raise(IndexError)
end
it "does not return subclass instance on Array subclasses" do
result = ArraySpecs::MyArray[ArraySpecs::MyArray[1, 2, 3], ArraySpecs::MyArray[4, 5, 6]].transpose
- result.should be_an_instance_of(Array)
- result[0].should be_an_instance_of(Array)
- result[1].should be_an_instance_of(Array)
+ result.should.instance_of?(Array)
+ result[0].should.instance_of?(Array)
+ result[1].should.instance_of?(Array)
end
end
diff --git a/spec/ruby/core/array/try_convert_spec.rb b/spec/ruby/core/array/try_convert_spec.rb
index 47b4722d80..3eaa0f4b7c 100644
--- a/spec/ruby/core/array/try_convert_spec.rb
+++ b/spec/ruby/core/array/try_convert_spec.rb
@@ -4,47 +4,47 @@ require_relative 'fixtures/classes'
describe "Array.try_convert" do
it "returns the argument if it's an Array" do
x = Array.new
- Array.try_convert(x).should equal(x)
+ Array.try_convert(x).should.equal?(x)
end
it "returns the argument if it's a kind of Array" do
x = ArraySpecs::MyArray[]
- Array.try_convert(x).should equal(x)
+ Array.try_convert(x).should.equal?(x)
end
it "returns nil when the argument does not respond to #to_ary" do
- Array.try_convert(Object.new).should be_nil
+ Array.try_convert(Object.new).should == nil
end
it "sends #to_ary to the argument and returns the result if it's nil" do
obj = mock("to_ary")
obj.should_receive(:to_ary).and_return(nil)
- Array.try_convert(obj).should be_nil
+ Array.try_convert(obj).should == nil
end
it "sends #to_ary to the argument and returns the result if it's an Array" do
x = Array.new
obj = mock("to_ary")
obj.should_receive(:to_ary).and_return(x)
- Array.try_convert(obj).should equal(x)
+ Array.try_convert(obj).should.equal?(x)
end
it "sends #to_ary to the argument and returns the result if it's a kind of Array" do
x = ArraySpecs::MyArray[]
obj = mock("to_ary")
obj.should_receive(:to_ary).and_return(x)
- Array.try_convert(obj).should equal(x)
+ Array.try_convert(obj).should.equal?(x)
end
it "sends #to_ary to the argument and raises TypeError if it's not a kind of Array" do
obj = mock("to_ary")
obj.should_receive(:to_ary).and_return(Object.new)
- -> { Array.try_convert obj }.should raise_error(TypeError)
+ -> { Array.try_convert obj }.should raise_consistent_error(TypeError, "can't convert MockObject into Array (MockObject#to_ary gives Object)")
end
it "does not rescue exceptions raised by #to_ary" do
obj = mock("to_ary")
obj.should_receive(:to_ary).and_raise(RuntimeError)
- -> { Array.try_convert obj }.should raise_error(RuntimeError)
+ -> { Array.try_convert obj }.should.raise(RuntimeError)
end
end
diff --git a/spec/ruby/core/array/union_spec.rb b/spec/ruby/core/array/union_spec.rb
index ba2cc0d6b7..110894e83d 100644
--- a/spec/ruby/core/array/union_spec.rb
+++ b/spec/ruby/core/array/union_spec.rb
@@ -15,7 +15,7 @@ describe "Array#union" do
end
it "does not return subclass instances for Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].union.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].union.should.instance_of?(Array)
end
it "accepts multiple arguments" do
diff --git a/spec/ruby/core/array/uniq_spec.rb b/spec/ruby/core/array/uniq_spec.rb
index 4461cae16b..0289bee7c2 100644
--- a/spec/ruby/core/array/uniq_spec.rb
+++ b/spec/ruby/core/array/uniq_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/iterable_and_tolerating_size_increasing'
describe "Array#uniq" do
it "returns an array with no duplicates" do
@@ -84,16 +85,8 @@ describe "Array#uniq" do
[false, nil, 42].uniq { :bar }.should == [false]
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(ArraySpecs::MyArray)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns Array instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(Array)
- end
+ it "returns Array instance on Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].uniq.should.instance_of?(Array)
end
it "properly handles an identical item even when its #eql? isn't reflexive" do
@@ -131,6 +124,11 @@ describe "Array#uniq" do
end
end
+describe "Array#uniq" do
+ @value_to_return = -> e { e }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :uniq
+end
+
describe "Array#uniq!" do
it "modifies the array in place" do
a = [ "a", "a", "b", "b", "c" ]
@@ -140,7 +138,7 @@ describe "Array#uniq!" do
it "returns self" do
a = [ "a", "a", "b", "b", "c" ]
- a.should equal(a.uniq!)
+ a.should.equal?(a.uniq!)
end
it "properly handles recursive arrays" do
@@ -187,17 +185,17 @@ describe "Array#uniq!" do
it "raises a FrozenError on a frozen array when the array is modified" do
dup_ary = [1, 1, 2]
dup_ary.freeze
- -> { dup_ary.uniq! }.should raise_error(FrozenError)
+ -> { dup_ary.uniq! }.should.raise(FrozenError)
end
# see [ruby-core:23666]
it "raises a FrozenError on a frozen array when the array would not be modified" do
- -> { ArraySpecs.frozen_array.uniq!}.should raise_error(FrozenError)
- -> { ArraySpecs.empty_frozen_array.uniq!}.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.uniq!}.should.raise(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.uniq!}.should.raise(FrozenError)
end
it "doesn't yield to the block on a frozen array" do
- -> { ArraySpecs.frozen_array.uniq!{ raise RangeError, "shouldn't yield"}}.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.uniq!{ raise RangeError, "shouldn't yield"}}.should.raise(FrozenError)
end
it "compares elements based on the value returned from the block" do
@@ -214,4 +212,32 @@ describe "Array#uniq!" do
a.uniq!
a.should == [x]
end
+
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.send(@method) { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
+ end
+
+ it "doesn't change array if error is raised" do
+ a = [1, 1, 2, 2, 3, 3, 4, 4]
+ begin
+ a.send(@method) do |e|
+ raise StandardError, 'Oops' if e == 3
+ e
+ end
+ rescue StandardError
+ end
+
+ a.should == [1, 1, 2, 2, 3, 3, 4, 4]
+ end
+end
+
+describe "Array#uniq!" do
+ @value_to_return = -> e { e }
+ it_behaves_like :array_iterable_and_tolerating_size_increasing, :uniq!
end
diff --git a/spec/ruby/core/array/unshift_spec.rb b/spec/ruby/core/array/unshift_spec.rb
index b8b675e5f8..c190db4d02 100644
--- a/spec/ruby/core/array/unshift_spec.rb
+++ b/spec/ruby/core/array/unshift_spec.rb
@@ -1,7 +1,67 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/unshift'
describe "Array#unshift" do
- it_behaves_like :array_unshift, :unshift
+ it "prepends object to the original array" do
+ a = [1, 2, 3]
+ a.unshift("a").should.equal?(a)
+ a.should == ['a', 1, 2, 3]
+ a.unshift.should.equal?(a)
+ a.should == ['a', 1, 2, 3]
+ a.unshift(5, 4, 3)
+ a.should == [5, 4, 3, 'a', 1, 2, 3]
+
+ # shift all but one element
+ a = [1, 2]
+ a.shift
+ a.unshift(3, 4)
+ a.should == [3, 4, 2]
+
+ # now shift all elements
+ a.shift
+ a.shift
+ a.shift
+ a.unshift(3, 4)
+ a.should == [3, 4]
+ end
+
+ it "returns self" do
+ a = [1, 2, 3]
+ a.unshift("a").should.equal?(a)
+ end
+
+ it "quietly ignores unshifting nothing" do
+ [].unshift.should == []
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.unshift(:new).should == [:new, empty]
+
+ array = ArraySpecs.recursive_array
+ array.unshift(:new)
+ array[0..5].should == [:new, 1, 'two', 3.0, array, array]
+ end
+
+ it "raises a FrozenError on a frozen array when the array is modified" do
+ -> { ArraySpecs.frozen_array.unshift(1) }.should.raise(FrozenError)
+ end
+
+ # see [ruby-core:23666]
+ it "raises a FrozenError on a frozen array when the array would not be modified" do
+ -> { ArraySpecs.frozen_array.unshift }.should.raise(FrozenError)
+ end
+
+ # https://github.com/truffleruby/truffleruby/issues/2772
+ it "doesn't rely on Array#[]= so it can be overridden" do
+ subclass = Class.new(Array) do
+ def []=(*)
+ raise "[]= is called"
+ end
+ end
+
+ array = subclass.new
+ array.unshift(1)
+ array.should == [1]
+ end
end
diff --git a/spec/ruby/core/array/values_at_spec.rb b/spec/ruby/core/array/values_at_spec.rb
index 2c6fd16947..e11e7e4451 100644
--- a/spec/ruby/core/array/values_at_spec.rb
+++ b/spec/ruby/core/array/values_at_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+# Should be synchronized with core/struct/values_at_spec.rb
describe "Array#values_at" do
it "returns an array of elements at the indexes when passed indexes" do
[1, 2, 3, 4, 5].values_at().should == []
@@ -58,7 +59,7 @@ describe "Array#values_at" do
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].values_at(0, 1..2, 1).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].values_at(0, 1..2, 1).should.instance_of?(Array)
end
it "works when given endless ranges" do
diff --git a/spec/ruby/core/array/zip_spec.rb b/spec/ruby/core/array/zip_spec.rb
index af4013debe..3ccdf143d6 100644
--- a/spec/ruby/core/array/zip_spec.rb
+++ b/spec/ruby/core/array/zip_spec.rb
@@ -60,6 +60,12 @@ describe "Array#zip" do
end
it "does not return subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].zip(["a", "b"]).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].zip(["a", "b"]).should.instance_of?(Array)
+ end
+
+ it "raises TypeError when some argument isn't Array and doesn't respond to #to_ary and #to_enum" do
+ -> { [1, 2, 3].zip(Object.new) }.should.raise(TypeError, "wrong argument type Object (must respond to :each)")
+ -> { [1, 2, 3].zip(1) }.should.raise(TypeError, "wrong argument type Integer (must respond to :each)")
+ -> { [1, 2, 3].zip(true) }.should.raise(TypeError, "wrong argument type TrueClass (must respond to :each)")
end
end
diff --git a/spec/ruby/core/basicobject/__send___spec.rb b/spec/ruby/core/basicobject/__send___spec.rb
index 005b1d0d90..2f814e448c 100644
--- a/spec/ruby/core/basicobject/__send___spec.rb
+++ b/spec/ruby/core/basicobject/__send___spec.rb
@@ -3,7 +3,7 @@ require_relative '../../shared/basicobject/send'
describe "BasicObject#__send__" do
it "is a public instance method" do
- BasicObject.should have_public_instance_method(:__send__)
+ BasicObject.public_instance_methods(false).should.include?(:__send__)
end
it_behaves_like :basicobject_send, :__send__
diff --git a/spec/ruby/core/basicobject/basicobject_spec.rb b/spec/ruby/core/basicobject/basicobject_spec.rb
index 27a322e72c..af28de0687 100644
--- a/spec/ruby/core/basicobject/basicobject_spec.rb
+++ b/spec/ruby/core/basicobject/basicobject_spec.rb
@@ -8,23 +8,23 @@ describe "BasicObject" do
end
it "raises NameError when referencing built-in constants" do
- -> { class BasicObjectSpecs::BOSubclass; Kernel; end }.should raise_error(NameError)
+ -> { class BasicObjectSpecs::BOSubclass; Kernel; end }.should.raise(NameError)
end
it "does not define built-in constants (according to const_defined?)" do
- BasicObject.const_defined?(:Kernel).should be_false
+ BasicObject.const_defined?(:Kernel).should == false
end
it "does not define built-in constants (according to defined?)" do
- BasicObjectSpecs::BOSubclass.kernel_defined?.should be_nil
+ BasicObjectSpecs::BOSubclass.kernel_defined?.should == nil
end
it "is included in Object's list of constants" do
- Object.constants(false).should include(:BasicObject)
+ Object.constants(false).should.include?(:BasicObject)
end
it "includes itself in its list of constants" do
- BasicObject.constants(false).should include(:BasicObject)
+ BasicObject.constants(false).should.include?(:BasicObject)
end
end
@@ -34,11 +34,11 @@ describe "BasicObject metaclass" do
end
it "is an instance of Class" do
- @meta.should be_an_instance_of(Class)
+ @meta.should.instance_of?(Class)
end
it "has Class as superclass" do
- @meta.superclass.should equal(Class)
+ @meta.superclass.should.equal?(Class)
end
it "contains methods for the BasicObject class" do
@@ -57,11 +57,11 @@ describe "BasicObject instance metaclass" do
end
it "is an instance of Class" do
- @meta.should be_an_instance_of(Class)
+ @meta.should.instance_of?(Class)
end
it "has BasicObject as superclass" do
- @meta.superclass.should equal(BasicObject)
+ @meta.superclass.should.equal?(BasicObject)
end
it "contains methods defined for the BasicObject instance" do
@@ -85,7 +85,7 @@ describe "BasicObject subclass" do
describe "BasicObject references" do
it "can refer to BasicObject from within itself" do
- -> { BasicObject::BasicObject }.should_not raise_error
+ -> { BasicObject::BasicObject }.should_not.raise
end
end
end
diff --git a/spec/ruby/core/basicobject/equal_spec.rb b/spec/ruby/core/basicobject/equal_spec.rb
index 3c1ad56d4a..c0f41dc0c0 100644
--- a/spec/ruby/core/basicobject/equal_spec.rb
+++ b/spec/ruby/core/basicobject/equal_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../shared/kernel/equal'
describe "BasicObject#equal?" do
it "is a public instance method" do
- BasicObject.should have_public_instance_method(:equal?)
+ BasicObject.public_instance_methods(false).should.include?(:equal?)
end
it_behaves_like :object_equal, :equal?
@@ -11,9 +11,11 @@ describe "BasicObject#equal?" do
it "is unaffected by overriding __id__" do
o1 = mock("object")
o2 = mock("object")
- def o1.__id__; 10; end
- def o2.__id__; 10; end
- o1.equal?(o2).should be_false
+ suppress_warning {
+ def o1.__id__; 10; end
+ def o2.__id__; 10; end
+ }
+ o1.equal?(o2).should == false
end
it "is unaffected by overriding object_id" do
@@ -21,7 +23,7 @@ describe "BasicObject#equal?" do
o1.stub!(:object_id).and_return(10)
o2 = mock("object")
o2.stub!(:object_id).and_return(10)
- o1.equal?(o2).should be_false
+ o1.equal?(o2).should == false
end
it "is unaffected by overriding ==" do
@@ -29,12 +31,12 @@ describe "BasicObject#equal?" do
o1 = mock("object")
o1.stub!(:==).and_return(true)
o2 = mock("object")
- o1.equal?(o2).should be_false
+ o1.equal?(o2).should == false
# same objects, overriding == to return false
o3 = mock("object")
o3.stub!(:==).and_return(false)
- o3.equal?(o3).should be_true
+ o3.equal?(o3).should == true
end
it "is unaffected by overriding eql?" do
@@ -42,11 +44,11 @@ describe "BasicObject#equal?" do
o1 = mock("object")
o1.stub!(:eql?).and_return(true)
o2 = mock("object")
- o1.equal?(o2).should be_false
+ o1.equal?(o2).should == false
# same objects, overriding eql? to return false
o3 = mock("object")
o3.stub!(:eql?).and_return(false)
- o3.equal?(o3).should be_true
+ o3.equal?(o3).should == true
end
end
diff --git a/spec/ruby/core/basicobject/equal_value_spec.rb b/spec/ruby/core/basicobject/equal_value_spec.rb
index 6c825513c1..eb951a8305 100644
--- a/spec/ruby/core/basicobject/equal_value_spec.rb
+++ b/spec/ruby/core/basicobject/equal_value_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../shared/kernel/equal'
describe "BasicObject#==" do
it "is a public instance method" do
- BasicObject.should have_public_instance_method(:==)
+ BasicObject.public_instance_methods(false).should.include?(:==)
end
it_behaves_like :object_equal, :==
diff --git a/spec/ruby/core/basicobject/fixtures/classes.rb b/spec/ruby/core/basicobject/fixtures/classes.rb
index d1785afe31..ed5a2dda17 100644
--- a/spec/ruby/core/basicobject/fixtures/classes.rb
+++ b/spec/ruby/core/basicobject/fixtures/classes.rb
@@ -15,8 +15,231 @@ module BasicObjectSpecs
include InstExec
end
- module InstEvalCVar
- instance_eval { @@count = 2 }
+ module InstEval
+ module CVar
+ module Get
+ class ReceiverScope
+ @@cvar = :value_defined_in_receiver_scope
+ end
+
+ class BlockDefinitionScope
+ @@cvar = :value_defined_in_block_definition_scope
+
+ def block
+ -> * { @@cvar }
+ end
+ end
+
+ class CallerScope
+ @@cvar = :value_defined_in_caller_scope
+
+ def get_class_variable_with_string(obj)
+ obj.instance_eval("@@cvar")
+ end
+
+ def get_class_variable_with_block(obj, block)
+ obj.instance_eval(&block)
+ end
+ end
+
+ class CallerWithoutCVarScope
+ def get_class_variable_with_string(obj)
+ obj.instance_eval("@@cvar")
+ end
+ end
+
+ ReceiverWithCVarDefinedInSingletonClass = Class.new.new.tap do |obj|
+ obj.singleton_class.class_variable_set(:@@cvar, :value_defined_in_receiver_singleton_class)
+ end
+ end
+
+ module Set
+ class ReceiverScope
+ end
+
+ class BlockDefinitionScope
+ def self.get_class_variable
+ @@cvar
+ end
+
+ def block_to_assign(value)
+ -> * { @@cvar = value }
+ end
+ end
+
+ class CallerScope
+ def self.get_class_variable
+ @@cvar
+ end
+
+ def set_class_variable_with_string(obj, value)
+ obj.instance_eval("@@cvar=#{value.inspect}")
+ end
+
+ def set_class_variable_with_block(obj, block)
+ obj.instance_eval(&block)
+ end
+ end
+ end
+ end
+ end
+
+ module InstEval
+ module Constants
+ module ConstantInReceiverSingletonClass
+ module ReceiverScope
+ FOO = :ReceiverScope
+
+ class ReceiverParent
+ FOO = :ReceiverParent
+ end
+
+ class Receiver < ReceiverParent
+ FOO = :Receiver
+
+ def initialize
+ self.singleton_class.const_set(:FOO, :singleton_class)
+ end
+ end
+ end
+
+ module CallerScope
+ FOO = :CallerScope
+
+ class CallerParent
+ FOO = :CallerParent
+ end
+
+ class Caller < CallerParent
+ FOO = :Caller
+
+ def get_constant_with_string(receiver)
+ receiver.instance_eval("FOO")
+ end
+ end
+ end
+ end
+
+ module ConstantInReceiverClass
+ module ReceiverScope
+ FOO = :ReceiverScope
+
+ class ReceiverParent
+ FOO = :ReceiverParent
+ end
+
+ class Receiver < ReceiverParent
+ FOO = :Receiver
+ end
+ end
+
+ module CallerScope
+ FOO = :CallerScope
+
+ class CallerParent
+ FOO = :CallerParent
+ end
+
+ class Caller < CallerParent
+ FOO = :Caller
+
+ def get_constant_with_string(receiver)
+ receiver.instance_eval("FOO")
+ end
+ end
+ end
+ end
+
+ module ConstantInCallerClass
+ module ReceiverScope
+ FOO = :ReceiverScope
+
+ class ReceiverParent
+ FOO = :ReceiverParent
+ end
+
+ class Receiver < ReceiverParent
+ # FOO is not declared in a receiver class
+ end
+ end
+
+ module CallerScope
+ FOO = :CallerScope
+
+ class CallerParent
+ FOO = :CallerParent
+ end
+
+ class Caller < CallerParent
+ FOO = :Caller
+
+ def get_constant_with_string(receiver)
+ receiver.instance_eval("FOO")
+ end
+ end
+ end
+ end
+
+ module ConstantInCallerOuterScopes
+ module ReceiverScope
+ FOO = :ReceiverScope
+
+ class ReceiverParent
+ FOO = :ReceiverParent
+ end
+
+ class Receiver < ReceiverParent
+ # FOO is not declared in a receiver class
+ end
+ end
+
+ module CallerScope
+ FOO = :CallerScope
+
+ class CallerParent
+ FOO = :CallerParent
+ end
+
+ class Caller < CallerParent
+ # FOO is not declared in a caller class
+
+ def get_constant_with_string(receiver)
+ receiver.instance_eval("FOO")
+ end
+ end
+ end
+ end
+
+ module ConstantInReceiverParentClass
+ module ReceiverScope
+ FOO = :ReceiverScope
+
+ class ReceiverParent
+ FOO = :ReceiverParent
+ end
+
+ class Receiver < ReceiverParent
+ # FOO is not declared in a receiver class
+ end
+ end
+
+ module CallerScope
+ # FOO is not declared in a caller outer scopes
+
+ class CallerParent
+ FOO = :CallerParent
+ end
+
+ class Caller < CallerParent
+ # FOO is not declared in a caller class
+
+ def get_constant_with_string(receiver)
+ receiver.instance_eval("FOO")
+ end
+ end
+ end
+ end
+ end
end
class InstEvalConst
@@ -26,7 +249,6 @@ module BasicObjectSpecs
module InstEvalOuter
module Inner
obj = InstEvalConst.new
- X_BY_STR = obj.instance_eval("INST_EVAL_CONST_X") rescue nil
X_BY_BLOCK = obj.instance_eval { INST_EVAL_CONST_X } rescue nil
end
end
diff --git a/spec/ruby/core/basicobject/initialize_spec.rb b/spec/ruby/core/basicobject/initialize_spec.rb
index b7ce73ffd5..09e86676b6 100644
--- a/spec/ruby/core/basicobject/initialize_spec.rb
+++ b/spec/ruby/core/basicobject/initialize_spec.rb
@@ -2,12 +2,12 @@ require_relative '../../spec_helper'
describe "BasicObject#initialize" do
it "is a private instance method" do
- BasicObject.should have_private_instance_method(:initialize)
+ BasicObject.private_instance_methods(false).should.include?(:initialize)
end
it "does not accept arguments" do
-> {
BasicObject.new("This", "makes it easier", "to call super", "from other constructors")
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/basicobject/instance_eval_spec.rb b/spec/ruby/core/basicobject/instance_eval_spec.rb
index b6a146095d..124d179b5a 100644
--- a/spec/ruby/core/basicobject/instance_eval_spec.rb
+++ b/spec/ruby/core/basicobject/instance_eval_spec.rb
@@ -7,25 +7,31 @@ describe "BasicObject#instance_eval" do
end
it "is a public instance method" do
- BasicObject.should have_public_instance_method(:instance_eval)
+ BasicObject.public_instance_methods(false).should.include?(:instance_eval)
end
it "sets self to the receiver in the context of the passed block" do
a = BasicObject.new
- a.instance_eval { self }.equal?(a).should be_true
+ a.instance_eval { self }.equal?(a).should == true
end
it "evaluates strings" do
a = BasicObject.new
- a.instance_eval('self').equal?(a).should be_true
+ a.instance_eval('self').equal?(a).should == true
end
- it "expects a block with no arguments" do
- -> { "hola".instance_eval }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when no arguments and no block are given" do
+ -> { "hola".instance_eval }.should.raise(ArgumentError, "wrong number of arguments (given 0, expected 1..3)")
end
- it "takes no arguments with a block" do
- -> { "hola".instance_eval(4, 5) {|a,b| a + b } }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when a block and normal arguments are given" do
+ -> { "hola".instance_eval(4, 5) {|a,b| a + b } }.should.raise(ArgumentError, "wrong number of arguments (given 2, expected 0)")
+ end
+
+ it "raises an ArgumentError when more than 3 arguments are given" do
+ -> {
+ "hola".instance_eval("1 + 1", "some file", 0, "bogus")
+ }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
it "yields the object to the block" do
@@ -45,7 +51,7 @@ describe "BasicObject#instance_eval" do
end
end
f.foo.should == 1
- -> { Object.new.foo }.should raise_error(NoMethodError)
+ -> { Object.new.foo }.should.raise(NoMethodError)
end
it "preserves self in the original block when passed a block argument" do
@@ -65,9 +71,9 @@ describe "BasicObject#instance_eval" do
it "binds self to the receiver" do
s = "hola"
- (s == s.instance_eval { self }).should be_true
+ (s == s.instance_eval { self }).should == true
o = mock('o')
- (o == o.instance_eval("self")).should be_true
+ (o == o.instance_eval("self")).should == true
end
it "executes in the context of the receiver" do
@@ -78,11 +84,28 @@ describe "BasicObject#instance_eval" do
end
+ it "uses the caller location as default location" do
+ f = Object.new
+ f.instance_eval("[__FILE__, __LINE__]").should == ["(eval at #{__FILE__}:#{__LINE__})", 1]
+ end
+
it "has access to receiver's instance variables" do
BasicObjectSpecs::IVars.new.instance_eval { @secret }.should == 99
BasicObjectSpecs::IVars.new.instance_eval("@secret").should == 99
end
+ it "raises TypeError for frozen objects when tries to set receiver's instance variables" do
+ -> { nil.instance_eval { @foo = 42 } }.should.raise(FrozenError, "can't modify frozen NilClass: nil")
+ -> { true.instance_eval { @foo = 42 } }.should.raise(FrozenError, "can't modify frozen TrueClass: true")
+ -> { false.instance_eval { @foo = 42 } }.should.raise(FrozenError, "can't modify frozen FalseClass: false")
+ -> { 1.instance_eval { @foo = 42 } }.should.raise(FrozenError, "can't modify frozen Integer: 1")
+ -> { :symbol.instance_eval { @foo = 42 } }.should.raise(FrozenError, "can't modify frozen Symbol: :symbol")
+
+ obj = Object.new
+ obj.freeze
+ -> { obj.instance_eval { @foo = 42 } }.should.raise(FrozenError)
+ end
+
it "treats block-local variables as local to the block" do
prc = instance_eval <<-CODE
proc do |x, prc|
@@ -99,56 +122,118 @@ describe "BasicObject#instance_eval" do
prc.call(false, prc).should == 1
end
- it "sets class variables in the receiver" do
- BasicObjectSpecs::InstEvalCVar.class_variables.should include(:@@count)
- BasicObjectSpecs::InstEvalCVar.send(:class_variable_get, :@@count).should == 2
- end
-
it "makes the receiver metaclass the scoped class when used with a string" do
obj = Object.new
obj.instance_eval %{
class B; end
B
}
- obj.singleton_class.const_get(:B).should be_an_instance_of(Class)
+ obj.singleton_class.const_get(:B).should.instance_of?(Class)
end
- it "gets constants in the receiver if a string given" do
- BasicObjectSpecs::InstEvalOuter::Inner::X_BY_STR.should == 2
+ describe "constants lookup when a String given" do
+ it "looks in the receiver singleton class first" do
+ receiver = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverSingletonClass::ReceiverScope::Receiver.new
+ caller = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverSingletonClass::CallerScope::Caller.new
+
+ caller.get_constant_with_string(receiver).should == :singleton_class
+ end
+
+ it "looks in the receiver class next" do
+ receiver = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverClass::ReceiverScope::Receiver.new
+ caller = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverClass::CallerScope::Caller.new
+
+ caller.get_constant_with_string(receiver).should == :Receiver
+ end
+
+ it "looks in the caller class next" do
+ receiver = BasicObjectSpecs::InstEval::Constants::ConstantInCallerClass::ReceiverScope::Receiver.new
+ caller = BasicObjectSpecs::InstEval::Constants::ConstantInCallerClass::CallerScope::Caller.new
+
+ caller.get_constant_with_string(receiver).should == :Caller
+ end
+
+ it "looks in the caller outer scopes next" do
+ receiver = BasicObjectSpecs::InstEval::Constants::ConstantInCallerOuterScopes::ReceiverScope::Receiver.new
+ caller = BasicObjectSpecs::InstEval::Constants::ConstantInCallerOuterScopes::CallerScope::Caller.new
+
+ caller.get_constant_with_string(receiver).should == :CallerScope
+ end
+
+ it "looks in the receiver class hierarchy next" do
+ receiver = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverParentClass::ReceiverScope::Receiver.new
+ caller = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverParentClass::CallerScope::Caller.new
+
+ caller.get_constant_with_string(receiver).should == :ReceiverParent
+ end
end
it "doesn't get constants in the receiver if a block given" do
- BasicObjectSpecs::InstEvalOuter::Inner::X_BY_BLOCK.should be_nil
+ BasicObjectSpecs::InstEvalOuter::Inner::X_BY_BLOCK.should == nil
end
it "raises a TypeError when defining methods on an immediate" do
-> do
1.instance_eval { def foo; end }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
-> do
:foo.instance_eval { def foo; end }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
-quarantine! do # Not clean, leaves cvars lying around to break other specs
- it "scopes class var accesses in the caller when called on an Integer" do
- # Integer can take instance vars
- Integer.class_eval "@@__tmp_instance_eval_spec = 1"
- (defined? @@__tmp_instance_eval_spec).should be_nil
+ describe "class variables lookup" do
+ it "gets class variables in the caller class when called with a String" do
+ receiver = BasicObjectSpecs::InstEval::CVar::Get::ReceiverScope.new
+ caller = BasicObjectSpecs::InstEval::CVar::Get::CallerScope.new
+
+ caller.get_class_variable_with_string(receiver).should == :value_defined_in_caller_scope
+ end
+
+ it "gets class variables in the block definition scope when called with a block" do
+ receiver = BasicObjectSpecs::InstEval::CVar::Get::ReceiverScope.new
+ caller = BasicObjectSpecs::InstEval::CVar::Get::CallerScope.new
+ block = BasicObjectSpecs::InstEval::CVar::Get::BlockDefinitionScope.new.block
+
+ caller.get_class_variable_with_block(receiver, block).should == :value_defined_in_block_definition_scope
+ end
+
+ it "sets class variables in the caller class when called with a String" do
+ receiver = BasicObjectSpecs::InstEval::CVar::Set::ReceiverScope.new
+ caller = BasicObjectSpecs::InstEval::CVar::Set::CallerScope.new
- @@__tmp_instance_eval_spec = 2
- 1.instance_eval { @@__tmp_instance_eval_spec }.should == 2
- Integer.__send__(:remove_class_variable, :@@__tmp_instance_eval_spec)
+ caller.set_class_variable_with_string(receiver, 1)
+ BasicObjectSpecs::InstEval::CVar::Set::CallerScope.get_class_variable.should == 1
+ end
+
+ it "sets class variables in the block definition scope when called with a block" do
+ receiver = BasicObjectSpecs::InstEval::CVar::Set::ReceiverScope.new
+ caller = BasicObjectSpecs::InstEval::CVar::Set::CallerScope.new
+ block = BasicObjectSpecs::InstEval::CVar::Set::BlockDefinitionScope.new.block_to_assign(1)
+
+ caller.set_class_variable_with_block(receiver, block)
+ BasicObjectSpecs::InstEval::CVar::Set::BlockDefinitionScope.get_class_variable.should == 1
+ end
+
+ it "does not have access to class variables in the receiver class when called with a String" do
+ receiver = BasicObjectSpecs::InstEval::CVar::Get::ReceiverScope.new
+ caller = BasicObjectSpecs::InstEval::CVar::Get::CallerWithoutCVarScope.new
+ -> { caller.get_class_variable_with_string(receiver) }.should.raise(NameError, /uninitialized class variable @@cvar/)
+ end
+
+ it "does not have access to class variables in the receiver's singleton class when called with a String" do
+ receiver = BasicObjectSpecs::InstEval::CVar::Get::ReceiverWithCVarDefinedInSingletonClass
+ caller = BasicObjectSpecs::InstEval::CVar::Get::CallerWithoutCVarScope.new
+ -> { caller.get_class_variable_with_string(receiver) }.should.raise(NameError, /uninitialized class variable @@cvar/)
+ end
end
-end
it "raises a TypeError when defining methods on numerics" do
-> do
(1.0).instance_eval { def foo; end }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
-> do
(1 << 64).instance_eval { def foo; end }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "evaluates procs originating from methods" do
@@ -185,4 +270,58 @@ end
x.should == :value
end
+
+ it "converts string argument with #to_str method" do
+ source_code = Object.new
+ def source_code.to_str() "1" end
+
+ a = BasicObject.new
+ a.instance_eval(source_code).should == 1
+ end
+
+ it "raises ArgumentError if returned value is not String" do
+ source_code = Object.new
+ def source_code.to_str() :symbol end
+
+ a = BasicObject.new
+ -> { a.instance_eval(source_code) }.should raise_consistent_error(TypeError, /can't convert Object into String/)
+ end
+
+ it "converts filename argument with #to_str method" do
+ filename = Object.new
+ def filename.to_str() "file.rb" end
+
+ err = begin
+ Object.new.instance_eval("raise", filename)
+ rescue => e
+ e
+ end
+ err.backtrace.first.split(":")[0].should == "file.rb"
+ end
+
+ it "raises ArgumentError if returned value is not String" do
+ filename = Object.new
+ def filename.to_str() :symbol end
+
+ -> { Object.new.instance_eval("raise", filename) }.should raise_consistent_error(TypeError, /can't convert Object into String/)
+ end
+
+ it "converts lineno argument with #to_int method" do
+ lineno = Object.new
+ def lineno.to_int() 15 end
+
+ err = begin
+ Object.new.instance_eval("raise", "file.rb", lineno)
+ rescue => e
+ e
+ end
+ err.backtrace.first.split(":")[1].should == "15"
+ end
+
+ it "raises ArgumentError if returned value is not Integer" do
+ lineno = Object.new
+ def lineno.to_int() :symbol end
+
+ -> { Object.new.instance_eval("raise", "file.rb", lineno) }.should raise_consistent_error(TypeError, /can't convert Object into Integer/)
+ end
end
diff --git a/spec/ruby/core/basicobject/instance_exec_spec.rb b/spec/ruby/core/basicobject/instance_exec_spec.rb
index 289fdd889b..cfce9a65ad 100644
--- a/spec/ruby/core/basicobject/instance_exec_spec.rb
+++ b/spec/ruby/core/basicobject/instance_exec_spec.rb
@@ -3,21 +3,21 @@ require_relative 'fixtures/classes'
describe "BasicObject#instance_exec" do
it "is a public instance method" do
- BasicObject.should have_public_instance_method(:instance_exec)
+ BasicObject.public_instance_methods(false).should.include?(:instance_exec)
end
it "sets self to the receiver in the context of the passed block" do
a = BasicObject.new
- a.instance_exec { self }.equal?(a).should be_true
+ a.instance_exec { self }.equal?(a).should == true
end
it "passes arguments to the block" do
a = BasicObject.new
- a.instance_exec(1) { |b| b }.should equal(1)
+ a.instance_exec(1) { |b| b }.should.equal?(1)
end
it "raises a LocalJumpError unless given a block" do
- -> { "hola".instance_exec }.should raise_error(LocalJumpError)
+ -> { "hola".instance_exec }.should.raise(LocalJumpError)
end
it "has an arity of -1" do
@@ -25,17 +25,23 @@ describe "BasicObject#instance_exec" do
end
it "accepts arguments with a block" do
- -> { "hola".instance_exec(4, 5) { |a,b| a + b } }.should_not raise_error
+ -> { "hola".instance_exec(4, 5) { |a,b| a + b } }.should_not.raise
end
it "doesn't pass self to the block as an argument" do
- "hola".instance_exec { |o| o }.should be_nil
+ "hola".instance_exec { |o| o }.should == nil
end
it "passes any arguments to the block" do
Object.new.instance_exec(1,2) {|one, two| one + two}.should == 3
end
+ describe "with optional argument" do
+ it "does not destructure a single array argument" do
+ Object.new.instance_exec([1, 2, 3]) { |a = 99| a }.should == [1, 2, 3]
+ end
+ end
+
it "only binds the exec to the receiver" do
f = Object.new
f.instance_exec do
@@ -44,7 +50,7 @@ describe "BasicObject#instance_exec" do
end
end
f.foo.should == 1
- -> { Object.new.foo }.should raise_error(NoMethodError)
+ -> { Object.new.foo }.should.raise(NoMethodError)
end
# TODO: This should probably be replaced with a "should behave like" that uses
@@ -71,37 +77,37 @@ describe "BasicObject#instance_exec" do
end
it "sets class variables in the receiver" do
- BasicObjectSpecs::InstExec.class_variables.should include(:@@count)
+ BasicObjectSpecs::InstExec.class_variables.should.include?(:@@count)
BasicObjectSpecs::InstExec.send(:class_variable_get, :@@count).should == 2
end
it "raises a TypeError when defining methods on an immediate" do
-> do
1.instance_exec { def foo; end }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
-> do
:foo.instance_exec { def foo; end }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
-quarantine! do # Not clean, leaves cvars lying around to break other specs
- it "scopes class var accesses in the caller when called on an Integer" do
- # Integer can take instance vars
- Integer.class_eval "@@__tmp_instance_exec_spec = 1"
- (defined? @@__tmp_instance_exec_spec).should == nil
+ quarantine! do # Not clean, leaves cvars lying around to break other specs
+ it "scopes class var accesses in the caller when called on an Integer" do
+ # Integer can take instance vars
+ Integer.class_eval "@@__tmp_instance_exec_spec = 1"
+ (defined? @@__tmp_instance_exec_spec).should == nil
- @@__tmp_instance_exec_spec = 2
- 1.instance_exec { @@__tmp_instance_exec_spec }.should == 2
- Integer.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec)
+ @@__tmp_instance_exec_spec = 2
+ 1.instance_exec { @@__tmp_instance_exec_spec }.should == 2
+ Integer.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec)
+ end
end
-end
it "raises a TypeError when defining methods on numerics" do
-> do
(1.0).instance_exec { def foo; end }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
-> do
(1 << 64).instance_exec { def foo; end }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/basicobject/method_missing_spec.rb b/spec/ruby/core/basicobject/method_missing_spec.rb
index b048780ee8..8785b41b21 100644
--- a/spec/ruby/core/basicobject/method_missing_spec.rb
+++ b/spec/ruby/core/basicobject/method_missing_spec.rb
@@ -1,8 +1,9 @@
+require_relative "../../spec_helper"
require_relative '../../shared/basicobject/method_missing'
describe "BasicObject#method_missing" do
it "is a private method" do
- BasicObject.should have_private_instance_method(:method_missing)
+ BasicObject.private_instance_methods(false).should.include?(:method_missing)
end
end
diff --git a/spec/ruby/core/basicobject/not_equal_spec.rb b/spec/ruby/core/basicobject/not_equal_spec.rb
index 9329128c43..29b14b0fff 100644
--- a/spec/ruby/core/basicobject/not_equal_spec.rb
+++ b/spec/ruby/core/basicobject/not_equal_spec.rb
@@ -2,24 +2,24 @@ require_relative '../../spec_helper'
describe "BasicObject#!=" do
it "is a public instance method" do
- BasicObject.should have_public_instance_method(:'!=')
+ BasicObject.public_instance_methods(false).should.include?(:'!=')
end
it "returns true if other is not identical to self" do
a = BasicObject.new
b = BasicObject.new
- (a != b).should be_true
+ (a != b).should == true
end
it "returns true if other is an Object" do
a = BasicObject.new
b = Object.new
- (a != b).should be_true
+ (a != b).should == true
end
it "returns false if other is identical to self" do
a = BasicObject.new
- (a != a).should be_false
+ (a != a).should == false
end
it "dispatches to #==" do
@@ -27,19 +27,19 @@ describe "BasicObject#!=" do
b = BasicObject.new
a.should_receive(:==).and_return(true)
- (a != b).should be_false
+ (a != b).should == false
end
describe "when invoked using Kernel#send" do
it "returns true if other is not identical to self" do
a = Object.new
b = Object.new
- a.send(:!=, b).should be_true
+ a.send(:!=, b).should == true
end
it "returns false if other is identical to self" do
a = Object.new
- a.send(:!=, a).should be_false
+ a.send(:!=, a).should == false
end
it "dispatches to #==" do
@@ -47,7 +47,7 @@ describe "BasicObject#!=" do
b = Object.new
a.should_receive(:==).and_return(true)
- a.send(:!=, b).should be_false
+ a.send(:!=, b).should == false
end
end
end
diff --git a/spec/ruby/core/basicobject/not_spec.rb b/spec/ruby/core/basicobject/not_spec.rb
index ca4cb6f5ff..a6f58ae6f5 100644
--- a/spec/ruby/core/basicobject/not_spec.rb
+++ b/spec/ruby/core/basicobject/not_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "BasicObject#!" do
it "is a public instance method" do
- BasicObject.should have_public_instance_method(:'!')
+ BasicObject.public_instance_methods(false).should.include?(:'!')
end
it "returns false" do
- (!BasicObject.new).should be_false
+ (!BasicObject.new).should == false
end
end
diff --git a/spec/ruby/core/basicobject/singleton_method_added_spec.rb b/spec/ruby/core/basicobject/singleton_method_added_spec.rb
index ab6b2a2d10..f39b91768c 100644
--- a/spec/ruby/core/basicobject/singleton_method_added_spec.rb
+++ b/spec/ruby/core/basicobject/singleton_method_added_spec.rb
@@ -7,7 +7,7 @@ describe "BasicObject#singleton_method_added" do
end
it "is a private method" do
- BasicObject.should have_private_instance_method(:singleton_method_added)
+ BasicObject.private_instance_methods(false).should.include?(:singleton_method_added)
end
it "is called when a singleton method is defined on an object" do
@@ -35,7 +35,7 @@ describe "BasicObject#singleton_method_added" do
end
end
- ScratchPad.recorded.should_not include(:new_instance_method)
+ ScratchPad.recorded.should_not.include?(:new_instance_method)
end
it "is called when a singleton method is defined on a module" do
@@ -94,8 +94,10 @@ describe "BasicObject#singleton_method_added" do
-> {
def self.foo
end
- }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for/)
+ }.should.raise(NoMethodError, /undefined method [`']singleton_method_added' for/)
end
+ ensure
+ BasicObjectSpecs.send(:remove_const, :NoSingletonMethodAdded)
end
it "raises NoMethodError for a singleton instance" do
@@ -106,16 +108,16 @@ describe "BasicObject#singleton_method_added" do
-> {
def foo
end
- }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for #<Object:/)
+ }.should.raise(NoMethodError, /undefined method [`']singleton_method_added' for #<Object:/)
-> {
define_method(:bar) {}
- }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for #<Object:/)
+ }.should.raise(NoMethodError, /undefined method [`']singleton_method_added' for #<Object:/)
end
-> {
object.define_singleton_method(:baz) {}
- }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for #<Object:/)
+ }.should.raise(NoMethodError, /undefined method [`']singleton_method_added' for #<Object:/)
end
it "calls #method_missing" do
diff --git a/spec/ruby/core/basicobject/singleton_method_removed_spec.rb b/spec/ruby/core/basicobject/singleton_method_removed_spec.rb
index 46f9a6894c..1831e3c070 100644
--- a/spec/ruby/core/basicobject/singleton_method_removed_spec.rb
+++ b/spec/ruby/core/basicobject/singleton_method_removed_spec.rb
@@ -6,7 +6,7 @@ describe "BasicObject#singleton_method_removed" do
end
it "is a private method" do
- BasicObject.should have_private_instance_method(:singleton_method_removed)
+ BasicObject.private_instance_methods(false).should.include?(:singleton_method_removed)
end
it "is called when a method is removed on self" do
diff --git a/spec/ruby/core/basicobject/singleton_method_undefined_spec.rb b/spec/ruby/core/basicobject/singleton_method_undefined_spec.rb
index 7d6c7207db..cc47341878 100644
--- a/spec/ruby/core/basicobject/singleton_method_undefined_spec.rb
+++ b/spec/ruby/core/basicobject/singleton_method_undefined_spec.rb
@@ -6,7 +6,7 @@ describe "BasicObject#singleton_method_undefined" do
end
it "is a private method" do
- BasicObject.should have_private_instance_method(:singleton_method_undefined)
+ BasicObject.private_instance_methods(false).should.include?(:singleton_method_undefined)
end
it "is called when a method is removed on self" do
diff --git a/spec/ruby/core/binding/clone_spec.rb b/spec/ruby/core/binding/clone_spec.rb
index ebd40f5377..f1769ac6de 100644
--- a/spec/ruby/core/binding/clone_spec.rb
+++ b/spec/ruby/core/binding/clone_spec.rb
@@ -4,4 +4,10 @@ require_relative 'shared/clone'
describe "Binding#clone" do
it_behaves_like :binding_clone, :clone
+
+ it "preserves frozen status" do
+ bind = binding.freeze
+ bind.frozen?.should == true
+ bind.clone.frozen?.should == true
+ end
end
diff --git a/spec/ruby/core/binding/dup_spec.rb b/spec/ruby/core/binding/dup_spec.rb
index 43968213c8..f5f0c72d5d 100644
--- a/spec/ruby/core/binding/dup_spec.rb
+++ b/spec/ruby/core/binding/dup_spec.rb
@@ -4,4 +4,27 @@ require_relative 'shared/clone'
describe "Binding#dup" do
it_behaves_like :binding_clone, :dup
+
+ it "resets frozen status" do
+ bind = binding.freeze
+ bind.frozen?.should == true
+ bind.dup.frozen?.should == false
+ end
+
+ it "retains original binding variables but the list is distinct" do
+ bind1 = binding
+ eval "a = 1", bind1
+
+ bind2 = bind1.dup
+ eval("a = 2", bind2)
+ eval("a", bind1).should == 2
+ eval("a", bind2).should == 2
+
+ eval("b = 2", bind2)
+ -> { eval("b", bind1) }.should.raise(NameError)
+ eval("b", bind2).should == 2
+
+ bind1.local_variables.sort.should == [:a, :bind1, :bind2]
+ bind2.local_variables.sort.should == [:a, :b, :bind1, :bind2]
+ end
end
diff --git a/spec/ruby/core/binding/eval_spec.rb b/spec/ruby/core/binding/eval_spec.rb
index 4bb3da7a6c..f1d8591320 100644
--- a/spec/ruby/core/binding/eval_spec.rb
+++ b/spec/ruby/core/binding/eval_spec.rb
@@ -7,7 +7,7 @@ describe "Binding#eval" do
bind = obj.get_binding
bind.eval("@secret += square(3)").should == 10
- bind.eval("a").should be_true
+ bind.eval("a").should == true
bind.eval("class Inside; end")
bind.eval("Inside.name").should == "BindingSpecs::Demo::Inside"
@@ -23,58 +23,29 @@ describe "Binding#eval" do
bind2.local_variables.should == []
end
- ruby_version_is ""..."3.0" do
- it "inherits __LINE__ from the enclosing scope" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- suppress_warning {bind.eval("__LINE__")}.should == obj.get_line_of_binding
- end
-
- it "preserves __LINE__ across multiple calls to eval" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- suppress_warning {bind.eval("__LINE__")}.should == obj.get_line_of_binding
- suppress_warning {bind.eval("__LINE__")}.should == obj.get_line_of_binding
- end
-
- it "increments __LINE__ on each line of a multiline eval" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- suppress_warning {bind.eval("#foo\n__LINE__")}.should == obj.get_line_of_binding + 1
- end
-
- it "inherits __LINE__ from the enclosing scope even if the Binding is created with #send" do
- obj = BindingSpecs::Demo.new(1)
- bind, line = obj.get_binding_with_send_and_line
- suppress_warning {bind.eval("__LINE__")}.should == line
- end
+ it "starts with line 1 if single argument is given" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("__LINE__").should == 1
end
- ruby_version_is "3.0" do
- it "starts with line 1 if single argument is given" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- bind.eval("__LINE__").should == 1
- end
-
- it "preserves __LINE__ across multiple calls to eval" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- bind.eval("__LINE__").should == 1
- bind.eval("__LINE__").should == 1
- end
+ it "preserves __LINE__ across multiple calls to eval" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("__LINE__").should == 1
+ bind.eval("__LINE__").should == 1
+ end
- it "increments __LINE__ on each line of a multiline eval" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- bind.eval("#foo\n__LINE__").should == 2
- end
+ it "increments __LINE__ on each line of a multiline eval" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("#foo\n__LINE__").should == 2
+ end
- it "starts with line 1 if the Binding is created with #send" do
- obj = BindingSpecs::Demo.new(1)
- bind, line = obj.get_binding_with_send_and_line
- bind.eval("__LINE__").should == 1
- end
+ it "starts with line 1 if the Binding is created with #send" do
+ obj = BindingSpecs::Demo.new(1)
+ bind, line = obj.get_binding_with_send_and_line
+ bind.eval("__LINE__").should == 1
end
it "starts with a __LINE__ of 1 if a filename is passed" do
@@ -89,32 +60,10 @@ describe "Binding#eval" do
bind.eval("#foo\n__LINE__", "(test)", 88).should == 89
end
- ruby_version_is ""..."3.0" do
- it "inherits __FILE__ from the enclosing scope" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- suppress_warning { bind.eval("__FILE__") }.should == obj.get_file_of_binding
- end
-
- it "inherits __LINE__ from the enclosing scope" do
- obj = BindingSpecs::Demo.new(1)
- bind, line = obj.get_binding_and_line
- suppress_warning { bind.eval("__LINE__") }.should == line
- end
- end
-
- ruby_version_is "3.0" do
- it "uses (eval) as __FILE__ if single argument given" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- bind.eval("__FILE__").should == '(eval)'
- end
-
- it "uses 1 as __LINE__" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- suppress_warning { bind.eval("__LINE__") }.should == 1
- end
+ it "uses 1 as __LINE__" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ suppress_warning { bind.eval("__LINE__") }.should == 1
end
it "uses the __FILE__ that is passed in" do
@@ -149,4 +98,8 @@ describe "Binding#eval" do
bind.eval("'bar'.foo").should == "foo"
end
+
+ it "uses the caller location as default filename" do
+ binding.eval("[__FILE__, __LINE__]").should == ["(eval at #{__FILE__}:#{__LINE__})", 1]
+ end
end
diff --git a/spec/ruby/core/binding/fixtures/irb.rb b/spec/ruby/core/binding/fixtures/irb.rb
deleted file mode 100644
index 5f305f2d5d..0000000000
--- a/spec/ruby/core/binding/fixtures/irb.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-a = 10
-
-binding.irb
diff --git a/spec/ruby/core/binding/fixtures/irbrc b/spec/ruby/core/binding/fixtures/irbrc
deleted file mode 100644
index 2bc12af2f7..0000000000
--- a/spec/ruby/core/binding/fixtures/irbrc
+++ /dev/null
@@ -1 +0,0 @@
-# empty configuration
diff --git a/spec/ruby/core/binding/irb_spec.rb b/spec/ruby/core/binding/irb_spec.rb
deleted file mode 100644
index b3bc274f78..0000000000
--- a/spec/ruby/core/binding/irb_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Binding#irb" do
- it "creates an IRB session with the binding in scope" do
- irb_fixture = fixture __FILE__, "irb.rb"
- irbrc_fixture = fixture __FILE__, "irbrc"
-
- out = IO.popen([{"IRBRC"=>irbrc_fixture}, *ruby_exe, irb_fixture], "r+") do |pipe|
- pipe.puts "a ** 2"
- pipe.puts "exit"
- pipe.readlines.map(&:chomp)
- end
-
- out[-3..-1].should == ["a ** 2", "100", "exit"]
- end
-end
diff --git a/spec/ruby/core/binding/local_variable_get_spec.rb b/spec/ruby/core/binding/local_variable_get_spec.rb
index 005670becc..d97100deda 100644
--- a/spec/ruby/core/binding/local_variable_get_spec.rb
+++ b/spec/ruby/core/binding/local_variable_get_spec.rb
@@ -13,7 +13,7 @@ describe "Binding#local_variable_get" do
-> {
bind.local_variable_get(:no_such_variable)
- }.should raise_error(NameError)
+ }.should.raise(NameError)
end
it "reads variables added later to the binding" do
@@ -21,7 +21,7 @@ describe "Binding#local_variable_get" do
-> {
bind.local_variable_get(:a)
- }.should raise_error(NameError)
+ }.should.raise(NameError)
bind.local_variable_set(:a, 42)
@@ -45,12 +45,12 @@ describe "Binding#local_variable_get" do
it "raises a NameError on global access" do
bind = binding
- -> { bind.local_variable_get(:$0) }.should raise_error(NameError)
+ -> { bind.local_variable_get(:$0) }.should.raise(NameError)
end
it "raises a NameError on special variable access" do
bind = binding
- -> { bind.local_variable_get(:$~) }.should raise_error(NameError)
- -> { bind.local_variable_get(:$_) }.should raise_error(NameError)
+ -> { bind.local_variable_get(:$~) }.should.raise(NameError)
+ -> { bind.local_variable_get(:$_) }.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/binding/local_variable_set_spec.rb b/spec/ruby/core/binding/local_variable_set_spec.rb
index 1456c6dda1..3e4f407fc3 100644
--- a/spec/ruby/core/binding/local_variable_set_spec.rb
+++ b/spec/ruby/core/binding/local_variable_set_spec.rb
@@ -38,7 +38,7 @@ describe "Binding#local_variable_set" do
bind = binding
bind.local_variable_set(:number, 10)
- -> { number }.should raise_error(NameError)
+ -> { number }.should.raise(NameError)
end
it 'overwrites an existing local variable defined before a Binding' do
@@ -59,13 +59,13 @@ describe "Binding#local_variable_set" do
it "raises a NameError on global access" do
bind = binding
- -> { bind.local_variable_set(:$0, "") }.should raise_error(NameError)
+ -> { bind.local_variable_set(:$0, "") }.should.raise(NameError)
end
it "raises a NameError on special variable access" do
bind = binding
- -> { bind.local_variable_set(:$~, "") }.should raise_error(NameError)
- -> { bind.local_variable_set(:$_, "") }.should raise_error(NameError)
+ -> { bind.local_variable_set(:$~, "") }.should.raise(NameError)
+ -> { bind.local_variable_set(:$_, "") }.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/binding/local_variables_spec.rb b/spec/ruby/core/binding/local_variables_spec.rb
index 92c817b9a8..0f59681342 100644
--- a/spec/ruby/core/binding/local_variables_spec.rb
+++ b/spec/ruby/core/binding/local_variables_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Binding#local_variables" do
it "returns an Array" do
- binding.local_variables.should be_kind_of(Array)
+ binding.local_variables.should.is_a?(Array)
end
it "includes local variables in the current scope" do
diff --git a/spec/ruby/core/binding/shared/clone.rb b/spec/ruby/core/binding/shared/clone.rb
index 0e934ac1b5..2d854fce96 100644
--- a/spec/ruby/core/binding/shared/clone.rb
+++ b/spec/ruby/core/binding/shared/clone.rb
@@ -31,4 +31,26 @@ describe :binding_clone, shared: true do
b2.local_variable_defined?(:x).should == false
end
end
+
+ ruby_version_is "3.4" do
+ it "copies instance variables" do
+ @b1.instance_variable_set(:@ivar, 1)
+ cl = @b1.send(@method)
+ cl.instance_variables.should == [:@ivar]
+ end
+
+ it "copies the finalizer" do
+ code = <<-'RUBY'
+ obj = binding
+
+ ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
+
+ obj.clone
+
+ exit 0
+ RUBY
+
+ ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"]
+ end
+ end
end
diff --git a/spec/ruby/core/binding/source_location_spec.rb b/spec/ruby/core/binding/source_location_spec.rb
index d439c3e399..d1c8191ea8 100644
--- a/spec/ruby/core/binding/source_location_spec.rb
+++ b/spec/ruby/core/binding/source_location_spec.rb
@@ -6,4 +6,9 @@ describe "Binding#source_location" do
b = BindingSpecs::LocationMethod::TEST_BINDING
b.source_location.should == [BindingSpecs::LocationMethod::FILE_PATH, 4]
end
+
+ it "works for eval with a given line" do
+ b = eval('binding', nil, "foo", 100)
+ b.source_location.should == ["foo", 100]
+ end
end
diff --git a/spec/ruby/core/builtin_constants/builtin_constants_spec.rb b/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
index b0b86030e2..67b3339aa6 100644
--- a/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
+++ b/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
@@ -2,54 +2,148 @@ require_relative '../../spec_helper'
describe "RUBY_VERSION" do
it "is a String" do
- RUBY_VERSION.should be_kind_of(String)
+ RUBY_VERSION.should.is_a?(String)
+ end
+
+ it "is frozen" do
+ RUBY_VERSION.should.frozen?
end
end
describe "RUBY_PATCHLEVEL" do
it "is an Integer" do
- RUBY_PATCHLEVEL.should be_kind_of(Integer)
+ RUBY_PATCHLEVEL.should.is_a?(Integer)
end
end
describe "RUBY_COPYRIGHT" do
it "is a String" do
- RUBY_COPYRIGHT.should be_kind_of(String)
+ RUBY_COPYRIGHT.should.is_a?(String)
+ end
+
+ it "is frozen" do
+ RUBY_COPYRIGHT.should.frozen?
end
end
describe "RUBY_DESCRIPTION" do
it "is a String" do
- RUBY_DESCRIPTION.should be_kind_of(String)
+ RUBY_DESCRIPTION.should.is_a?(String)
+ end
+
+ it "is frozen" do
+ RUBY_DESCRIPTION.should.frozen?
end
end
describe "RUBY_ENGINE" do
it "is a String" do
- RUBY_ENGINE.should be_kind_of(String)
+ RUBY_ENGINE.should.is_a?(String)
+ end
+
+ it "is frozen" do
+ RUBY_ENGINE.should.frozen?
+ end
+end
+
+describe "RUBY_ENGINE_VERSION" do
+ it "is a String" do
+ RUBY_ENGINE_VERSION.should.is_a?(String)
+ end
+
+ it "is frozen" do
+ RUBY_ENGINE_VERSION.should.frozen?
end
end
describe "RUBY_PLATFORM" do
it "is a String" do
- RUBY_PLATFORM.should be_kind_of(String)
+ RUBY_PLATFORM.should.is_a?(String)
end
- platform_is :darwin do
- it 'ends with the build time kernel major version on darwin' do
- RUBY_PLATFORM.should =~ /-darwin\d+$/
- end
+ it "is frozen" do
+ RUBY_PLATFORM.should.frozen?
end
end
describe "RUBY_RELEASE_DATE" do
it "is a String" do
- RUBY_RELEASE_DATE.should be_kind_of(String)
+ RUBY_RELEASE_DATE.should.is_a?(String)
+ end
+
+ it "is frozen" do
+ RUBY_RELEASE_DATE.should.frozen?
end
end
describe "RUBY_REVISION" do
it "is a String" do
- RUBY_REVISION.should be_kind_of(String)
+ RUBY_REVISION.should.is_a?(String)
+ end
+
+ it "is frozen" do
+ RUBY_REVISION.should.frozen?
+ end
+end
+
+ruby_version_is "4.0" do
+ describe "Ruby" do
+ it "is a Module" do
+ Ruby.should.instance_of?(Module)
+ end
+ end
+
+ describe "Ruby::VERSION" do
+ it "is equal to RUBY_VERSION" do
+ Ruby::VERSION.should.equal?(RUBY_VERSION)
+ end
+ end
+
+ describe "RUBY::PATCHLEVEL" do
+ it "is equal to RUBY_PATCHLEVEL" do
+ Ruby::PATCHLEVEL.should.equal?(RUBY_PATCHLEVEL)
+ end
+ end
+
+ describe "Ruby::COPYRIGHT" do
+ it "is equal to RUBY_COPYRIGHT" do
+ Ruby::COPYRIGHT.should.equal?(RUBY_COPYRIGHT)
+ end
+ end
+
+ describe "Ruby::DESCRIPTION" do
+ it "is equal to RUBY_DESCRIPTION" do
+ Ruby::DESCRIPTION.should.equal?(RUBY_DESCRIPTION)
+ end
+ end
+
+ describe "Ruby::ENGINE" do
+ it "is equal to RUBY_ENGINE" do
+ Ruby::ENGINE.should.equal?(RUBY_ENGINE)
+ end
+ end
+
+ describe "Ruby::ENGINE_VERSION" do
+ it "is equal to RUBY_ENGINE_VERSION" do
+ Ruby::ENGINE_VERSION.should.equal?(RUBY_ENGINE_VERSION)
+ end
+ end
+
+ describe "Ruby::PLATFORM" do
+ it "is equal to RUBY_PLATFORM" do
+ Ruby::PLATFORM.should.equal?(RUBY_PLATFORM)
+ end
+ end
+
+ describe "Ruby::RELEASE_DATE" do
+ it "is equal to RUBY_RELEASE_DATE" do
+ Ruby::RELEASE_DATE.should.equal?(RUBY_RELEASE_DATE)
+ end
+ end
+
+ describe "Ruby::REVISION" do
+ it "is equal to RUBY_REVISION" do
+ Ruby::REVISION.should.equal?(RUBY_REVISION)
+ end
end
end
diff --git a/spec/ruby/core/class/allocate_spec.rb b/spec/ruby/core/class/allocate_spec.rb
index b39622e06a..b8950a678e 100644
--- a/spec/ruby/core/class/allocate_spec.rb
+++ b/spec/ruby/core/class/allocate_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Class#allocate" do
it "returns an instance of self" do
klass = Class.new
- klass.allocate.should be_an_instance_of(klass)
+ klass.allocate.should.instance_of?(klass)
end
it "returns a fully-formed instance of Module" do
@@ -16,7 +16,7 @@ describe "Class#allocate" do
klass = Class.allocate
-> do
klass.new
- end.should raise_error(Exception)
+ end.should.raise(Exception)
end
it "does not call initialize on the new instance" do
@@ -36,6 +36,6 @@ describe "Class#allocate" do
it "raises TypeError for #superclass" do
-> do
Class.allocate.superclass
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/class/attached_object_spec.rb b/spec/ruby/core/class/attached_object_spec.rb
new file mode 100644
index 0000000000..b75e61ca07
--- /dev/null
+++ b/spec/ruby/core/class/attached_object_spec.rb
@@ -0,0 +1,29 @@
+require_relative '../../spec_helper'
+
+describe "Class#attached_object" do
+ it "returns the object that is attached to a singleton class" do
+ a = Class.new
+
+ a_obj = a.new
+ a_obj.singleton_class.attached_object.should == a_obj
+ end
+
+ it "returns the class object that is attached to a class's singleton class" do
+ a = Class.new
+ singleton_class = (class << a; self; end)
+
+ singleton_class.attached_object.should == a
+ end
+
+ it "raises TypeError if the class is not a singleton class" do
+ a = Class.new
+
+ -> { a.attached_object }.should.raise(TypeError, /is not a singleton class/)
+ end
+
+ it "raises TypeError for special singleton classes" do
+ -> { nil.singleton_class.attached_object }.should.raise(TypeError, /[`']NilClass' is not a singleton class/)
+ -> { true.singleton_class.attached_object }.should.raise(TypeError, /[`']TrueClass' is not a singleton class/)
+ -> { false.singleton_class.attached_object }.should.raise(TypeError, /[`']FalseClass' is not a singleton class/)
+ end
+end
diff --git a/spec/ruby/core/class/dup_spec.rb b/spec/ruby/core/class/dup_spec.rb
index 701fd72e19..17c0171ceb 100644
--- a/spec/ruby/core/class/dup_spec.rb
+++ b/spec/ruby/core/class/dup_spec.rb
@@ -53,12 +53,17 @@ describe "Class#dup" do
it "sets the name from the class to nil if not assigned to a constant" do
copy = CoreClassSpecs::Record.dup
- copy.name.should be_nil
+ copy.name.should == nil
end
it "stores the new name if assigned to a constant" do
CoreClassSpecs::RecordCopy = CoreClassSpecs::Record.dup
CoreClassSpecs::RecordCopy.name.should == "CoreClassSpecs::RecordCopy"
+ ensure
+ CoreClassSpecs.send(:remove_const, :RecordCopy)
end
+ it "raises TypeError if called on BasicObject" do
+ -> { BasicObject.dup }.should.raise(TypeError, "can't copy the root class")
+ end
end
diff --git a/spec/ruby/core/class/inherited_spec.rb b/spec/ruby/core/class/inherited_spec.rb
index 8ef8bb8c35..c9acc740a1 100644
--- a/spec/ruby/core/class/inherited_spec.rb
+++ b/spec/ruby/core/class/inherited_spec.rb
@@ -92,10 +92,27 @@ describe "Class.inherited" do
end
class << top; private :inherited; end
- -> { Class.new(top) }.should_not raise_error
+ -> { Class.new(top) }.should_not.raise
class << top; protected :inherited; end
- -> { Class.new(top) }.should_not raise_error
+ -> { Class.new(top) }.should_not.raise
end
+ it "if the subclass is assigned to a constant, it is all set" do
+ ScratchPad.record []
+
+ parent = Class.new do
+ def self.inherited(subclass)
+ ScratchPad << defined?(self::C)
+ ScratchPad << const_defined?(:C)
+ ScratchPad << constants
+ ScratchPad << const_get(:C)
+ ScratchPad << subclass.name.match?(/\A#<Class:0x\w+>::C\z/)
+ end
+ end
+
+ class parent::C < parent; end
+
+ ScratchPad.recorded.should == ["constant", true, [:C], parent::C, true]
+ end
end
diff --git a/spec/ruby/core/class/initialize_spec.rb b/spec/ruby/core/class/initialize_spec.rb
index 6348758485..ab8f0a157e 100644
--- a/spec/ruby/core/class/initialize_spec.rb
+++ b/spec/ruby/core/class/initialize_spec.rb
@@ -2,24 +2,24 @@ require_relative '../../spec_helper'
describe "Class#initialize" do
it "is private" do
- Class.should have_private_method(:initialize)
+ Class.private_methods(false).should.include?(:initialize)
end
it "raises a TypeError when called on already initialized classes" do
->{
Integer.send :initialize
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
->{
Object.send :initialize
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
# See [redmine:2601]
it "raises a TypeError when called on BasicObject" do
->{
BasicObject.send :initialize
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
describe "when given the Class" do
@@ -28,7 +28,7 @@ describe "Class#initialize" do
end
it "raises a TypeError" do
- ->{@uninitialized.send(:initialize, Class)}.should raise_error(TypeError)
+ ->{@uninitialized.send(:initialize, Class)}.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/class/new_spec.rb b/spec/ruby/core/class/new_spec.rb
index 93152a83ee..111e31252e 100644
--- a/spec/ruby/core/class/new_spec.rb
+++ b/spec/ruby/core/class/new_spec.rb
@@ -7,7 +7,7 @@ describe "Class.new with a block given" do
klass = Class.new do
self_in_block = self
end
- self_in_block.should equal klass
+ self_in_block.should.equal? klass
end
it "uses the given block as the class' body" do
@@ -70,11 +70,11 @@ describe "Class.new" do
it "raises a TypeError if passed a metaclass" do
obj = mock("Class.new metaclass")
meta = obj.singleton_class
- -> { Class.new meta }.should raise_error(TypeError)
+ -> { Class.new meta }.should.raise(TypeError)
end
it "creates a class without a name" do
- Class.new.name.should be_nil
+ Class.new.name.should == nil
end
it "creates a class that can be given a name by assigning it to a constant" do
@@ -83,6 +83,8 @@ describe "Class.new" do
a = Class.new
MyClass::NestedClass = a
MyClass::NestedClass.name.should == "MyClass::NestedClass"
+ ensure
+ Object.send(:remove_const, :MyClass)
end
it "sets the new class' superclass to the given class" do
@@ -96,12 +98,12 @@ describe "Class.new" do
it "raises a TypeError when given a non-Class" do
error_msg = /superclass must be a.*Class/
- -> { Class.new("") }.should raise_error(TypeError, error_msg)
- -> { Class.new(1) }.should raise_error(TypeError, error_msg)
- -> { Class.new(:symbol) }.should raise_error(TypeError, error_msg)
- -> { Class.new(mock('o')) }.should raise_error(TypeError, error_msg)
- -> { Class.new(Module.new) }.should raise_error(TypeError, error_msg)
- -> { Class.new(BasicObject.new) }.should raise_error(TypeError, error_msg)
+ -> { Class.new("") }.should.raise(TypeError, error_msg)
+ -> { Class.new(1) }.should.raise(TypeError, error_msg)
+ -> { Class.new(:symbol) }.should.raise(TypeError, error_msg)
+ -> { Class.new(mock('o')) }.should.raise(TypeError, error_msg)
+ -> { Class.new(Module.new) }.should.raise(TypeError, error_msg)
+ -> { Class.new(BasicObject.new) }.should.raise(TypeError, error_msg)
end
end
@@ -139,8 +141,8 @@ describe "Class#new" do
end
instance = klass.new
- instance.should be_kind_of klass
- instance.class.should equal klass
+ instance.should.is_a? klass
+ instance.class.should.equal? klass
end
it "passes the block to #initialize" do
diff --git a/spec/ruby/core/class/subclasses_spec.rb b/spec/ruby/core/class/subclasses_spec.rb
index ddbcfb02c0..c3d7b07e12 100644
--- a/spec/ruby/core/class/subclasses_spec.rb
+++ b/spec/ruby/core/class/subclasses_spec.rb
@@ -1,38 +1,85 @@
require_relative '../../spec_helper'
require_relative '../module/fixtures/classes'
-ruby_version_is '3.1' do
- describe "Class#subclasses" do
- it "returns a list of classes directly inheriting from self" do
- assert_subclasses(ModuleSpecs::Parent, [ModuleSpecs::Child, ModuleSpecs::Child2])
- end
+describe "Class#subclasses" do
+ it "returns a list of classes directly inheriting from self" do
+ assert_subclasses(ModuleSpecs::Parent, [ModuleSpecs::Child, ModuleSpecs::Child2])
+ end
- it "does not return included modules" do
- parent = Class.new
- child = Class.new(parent)
- mod = Module.new
- parent.include(mod)
+ it "does not return included modules from the parent" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.include(mod)
- assert_subclasses(parent, [child])
- end
+ assert_subclasses(parent, [child])
+ end
- it "does not return singleton classes" do
- a = Class.new
+ it "does not return included modules from the child" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.include(mod)
- a_obj = a.new
- def a_obj.force_singleton_class
- 42
- end
+ assert_subclasses(parent, [child])
+ end
- a.subclasses.should_not include(a_obj.singleton_class)
- end
+ it "does not return prepended modules from the parent" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.prepend(mod)
+
+ assert_subclasses(parent, [child])
+ end
+
+ it "does not return prepended modules from the child" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ child.prepend(mod)
+
+ assert_subclasses(parent, [child])
+ end
- it "has 1 entry per module or class" do
- ModuleSpecs::Parent.subclasses.should == ModuleSpecs::Parent.subclasses.uniq
+ it "does not return singleton classes" do
+ a = Class.new
+
+ a_obj = a.new
+ def a_obj.force_singleton_class
+ 42
end
- def assert_subclasses(mod,subclasses)
- mod.subclasses.sort_by(&:inspect).should == subclasses.sort_by(&:inspect)
+ a.subclasses.should_not.include?(a_obj.singleton_class)
+ end
+
+ it "has 1 entry per module or class" do
+ ModuleSpecs::Parent.subclasses.should == ModuleSpecs::Parent.subclasses.uniq
+ end
+
+ it "works when creating subclasses concurrently" do
+ t = 16
+ n = 1000
+ go = false
+ superclass = Class.new
+
+ threads = t.times.map do
+ Thread.new do
+ Thread.pass until go
+ n.times.map do
+ Class.new(superclass)
+ end
+ end
end
+
+ go = true
+ classes = threads.map(&:value)
+
+ superclass.subclasses.size.should == t * n
+ superclass.subclasses.each { |c| c.should.is_a?(Class) }
+ end
+
+ def assert_subclasses(mod,subclasses)
+ mod.subclasses.sort_by(&:inspect).should == subclasses.sort_by(&:inspect)
end
end
diff --git a/spec/ruby/core/class/superclass_spec.rb b/spec/ruby/core/class/superclass_spec.rb
index 00579238a6..87d9b20490 100644
--- a/spec/ruby/core/class/superclass_spec.rb
+++ b/spec/ruby/core/class/superclass_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Class#superclass" do
it "returns the superclass of self" do
- BasicObject.superclass.should be_nil
+ BasicObject.superclass.should == nil
Object.superclass.should == BasicObject
Class.superclass.should == Module
Class.new.superclass.should == Object
diff --git a/spec/ruby/core/comparable/clamp_spec.rb b/spec/ruby/core/comparable/clamp_spec.rb
index 796d4a18c1..eb1dc1ff98 100644
--- a/spec/ruby/core/comparable/clamp_spec.rb
+++ b/spec/ruby/core/comparable/clamp_spec.rb
@@ -7,9 +7,9 @@ describe 'Comparable#clamp' do
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
c = ComparableSpecs::Weird.new(3)
- -> { c.clamp(two, one) }.should raise_error(ArgumentError)
+ -> { c.clamp(two, one) }.should.raise(ArgumentError)
one.should_receive(:<=>).any_number_of_times.and_return(nil)
- -> { c.clamp(one, two) }.should raise_error(ArgumentError)
+ -> { c.clamp(one, two) }.should.raise(ArgumentError)
end
it 'returns self if within the given parameters' do
@@ -18,18 +18,18 @@ describe 'Comparable#clamp' do
three = ComparableSpecs::WithOnlyCompareDefined.new(3)
c = ComparableSpecs::Weird.new(2)
- c.clamp(one, two).should equal(c)
- c.clamp(two, two).should equal(c)
- c.clamp(one, three).should equal(c)
- c.clamp(two, three).should equal(c)
+ c.clamp(one, two).should.equal?(c)
+ c.clamp(two, two).should.equal?(c)
+ c.clamp(one, three).should.equal?(c)
+ c.clamp(two, three).should.equal?(c)
end
- it 'returns the min parameter if smaller than it' do
+ it 'returns the min parameter if less than it' do
one = ComparableSpecs::WithOnlyCompareDefined.new(1)
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
c = ComparableSpecs::Weird.new(0)
- c.clamp(one, two).should equal(one)
+ c.clamp(one, two).should.equal?(one)
end
it 'returns the max parameter if greater than it' do
@@ -37,7 +37,40 @@ describe 'Comparable#clamp' do
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
c = ComparableSpecs::Weird.new(3)
- c.clamp(one, two).should equal(two)
+ c.clamp(one, two).should.equal?(two)
+ end
+
+ context 'max is nil' do
+ it 'returns min if less than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(0)
+ c.clamp(one, nil).should.equal?(one)
+ end
+
+ it 'always returns self if greater than min' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+ c.clamp(one, nil).should.equal?(c)
+ end
+ end
+
+ context 'min is nil' do
+ it 'returns max if greater than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+ c.clamp(nil, one).should.equal?(one)
+ end
+
+ it 'always returns self if less than max' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(0)
+ c.clamp(nil, one).should.equal?(c)
+ end
+ end
+
+ it 'always returns self when min is nil and max is nil' do
+ c = ComparableSpecs::Weird.new(1)
+ c.clamp(nil, nil).should.equal?(c)
end
it 'returns self if within the given range parameters' do
@@ -46,18 +79,18 @@ describe 'Comparable#clamp' do
three = ComparableSpecs::WithOnlyCompareDefined.new(3)
c = ComparableSpecs::Weird.new(2)
- c.clamp(one..two).should equal(c)
- c.clamp(two..two).should equal(c)
- c.clamp(one..three).should equal(c)
- c.clamp(two..three).should equal(c)
+ c.clamp(one..two).should.equal?(c)
+ c.clamp(two..two).should.equal?(c)
+ c.clamp(one..three).should.equal?(c)
+ c.clamp(two..three).should.equal?(c)
end
- it 'returns the minimum value of the range parameters if smaller than it' do
+ it 'returns the minimum value of the range parameters if less than it' do
one = ComparableSpecs::WithOnlyCompareDefined.new(1)
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
c = ComparableSpecs::Weird.new(0)
- c.clamp(one..two).should equal(one)
+ c.clamp(one..two).should.equal?(one)
end
it 'returns the maximum value of the range parameters if greater than it' do
@@ -65,7 +98,7 @@ describe 'Comparable#clamp' do
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
c = ComparableSpecs::Weird.new(3)
- c.clamp(one..two).should equal(two)
+ c.clamp(one..two).should.equal?(two)
end
it 'raises an Argument error if the range parameter is exclusive' do
@@ -73,6 +106,118 @@ describe 'Comparable#clamp' do
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
c = ComparableSpecs::Weird.new(3)
- -> { c.clamp(one...two) }.should raise_error(ArgumentError)
+ -> { c.clamp(one...two) }.should.raise(ArgumentError)
+ end
+
+ context 'with nil as the max argument' do
+ it 'returns min argument if less than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ zero = ComparableSpecs::WithOnlyCompareDefined.new(0)
+ c = ComparableSpecs::Weird.new(0)
+
+ c.clamp(one, nil).should.equal?(one)
+ c.clamp(zero, nil).should.equal?(c)
+ end
+
+ it 'always returns self if greater than min argument' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ two = ComparableSpecs::WithOnlyCompareDefined.new(2)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(one, nil).should.equal?(c)
+ c.clamp(two, nil).should.equal?(c)
+ end
+ end
+
+ context 'with endless range' do
+ it 'returns minimum value of the range parameters if less than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ zero = ComparableSpecs::WithOnlyCompareDefined.new(0)
+ c = ComparableSpecs::Weird.new(0)
+
+ c.clamp(one..).should.equal?(one)
+ c.clamp(zero..).should.equal?(c)
+ end
+
+ it 'always returns self if greater than minimum value of the range parameters' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ two = ComparableSpecs::WithOnlyCompareDefined.new(2)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(one..).should.equal?(c)
+ c.clamp(two..).should.equal?(c)
+ end
+
+ it 'works with exclusive range' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(one...).should.equal?(c)
+ end
+ end
+
+ context 'with nil as the min argument' do
+ it 'returns max argument if greater than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(nil, one).should.equal?(one)
+ end
+
+ it 'always returns self if less than max argument' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ zero = ComparableSpecs::WithOnlyCompareDefined.new(0)
+ c = ComparableSpecs::Weird.new(0)
+
+ c.clamp(nil, one).should.equal?(c)
+ c.clamp(nil, zero).should.equal?(c)
+ end
+ end
+
+ context 'with beginless range' do
+ it 'returns maximum value of the range parameters if greater than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(..one).should.equal?(one)
+ end
+
+ it 'always returns self if less than maximum value of the range parameters' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ zero = ComparableSpecs::WithOnlyCompareDefined.new(0)
+ c = ComparableSpecs::Weird.new(0)
+
+ c.clamp(..one).should.equal?(c)
+ c.clamp(..zero).should.equal?(c)
+ end
+
+ it 'raises an Argument error if the range parameter is exclusive' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(0)
+
+ -> { c.clamp(...one) }.should.raise(ArgumentError)
+ end
+ end
+
+ context 'with nil as the min and the max argument' do
+ it 'always returns self' do
+ c = ComparableSpecs::Weird.new(1)
+
+ c.clamp(nil, nil).should.equal?(c)
+ end
+ end
+
+ context 'with beginless-and-endless range' do
+ it 'always returns self' do
+ c = ComparableSpecs::Weird.new(1)
+
+ c.clamp(nil..nil).should.equal?(c)
+ end
+
+ it 'works with exclusive range' do
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(nil...nil).should.equal?(c)
+ end
end
end
diff --git a/spec/ruby/core/comparable/equal_value_spec.rb b/spec/ruby/core/comparable/equal_value_spec.rb
index ddcc03cb41..3af40d1c7e 100644
--- a/spec/ruby/core/comparable/equal_value_spec.rb
+++ b/spec/ruby/core/comparable/equal_value_spec.rb
@@ -39,7 +39,7 @@ describe "Comparable#==" do
end
it "returns false" do
- (a == b).should be_false
+ (a == b).should == false
end
end
@@ -49,7 +49,7 @@ describe "Comparable#==" do
end
it "raises an ArgumentError" do
- -> { (a == b) }.should raise_error(ArgumentError)
+ -> { (a == b) }.should.raise(ArgumentError)
end
end
@@ -60,7 +60,7 @@ describe "Comparable#==" do
end
it "lets it go through" do
- -> { (a == b) }.should raise_error(StandardError)
+ -> { (a == b) }.should.raise(StandardError)
end
end
@@ -71,13 +71,13 @@ describe "Comparable#==" do
end
it "lets it go through" do
- -> { (a == b) }.should raise_error(TypeError)
+ -> { (a == b) }.should.raise(TypeError)
end
end
it "lets it go through if it is not a StandardError" do
a.should_receive(:<=>).once.and_raise(Exception)
- -> { (a == b) }.should raise_error(Exception)
+ -> { (a == b) }.should.raise(Exception)
end
end
diff --git a/spec/ruby/core/comparable/fixtures/classes.rb b/spec/ruby/core/comparable/fixtures/classes.rb
index 4239a47d2f..2bdabbf014 100644
--- a/spec/ruby/core/comparable/fixtures/classes.rb
+++ b/spec/ruby/core/comparable/fixtures/classes.rb
@@ -7,6 +7,7 @@ module ComparableSpecs
end
def <=>(other)
+ return nil if other.nil?
self.value <=> other.value
end
end
diff --git a/spec/ruby/core/comparable/gt_spec.rb b/spec/ruby/core/comparable/gt_spec.rb
index 150e653dc7..cebb5464ad 100644
--- a/spec/ruby/core/comparable/gt_spec.rb
+++ b/spec/ruby/core/comparable/gt_spec.rb
@@ -38,6 +38,6 @@ describe "Comparable#>" do
b = ComparableSpecs::Weird.new(20)
a.should_receive(:<=>).any_number_of_times.and_return(nil)
- -> { (a > b) }.should raise_error(ArgumentError)
+ -> { (a > b) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/comparable/gte_spec.rb b/spec/ruby/core/comparable/gte_spec.rb
index 328f58c66c..16da81b3ea 100644
--- a/spec/ruby/core/comparable/gte_spec.rb
+++ b/spec/ruby/core/comparable/gte_spec.rb
@@ -42,6 +42,6 @@ describe "Comparable#>=" do
b = ComparableSpecs::Weird.new(20)
a.should_receive(:<=>).any_number_of_times.and_return(nil)
- -> { (a >= b) }.should raise_error(ArgumentError)
+ -> { (a >= b) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/comparable/lt_spec.rb b/spec/ruby/core/comparable/lt_spec.rb
index bca95f8d25..175646d0d7 100644
--- a/spec/ruby/core/comparable/lt_spec.rb
+++ b/spec/ruby/core/comparable/lt_spec.rb
@@ -38,12 +38,12 @@ describe "Comparable#<" do
b = ComparableSpecs::Weird.new(20)
a.should_receive(:<=>).any_number_of_times.and_return(nil)
- -> { (a < b) }.should raise_error(ArgumentError)
+ -> { (a < b) }.should.raise(ArgumentError)
end
it "raises an argument error with a message containing the value" do
- -> { ("foo" < 7) }.should raise_error(ArgumentError) { |e|
- e.message.should == "comparison of String with 7 failed"
+ -> { ("foo" < 7) }.should.raise(ArgumentError) { |e|
+ e.message.should.include? "String with 7 failed"
}
end
end
diff --git a/spec/ruby/core/comparable/lte_spec.rb b/spec/ruby/core/comparable/lte_spec.rb
index b5cb9cc4e7..8cbbd5ebb4 100644
--- a/spec/ruby/core/comparable/lte_spec.rb
+++ b/spec/ruby/core/comparable/lte_spec.rb
@@ -41,6 +41,6 @@ describe "Comparable#<=" do
b = ComparableSpecs::Weird.new(20)
a.should_receive(:<=>).any_number_of_times.and_return(nil)
- -> { (a <= b) }.should raise_error(ArgumentError)
+ -> { (a <= b) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/complex/abs_spec.rb b/spec/ruby/core/complex/abs_spec.rb
index 43912c517f..ed5aebb11d 100644
--- a/spec/ruby/core/complex/abs_spec.rb
+++ b/spec/ruby/core/complex/abs_spec.rb
@@ -1,6 +1,12 @@
require_relative '../../spec_helper'
-require_relative 'shared/abs'
describe "Complex#abs" do
- it_behaves_like :complex_abs, :abs
+ it "returns the modulus: |a + bi| = sqrt((a ^ 2) + (b ^ 2))" do
+ Complex(0, 0).abs.should == 0
+ Complex(3, 4).abs.should == 5 # well-known integer case
+ Complex(-3, 4).abs.should == 5
+ Complex(1, -1).abs.should be_close(Math.sqrt(2), TOLERANCE)
+ Complex(6.5, 0).abs.should be_close(6.5, TOLERANCE)
+ Complex(0, -7.2).abs.should be_close(7.2, TOLERANCE)
+ end
end
diff --git a/spec/ruby/core/complex/angle_spec.rb b/spec/ruby/core/complex/angle_spec.rb
index 4aa176956f..7551214d2b 100644
--- a/spec/ruby/core/complex/angle_spec.rb
+++ b/spec/ruby/core/complex/angle_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/arg'
describe "Complex#angle" do
- it_behaves_like :complex_arg, :angle
+ it "is an alias of Complex#arg" do
+ Complex.instance_method(:angle).should == Complex.instance_method(:arg)
+ end
end
diff --git a/spec/ruby/core/complex/arg_spec.rb b/spec/ruby/core/complex/arg_spec.rb
index 009f19429f..dd64102d77 100644
--- a/spec/ruby/core/complex/arg_spec.rb
+++ b/spec/ruby/core/complex/arg_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
-require_relative 'shared/arg'
describe "Complex#arg" do
- it_behaves_like :complex_arg, :arg
+ it "returns the argument -- i.e., the angle from (1, 0) in the complex plane" do
+ two_pi = 2 * Math::PI
+ (Complex(1, 0).arg % two_pi).should be_close(0, TOLERANCE)
+ (Complex(0, 2).arg % two_pi).should be_close(Math::PI * 0.5, TOLERANCE)
+ (Complex(-100, 0).arg % two_pi).should be_close(Math::PI, TOLERANCE)
+ (Complex(0, -75.3).arg % two_pi).should be_close(Math::PI * 1.5, TOLERANCE)
+ end
end
diff --git a/spec/ruby/core/complex/coerce_spec.rb b/spec/ruby/core/complex/coerce_spec.rb
index a30a6c1d5f..d4ea85a713 100644
--- a/spec/ruby/core/complex/coerce_spec.rb
+++ b/spec/ruby/core/complex/coerce_spec.rb
@@ -8,37 +8,37 @@ describe "Complex#coerce" do
it "returns an array containing other and self as Complex when other is an Integer" do
result = @one.coerce(2)
result.should == [2, 1]
- result.first.should be_kind_of(Complex)
- result.last.should be_kind_of(Complex)
+ result.first.should.is_a?(Complex)
+ result.last.should.is_a?(Complex)
end
it "returns an array containing other and self as Complex when other is a Float" do
result = @one.coerce(20.5)
result.should == [20.5, 1]
- result.first.should be_kind_of(Complex)
- result.last.should be_kind_of(Complex)
+ result.first.should.is_a?(Complex)
+ result.last.should.is_a?(Complex)
end
it "returns an array containing other and self as Complex when other is a Bignum" do
result = @one.coerce(4294967296)
result.should == [4294967296, 1]
- result.first.should be_kind_of(Complex)
- result.last.should be_kind_of(Complex)
+ result.first.should.is_a?(Complex)
+ result.last.should.is_a?(Complex)
end
it "returns an array containing other and self as Complex when other is a Rational" do
result = @one.coerce(Rational(5,6))
result.should == [Rational(5,6), 1]
- result.first.should be_kind_of(Complex)
- result.last.should be_kind_of(Complex)
+ result.first.should.is_a?(Complex)
+ result.last.should.is_a?(Complex)
end
it "returns an array containing other and self when other is a Complex" do
other = Complex(2)
result = @one.coerce(other)
result.should == [other, @one]
- result.first.should equal(other)
- result.last.should equal(@one)
+ result.first.should.equal?(other)
+ result.last.should.equal?(@one)
end
it "returns an array containing other as Complex and self when other is a Numeric which responds to #real? with true" do
@@ -46,25 +46,25 @@ describe "Complex#coerce" do
other.should_receive(:real?).any_number_of_times.and_return(true)
result = @one.coerce(other)
result.should == [other, @one]
- result.first.should eql(Complex(other))
- result.last.should equal(@one)
+ result.first.should.eql?(Complex(other))
+ result.last.should.equal?(@one)
end
it "raises TypeError when other is a Numeric which responds to #real? with false" do
other = mock_numeric('other')
other.should_receive(:real?).any_number_of_times.and_return(false)
- -> { @one.coerce(other) }.should raise_error(TypeError)
+ -> { @one.coerce(other) }.should.raise(TypeError)
end
it "raises a TypeError when other is a String" do
- -> { @one.coerce("20") }.should raise_error(TypeError)
+ -> { @one.coerce("20") }.should.raise(TypeError)
end
it "raises a TypeError when other is nil" do
- -> { @one.coerce(nil) }.should raise_error(TypeError)
+ -> { @one.coerce(nil) }.should.raise(TypeError)
end
it "raises a TypeError when other is false" do
- -> { @one.coerce(false) }.should raise_error(TypeError)
+ -> { @one.coerce(false) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/complex/comparison_spec.rb b/spec/ruby/core/complex/comparison_spec.rb
index 3a3142f234..3115f4e205 100644
--- a/spec/ruby/core/complex/comparison_spec.rb
+++ b/spec/ruby/core/complex/comparison_spec.rb
@@ -2,15 +2,15 @@ require_relative '../../spec_helper'
describe "Complex#<=>" do
it "returns nil if either self or argument has imaginary part" do
- (Complex(5, 1) <=> Complex(2)).should be_nil
- (Complex(1) <=> Complex(2, 1)).should be_nil
- (5 <=> Complex(2, 1)).should be_nil
+ (Complex(5, 1) <=> Complex(2)).should == nil
+ (Complex(1) <=> Complex(2, 1)).should == nil
+ (5 <=> Complex(2, 1)).should == nil
end
it "returns nil if argument is not numeric" do
- (Complex(5, 1) <=> "cmp").should be_nil
- (Complex(1) <=> "cmp").should be_nil
- (Complex(1) <=> Object.new).should be_nil
+ (Complex(5, 1) <=> "cmp").should == nil
+ (Complex(1) <=> "cmp").should == nil
+ (Complex(1) <=> Object.new).should == nil
end
it "returns 0, 1, or -1 if self and argument do not have imaginary part" do
diff --git a/spec/ruby/core/complex/conj_spec.rb b/spec/ruby/core/complex/conj_spec.rb
index 5e3bc1acb8..063c85faec 100644
--- a/spec/ruby/core/complex/conj_spec.rb
+++ b/spec/ruby/core/complex/conj_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/conjugate'
describe "Complex#conj" do
- it_behaves_like :complex_conjugate, :conj
+ it "is an alias of Complex#conjugate" do
+ Complex.instance_method(:conj).should == Complex.instance_method(:conjugate)
+ end
end
diff --git a/spec/ruby/core/complex/conjugate_spec.rb b/spec/ruby/core/complex/conjugate_spec.rb
index f658bab4da..256fe4b3be 100644
--- a/spec/ruby/core/complex/conjugate_spec.rb
+++ b/spec/ruby/core/complex/conjugate_spec.rb
@@ -1,6 +1,10 @@
require_relative '../../spec_helper'
-require_relative 'shared/conjugate'
describe "Complex#conjugate" do
- it_behaves_like :complex_conjugate, :conjugate
+ it "returns the complex conjugate: conj a + bi = a - bi" do
+ Complex(3, 5).conjugate.should == Complex(3, -5)
+ Complex(3, -5).conjugate.should == Complex(3, 5)
+ Complex(-3.0, 5.2).conjugate.should be_close(Complex(-3.0, -5.2), TOLERANCE)
+ Complex(3.0, -5.2).conjugate.should be_close(Complex(3.0, 5.2), TOLERANCE)
+ end
end
diff --git a/spec/ruby/core/complex/constants_spec.rb b/spec/ruby/core/complex/constants_spec.rb
index 50303de16c..200e97731a 100644
--- a/spec/ruby/core/complex/constants_spec.rb
+++ b/spec/ruby/core/complex/constants_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../spec_helper'
describe "Complex::I" do
it "is Complex(0, 1)" do
- Complex::I.should eql(Complex(0, 1))
+ Complex::I.should.eql?(Complex(0, 1))
end
end
diff --git a/spec/ruby/core/complex/divide_spec.rb b/spec/ruby/core/complex/divide_spec.rb
index bebf862312..d5b4aa3885 100644
--- a/spec/ruby/core/complex/divide_spec.rb
+++ b/spec/ruby/core/complex/divide_spec.rb
@@ -1,6 +1,84 @@
require_relative '../../spec_helper'
-require_relative 'shared/divide'
describe "Complex#/" do
- it_behaves_like :complex_divide, :/
+ describe "with Complex" do
+ it "divides according to the usual rule for complex numbers" do
+ a = Complex((1 * 10) - (2 * 20), (1 * 20) + (2 * 10))
+ b = Complex(1, 2)
+ (a / b).should == Complex(10, 20)
+
+ c = Complex((1.5 * 100.2) - (2.1 * -30.3), (1.5 * -30.3) + (2.1 * 100.2))
+ d = Complex(1.5, 2.1)
+ # remember the floating-point arithmetic
+ (c / d).should be_close(Complex(100.2, -30.3), TOLERANCE)
+ end
+ end
+
+ describe "with Fixnum" do
+ it "divides both parts of the Complex number" do
+ (Complex(20, 40) / 2).should == Complex(10, 20)
+ (Complex(30, 30) / 10).should == Complex(3, 3)
+ end
+
+ it "raises a ZeroDivisionError when given zero" do
+ -> { Complex(20, 40) / 0 }.should.raise(ZeroDivisionError)
+ end
+
+ it "produces Rational parts" do
+ (Complex(5, 9) / 2).should.eql?(Complex(Rational(5,2), Rational(9,2)))
+ end
+ end
+
+ describe "with Bignum" do
+ it "divides both parts of the Complex number" do
+ (Complex(20, 40) / 2).should == Complex(10, 20)
+ (Complex(15, 16) / 2.0).should be_close(Complex(7.5, 8), TOLERANCE)
+ end
+ end
+
+ describe "with Float" do
+ it "divides both parts of the Complex number" do
+ (Complex(3, 9) / 1.5).should == Complex(2, 6)
+ (Complex(15, 16) / 2.0).should be_close(Complex(7.5, 8), TOLERANCE)
+ end
+
+ it "returns Complex(Infinity, Infinity) when given zero" do
+ (Complex(20, 40) / 0.0).real.infinite?.should == 1
+ (Complex(20, 40) / 0.0).imag.infinite?.should == 1
+ (Complex(-20, 40) / 0.0).real.infinite?.should == -1
+ (Complex(-20, 40) / 0.0).imag.infinite?.should == 1
+ end
+ end
+
+ describe "with Object" do
+ it "tries to coerce self into other" do
+ value = Complex(3, 9)
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(value).and_return([4, 2])
+ (value / obj).should == 2
+ end
+ end
+
+ describe "with a Numeric which responds to #real? with true" do
+ it "returns Complex(real.quo(other), imag.quo(other))" do
+ other = mock_numeric('other')
+ real = mock_numeric('real')
+ imag = mock_numeric('imag')
+ other.should_receive(:real?).and_return(true)
+ real.should_receive(:quo).with(other).and_return(1)
+ imag.should_receive(:quo).with(other).and_return(2)
+ (Complex(real, imag) / other).should == Complex(1, 2)
+ end
+ end
+
+ describe "with a Numeric which responds to #real? with false" do
+ it "coerces the passed argument to Complex and divides the resulting elements" do
+ complex = Complex(3, 0)
+ other = mock_numeric('other')
+ other.should_receive(:real?).any_number_of_times.and_return(false)
+ other.should_receive(:coerce).with(complex).and_return([5, 2])
+ (complex / other).should.eql?(Rational(5, 2))
+ end
+ end
end
diff --git a/spec/ruby/core/complex/eql_spec.rb b/spec/ruby/core/complex/eql_spec.rb
index 9194efc074..2082a22feb 100644
--- a/spec/ruby/core/complex/eql_spec.rb
+++ b/spec/ruby/core/complex/eql_spec.rb
@@ -2,23 +2,23 @@ require_relative '../../spec_helper'
describe "Complex#eql?" do
it "returns false if other is not Complex" do
- Complex(1).eql?(1).should be_false
+ Complex(1).eql?(1).should == false
end
it "returns true when the respective parts are of the same classes and self == other" do
- Complex(1, 2).eql?(Complex(1, 2)).should be_true
+ Complex(1, 2).eql?(Complex(1, 2)).should == true
end
it "returns false when the real parts are of different classes" do
- Complex(1).eql?(Complex(1.0)).should be_false
+ Complex(1).eql?(Complex(1.0)).should == false
end
it "returns false when the imaginary parts are of different classes" do
- Complex(1, 2).eql?(Complex(1, 2.0)).should be_false
+ Complex(1, 2).eql?(Complex(1, 2.0)).should == false
end
it "returns false when self == other is false" do
- Complex(1, 2).eql?(Complex(2, 3)).should be_false
+ Complex(1, 2).eql?(Complex(2, 3)).should == false
end
it "does NOT send #eql? to real or imaginary parts" do
@@ -26,6 +26,6 @@ describe "Complex#eql?" do
imag = mock_numeric('imag')
real.should_not_receive(:eql?)
imag.should_not_receive(:eql?)
- Complex(real, imag).eql?(Complex(real, imag)).should be_true
+ Complex(real, imag).eql?(Complex(real, imag)).should == true
end
end
diff --git a/spec/ruby/core/complex/equal_value_spec.rb b/spec/ruby/core/complex/equal_value_spec.rb
index ad7236b1bd..b3562ff3fb 100644
--- a/spec/ruby/core/complex/equal_value_spec.rb
+++ b/spec/ruby/core/complex/equal_value_spec.rb
@@ -60,7 +60,7 @@ describe "Complex#==" do
obj = mock("Object")
obj.should_receive(:==).with(value).and_return(:expected)
- (value == obj).should_not be_false
+ (value == obj).should_not == false
end
end
@@ -73,11 +73,11 @@ describe "Complex#==" do
it "returns real == other when the imaginary part is zero" do
real = mock_numeric('real')
real.should_receive(:==).with(@other).and_return(true)
- (Complex(real, 0) == @other).should be_true
+ (Complex(real, 0) == @other).should == true
end
- it "returns false when when the imaginary part is not zero" do
- (Complex(3, 1) == @other).should be_false
+ it "returns false when the imaginary part is not zero" do
+ (Complex(3, 1) == @other).should == false
end
end
@@ -87,7 +87,7 @@ describe "Complex#==" do
other = mock_numeric('other')
other.should_receive(:real?).any_number_of_times.and_return(false)
other.should_receive(:==).with(complex).and_return(true)
- (complex == other).should be_true
+ (complex == other).should == true
end
end
end
diff --git a/spec/ruby/core/complex/exponent_spec.rb b/spec/ruby/core/complex/exponent_spec.rb
index 86f827aece..d0db0a40c2 100644
--- a/spec/ruby/core/complex/exponent_spec.rb
+++ b/spec/ruby/core/complex/exponent_spec.rb
@@ -3,13 +3,13 @@ require_relative '../../spec_helper'
describe "Complex#**" do
describe "with Integer 0" do
it "returns Complex(1)" do
- (Complex(3, 4) ** 0).should eql(Complex(1))
+ (Complex(3, 4) ** 0).should.eql?(Complex(1))
end
end
describe "with Float 0.0" do
it "returns Complex(1.0, 0.0)" do
- (Complex(3, 4) ** 0.0).should eql(Complex(1.0, 0.0))
+ (Complex(3, 4) ** 0.0).should.eql?(Complex(1.0, 0.0))
end
end
diff --git a/spec/ruby/core/complex/fdiv_spec.rb b/spec/ruby/core/complex/fdiv_spec.rb
index 68f7d1b309..fdcbc6a95d 100644
--- a/spec/ruby/core/complex/fdiv_spec.rb
+++ b/spec/ruby/core/complex/fdiv_spec.rb
@@ -2,44 +2,44 @@ require_relative '../../spec_helper'
describe "Complex#fdiv" do
it "accepts a numeric argument" do
- -> { Complex(20).fdiv(2) }.should_not raise_error(TypeError)
- -> { Complex(20).fdiv(2.0) }.should_not raise_error(TypeError)
- -> { Complex(20).fdiv(bignum_value) }.should_not raise_error(TypeError)
+ -> { Complex(20).fdiv(2) }.should_not.raise(TypeError)
+ -> { Complex(20).fdiv(2.0) }.should_not.raise(TypeError)
+ -> { Complex(20).fdiv(bignum_value) }.should_not.raise(TypeError)
end
it "accepts a negative numeric argument" do
- -> { Complex(20).fdiv(-2) }.should_not raise_error(TypeError)
- -> { Complex(20).fdiv(-2.0) }.should_not raise_error(TypeError)
- -> { Complex(20).fdiv(-bignum_value) }.should_not raise_error(TypeError)
+ -> { Complex(20).fdiv(-2) }.should_not.raise(TypeError)
+ -> { Complex(20).fdiv(-2.0) }.should_not.raise(TypeError)
+ -> { Complex(20).fdiv(-bignum_value) }.should_not.raise(TypeError)
end
it "raises a TypeError if passed a non-numeric argument" do
- -> { Complex(20).fdiv([]) }.should raise_error(TypeError)
- -> { Complex(20).fdiv(:sym) }.should raise_error(TypeError)
- -> { Complex(20).fdiv('s') }.should raise_error(TypeError)
+ -> { Complex(20).fdiv([]) }.should.raise(TypeError)
+ -> { Complex(20).fdiv(:sym) }.should.raise(TypeError)
+ -> { Complex(20).fdiv('s') }.should.raise(TypeError)
end
it "sets the real part to NaN if self's real part is NaN" do
- Complex(nan_value).fdiv(2).real.nan?.should be_true
+ Complex(nan_value).fdiv(2).real.nan?.should == true
end
it "sets the imaginary part to NaN if self's imaginary part is NaN" do
- Complex(2, nan_value).fdiv(2).imag.nan?.should be_true
+ Complex(2, nan_value).fdiv(2).imag.nan?.should == true
end
it "sets the real and imaginary part to NaN if self's real and imaginary parts are NaN" do
- Complex(nan_value, nan_value).fdiv(2).imag.nan?.should be_true
- Complex(nan_value, nan_value).fdiv(2).real.nan?.should be_true
+ Complex(nan_value, nan_value).fdiv(2).imag.nan?.should == true
+ Complex(nan_value, nan_value).fdiv(2).real.nan?.should == true
end
it "sets the real and imaginary part to NaN if self's real part and the argument are both NaN" do
- Complex(nan_value, 2).fdiv(nan_value).imag.nan?.should be_true
- Complex(nan_value, 2).fdiv(nan_value).real.nan?.should be_true
+ Complex(nan_value, 2).fdiv(nan_value).imag.nan?.should == true
+ Complex(nan_value, 2).fdiv(nan_value).real.nan?.should == true
end
it "sets the real and imaginary part to NaN if self's real part, self's imaginary part, and the argument are NaN" do
- Complex(nan_value, nan_value).fdiv(nan_value).imag.nan?.should be_true
- Complex(nan_value, nan_value).fdiv(nan_value).real.nan?.should be_true
+ Complex(nan_value, nan_value).fdiv(nan_value).imag.nan?.should == true
+ Complex(nan_value, nan_value).fdiv(nan_value).real.nan?.should == true
end
it "sets the real part to Infinity if self's real part is Infinity" do
@@ -58,8 +58,8 @@ describe "Complex#fdiv" do
end
it "sets the real part to NaN and the imaginary part to NaN if self's imaginary part, self's real part, and the argument are Infinity" do
- Complex(infinity_value, infinity_value).fdiv(infinity_value).real.nan?.should be_true
- Complex(infinity_value, infinity_value).fdiv(infinity_value).imag.nan?.should be_true
+ Complex(infinity_value, infinity_value).fdiv(infinity_value).real.nan?.should == true
+ Complex(infinity_value, infinity_value).fdiv(infinity_value).imag.nan?.should == true
end
end
@@ -71,7 +71,7 @@ describe "Complex#fdiv with no imaginary part" do
it "returns a Complex number" do
@numbers.each do |real|
@numbers.each do |other|
- Complex(real).fdiv(other).should be_an_instance_of(Complex)
+ Complex(real).fdiv(other).should.instance_of?(Complex)
end
end
end
@@ -103,7 +103,7 @@ describe "Complex#fdiv with an imaginary part" do
@numbers.each_with_index do |other,idx|
Complex(
real,@numbers[idx == 0 ? -1 : idx-1]
- ).fdiv(other).should be_an_instance_of(Complex)
+ ).fdiv(other).should.instance_of?(Complex)
end
end
end
diff --git a/spec/ruby/core/complex/imag_spec.rb b/spec/ruby/core/complex/imag_spec.rb
index 2bafd1ab54..225f168e78 100644
--- a/spec/ruby/core/complex/imag_spec.rb
+++ b/spec/ruby/core/complex/imag_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/image'
describe "Complex#imag" do
- it_behaves_like :complex_image, :imag
+ it "is an alias of Complex#imaginary" do
+ Complex.instance_method(:imag).should == Complex.instance_method(:imaginary)
+ end
end
diff --git a/spec/ruby/core/complex/imaginary_spec.rb b/spec/ruby/core/complex/imaginary_spec.rb
index a8a1bfea90..ac9284e934 100644
--- a/spec/ruby/core/complex/imaginary_spec.rb
+++ b/spec/ruby/core/complex/imaginary_spec.rb
@@ -1,6 +1,10 @@
require_relative '../../spec_helper'
-require_relative 'shared/image'
describe "Complex#imaginary" do
- it_behaves_like :complex_image, :imaginary
+ it "returns the imaginary part of self" do
+ Complex(1, 0).imaginary.should == 0
+ Complex(2, 1).imaginary.should == 1
+ Complex(6.7, 8.9).imaginary.should == 8.9
+ Complex(1, bignum_value).imaginary.should == bignum_value
+ end
end
diff --git a/spec/ruby/core/complex/inspect_spec.rb b/spec/ruby/core/complex/inspect_spec.rb
index 71aabde5be..045be94b22 100644
--- a/spec/ruby/core/complex/inspect_spec.rb
+++ b/spec/ruby/core/complex/inspect_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative '../numeric/fixtures/classes'
describe "Complex#inspect" do
it "returns (${real}+${image}i) for positive imaginary parts" do
@@ -13,4 +14,24 @@ describe "Complex#inspect" do
Complex(-1, -4).inspect.should == "(-1-4i)"
Complex(-7, -6.7).inspect.should == "(-7-6.7i)"
end
+
+ it "calls #inspect on real and imaginary" do
+ real = NumericSpecs::Subclass.new
+ # + because of https://bugs.ruby-lang.org/issues/20337
+ real.should_receive(:inspect).and_return(+"1")
+ imaginary = NumericSpecs::Subclass.new
+ imaginary.should_receive(:inspect).and_return("2")
+ imaginary.should_receive(:<).any_number_of_times.and_return(false)
+ Complex(real, imaginary).inspect.should == "(1+2i)"
+ end
+
+ it "adds an `*' before the `i' if the last character of the imaginary part is not numeric" do
+ real = NumericSpecs::Subclass.new
+ # + because of https://bugs.ruby-lang.org/issues/20337
+ real.should_receive(:inspect).and_return(+"(1)")
+ imaginary = NumericSpecs::Subclass.new
+ imaginary.should_receive(:inspect).and_return("(2)")
+ imaginary.should_receive(:<).any_number_of_times.and_return(false)
+ Complex(real, imaginary).inspect.should == "((1)+(2)*i)"
+ end
end
diff --git a/spec/ruby/core/complex/integer_spec.rb b/spec/ruby/core/complex/integer_spec.rb
index 0957accb70..559bfbccfd 100644
--- a/spec/ruby/core/complex/integer_spec.rb
+++ b/spec/ruby/core/complex/integer_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Complex#integer?" do
it "returns false for a Complex with no imaginary part" do
- Complex(20).integer?.should be_false
+ Complex(20).integer?.should == false
end
it "returns false for a Complex with an imaginary part" do
- Complex(20,3).integer?.should be_false
+ Complex(20,3).integer?.should == false
end
end
diff --git a/spec/ruby/core/complex/magnitude_spec.rb b/spec/ruby/core/complex/magnitude_spec.rb
index 86f3b29868..6341b4eec8 100644
--- a/spec/ruby/core/complex/magnitude_spec.rb
+++ b/spec/ruby/core/complex/magnitude_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/abs'
describe "Complex#magnitude" do
- it_behaves_like :complex_abs, :magnitude
+ it "is an alias of Complex#abs" do
+ Complex.instance_method(:magnitude).should == Complex.instance_method(:abs)
+ end
end
diff --git a/spec/ruby/core/complex/marshal_dump_spec.rb b/spec/ruby/core/complex/marshal_dump_spec.rb
index 116899b0ad..201d55e9e5 100644
--- a/spec/ruby/core/complex/marshal_dump_spec.rb
+++ b/spec/ruby/core/complex/marshal_dump_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Complex#marshal_dump" do
it "is a private method" do
- Complex.should have_private_instance_method(:marshal_dump, false)
+ Complex.private_instance_methods(false).should.include?(:marshal_dump)
end
it "dumps real and imaginary parts" do
diff --git a/spec/ruby/core/complex/negative_spec.rb b/spec/ruby/core/complex/negative_spec.rb
index 62ab89c04a..566975b8e1 100644
--- a/spec/ruby/core/complex/negative_spec.rb
+++ b/spec/ruby/core/complex/negative_spec.rb
@@ -4,10 +4,10 @@ describe "Complex#negative?" do
it "is undefined" do
c = Complex(1)
- c.methods.should_not include(:negative?)
+ c.methods.should_not.include?(:negative?)
-> {
c.negative?
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
end
diff --git a/spec/ruby/core/complex/phase_spec.rb b/spec/ruby/core/complex/phase_spec.rb
index 89574bf533..2ab90989e1 100644
--- a/spec/ruby/core/complex/phase_spec.rb
+++ b/spec/ruby/core/complex/phase_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/arg'
describe "Complex#phase" do
- it_behaves_like :complex_arg, :phase
+ it "is an alias of Complex#arg" do
+ Complex.instance_method(:phase).should == Complex.instance_method(:arg)
+ end
end
diff --git a/spec/ruby/core/complex/polar_spec.rb b/spec/ruby/core/complex/polar_spec.rb
index 2a5d8ebd69..824211fcd0 100644
--- a/spec/ruby/core/complex/polar_spec.rb
+++ b/spec/ruby/core/complex/polar_spec.rb
@@ -7,8 +7,22 @@ describe "Complex.polar" do
end
it "raises a TypeError when given non real arguments" do
- ->{ Complex.polar(nil) }.should raise_error(TypeError)
- ->{ Complex.polar(nil, nil) }.should raise_error(TypeError)
+ ->{ Complex.polar(nil) }.should.raise(TypeError)
+ ->{ Complex.polar(nil, nil) }.should.raise(TypeError)
+ end
+
+ it "computes the real values of the real & imaginary parts from the polar form" do
+ a = Complex.polar(1.0+0.0i, Math::PI/2+0.0i)
+ a.real.should be_close(0.0, TOLERANCE)
+ a.imag.should be_close(1.0, TOLERANCE)
+ a.real.real?.should == true
+ a.imag.real?.should == true
+
+ b = Complex.polar(1+0.0i)
+ b.real.should be_close(1.0, TOLERANCE)
+ b.imag.should be_close(0.0, TOLERANCE)
+ b.real.real?.should == true
+ b.imag.real?.should == true
end
end
diff --git a/spec/ruby/core/complex/positive_spec.rb b/spec/ruby/core/complex/positive_spec.rb
index f1bad8608c..d2fb256538 100644
--- a/spec/ruby/core/complex/positive_spec.rb
+++ b/spec/ruby/core/complex/positive_spec.rb
@@ -4,10 +4,10 @@ describe "Complex#positive?" do
it "is undefined" do
c = Complex(1)
- c.methods.should_not include(:positive?)
+ c.methods.should_not.include?(:positive?)
-> {
c.positive?
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
end
diff --git a/spec/ruby/core/complex/quo_spec.rb b/spec/ruby/core/complex/quo_spec.rb
index ee6fd65c79..be0a44d532 100644
--- a/spec/ruby/core/complex/quo_spec.rb
+++ b/spec/ruby/core/complex/quo_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'shared/divide'
describe "Complex#quo" do
- it_behaves_like :complex_divide, :quo
+ it "is an alias of Complex#/" do
+ Complex.instance_method(:quo).should == Complex.instance_method(:/)
+ end
end
diff --git a/spec/ruby/core/complex/rationalize_spec.rb b/spec/ruby/core/complex/rationalize_spec.rb
index 043b8ddf2a..d49bb52def 100644
--- a/spec/ruby/core/complex/rationalize_spec.rb
+++ b/spec/ruby/core/complex/rationalize_spec.rb
@@ -2,11 +2,11 @@ require_relative '../../spec_helper'
describe "Complex#rationalize" do
it "raises RangeError if self has non-zero imaginary part" do
- -> { Complex(1,5).rationalize }.should raise_error(RangeError)
+ -> { Complex(1,5).rationalize }.should.raise(RangeError)
end
it "raises RangeError if self has 0.0 imaginary part" do
- -> { Complex(1,0.0).rationalize }.should raise_error(RangeError)
+ -> { Complex(1,0.0).rationalize }.should.raise(RangeError)
end
it "returns a Rational if self has zero imaginary part" do
@@ -25,7 +25,7 @@ describe "Complex#rationalize" do
end
it "raises ArgumentError when passed more than one argument" do
- -> { Complex(1,0).rationalize(0.1, 0.1) }.should raise_error(ArgumentError)
- -> { Complex(1,0).rationalize(0.1, 0.1, 2) }.should raise_error(ArgumentError)
+ -> { Complex(1,0).rationalize(0.1, 0.1) }.should.raise(ArgumentError)
+ -> { Complex(1,0).rationalize(0.1, 0.1, 2) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/complex/real_spec.rb b/spec/ruby/core/complex/real_spec.rb
index 2ea791c005..41734b23f0 100644
--- a/spec/ruby/core/complex/real_spec.rb
+++ b/spec/ruby/core/complex/real_spec.rb
@@ -11,18 +11,18 @@ end
describe "Complex#real?" do
it "returns false if there is an imaginary part" do
- Complex(2,3).real?.should be_false
+ Complex(2,3).real?.should == false
end
it "returns false if there is not an imaginary part" do
- Complex(2).real?.should be_false
+ Complex(2).real?.should == false
end
it "returns false if the real part is Infinity" do
- Complex(infinity_value).real?.should be_false
+ Complex(infinity_value).real?.should == false
end
it "returns false if the real part is NaN" do
- Complex(nan_value).real?.should be_false
+ Complex(nan_value).real?.should == false
end
end
diff --git a/spec/ruby/core/complex/rect_spec.rb b/spec/ruby/core/complex/rect_spec.rb
index 9e95f3efc2..72f2bf9930 100644
--- a/spec/ruby/core/complex/rect_spec.rb
+++ b/spec/ruby/core/complex/rect_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'shared/rect'
describe "Complex#rect" do
- it_behaves_like :complex_rect, :rect
+ it "is an alias of Complex#rectangular" do
+ Complex.instance_method(:rect).should == Complex.instance_method(:rectangular)
+ end
end
describe "Complex.rect" do
- it_behaves_like :complex_rect_class, :rect
+ it "is an alias of Complex#rectangular" do
+ Complex.method(:rect).should == Complex.method(:rectangular)
+ end
end
diff --git a/spec/ruby/core/complex/rectangular_spec.rb b/spec/ruby/core/complex/rectangular_spec.rb
index d4b8ad9782..7789bf925e 100644
--- a/spec/ruby/core/complex/rectangular_spec.rb
+++ b/spec/ruby/core/complex/rectangular_spec.rb
@@ -1,10 +1,114 @@
require_relative '../../spec_helper'
-require_relative 'shared/rect'
describe "Complex#rectangular" do
- it_behaves_like :complex_rect, :rectangular
+ before :each do
+ @numbers = [
+ Complex(1),
+ Complex(0, 20),
+ Complex(0, 0),
+ Complex(0.0),
+ Complex(9999999**99),
+ Complex(-20),
+ Complex.polar(76, 10)
+ ]
+ end
+
+ it "returns an Array" do
+ @numbers.each do |number|
+ number.rectangular.should.instance_of?(Array)
+ end
+ end
+
+ it "returns a two-element Array" do
+ @numbers.each do |number|
+ number.rectangular.size.should == 2
+ end
+ end
+
+ it "returns the real part of self as the first element" do
+ @numbers.each do |number|
+ number.rectangular.first.should == number.real
+ end
+ end
+
+ it "returns the imaginary part of self as the last element" do
+ @numbers.each do |number|
+ number.rectangular.last.should == number.imaginary
+ end
+ end
+
+ it "raises an ArgumentError if given any arguments" do
+ @numbers.each do |number|
+ -> { number.rectangular(number) }.should.raise(ArgumentError)
+ end
+ end
end
describe "Complex.rectangular" do
- it_behaves_like :complex_rect_class, :rectangular
+ describe "passed a Numeric n which responds to #real? with true" do
+ it "returns a Complex with real part n and imaginary part 0" do
+ n = mock_numeric('n')
+ n.should_receive(:real?).any_number_of_times.and_return(true)
+ result = Complex.rectangular(n)
+ result.real.should == n
+ result.imag.should == 0
+ end
+ end
+
+ describe "passed a Numeric which responds to #real? with false" do
+ it "raises TypeError" do
+ n = mock_numeric('n')
+ n.should_receive(:real?).any_number_of_times.and_return(false)
+ -> { Complex.rectangular(n) }.should.raise(TypeError)
+ end
+ end
+
+ describe "passed Numerics n1 and n2 and at least one responds to #real? with false" do
+ [[false, false], [false, true], [true, false]].each do |r1, r2|
+ it "raises TypeError" do
+ n1 = mock_numeric('n1')
+ n2 = mock_numeric('n2')
+ n1.should_receive(:real?).any_number_of_times.and_return(r1)
+ n2.should_receive(:real?).any_number_of_times.and_return(r2)
+ -> { Complex.rectangular(n1, n2) }.should.raise(TypeError)
+ end
+ end
+ end
+
+ describe "passed Numerics n1 and n2 and both respond to #real? with true" do
+ it "returns a Complex with real part n1 and imaginary part n2" do
+ n1 = mock_numeric('n1')
+ n2 = mock_numeric('n2')
+ n1.should_receive(:real?).any_number_of_times.and_return(true)
+ n2.should_receive(:real?).any_number_of_times.and_return(true)
+ result = Complex.rectangular(n1, n2)
+ result.real.should == n1
+ result.imag.should == n2
+ end
+ end
+
+ describe "when passed a Complex" do
+ it "raises a TypeError when the imaginary part is not zero" do
+ -> {
+ Complex.rectangular(1.0+1i, 2)
+ }.should.raise(TypeError)
+
+ -> {
+ Complex.rectangular(1.0, 2i)
+ }.should.raise(TypeError)
+ end
+
+ it "ignores the imaginary part if it is zero" do
+ result = Complex.rectangular(1.0+0i, 2+0.0i)
+ result.real.should == 1.0
+ result.imag.should == 2
+ end
+ end
+
+ describe "passed a non-Numeric" do
+ it "raises TypeError" do
+ -> { Complex.rectangular(:sym) }.should.raise(TypeError)
+ -> { Complex.rectangular(0, :sym) }.should.raise(TypeError)
+ end
+ end
end
diff --git a/spec/ruby/core/complex/shared/abs.rb b/spec/ruby/core/complex/shared/abs.rb
deleted file mode 100644
index 2299479341..0000000000
--- a/spec/ruby/core/complex/shared/abs.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-describe :complex_abs, shared: true do
- it "returns the modulus: |a + bi| = sqrt((a ^ 2) + (b ^ 2))" do
- Complex(0, 0).send(@method).should == 0
- Complex(3, 4).send(@method).should == 5 # well-known integer case
- Complex(-3, 4).send(@method).should == 5
- Complex(1, -1).send(@method).should be_close(Math.sqrt(2), TOLERANCE)
- Complex(6.5, 0).send(@method).should be_close(6.5, TOLERANCE)
- Complex(0, -7.2).send(@method).should be_close(7.2, TOLERANCE)
- end
-end
diff --git a/spec/ruby/core/complex/shared/arg.rb b/spec/ruby/core/complex/shared/arg.rb
deleted file mode 100644
index c81f197433..0000000000
--- a/spec/ruby/core/complex/shared/arg.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-describe :complex_arg, shared: true do
- it "returns the argument -- i.e., the angle from (1, 0) in the complex plane" do
- two_pi = 2 * Math::PI
- (Complex(1, 0).send(@method) % two_pi).should be_close(0, TOLERANCE)
- (Complex(0, 2).send(@method) % two_pi).should be_close(Math::PI * 0.5, TOLERANCE)
- (Complex(-100, 0).send(@method) % two_pi).should be_close(Math::PI, TOLERANCE)
- (Complex(0, -75.3).send(@method) % two_pi).should be_close(Math::PI * 1.5, TOLERANCE)
- end
-end
diff --git a/spec/ruby/core/complex/shared/conjugate.rb b/spec/ruby/core/complex/shared/conjugate.rb
deleted file mode 100644
index d1ae47bcb6..0000000000
--- a/spec/ruby/core/complex/shared/conjugate.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-describe :complex_conjugate, shared: true do
- it "returns the complex conjugate: conj a + bi = a - bi" do
- Complex(3, 5).send(@method).should == Complex(3, -5)
- Complex(3, -5).send(@method).should == Complex(3, 5)
- Complex(-3.0, 5.2).send(@method).should be_close(Complex(-3.0, -5.2), TOLERANCE)
- Complex(3.0, -5.2).send(@method).should be_close(Complex(3.0, 5.2), TOLERANCE)
- end
-end
diff --git a/spec/ruby/core/complex/shared/divide.rb b/spec/ruby/core/complex/shared/divide.rb
deleted file mode 100644
index a60802c74c..0000000000
--- a/spec/ruby/core/complex/shared/divide.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-describe :complex_divide, shared: true do
- describe "with Complex" do
- it "divides according to the usual rule for complex numbers" do
- a = Complex((1 * 10) - (2 * 20), (1 * 20) + (2 * 10))
- b = Complex(1, 2)
- a.send(@method, b).should == Complex(10, 20)
-
- c = Complex((1.5 * 100.2) - (2.1 * -30.3), (1.5 * -30.3) + (2.1 * 100.2))
- d = Complex(1.5, 2.1)
- # remember the floating-point arithmetic
- c.send(@method, d).should be_close(Complex(100.2, -30.3), TOLERANCE)
- end
- end
-
- describe "with Fixnum" do
- it "divides both parts of the Complex number" do
- Complex(20, 40).send(@method, 2).should == Complex(10, 20)
- Complex(30, 30).send(@method, 10).should == Complex(3, 3)
- end
-
- it "raises a ZeroDivisionError when given zero" do
- -> { Complex(20, 40).send(@method, 0) }.should raise_error(ZeroDivisionError)
- end
-
- it "produces Rational parts" do
- Complex(5, 9).send(@method, 2).should eql(Complex(Rational(5,2), Rational(9,2)))
- end
- end
-
- describe "with Bignum" do
- it "divides both parts of the Complex number" do
- Complex(20, 40).send(@method, 2).should == Complex(10, 20)
- Complex(15, 16).send(@method, 2.0).should be_close(Complex(7.5, 8), TOLERANCE)
- end
- end
-
- describe "with Float" do
- it "divides both parts of the Complex number" do
- Complex(3, 9).send(@method, 1.5).should == Complex(2, 6)
- Complex(15, 16).send(@method, 2.0).should be_close(Complex(7.5, 8), TOLERANCE)
- end
-
- it "returns Complex(Infinity, Infinity) when given zero" do
- Complex(20, 40).send(@method, 0.0).real.infinite?.should == 1
- Complex(20, 40).send(@method, 0.0).imag.infinite?.should == 1
- Complex(-20, 40).send(@method, 0.0).real.infinite?.should == -1
- Complex(-20, 40).send(@method, 0.0).imag.infinite?.should == 1
- end
- end
-
- describe "with Object" do
- it "tries to coerce self into other" do
- value = Complex(3, 9)
-
- obj = mock("Object")
- obj.should_receive(:coerce).with(value).and_return([4, 2])
- value.send(@method, obj).should == 2
- end
- end
-
- describe "with a Numeric which responds to #real? with true" do
- it "returns Complex(real.quo(other), imag.quo(other))" do
- other = mock_numeric('other')
- real = mock_numeric('real')
- imag = mock_numeric('imag')
- other.should_receive(:real?).and_return(true)
- real.should_receive(:quo).with(other).and_return(1)
- imag.should_receive(:quo).with(other).and_return(2)
- Complex(real, imag).send(@method, other).should == Complex(1, 2)
- end
- end
-
- describe "with a Numeric which responds to #real? with false" do
- it "coerces the passed argument to Complex and divides the resulting elements" do
- complex = Complex(3, 0)
- other = mock_numeric('other')
- other.should_receive(:real?).any_number_of_times.and_return(false)
- other.should_receive(:coerce).with(complex).and_return([5, 2])
- complex.send(@method, other).should eql(Rational(5, 2))
- end
- end
-end
diff --git a/spec/ruby/core/complex/shared/image.rb b/spec/ruby/core/complex/shared/image.rb
deleted file mode 100644
index f839dbcaf9..0000000000
--- a/spec/ruby/core/complex/shared/image.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-describe :complex_image, shared: true do
- it "returns the imaginary part of self" do
- Complex(1, 0).send(@method).should == 0
- Complex(2, 1).send(@method).should == 1
- Complex(6.7, 8.9).send(@method).should == 8.9
- Complex(1, bignum_value).send(@method).should == bignum_value
- end
-end
diff --git a/spec/ruby/core/complex/shared/rect.rb b/spec/ruby/core/complex/shared/rect.rb
deleted file mode 100644
index 9f5de1ffeb..0000000000
--- a/spec/ruby/core/complex/shared/rect.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-describe :complex_rect, shared: true do
- before :each do
- @numbers = [
- Complex(1),
- Complex(0, 20),
- Complex(0, 0),
- Complex(0.0),
- Complex(9999999**99),
- Complex(-20),
- Complex.polar(76, 10)
- ]
- end
-
- it "returns an Array" do
- @numbers.each do |number|
- number.send(@method).should be_an_instance_of(Array)
- end
- end
-
- it "returns a two-element Array" do
- @numbers.each do |number|
- number.send(@method).size.should == 2
- end
- end
-
- it "returns the real part of self as the first element" do
- @numbers.each do |number|
- number.send(@method).first.should == number.real
- end
- end
-
- it "returns the imaginary part of self as the last element" do
- @numbers.each do |number|
- number.send(@method).last.should == number.imaginary
- end
- end
-
- it "raises an ArgumentError if given any arguments" do
- @numbers.each do |number|
- -> { number.send(@method, number) }.should raise_error(ArgumentError)
- end
- end
-end
-
-describe :complex_rect_class, shared: true do
- describe "passed a Numeric n which responds to #real? with true" do
- it "returns a Complex with real part n and imaginary part 0" do
- n = mock_numeric('n')
- n.should_receive(:real?).any_number_of_times.and_return(true)
- result = Complex.send(@method, n)
- result.real.should == n
- result.imag.should == 0
- end
- end
-
- describe "passed a Numeric which responds to #real? with false" do
- it "raises TypeError" do
- n = mock_numeric('n')
- n.should_receive(:real?).any_number_of_times.and_return(false)
- -> { Complex.send(@method, n) }.should raise_error(TypeError)
- end
- end
-
- describe "passed Numerics n1 and n2 and at least one responds to #real? with false" do
- [[false, false], [false, true], [true, false]].each do |r1, r2|
- it "raises TypeError" do
- n1 = mock_numeric('n1')
- n2 = mock_numeric('n2')
- n1.should_receive(:real?).any_number_of_times.and_return(r1)
- n2.should_receive(:real?).any_number_of_times.and_return(r2)
- -> { Complex.send(@method, n1, n2) }.should raise_error(TypeError)
- end
- end
- end
-
- describe "passed Numerics n1 and n2 and both respond to #real? with true" do
- it "returns a Complex with real part n1 and imaginary part n2" do
- n1 = mock_numeric('n1')
- n2 = mock_numeric('n2')
- n1.should_receive(:real?).any_number_of_times.and_return(true)
- n2.should_receive(:real?).any_number_of_times.and_return(true)
- result = Complex.send(@method, n1, n2)
- result.real.should == n1
- result.imag.should == n2
- end
- end
-
- describe "passed a non-Numeric" do
- it "raises TypeError" do
- -> { Complex.send(@method, :sym) }.should raise_error(TypeError)
- -> { Complex.send(@method, 0, :sym) }.should raise_error(TypeError)
- end
- end
-end
diff --git a/spec/ruby/core/complex/to_c_spec.rb b/spec/ruby/core/complex/to_c_spec.rb
index 5ce01d9d4e..cd7195556c 100644
--- a/spec/ruby/core/complex/to_c_spec.rb
+++ b/spec/ruby/core/complex/to_c_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Complex#to_c" do
it "returns self" do
value = Complex(1, 5)
- value.to_c.should equal(value)
+ value.to_c.should.equal?(value)
end
it 'returns the same value' do
diff --git a/spec/ruby/core/complex/to_f_spec.rb b/spec/ruby/core/complex/to_f_spec.rb
index b53471c1fc..9f3265cdb9 100644
--- a/spec/ruby/core/complex/to_f_spec.rb
+++ b/spec/ruby/core/complex/to_f_spec.rb
@@ -29,13 +29,13 @@ describe "Complex#to_f" do
describe "when the imaginary part is non-zero" do
it "raises RangeError" do
- -> { Complex(0, 1).to_f }.should raise_error(RangeError)
+ -> { Complex(0, 1).to_f }.should.raise(RangeError)
end
end
describe "when the imaginary part is Float 0.0" do
it "raises RangeError" do
- -> { Complex(0, 0.0).to_f }.should raise_error(RangeError)
+ -> { Complex(0, 0.0).to_f }.should.raise(RangeError)
end
end
end
diff --git a/spec/ruby/core/complex/to_i_spec.rb b/spec/ruby/core/complex/to_i_spec.rb
index 1e78f5ec0e..9149ffbbaa 100644
--- a/spec/ruby/core/complex/to_i_spec.rb
+++ b/spec/ruby/core/complex/to_i_spec.rb
@@ -29,13 +29,13 @@ describe "Complex#to_i" do
describe "when the imaginary part is non-zero" do
it "raises RangeError" do
- -> { Complex(0, 1).to_i }.should raise_error(RangeError)
+ -> { Complex(0, 1).to_i }.should.raise(RangeError)
end
end
describe "when the imaginary part is Float 0.0" do
it "raises RangeError" do
- -> { Complex(0, 0.0).to_i }.should raise_error(RangeError)
+ -> { Complex(0, 0.0).to_i }.should.raise(RangeError)
end
end
end
diff --git a/spec/ruby/core/complex/to_r_spec.rb b/spec/ruby/core/complex/to_r_spec.rb
index 4559921492..6587ae9e2e 100644
--- a/spec/ruby/core/complex/to_r_spec.rb
+++ b/spec/ruby/core/complex/to_r_spec.rb
@@ -29,13 +29,21 @@ describe "Complex#to_r" do
describe "when the imaginary part is non-zero" do
it "raises RangeError" do
- -> { Complex(0, 1).to_r }.should raise_error(RangeError)
+ -> { Complex(0, 1).to_r }.should.raise(RangeError)
end
end
describe "when the imaginary part is Float 0.0" do
- it "raises RangeError" do
- -> { Complex(0, 0.0).to_r }.should raise_error(RangeError)
+ ruby_version_is ''...'3.4' do
+ it "raises RangeError" do
+ -> { Complex(0, 0.0).to_r }.should.raise(RangeError)
+ end
+ end
+
+ ruby_version_is '3.4' do
+ it "returns a Rational" do
+ Complex(0, 0.0).to_r.should == 0r
+ end
end
end
end
diff --git a/spec/ruby/core/complex/to_s_spec.rb b/spec/ruby/core/complex/to_s_spec.rb
index 989a7ae0b7..ceccffe470 100644
--- a/spec/ruby/core/complex/to_s_spec.rb
+++ b/spec/ruby/core/complex/to_s_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative '../numeric/fixtures/classes'
describe "Complex#to_s" do
describe "when self's real component is 0" do
@@ -41,4 +42,14 @@ describe "Complex#to_s" do
it "returns 1+NaN*i for Complex(1, NaN)" do
Complex(1, nan_value).to_s.should == "1+NaN*i"
end
+
+ it "treats real and imaginary parts as strings" do
+ real = NumericSpecs::Subclass.new
+ # + because of https://bugs.ruby-lang.org/issues/20337
+ real.should_receive(:to_s).and_return(+"1")
+ imaginary = NumericSpecs::Subclass.new
+ imaginary.should_receive(:to_s).and_return("2")
+ imaginary.should_receive(:<).any_number_of_times.and_return(false)
+ Complex(real, imaginary).to_s.should == "1+2i"
+ end
end
diff --git a/spec/ruby/core/conditionvariable/broadcast_spec.rb b/spec/ruby/core/conditionvariable/broadcast_spec.rb
index d88159df23..16c7b4cc8d 100644
--- a/spec/ruby/core/conditionvariable/broadcast_spec.rb
+++ b/spec/ruby/core/conditionvariable/broadcast_spec.rb
@@ -1,5 +1,4 @@
require_relative '../../spec_helper'
-require 'thread'
describe "ConditionVariable#broadcast" do
it "releases all threads waiting in line for this resource" do
@@ -25,7 +24,7 @@ describe "ConditionVariable#broadcast" do
# wait until all threads are sleeping (ie waiting)
Thread.pass until threads.all?(&:stop?)
- r2.should be_empty
+ r2.should.empty?
m.synchronize do
cv.broadcast
end
diff --git a/spec/ruby/core/conditionvariable/marshal_dump_spec.rb b/spec/ruby/core/conditionvariable/marshal_dump_spec.rb
index f951a13e28..594c178e88 100644
--- a/spec/ruby/core/conditionvariable/marshal_dump_spec.rb
+++ b/spec/ruby/core/conditionvariable/marshal_dump_spec.rb
@@ -1,9 +1,8 @@
require_relative '../../spec_helper'
-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/)
+ -> { cv.marshal_dump }.should.raise(TypeError, /can't dump/)
end
end
diff --git a/spec/ruby/core/conditionvariable/signal_spec.rb b/spec/ruby/core/conditionvariable/signal_spec.rb
index 86383073f1..3b266cf8c6 100644
--- a/spec/ruby/core/conditionvariable/signal_spec.rb
+++ b/spec/ruby/core/conditionvariable/signal_spec.rb
@@ -1,5 +1,4 @@
require_relative '../../spec_helper'
-require 'thread'
describe "ConditionVariable#signal" do
it "releases the first thread waiting in line for this resource" do
@@ -25,7 +24,7 @@ describe "ConditionVariable#signal" do
# wait until all threads are sleeping (ie waiting)
Thread.pass until threads.all?(&:stop?)
- r2.should be_empty
+ r2.should.empty?
100.times do |i|
m.synchronize do
cv.signal
diff --git a/spec/ruby/core/conditionvariable/wait_spec.rb b/spec/ruby/core/conditionvariable/wait_spec.rb
index 9a68c2b5a1..1af53a15a2 100644
--- a/spec/ruby/core/conditionvariable/wait_spec.rb
+++ b/spec/ruby/core/conditionvariable/wait_spec.rb
@@ -1,5 +1,4 @@
require_relative '../../spec_helper'
-require 'thread'
describe "ConditionVariable#wait" do
it "calls #sleep on the given object" do
@@ -164,7 +163,7 @@ describe "ConditionVariable#wait" do
# On TruffleRuby, this causes a safepoint which has interesting
# interactions with the ConditionVariable.
bt = t.backtrace
- bt.should be_kind_of(Array)
+ bt.should.is_a?(Array)
bt.size.should >= 2
}
end
diff --git a/spec/ruby/core/data/constants_spec.rb b/spec/ruby/core/data/constants_spec.rb
index 1d469f9237..ad0b1ddea7 100644
--- a/spec/ruby/core/data/constants_spec.rb
+++ b/spec/ruby/core/data/constants_spec.rb
@@ -1,23 +1,11 @@
require_relative '../../spec_helper'
-ruby_version_is ''...'3.0' do
- describe "Data" do
- it "is a subclass of Object" do
- suppress_warning do
- Data.superclass.should == Object
- end
- end
-
- it "is deprecated" do
- -> { Data }.should complain(/constant ::Data is deprecated/)
- end
+describe "Data" do
+ it "is a new constant" do
+ Data.superclass.should == Object
end
-end
-ruby_version_is '3.0' do
- describe "Data" do
- it "does not exist anymore" do
- Object.should_not have_constant(:Data)
- end
+ it "is not deprecated" do
+ -> { Data }.should_not complain
end
end
diff --git a/spec/ruby/core/data/deconstruct_keys_spec.rb b/spec/ruby/core/data/deconstruct_keys_spec.rb
new file mode 100644
index 0000000000..7e81f966ea
--- /dev/null
+++ b/spec/ruby/core/data/deconstruct_keys_spec.rb
@@ -0,0 +1,110 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#deconstruct_keys" do
+ it "returns a hash of attributes" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ end
+
+ it "requires one argument" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> {
+ d.deconstruct_keys
+ }.should.raise(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
+ end
+
+ it "returns only specified keys" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ d.deconstruct_keys([:x] ).should == {x: 1}
+ d.deconstruct_keys([] ).should == {}
+ end
+
+ it "accepts string attribute names" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2}
+ end
+
+ it "returns an empty hash when there are more keys than attributes" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:x, :y, :x]).should == {}
+ end
+
+ it "returns at first not existing attribute name" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:a, :x]).should == {}
+ d.deconstruct_keys([:x, :a]).should == {x: 1}
+ end
+
+ it "accepts nil argument and return all the attributes" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys(nil).should == {x: 1, y: 2}
+ end
+
+ ruby_version_is "4.0" do # https://bugs.ruby-lang.org/issues/21844
+ it "tries to convert a key with #to_str if index is not a String nor a Symbol, but responds to #to_str" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ key = mock("to_str")
+ key.should_receive(:to_str).and_return("y")
+
+ d.deconstruct_keys([key]).should == { "y" => 2 }
+ end
+
+ it "raise an error on argument position number" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> {
+ d.deconstruct_keys([0, 1])
+ }.should.raise(TypeError, "0 is not a symbol nor a string")
+ end
+
+ it "raises a TypeError if the conversion with #to_str does not return a String" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ key = mock("to_str")
+ key.should_receive(:to_str).and_return(0)
+
+ -> {
+ d.deconstruct_keys([key])
+ }.should raise_consistent_error(TypeError, /can't convert MockObject into String/)
+ end
+
+ it "raises TypeError if index is not a Symbol and not convertible to String" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> {
+ d.deconstruct_keys([0, []])
+ }.should.raise(TypeError, "0 is not a symbol nor a string")
+ end
+ end
+
+ it "raise TypeError if passed anything except nil or array" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> { d.deconstruct_keys('x') }.should.raise(TypeError, /expected Array or nil/)
+ -> { d.deconstruct_keys(1) }.should.raise(TypeError, /expected Array or nil/)
+ -> { d.deconstruct_keys(:x) }.should.raise(TypeError, /expected Array or nil/)
+ -> { d.deconstruct_keys({}) }.should.raise(TypeError, /expected Array or nil/)
+ end
+end
diff --git a/spec/ruby/core/data/deconstruct_spec.rb b/spec/ruby/core/data/deconstruct_spec.rb
new file mode 100644
index 0000000000..4ca0b87039
--- /dev/null
+++ b/spec/ruby/core/data/deconstruct_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#deconstruct" do
+ it "returns an array of attribute values" do
+ DataSpecs::Measure.new(42, "km").deconstruct.should == [42, "km"]
+ end
+end
diff --git a/spec/ruby/core/data/define_spec.rb b/spec/ruby/core/data/define_spec.rb
new file mode 100644
index 0000000000..c0b4671e39
--- /dev/null
+++ b/spec/ruby/core/data/define_spec.rb
@@ -0,0 +1,34 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data.define" do
+ it "accepts no arguments" do
+ empty_data = Data.define
+ empty_data.members.should == []
+ end
+
+ it "accepts symbols" do
+ movie = Data.define(:title, :year)
+ movie.members.should == [:title, :year]
+ end
+
+ it "accepts strings" do
+ movie = Data.define("title", "year")
+ movie.members.should == [:title, :year]
+ end
+
+ it "accepts a mix of strings and symbols" do
+ movie = Data.define("title", :year, "genre")
+ movie.members.should == [:title, :year, :genre]
+ end
+
+ it "accepts a block" do
+ movie = Data.define(:title, :year) do
+ def title_with_year
+ "#{title} (#{year})"
+ end
+ end
+ movie.members.should == [:title, :year]
+ movie.new("Matrix", 1999).title_with_year.should == "Matrix (1999)"
+ end
+end
diff --git a/spec/ruby/core/data/eql_spec.rb b/spec/ruby/core/data/eql_spec.rb
new file mode 100644
index 0000000000..6958d5de4a
--- /dev/null
+++ b/spec/ruby/core/data/eql_spec.rb
@@ -0,0 +1,63 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#eql?" do
+ it "returns true if the other is the same object" do
+ a = DataSpecs::Measure.new(42, "km")
+ a.should.eql?(a)
+ end
+
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "km")
+ a.should.eql?(b)
+ end
+
+ it "returns false if the other is a different object or has different fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "mi")
+ a.should_not.eql?(b)
+ end
+
+ it "returns false if other is of a different class" do
+ a = DataSpecs::Measure.new(42, "km")
+ klass = Data.define(*DataSpecs::Measure.members)
+ b = klass.new(42, "km")
+ a.should_not.eql?(b)
+ end
+
+ it "returns false if any corresponding elements are not equal with #eql?" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42.0, "mi")
+ a.should_not.eql?(b)
+ end
+
+ context "recursive structure" do
+ it "returns true the other is the same object" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ a.should.eql?(a)
+ end
+
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: 42, unit: b)
+
+ a.should.eql?(b)
+ end
+
+ it "returns false if any corresponding elements are not equal with #eql?" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: a, unit: "km")
+
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: b, unit: "mi")
+
+ a.should_not.eql?(b)
+ end
+ end
+end
diff --git a/spec/ruby/core/data/equal_value_spec.rb b/spec/ruby/core/data/equal_value_spec.rb
new file mode 100644
index 0000000000..d9a0dcff3e
--- /dev/null
+++ b/spec/ruby/core/data/equal_value_spec.rb
@@ -0,0 +1,63 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#==" do
+ it "returns true if the other is the same object" do
+ a = DataSpecs::Measure.new(42, "km")
+ a.should == a
+ end
+
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "km")
+ a.should == b
+ end
+
+ it "returns false if the other is a different object or has different fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "mi")
+ a.should_not == b
+ end
+
+ it "returns false if other is of a different class" do
+ a = DataSpecs::Measure.new(42, "km")
+ klass = Data.define(*DataSpecs::Measure.members)
+ b = klass.new(42, "km")
+ a.should_not == b
+ end
+
+ it "returns false if any corresponding elements are not equal with #==" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42.0, "mi")
+ a.should_not == b
+ end
+
+ context "recursive structure" do
+ it "returns true the other is the same object" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ a.should == a
+ end
+
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: 42, unit: b)
+
+ a.should == b
+ end
+
+ it "returns false if any corresponding elements are not equal with #==" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: a, unit: "km")
+
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: b, unit: "mi")
+
+ a.should_not == b
+ end
+ end
+end
diff --git a/spec/ruby/core/data/fixtures/classes.rb b/spec/ruby/core/data/fixtures/classes.rb
new file mode 100644
index 0000000000..147293ee45
--- /dev/null
+++ b/spec/ruby/core/data/fixtures/classes.rb
@@ -0,0 +1,41 @@
+module DataSpecs
+ if Data.respond_to?(:define)
+ Measure = Data.define(:amount, :unit)
+ Single = Data.define(:value)
+
+ class MeasureWithOverriddenName < Measure
+ def self.name
+ "A"
+ end
+ end
+
+ class SingleWithOverriddenName < Single
+ def self.name
+ "A"
+ end
+ end
+
+ class DataSubclass < Data; end
+
+ MeasureSubclass = Class.new(Measure) do
+ def initialize(amount:, unit:)
+ super
+ end
+ end
+
+ Empty = Data.define()
+
+ DataWithOverriddenInitialize = Data.define(:amount, :unit) do
+ def initialize(*rest, **kw)
+ super
+ ScratchPad.record [:initialize, rest, kw]
+ end
+ end
+
+ Area = Data.define(:width, :height, :area) do
+ def initialize(width:, height:)
+ super(width: width, height: height, area: width * height)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/data/hash_spec.rb b/spec/ruby/core/data/hash_spec.rb
new file mode 100644
index 0000000000..bab146c92e
--- /dev/null
+++ b/spec/ruby/core/data/hash_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#hash" do
+ it "returns the same integer for objects with the same content" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "km")
+ a.hash.should == b.hash
+ a.hash.should.instance_of?(Integer)
+ end
+
+ it "returns different hashes for objects with different values" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "ml")
+ a.hash.should_not == b.hash
+
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(13, "km")
+ a.hash.should_not == b.hash
+ end
+
+ it "returns different hashes for different classes" do
+ Data.define(:x).new(1).hash.should != Data.define(:x).new(1).hash
+ end
+end
diff --git a/spec/ruby/core/data/initialize_spec.rb b/spec/ruby/core/data/initialize_spec.rb
new file mode 100644
index 0000000000..0320ca880c
--- /dev/null
+++ b/spec/ruby/core/data/initialize_spec.rb
@@ -0,0 +1,204 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#initialize" do
+ context "with no members" do
+ ruby_bug "#21819", ""..."4.0.1" do
+ it "is frozen" do
+ data = Data.define
+
+ data.new.should.frozen?
+ end
+ end
+ end
+
+ it "accepts positional arguments" do
+ data = DataSpecs::Measure.new(42, "km")
+
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "accepts alternative positional arguments" do
+ data = DataSpecs::Measure[42, "km"]
+
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "accepts keyword arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "accepts alternative keyword arguments" do
+ data = DataSpecs::Measure[amount: 42, unit: "km"]
+
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "accepts String keyword arguments" do
+ data = DataSpecs::Measure.new("amount" => 42, "unit" => "km")
+
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "accepts the last entry when a keyword is given as both String and Symbol" do
+ data = DataSpecs::Single.new("value" => -1, value: 42)
+
+ data.value.should == 42
+ end
+
+ it "accepts positional arguments with empty keyword arguments" do
+ data = DataSpecs::Single.new(42, **{})
+
+ data.value.should == 42
+
+ data = DataSpecs::Measure.new(42, "km", **{})
+
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "raises ArgumentError if no arguments are given" do
+ -> {
+ DataSpecs::Measure.new
+ }.should.raise(ArgumentError) { |e|
+ e.message.should.include?("missing keywords: :amount, :unit")
+ }
+ end
+
+ it "raises ArgumentError if at least one argument is missing" do
+ -> {
+ DataSpecs::Measure.new(unit: "km")
+ }.should.raise(ArgumentError) { |e|
+ e.message.should.include?("missing keyword: :amount")
+ }
+ end
+
+ ruby_version_is "4.0" do # https://bugs.ruby-lang.org/issues/21844
+ it "raises ArgumentError if at least one argument is missing and other is provided as both String and Symbol" do
+ -> {
+ DataSpecs::Measure.new(unit: "km", "unit" => "km")
+ }.should.raise(ArgumentError) { |e|
+ e.message.should.include?("missing keyword: :amount")
+ }
+ end
+ end
+
+ it "raises ArgumentError if unknown keyword is given" do
+ -> {
+ DataSpecs::Measure.new(amount: 42, unit: "km", system: "metric")
+ }.should.raise(ArgumentError) { |e|
+ e.message.should.include?("unknown keyword: :system")
+ }
+ end
+
+ ruby_version_is "4.0" do # https://bugs.ruby-lang.org/issues/21844
+ it "raises ArgumentError if unknown keyword is given which is convertable to String" do
+ key = mock("to_str")
+ key.should_receive(:to_str).and_return("system")
+
+ -> {
+ DataSpecs::Measure.new(amount: 42, unit: "km", key => "metric")
+ }.should.raise(ArgumentError) { |e|
+ e.message.should.include?('unknown keyword: "system"')
+ }
+ end
+
+ it "raises TypeError when the keyword is not convertable to String" do
+ -> {
+ DataSpecs::Measure.new(1 => 2)
+ }.should.raise(TypeError) { |e|
+ e.message.should == "1 is not a symbol nor a string"
+ }
+ end
+
+ it "raises TypeError if the conversion with #to_str does not return a String" do
+ klass = Data.define(:x, :y)
+
+ key = mock("to_str")
+ key.should_receive(:to_str).and_return(0)
+
+ -> {
+ klass.new(key => 2)
+ }.should raise_consistent_error(TypeError, /can't convert MockObject into String/)
+ end
+ end
+
+ it "supports super from a subclass" do
+ ms = DataSpecs::MeasureSubclass.new(amount: 1, unit: "km")
+
+ ms.amount.should == 1
+ ms.unit.should == "km"
+ end
+
+ it "supports Data with no fields" do
+ -> { DataSpecs::Empty.new }.should_not.raise
+ end
+
+ it "can be overridden" do
+ ScratchPad.record []
+
+ measure_class = Data.define(:amount, :unit) do
+ def initialize(*, **)
+ super
+ ScratchPad << :initialize
+ end
+ end
+
+ measure_class.new(42, "m")
+ ScratchPad.recorded.should == [:initialize]
+ end
+
+ context "when it is overridden" do
+ it "is called with keyword arguments when given positional arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize.new(42, "m")
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
+ end
+
+ it "is called with keyword arguments when given keyword arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize.new(amount: 42, unit: "m")
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
+ end
+
+ it "is called with keyword arguments when given alternative positional arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize[42, "m"]
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
+ end
+
+ it "is called with keyword arguments when given alternative keyword arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize[amount: 42, unit: "m"]
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
+ end
+
+ it "accepts positional arguments with empty keyword arguments" do
+ data = DataSpecs::SingleWithOverriddenName.new(42, **{})
+
+ data.value.should == 42
+
+ data = DataSpecs::MeasureWithOverriddenName.new(42, "km", **{})
+
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ # See https://github.com/ruby/psych/pull/765
+ it "can be deserialized by calling Data.instance_method(:initialize)" do
+ d1 = DataSpecs::Area.new(width: 2, height: 3)
+ d1.area.should == 6
+
+ d2 = DataSpecs::Area.allocate
+ Data.instance_method(:initialize).bind_call(d2, **d1.to_h)
+ d2.should == d1
+ end
+ end
+end
diff --git a/spec/ruby/core/data/inspect_spec.rb b/spec/ruby/core/data/inspect_spec.rb
new file mode 100644
index 0000000000..6c97a719e3
--- /dev/null
+++ b/spec/ruby/core/data/inspect_spec.rb
@@ -0,0 +1,63 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#inspect" do
+ it "returns a string representation showing members and values" do
+ a = DataSpecs::Measure.new(42, "km")
+ a.inspect.should == '#<data DataSpecs::Measure amount=42, unit="km">'
+ end
+
+ it "returns a string representation without the class name for anonymous structs" do
+ Data.define(:a).new("").inspect.should == '#<data a="">'
+ end
+
+ it "returns a string representation without the class name for structs nested in anonymous classes" do
+ c = Class.new
+ c.class_eval <<~DOC
+ Foo = Data.define(:a)
+ DOC
+
+ c::Foo.new("").inspect.should == '#<data a="">'
+ end
+
+ it "returns a string representation without the class name for structs nested in anonymous modules" do
+ m = Module.new
+ m.class_eval <<~DOC
+ Foo = Data.define(:a)
+ DOC
+
+ m::Foo.new("").inspect.should == '#<data a="">'
+ end
+
+ it "does not call #name method" do
+ struct = DataSpecs::MeasureWithOverriddenName.new(42, "km")
+ struct.inspect.should == '#<data DataSpecs::MeasureWithOverriddenName amount=42, unit="km">'
+ end
+
+ it "does not call #name method when struct is anonymous" do
+ klass = Class.new(DataSpecs::Measure) do
+ def self.name
+ "A"
+ end
+ end
+ struct = klass.new(42, "km")
+ struct.inspect.should == '#<data amount=42, unit="km">'
+ end
+
+ context "recursive structure" do
+ it "returns string representation with recursive attribute replaced with ..." do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ a.inspect.should == "#<data DataSpecs::Measure amount=42, unit=#<data DataSpecs::Measure:...>>"
+ end
+
+ it "returns string representation with recursive attribute replaced with ... when an anonymous class" do
+ klass = Class.new(DataSpecs::Measure)
+ a = klass.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ a.inspect.should =~ /#<data amount=42, unit=#<data #<Class:0x.+?>:\.\.\.>>/
+ end
+ end
+end
diff --git a/spec/ruby/core/data/members_spec.rb b/spec/ruby/core/data/members_spec.rb
new file mode 100644
index 0000000000..457a90a0d6
--- /dev/null
+++ b/spec/ruby/core/data/members_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#members" do
+ it "returns an array of attribute names" do
+ measure = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ measure.members.should == [:amount, :unit]
+ end
+end
+
+describe "DataClass#members" do
+ it "returns an array of attribute names" do
+ DataSpecs::Measure.members.should == [:amount, :unit]
+ end
+
+ context "class inheriting Data" do
+ it "isn't available in a subclass" do
+ DataSpecs::DataSubclass.should_not.respond_to?(:members)
+ end
+ end
+end
diff --git a/spec/ruby/core/data/to_h_spec.rb b/spec/ruby/core/data/to_h_spec.rb
new file mode 100644
index 0000000000..41925cf3b2
--- /dev/null
+++ b/spec/ruby/core/data/to_h_spec.rb
@@ -0,0 +1,63 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#to_h" do
+ it "transforms the data object into a hash" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ data.to_h.should == { amount: 42, unit: 'km' }
+ end
+
+ context "with block" do
+ it "transforms [key, value] pairs returned by the block into a hash" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ data.to_h { |key, value| [value, key] }.should == { 42 => :amount, 'km' => :unit }
+ end
+
+ it "passes to a block each pair's key and value as separate arguments" do
+ ScratchPad.record []
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ data.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
+ ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
+
+ ScratchPad.record []
+ data.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
+ end
+
+ it "raises ArgumentError if block returns longer or shorter array" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ -> do
+ data.to_h { |k, v| [k.to_s, v*v, 1] }
+ end.should.raise(ArgumentError, /element has wrong array length/)
+
+ -> do
+ data.to_h { |k, v| [k] }
+ end.should.raise(ArgumentError, /element has wrong array length/)
+ end
+
+ it "raises TypeError if block returns something other than Array" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ -> do
+ data.to_h { |k, v| "not-array" }
+ end.should.raise(TypeError, /wrong element type String/)
+ end
+
+ it "coerces returned pair to Array with #to_ary" do
+ x = mock('x')
+ x.stub!(:to_ary).and_return([:b, 'b'])
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+
+ data.to_h { |k| x }.should == { :b => 'b' }
+ end
+
+ it "does not coerce returned pair to Array with #to_a" do
+ x = mock('x')
+ x.stub!(:to_a).and_return([:b, 'b'])
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+
+ -> do
+ data.to_h { |k| x }
+ end.should.raise(TypeError, /wrong element type MockObject/)
+ end
+ end
+end
diff --git a/spec/ruby/core/data/to_s_spec.rb b/spec/ruby/core/data/to_s_spec.rb
new file mode 100644
index 0000000000..a552e4659b
--- /dev/null
+++ b/spec/ruby/core/data/to_s_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#to_s" do
+ it "is an alias of Data#inspect" do
+ a = DataSpecs::Measure.new(42, "km")
+ a.method(:to_s).should == a.method(:inspect)
+ end
+end
diff --git a/spec/ruby/core/data/with_spec.rb b/spec/ruby/core/data/with_spec.rb
new file mode 100644
index 0000000000..b74df185c7
--- /dev/null
+++ b/spec/ruby/core/data/with_spec.rb
@@ -0,0 +1,55 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#with" do
+ it "returns self if given no arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data = data.with.should.equal?(data)
+ end
+
+ it "accepts keyword arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data = data.with(amount: 4, unit: "m")
+
+ data.amount.should == 4
+ data.unit.should == "m"
+ end
+
+ it "accepts String keyword arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data = data.with("amount" => 4, "unit" => "m")
+
+ data.amount.should == 4
+ data.unit.should == "m"
+ end
+
+ it "raises ArgumentError if no keyword arguments are given" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+
+ -> {
+ data.with(4, "m")
+ }.should.raise(ArgumentError, "wrong number of arguments (given 2, expected 0)")
+ end
+
+ it "does not depend on the Data.new method" do
+ subclass = Class.new(DataSpecs::Measure)
+ data = subclass.new(amount: 42, unit: "km")
+
+ def subclass.new(*)
+ raise "Data.new is called"
+ end
+
+ data_copy = data.with(unit: "m")
+ data_copy.amount.should == 42
+ data_copy.unit.should == "m"
+ end
+
+ it "calls #initialize" do
+ data = DataSpecs::DataWithOverriddenInitialize.new(42, "m")
+ ScratchPad.clear
+
+ data.with(amount: 0)
+
+ ScratchPad.recorded.should == [:initialize, [], {amount: 0, unit: "m"}]
+ end
+end
diff --git a/spec/ruby/core/dir/chdir_spec.rb b/spec/ruby/core/dir/chdir_spec.rb
index 729ac403e3..2dc598e2a9 100644
--- a/spec/ruby/core/dir/chdir_spec.rb
+++ b/spec/ruby/core/dir/chdir_spec.rb
@@ -19,14 +19,14 @@ describe "Dir.chdir" do
end
it "defaults to $HOME with no arguments" do
- if ENV['HOME']
- Dir.chdir
- current_dir = Dir.pwd
+ skip "$HOME not valid directory" unless ENV['HOME'] && File.directory?(ENV['HOME'])
- Dir.chdir(ENV['HOME'])
- home = Dir.pwd
- current_dir.should == home
- end
+ Dir.chdir
+ current_dir = Dir.pwd
+
+ Dir.chdir(ENV['HOME'])
+ home = Dir.pwd
+ current_dir.should == home
end
it "changes to the specified directory" do
@@ -70,6 +70,8 @@ describe "Dir.chdir" do
end
it "defaults to the home directory when given a block but no argument" do
+ skip "$HOME not valid directory" unless ENV['HOME'] && File.directory?(ENV['HOME'])
+
# Windows will return a path with forward slashes for ENV["HOME"] so we have
# to compare the route representations returned by Dir.chdir.
current_dir = ""
@@ -88,15 +90,15 @@ describe "Dir.chdir" do
end
it "raises an Errno::ENOENT if the directory does not exist" do
- -> { Dir.chdir DirSpecs.nonexistent }.should raise_error(Errno::ENOENT)
- -> { Dir.chdir(DirSpecs.nonexistent) { } }.should raise_error(Errno::ENOENT)
+ -> { Dir.chdir DirSpecs.nonexistent }.should.raise(Errno::ENOENT)
+ -> { Dir.chdir(DirSpecs.nonexistent) { } }.should.raise(Errno::ENOENT)
end
it "raises an Errno::ENOENT if the original directory no longer exists" do
- dir1 = tmp('/testdir1')
- dir2 = tmp('/testdir2')
- File.should_not.exist?(dir1)
- File.should_not.exist?(dir2)
+ dir1 = tmp('testdir1')
+ dir2 = tmp('testdir2')
+ Dir.should_not.exist?(dir1)
+ Dir.should_not.exist?(dir2)
Dir.mkdir dir1
Dir.mkdir dir2
begin
@@ -104,10 +106,10 @@ describe "Dir.chdir" do
Dir.chdir dir1 do
Dir.chdir(dir2) { Dir.unlink dir1 }
end
- }.should raise_error(Errno::ENOENT)
+ }.should.raise(Errno::ENOENT)
ensure
- Dir.unlink dir1 if File.exist?(dir1)
- Dir.unlink dir2 if File.exist?(dir2)
+ Dir.unlink dir1 if Dir.exist?(dir1)
+ Dir.unlink dir2 if Dir.exist?(dir2)
end
end
@@ -122,3 +124,95 @@ describe "Dir.chdir" do
Dir.pwd.should == @original
end
end
+
+describe "Dir#chdir" do
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
+
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
+
+ before :each do
+ @original = Dir.pwd
+ end
+
+ after :each do
+ Dir.chdir(@original)
+ end
+
+ it "changes the current working directory to self" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir.chdir
+ Dir.pwd.should == DirSpecs.mock_dir
+ ensure
+ dir.close
+ end
+
+ it "changes the current working directory to self for duration of the block when a block is given" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ pwd_in_block = nil
+
+ dir.chdir { pwd_in_block = Dir.pwd }
+
+ pwd_in_block.should == DirSpecs.mock_dir
+ Dir.pwd.should == @original
+ ensure
+ dir.close
+ end
+
+ it "returns 0 when successfully changing directory" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir.chdir.should == 0
+ ensure
+ dir.close
+ end
+
+ it "returns the value of the block when a block is given" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir.chdir { :block_value }.should == :block_value
+ ensure
+ dir.close
+ end
+
+ platform_is_not :windows do
+ it "does not raise an Errno::ENOENT if the original directory no longer exists" do
+ dir_name1 = tmp('testdir1')
+ dir_name2 = tmp('testdir2')
+ Dir.should_not.exist?(dir_name1)
+ Dir.should_not.exist?(dir_name2)
+ Dir.mkdir dir_name1
+ Dir.mkdir dir_name2
+
+ dir2 = Dir.new(dir_name2)
+
+ begin
+ Dir.chdir(dir_name1) do
+ dir2.chdir { Dir.unlink dir_name1 }
+ end
+ Dir.pwd.should == @original
+ ensure
+ Dir.unlink dir_name1 if Dir.exist?(dir_name1)
+ Dir.unlink dir_name2 if Dir.exist?(dir_name2)
+ end
+ ensure
+ dir2.close
+ end
+ end
+
+ it "always returns to the original directory when given a block" do
+ dir = Dir.new(DirSpecs.mock_dir)
+
+ begin
+ dir.chdir do
+ raise StandardError, "something bad happened"
+ end
+ rescue StandardError
+ end
+
+ Dir.pwd.should == @original
+ ensure
+ dir.close
+ end
+end
diff --git a/spec/ruby/core/dir/children_spec.rb b/spec/ruby/core/dir/children_spec.rb
index 03698cc246..6e6da1dd44 100644
--- a/spec/ruby/core/dir/children_spec.rb
+++ b/spec/ruby/core/dir/children_spec.rb
@@ -47,25 +47,25 @@ describe "Dir.children" do
encoding = Encoding.find("filesystem")
encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
platform_is_not :windows do
- children.should include("こんにちは.txt".force_encoding(encoding))
+ children.should.include?("こんにちは.txt".dup.force_encoding(encoding))
end
- children.first.encoding.should equal(Encoding.find("filesystem"))
+ children.first.encoding.should.equal?(Encoding.find("filesystem"))
end
it "returns children encoded with the specified encoding" do
dir = File.join(DirSpecs.mock_dir, 'special')
children = Dir.children(dir, encoding: "euc-jp").sort
- children.first.encoding.should equal(Encoding::EUC_JP)
+ children.first.encoding.should.equal?(Encoding::EUC_JP)
end
it "returns children transcoded to the default internal encoding" do
Encoding.default_internal = Encoding::EUC_KR
children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort
- children.first.encoding.should equal(Encoding::EUC_KR)
+ children.first.encoding.should.equal?(Encoding::EUC_KR)
end
it "raises a SystemCallError if called with a nonexistent directory" do
- -> { Dir.children DirSpecs.nonexistent }.should raise_error(SystemCallError)
+ -> { Dir.children DirSpecs.nonexistent }.should.raise(SystemCallError)
end
end
@@ -113,22 +113,35 @@ describe "Dir#children" do
encoding = Encoding.find("filesystem")
encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
platform_is_not :windows do
- children.should include("こんにちは.txt".force_encoding(encoding))
+ children.should.include?("こんにちは.txt".dup.force_encoding(encoding))
end
- children.first.encoding.should equal(Encoding.find("filesystem"))
+ children.first.encoding.should.equal?(Encoding.find("filesystem"))
end
it "returns children encoded with the specified encoding" do
path = File.join(DirSpecs.mock_dir, 'special')
@dir = Dir.new(path, encoding: "euc-jp")
children = @dir.children.sort
- children.first.encoding.should equal(Encoding::EUC_JP)
+ children.first.encoding.should.equal?(Encoding::EUC_JP)
end
it "returns children transcoded to the default internal encoding" do
Encoding.default_internal = Encoding::EUC_KR
@dir = Dir.new(File.join(DirSpecs.mock_dir, 'special'))
children = @dir.children.sort
- children.first.encoding.should equal(Encoding::EUC_KR)
+ children.first.encoding.should.equal?(Encoding::EUC_KR)
+ end
+
+ it "returns the same result when called repeatedly" do
+ @dir = Dir.open DirSpecs.mock_dir
+
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
end
end
diff --git a/spec/ruby/core/dir/chroot_spec.rb b/spec/ruby/core/dir/chroot_spec.rb
index a5ca8943fc..79ad9759b0 100644
--- a/spec/ruby/core/dir/chroot_spec.rb
+++ b/spec/ruby/core/dir/chroot_spec.rb
@@ -21,17 +21,17 @@ platform_is_not :windows do
end
it "raises an Errno::EPERM exception if the directory exists" do
- -> { Dir.chroot('.') }.should raise_error(Errno::EPERM)
+ -> { Dir.chroot('.') }.should.raise(Errno::EPERM)
end
it "raises a SystemCallError if the directory doesn't exist" do
- -> { Dir.chroot('xgwhwhsjai2222jg') }.should raise_error(SystemCallError)
+ -> { Dir.chroot('xgwhwhsjai2222jg') }.should.raise(SystemCallError)
end
it "calls #to_path on non-String argument" do
p = mock('path')
p.should_receive(:to_path).and_return('.')
- -> { Dir.chroot(p) }.should raise_error(Errno::EPERM)
+ -> { Dir.chroot(p) }.should.raise(Errno::EPERM)
end
end
end
diff --git a/spec/ruby/core/dir/close_spec.rb b/spec/ruby/core/dir/close_spec.rb
index 5fad5eecfb..9902d98934 100644
--- a/spec/ruby/core/dir/close_spec.rb
+++ b/spec/ruby/core/dir/close_spec.rb
@@ -11,9 +11,43 @@ describe "Dir#close" do
it "does not raise an IOError even if the Dir instance is closed" do
dir = Dir.open DirSpecs.mock_dir
- dir.close
- -> {
- dir.close
- }.should_not raise_error(IOError)
+ dir.close.should == nil
+ dir.close.should == nil
+
+ platform_is_not :windows do
+ -> { dir.fileno }.should.raise(IOError, /closed directory/)
+ end
+ end
+
+ it "returns nil" do
+ dir = Dir.open DirSpecs.mock_dir
+ dir.close.should == nil
+ end
+
+ ruby_version_is ''...'3.4' do
+ platform_is_not :windows do
+ it "does not raise an error even if the file descriptor is closed with another Dir instance" do
+ dir = Dir.open DirSpecs.mock_dir
+ dir_new = Dir.for_fd(dir.fileno)
+
+ dir.close
+ dir_new.close
+
+ -> { dir.fileno }.should.raise(IOError, /closed directory/)
+ -> { dir_new.fileno }.should.raise(IOError, /closed directory/)
+ end
+ end
+ end
+
+ ruby_version_is '3.4' do
+ platform_is_not :windows do
+ it "raises an error if the file descriptor is closed with another Dir instance" do
+ dir = Dir.open DirSpecs.mock_dir
+ dir_new = Dir.for_fd(dir.fileno)
+ dir.close
+
+ -> { dir_new.close }.should.raise(Errno::EBADF, 'Bad file descriptor - closedir')
+ end
+ end
end
end
diff --git a/spec/ruby/core/dir/each_child_spec.rb b/spec/ruby/core/dir/each_child_spec.rb
index 520186e79e..4d6575df39 100644
--- a/spec/ruby/core/dir/each_child_spec.rb
+++ b/spec/ruby/core/dir/each_child_spec.rb
@@ -36,12 +36,12 @@ describe "Dir.each_child" do
end
it "raises a SystemCallError if passed a nonexistent directory" do
- -> { Dir.each_child(DirSpecs.nonexistent) {} }.should raise_error(SystemCallError)
+ -> { Dir.each_child(DirSpecs.nonexistent) {} }.should.raise(SystemCallError)
end
describe "when no block is given" do
it "returns an Enumerator" do
- Dir.each_child(DirSpecs.mock_dir).should be_an_instance_of(Enumerator)
+ Dir.each_child(DirSpecs.mock_dir).should.instance_of?(Enumerator)
Dir.each_child(DirSpecs.mock_dir).to_a.sort.should == DirSpecs.expected_paths - %w[. ..]
end
@@ -86,11 +86,24 @@ describe "Dir#each_child" do
@dir.each_child { |f| f }.should == @dir
end
+ it "returns the same result when called repeatedly" do
+ @dir = Dir.open DirSpecs.mock_dir
+
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
+ end
+
describe "when no block is given" do
it "returns an Enumerator" do
@dir = Dir.new(DirSpecs.mock_dir)
- @dir.each_child.should be_an_instance_of(Enumerator)
+ @dir.each_child.should.instance_of?(Enumerator)
@dir.each_child.to_a.sort.should == DirSpecs.expected_paths - %w|. ..|
end
diff --git a/spec/ruby/core/dir/each_spec.rb b/spec/ruby/core/dir/each_spec.rb
index 8c69a7212b..e997e340b1 100644
--- a/spec/ruby/core/dir/each_spec.rb
+++ b/spec/ruby/core/dir/each_spec.rb
@@ -32,12 +32,23 @@ describe "Dir#each" do
@dir.each {}.should == @dir
@dir.read.should == nil
@dir.rewind
- ls.should include(@dir.read)
+ ls.should.include?(@dir.read)
+ end
+
+ it "returns the same result when called repeatedly" do
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
end
describe "when no block is given" do
it "returns an Enumerator" do
- @dir.each.should be_an_instance_of(Enumerator)
+ @dir.each.should.instance_of?(Enumerator)
@dir.each.to_a.sort.should == DirSpecs.expected_paths
end
diff --git a/spec/ruby/core/dir/empty_spec.rb b/spec/ruby/core/dir/empty_spec.rb
index 8cc8757798..3b6b2bac85 100644
--- a/spec/ruby/core/dir/empty_spec.rb
+++ b/spec/ruby/core/dir/empty_spec.rb
@@ -12,20 +12,20 @@ describe "Dir.empty?" do
it "returns true for empty directories" do
result = Dir.empty? @empty_dir
- result.should be_true
+ result.should == true
end
it "returns false for non-empty directories" do
result = Dir.empty? __dir__
- result.should be_false
+ result.should == false
end
it "returns false for a non-directory" do
result = Dir.empty? __FILE__
- result.should be_false
+ result.should == false
end
it "raises ENOENT for nonexistent directories" do
- -> { Dir.empty? tmp("nonexistent") }.should raise_error(Errno::ENOENT)
+ -> { Dir.empty? tmp("nonexistent") }.should.raise(Errno::ENOENT)
end
end
diff --git a/spec/ruby/core/dir/entries_spec.rb b/spec/ruby/core/dir/entries_spec.rb
index 91c30fccae..f3ca49b26d 100644
--- a/spec/ruby/core/dir/entries_spec.rb
+++ b/spec/ruby/core/dir/entries_spec.rb
@@ -47,24 +47,24 @@ describe "Dir.entries" do
encoding = Encoding.find("filesystem")
encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
platform_is_not :windows do
- entries.should include("こんにちは.txt".force_encoding(encoding))
+ entries.should.include?("こんにちは.txt".dup.force_encoding(encoding))
end
- entries.first.encoding.should equal(Encoding.find("filesystem"))
+ entries.first.encoding.should.equal?(Encoding.find("filesystem"))
end
it "returns entries encoded with the specified encoding" do
dir = File.join(DirSpecs.mock_dir, 'special')
entries = Dir.entries(dir, encoding: "euc-jp").sort
- entries.first.encoding.should equal(Encoding::EUC_JP)
+ entries.first.encoding.should.equal?(Encoding::EUC_JP)
end
it "returns entries transcoded to the default internal encoding" do
Encoding.default_internal = Encoding::EUC_KR
entries = Dir.entries(File.join(DirSpecs.mock_dir, 'special')).sort
- entries.first.encoding.should equal(Encoding::EUC_KR)
+ entries.first.encoding.should.equal?(Encoding::EUC_KR)
end
it "raises a SystemCallError if called with a nonexistent directory" do
- -> { Dir.entries DirSpecs.nonexistent }.should raise_error(SystemCallError)
+ -> { Dir.entries DirSpecs.nonexistent }.should.raise(SystemCallError)
end
end
diff --git a/spec/ruby/core/dir/exist_spec.rb b/spec/ruby/core/dir/exist_spec.rb
index 43987b0f32..05ad67dd03 100644
--- a/spec/ruby/core/dir/exist_spec.rb
+++ b/spec/ruby/core/dir/exist_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
-require_relative 'shared/exist'
describe "Dir.exist?" do
before :all do
@@ -11,5 +10,65 @@ describe "Dir.exist?" do
DirSpecs.delete_mock_dirs
end
- it_behaves_like :dir_exist, :exist?
+ it "returns true if the given directory exists" do
+ Dir.exist?(__dir__).should == true
+ end
+
+ it "returns true for '.'" do
+ Dir.exist?('.').should == true
+ end
+
+ it "returns true for '..'" do
+ Dir.exist?('..').should == true
+ end
+
+ it "understands non-ASCII paths" do
+ subdir = File.join(tmp("\u{9876}\u{665}"))
+ Dir.exist?(subdir).should == false
+ Dir.mkdir(subdir)
+ Dir.exist?(subdir).should == true
+ Dir.rmdir(subdir)
+ end
+
+ it "understands relative paths" do
+ Dir.exist?(__dir__ + '/../').should == true
+ end
+
+ it "returns false if the given directory doesn't exist" do
+ Dir.exist?('y26dg27n2nwjs8a/').should == false
+ end
+
+ it "doesn't require the name to have a trailing slash" do
+ dir = __dir__
+ dir.sub!(/\/$/,'')
+ Dir.exist?(dir).should == true
+ end
+
+ it "doesn't expand paths" do
+ skip "$HOME not valid directory" unless ENV['HOME'] && File.directory?(ENV['HOME'])
+ Dir.exist?(File.expand_path('~')).should == true
+ Dir.exist?('~').should == false
+ end
+
+ it "returns false if the argument exists but is a file" do
+ File.should.exist?(__FILE__)
+ Dir.exist?(__FILE__).should == false
+ end
+
+ it "doesn't set $! when file doesn't exist" do
+ Dir.exist?("/path/to/non/existent/dir")
+ $!.should == nil
+ end
+
+ it "calls #to_path on non String arguments" do
+ p = mock('path')
+ p.should_receive(:to_path).and_return(__dir__)
+ Dir.exist?(p)
+ end
+end
+
+describe "Dir.exists?" do
+ it "has been removed" do
+ Dir.should_not.respond_to?(:exists?)
+ end
end
diff --git a/spec/ruby/core/dir/fchdir_spec.rb b/spec/ruby/core/dir/fchdir_spec.rb
new file mode 100644
index 0000000000..bd1a92b05e
--- /dev/null
+++ b/spec/ruby/core/dir/fchdir_spec.rb
@@ -0,0 +1,71 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
+
+platform_is_not :windows do
+ describe "Dir.fchdir" do
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
+
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
+
+ before :each do
+ @original = Dir.pwd
+ end
+
+ after :each do
+ Dir.chdir(@original)
+ end
+
+ it "changes the current working directory to the directory specified by the integer file descriptor" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ Dir.fchdir dir.fileno
+ Dir.pwd.should == DirSpecs.mock_dir
+ ensure
+ dir.close
+ end
+
+ it "returns 0 when successfully changing directory" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ Dir.fchdir(dir.fileno).should == 0
+ ensure
+ dir.close
+ end
+
+ it "returns the value of the block when a block is given" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ Dir.fchdir(dir.fileno) { :block_value }.should == :block_value
+ ensure
+ dir.close
+ end
+
+ it "changes to the specified directory for the duration of the block" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ Dir.fchdir(dir.fileno) { Dir.pwd }.should == DirSpecs.mock_dir
+ Dir.pwd.should == @original
+ ensure
+ dir.close
+ end
+
+ it "raises a SystemCallError if the file descriptor given is not valid" do
+ -> { Dir.fchdir(-1) }.should.raise(SystemCallError, "Bad file descriptor - fchdir")
+ -> { Dir.fchdir(-1) { } }.should.raise(SystemCallError, "Bad file descriptor - fchdir")
+ end
+
+ it "raises a SystemCallError if the file descriptor given is not for a directory" do
+ -> { Dir.fchdir $stdout.fileno }.should.raise(SystemCallError, /(Not a directory|Invalid argument) - fchdir/)
+ -> { Dir.fchdir($stdout.fileno) { } }.should.raise(SystemCallError, /(Not a directory|Invalid argument) - fchdir/)
+ end
+ end
+end
+
+platform_is :windows do
+ describe "Dir.fchdir" do
+ it "raises NotImplementedError" do
+ -> { Dir.fchdir 1 }.should.raise(NotImplementedError)
+ -> { Dir.fchdir(1) { } }.should.raise(NotImplementedError)
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/fileno_spec.rb b/spec/ruby/core/dir/fileno_spec.rb
index bb84ef5378..3b563eb18f 100644
--- a/spec/ruby/core/dir/fileno_spec.rb
+++ b/spec/ruby/core/dir/fileno_spec.rb
@@ -27,11 +27,11 @@ describe "Dir#fileno" do
if has_dir_fileno
it "returns the file descriptor of the dir" do
- @dir.fileno.should be_kind_of(Integer)
+ @dir.fileno.should.is_a?(Integer)
end
else
it "raises an error when not implemented on the platform" do
- -> { @dir.fileno }.should raise_error(NotImplementedError)
+ -> { @dir.fileno }.should.raise(NotImplementedError)
end
end
end
diff --git a/spec/ruby/core/dir/fixtures/common.rb b/spec/ruby/core/dir/fixtures/common.rb
index a8d6e69c44..cfec91f68f 100644
--- a/spec/ruby/core/dir/fixtures/common.rb
+++ b/spec/ruby/core/dir/fixtures/common.rb
@@ -82,6 +82,7 @@ module DirSpecs
special/test{1}/file[1]
special/{}/special
+ special/test\ +()[]{}/hello_world.erb
]
platform_is_not :windows do
@@ -114,6 +115,7 @@ module DirSpecs
end
def self.create_mock_dirs
+ delete_mock_dirs
mock_dir_files.each do |name|
file = File.join mock_dir, name
mkdir_p File.dirname(file)
@@ -171,33 +173,31 @@ module DirSpecs
end
end
+ def self.expected_paths_with_type
+ [
+ [".", :directory],
+ ["..", :directory],
+ [".dotfile", :file],
+ [".dotsubdir", :directory],
+ ["brace", :directory],
+ ["deeply", :directory],
+ ["dir", :directory],
+ ["dir_filename_ordering", :file],
+ ["file_one.ext", :file],
+ ["file_two.ext", :file],
+ ["nested", :directory],
+ ["nondotfile", :file],
+ ["special", :directory],
+ ["subdir_one", :directory],
+ ["subdir_two", :directory],
+ ]
+ end
+
def self.expected_paths
- %w[
- .
- ..
- .dotfile
- .dotsubdir
- brace
- deeply
- dir
- dir_filename_ordering
- file_one.ext
- file_two.ext
- nested
- nondotfile
- special
- subdir_one
- subdir_two
- ]
+ expected_paths_with_type.map(&:first)
end
- if RUBY_VERSION > '3.1'
- def self.expected_glob_paths
- expected_paths - ['..']
- end
- else
- def self.expected_glob_paths
- expected_paths
- end
+ def self.expected_glob_paths
+ expected_paths - ['..']
end
end
diff --git a/spec/ruby/core/dir/for_fd_spec.rb b/spec/ruby/core/dir/for_fd_spec.rb
new file mode 100644
index 0000000000..bbc75e0f8f
--- /dev/null
+++ b/spec/ruby/core/dir/for_fd_spec.rb
@@ -0,0 +1,77 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
+
+quarantine! do # leads to "Errno::EBADF: Bad file descriptor - closedir" in DirSpecs.delete_mock_dirs
+platform_is_not :windows do
+ describe "Dir.for_fd" do
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
+
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
+
+ before :each do
+ @original = Dir.pwd
+ end
+
+ after :each do
+ Dir.chdir(@original)
+ end
+
+ it "returns a new Dir object representing the directory specified by the given integer directory file descriptor" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir_new = Dir.for_fd(dir.fileno)
+
+ dir_new.should.instance_of?(Dir)
+ dir_new.children.should == dir.children
+ dir_new.fileno.should == dir.fileno
+ ensure
+ dir.close
+ end
+
+ it "returns a new Dir object without associated path" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir_new = Dir.for_fd(dir.fileno)
+
+ dir_new.path.should == nil
+ ensure
+ dir.close
+ end
+
+ it "calls #to_int to convert a value to an Integer" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ obj = mock("fd")
+ obj.should_receive(:to_int).and_return(dir.fileno)
+
+ dir_new = Dir.for_fd(obj)
+ dir_new.fileno.should == dir.fileno
+ ensure
+ dir.close
+ end
+
+ it "raises TypeError when value cannot be converted to Integer" do
+ -> {
+ Dir.for_fd(nil)
+ }.should raise_consistent_error(TypeError, "no implicit conversion of nil into Integer")
+ end
+
+ it "raises a SystemCallError if the file descriptor given is not valid" do
+ -> { Dir.for_fd(-1) }.should.raise(SystemCallError, "Bad file descriptor - fdopendir")
+ end
+
+ it "raises a SystemCallError if the file descriptor given is not for a directory" do
+ -> { Dir.for_fd $stdout.fileno }.should.raise(SystemCallError, "Not a directory - fdopendir")
+ end
+ end
+end
+
+platform_is :windows do
+ describe "Dir.for_fd" do
+ it "raises NotImplementedError" do
+ -> { Dir.for_fd 1 }.should.raise(NotImplementedError)
+ end
+ end
+end
+end
diff --git a/spec/ruby/core/dir/foreach_spec.rb b/spec/ruby/core/dir/foreach_spec.rb
index 9cf34b1d71..2a2265a029 100644
--- a/spec/ruby/core/dir/foreach_spec.rb
+++ b/spec/ruby/core/dir/foreach_spec.rb
@@ -31,11 +31,11 @@ describe "Dir.foreach" do
end
it "raises a SystemCallError if passed a nonexistent directory" do
- -> { Dir.foreach(DirSpecs.nonexistent) {} }.should raise_error(SystemCallError)
+ -> { Dir.foreach(DirSpecs.nonexistent) {} }.should.raise(SystemCallError)
end
it "returns an Enumerator if no block given" do
- Dir.foreach(DirSpecs.mock_dir).should be_an_instance_of(Enumerator)
+ Dir.foreach(DirSpecs.mock_dir).should.instance_of?(Enumerator)
Dir.foreach(DirSpecs.mock_dir).to_a.sort.should == DirSpecs.expected_paths
end
@@ -53,7 +53,7 @@ describe "Dir.foreach" do
describe "when no block is given" do
it "returns an Enumerator" do
- Dir.foreach(DirSpecs.mock_dir).should be_an_instance_of(Enumerator)
+ Dir.foreach(DirSpecs.mock_dir).should.instance_of?(Enumerator)
Dir.foreach(DirSpecs.mock_dir).to_a.sort.should == DirSpecs.expected_paths
end
diff --git a/spec/ruby/core/dir/getwd_spec.rb b/spec/ruby/core/dir/getwd_spec.rb
index 132634347c..138481821f 100644
--- a/spec/ruby/core/dir/getwd_spec.rb
+++ b/spec/ruby/core/dir/getwd_spec.rb
@@ -1,15 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/common'
-require_relative 'shared/pwd'
describe "Dir.getwd" do
- before :all do
- DirSpecs.create_mock_dirs
+ it "is an alias of Dir.pwd" do
+ Dir.method(:getwd).should == Dir.method(:pwd)
end
-
- after :all do
- DirSpecs.delete_mock_dirs
- end
-
- it_behaves_like :dir_pwd, :getwd
end
diff --git a/spec/ruby/core/dir/glob_spec.rb b/spec/ruby/core/dir/glob_spec.rb
index 43dac73eee..9e81feb15f 100644
--- a/spec/ruby/core/dir/glob_spec.rb
+++ b/spec/ruby/core/dir/glob_spec.rb
@@ -79,6 +79,7 @@ describe "Dir.glob" do
nested/
nested/.dotsubir/
special/
+ special/test\ +()[]{}/
special/test{1}/
special/{}/
subdir_one/
@@ -88,31 +89,15 @@ describe "Dir.glob" do
Dir.glob('**/', File::FNM_DOTMATCH).sort.should == expected
end
- ruby_version_is ''...'3.1' do
- it "recursively matches files and directories in nested dot subdirectory with 'nested/**/*' from the current directory and option File::FNM_DOTMATCH" do
- expected = %w[
- nested/.
- nested/.dotsubir
- nested/.dotsubir/.
- nested/.dotsubir/.dotfile
- nested/.dotsubir/nondotfile
- ]
-
- Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort
- end
- end
-
- ruby_version_is '3.1' do
- it "recursively matches files and directories in nested dot subdirectory except . with 'nested/**/*' from the current directory and option File::FNM_DOTMATCH" do
- expected = %w[
- nested/.
- nested/.dotsubir
- nested/.dotsubir/.dotfile
- nested/.dotsubir/nondotfile
- ]
+ it "recursively matches files and directories in nested dot subdirectory except . with 'nested/**/*' from the current directory and option File::FNM_DOTMATCH" do
+ expected = %w[
+ nested/.
+ nested/.dotsubir
+ nested/.dotsubir/.dotfile
+ nested/.dotsubir/nondotfile
+ ]
- Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort
- end
+ Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort
end
# This is a separate case to check **/ coming after a constant
@@ -130,6 +115,7 @@ describe "Dir.glob" do
./nested/
./nested/.dotsubir/
./special/
+ ./special/test\ +()[]{}/
./special/test{1}/
./special/{}/
./subdir_one/
@@ -163,7 +149,7 @@ describe "Dir.glob" do
it "accepts a block and yields it with each elements" do
ary = []
ret = Dir.glob(["file_o*", "file_t*"]) { |t| ary << t }
- ret.should be_nil
+ ret.should == nil
ary.should == %w!file_one.ext file_two.ext!
end
@@ -180,6 +166,131 @@ describe "Dir.glob" do
Dir.glob('**/**/**').should_not.empty?
end
+ it "handles **/** with base keyword argument" do
+ Dir.glob('**/**', base: "dir").should == ["filename_ordering"]
+
+ expected = %w[
+ nested
+ nested/directory
+ nested/directory/structure
+ nested/directory/structure/bar
+ nested/directory/structure/baz
+ nested/directory/structure/file_one
+ nested/directory/structure/file_one.ext
+ nested/directory/structure/foo
+ nondotfile
+ ].sort
+
+ Dir.glob('**/**', base: "deeply").sort.should == expected
+ end
+
+ it "handles **/ with base keyword argument" do
+ expected = %w[
+ /
+ directory/
+ directory/structure/
+ ]
+ Dir.glob('**/', base: "deeply/nested").sort.should == expected
+ end
+
+ it "handles **/nondotfile with base keyword argument" do
+ expected = %w[
+ deeply/nondotfile
+ nondotfile
+ subdir_one/nondotfile
+ subdir_two/nondotfile
+ ]
+ Dir.glob('**/nondotfile', base: ".").sort.should == expected
+ end
+
+ it "handles **/nondotfile with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .dotsubdir/nondotfile
+ deeply/nondotfile
+ nested/.dotsubir/nondotfile
+ nondotfile
+ subdir_one/nondotfile
+ subdir_two/nondotfile
+ ]
+ Dir.glob('**/nondotfile', File::FNM_DOTMATCH, base: ".").sort.should == expected
+ end
+
+ it "handles **/.dotfile with base keyword argument" do
+ expected = %w[
+ .dotfile
+ deeply/.dotfile
+ subdir_one/.dotfile
+ ]
+ Dir.glob('**/.dotfile', base: ".").sort.should == expected
+ end
+
+ it "handles **/.dotfile with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .dotfile
+ .dotsubdir/.dotfile
+ deeply/.dotfile
+ nested/.dotsubir/.dotfile
+ subdir_one/.dotfile
+ ]
+ Dir.glob('**/.dotfile', File::FNM_DOTMATCH, base: ".").sort.should == expected
+ end
+
+ it "handles **/.* with base keyword argument" do
+ expected = %w[
+ .dotfile.ext
+ directory/structure/.ext
+ ].sort
+
+ Dir.glob('**/.*', base: "deeply/nested").sort.should == expected
+ end
+
+ it "handles **/.* with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .
+ .dotfile.ext
+ directory/structure/.ext
+ ].sort
+
+ Dir.glob('**/.*', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
+ end
+
+ it "handles **/** with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .
+ .dotfile.ext
+ directory
+ directory/structure
+ directory/structure/.ext
+ directory/structure/bar
+ directory/structure/baz
+ directory/structure/file_one
+ directory/structure/file_one.ext
+ directory/structure/foo
+ ].sort
+
+ Dir.glob('**/**', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
+ end
+
+ it "handles **/*pattern* with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .dotfile.ext
+ directory/structure/file_one
+ directory/structure/file_one.ext
+ ]
+
+ Dir.glob('**/*file*', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
+ end
+
+ it "handles **/glob with base keyword argument and FNM_EXTGLOB" do
+ expected = %w[
+ directory/structure/bar
+ directory/structure/file_one
+ directory/structure/file_one.ext
+ ]
+
+ Dir.glob('**/*{file,bar}*', File::FNM_EXTGLOB, base: "deeply/nested").sort.should == expected
+ end
+
it "handles simple filename patterns" do
Dir.glob('.dotfile').should == ['.dotfile']
end
diff --git a/spec/ruby/core/dir/home_spec.rb b/spec/ruby/core/dir/home_spec.rb
index 8377f1dc97..f0b20e0687 100644
--- a/spec/ruby/core/dir/home_spec.rb
+++ b/spec/ruby/core/dir/home_spec.rb
@@ -19,16 +19,46 @@ describe "Dir.home" do
it "returns a non-frozen string" do
Dir.home.should_not.frozen?
end
- end
- describe "when called with the current user name" do
- platform_is :solaris do
- it "returns the named user's home directory from the user database" do
- Dir.home(ENV['USER']).should == `getent passwd #{ENV['USER']}|cut -d: -f6`.chomp
+ it "returns a string with the filesystem encoding" do
+ Dir.home.encoding.should == Encoding.find("filesystem")
+ end
+
+ platform_is_not :windows do
+ it "works even if HOME is unset" do
+ ENV.delete('HOME')
+ Dir.home.should.start_with?('/')
+ Dir.home.encoding.should == Encoding.find("filesystem")
+ end
+ end
+
+ platform_is :windows do
+ it "returns the home directory with forward slashs and as UTF-8" do
+ ENV['HOME'] = "C:\\rubyspäc\\home"
+ home = Dir.home
+ home.should == "C:/rubyspäc/home"
+ home.encoding.should == Encoding::UTF_8
+ end
+
+ it "retrieves the directory from HOME, USERPROFILE, HOMEDRIVE/HOMEPATH and the WinAPI in that order" do
+ old_dirs = [ENV.delete('HOME'), ENV.delete('USERPROFILE'), ENV.delete('HOMEDRIVE'), ENV.delete('HOMEPATH')]
+
+ Dir.home.should == old_dirs[1].gsub("\\", "/")
+ ENV['HOMEDRIVE'] = "C:"
+ ENV['HOMEPATH'] = "\\rubyspec\\home1"
+ Dir.home.should == "C:/rubyspec/home1"
+ ENV['USERPROFILE'] = "C:\\rubyspec\\home2"
+ Dir.home.should == "C:/rubyspec/home2"
+ ENV['HOME'] = "C:\\rubyspec\\home3"
+ Dir.home.should == "C:/rubyspec/home3"
+ ensure
+ ENV['HOME'], ENV['USERPROFILE'], ENV['HOMEDRIVE'], ENV['HOMEPATH'] = *old_dirs
end
end
+ end
- platform_is_not :windows, :solaris, :android, :wasi do
+ describe "when called with the current user name" do
+ platform_is_not :windows, :android, :wasi do
it "returns the named user's home directory, from the user database" do
Dir.home(ENV['USER']).should == `echo ~#{ENV['USER']}`.chomp
end
@@ -37,9 +67,19 @@ describe "Dir.home" do
it "returns a non-frozen string" do
Dir.home(ENV['USER']).should_not.frozen?
end
+
+ it "returns a string with the filesystem encoding" do
+ Dir.home(ENV['USER']).encoding.should == Encoding.find("filesystem")
+ end
end
it "raises an ArgumentError if the named user doesn't exist" do
- -> { Dir.home('geuw2n288dh2k') }.should raise_error(ArgumentError)
+ -> { Dir.home('geuw2n288dh2k') }.should.raise(ArgumentError)
+ end
+
+ describe "when called with a nil user name" do
+ it "returns the current user's home directory, reading $HOME first" do
+ Dir.home(nil).should == "/rubyspec_home"
+ end
end
end
diff --git a/spec/ruby/core/dir/inspect_spec.rb b/spec/ruby/core/dir/inspect_spec.rb
index 37338a97d4..eabaa54ce0 100644
--- a/spec/ruby/core/dir/inspect_spec.rb
+++ b/spec/ruby/core/dir/inspect_spec.rb
@@ -11,7 +11,7 @@ describe "Dir#inspect" do
end
it "returns a String" do
- @dir.inspect.should be_an_instance_of(String)
+ @dir.inspect.should.instance_of?(String)
end
it "includes the class name" do
@@ -19,6 +19,6 @@ describe "Dir#inspect" do
end
it "includes the directory name" do
- @dir.inspect.should include(Dir.getwd)
+ @dir.inspect.should.include?(Dir.getwd)
end
end
diff --git a/spec/ruby/core/dir/mkdir_spec.rb b/spec/ruby/core/dir/mkdir_spec.rb
index 0ed28f5a99..37513e417a 100644
--- a/spec/ruby/core/dir/mkdir_spec.rb
+++ b/spec/ruby/core/dir/mkdir_spec.rb
@@ -46,7 +46,7 @@ describe "Dir.mkdir" do
end
end
- it "calls #to_path on non-String arguments" do
+ it "calls #to_path on non-String path arguments" do
DirSpecs.clear_dirs
p = mock('path')
p.should_receive(:to_path).and_return(DirSpecs.mock_dir('nonexisting'))
@@ -54,16 +54,32 @@ describe "Dir.mkdir" do
DirSpecs.clear_dirs
end
+ it "calls #to_int on non-Integer permissions argument" do
+ DirSpecs.clear_dirs
+ path = DirSpecs.mock_dir('nonexisting')
+ permissions = mock('permissions')
+ permissions.should_receive(:to_int).and_return(0666)
+ Dir.mkdir(path, permissions)
+ DirSpecs.clear_dirs
+ end
+
+ it "raises TypeError if non-Integer permissions argument does not have #to_int method" do
+ path = DirSpecs.mock_dir('nonexisting')
+ permissions = Object.new
+
+ -> { Dir.mkdir(path, permissions) }.should.raise(TypeError, 'no implicit conversion of Object into Integer')
+ end
+
it "raises a SystemCallError if any of the directories in the path before the last does not exist" do
- -> { Dir.mkdir "#{DirSpecs.nonexistent}/subdir" }.should raise_error(SystemCallError)
+ -> { Dir.mkdir "#{DirSpecs.nonexistent}/subdir" }.should.raise(SystemCallError)
end
it "raises Errno::EEXIST if the specified directory already exists" do
- -> { Dir.mkdir("#{DirSpecs.mock_dir}/dir") }.should raise_error(Errno::EEXIST)
+ -> { Dir.mkdir("#{DirSpecs.mock_dir}/dir") }.should.raise(Errno::EEXIST)
end
it "raises Errno::EEXIST if the argument points to the existing file" do
- -> { Dir.mkdir("#{DirSpecs.mock_dir}/file_one.ext") }.should raise_error(Errno::EEXIST)
+ -> { Dir.mkdir("#{DirSpecs.mock_dir}/file_one.ext") }.should.raise(Errno::EEXIST)
end
end
@@ -84,7 +100,7 @@ platform_is_not :windows do
it "raises a SystemCallError when lacking adequate permissions in the parent dir" do
Dir.mkdir @dir, 0000
- -> { Dir.mkdir "#{@dir}/subdir" }.should raise_error(SystemCallError)
+ -> { Dir.mkdir "#{@dir}/subdir" }.should.raise(SystemCallError)
end
end
end
diff --git a/spec/ruby/core/dir/open_spec.rb b/spec/ruby/core/dir/open_spec.rb
index 27f362320b..be01638fbc 100644
--- a/spec/ruby/core/dir/open_spec.rb
+++ b/spec/ruby/core/dir/open_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
-require_relative 'shared/open'
describe "Dir.open" do
before :all do
@@ -11,5 +10,75 @@ describe "Dir.open" do
DirSpecs.delete_mock_dirs
end
- it_behaves_like :dir_open, :open
+ it "returns a Dir instance representing the specified directory" do
+ dir = Dir.open(DirSpecs.mock_dir)
+ dir.should.is_a?(Dir)
+ dir.close
+ end
+
+ it "raises a SystemCallError if the directory does not exist" do
+ -> do
+ Dir.open(DirSpecs.nonexistent)
+ end.should.raise(SystemCallError)
+ end
+
+ it "may take a block which is yielded to with the Dir instance" do
+ Dir.open(DirSpecs.mock_dir) {|dir| dir.should.is_a?(Dir)}
+ end
+
+ it "returns the value of the block if a block is given" do
+ Dir.open(DirSpecs.mock_dir) {|dir| :value }.should == :value
+ end
+
+ it "closes the Dir instance when the block exits if given a block" do
+ closed_dir = Dir.open(DirSpecs.mock_dir) { |dir| dir }
+ -> { closed_dir.read }.should.raise(IOError)
+ end
+
+ it "closes the Dir instance when the block exits the block even due to an exception" do
+ closed_dir = nil
+
+ -> do
+ Dir.open(DirSpecs.mock_dir) do |dir|
+ closed_dir = dir
+ raise "dir specs"
+ end
+ end.should.raise(RuntimeError, "dir specs")
+
+ -> { closed_dir.read }.should.raise(IOError)
+ end
+
+ it "calls #to_path on non-String arguments" do
+ p = mock('path')
+ p.should_receive(:to_path).and_return(DirSpecs.mock_dir)
+ Dir.open(p) { true }
+ end
+
+ it "accepts an options Hash" do
+ dir = Dir.open(DirSpecs.mock_dir, encoding: "utf-8") {|d| d }
+ dir.should.is_a?(Dir)
+ end
+
+ it "calls #to_hash to convert the options object" do
+ options = mock("dir_open")
+ options.should_receive(:to_hash).and_return({ encoding: Encoding::UTF_8 })
+
+ dir = Dir.open(DirSpecs.mock_dir, **options) {|d| d }
+ dir.should.is_a?(Dir)
+ end
+
+ it "ignores the :encoding option if it is nil" do
+ dir = Dir.open(DirSpecs.mock_dir, encoding: nil) {|d| d }
+ dir.should.is_a?(Dir)
+ end
+
+ platform_is_not :windows do
+ it 'sets the close-on-exec flag for the directory file descriptor' do
+ Dir.open(DirSpecs.mock_dir) do |dir|
+ io = IO.for_fd(dir.fileno)
+ io.autoclose = false
+ io.should.close_on_exec?
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/dir/path_spec.rb b/spec/ruby/core/dir/path_spec.rb
index b1c24c406b..02ddd2cd42 100644
--- a/spec/ruby/core/dir/path_spec.rb
+++ b/spec/ruby/core/dir/path_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
-require_relative 'shared/path'
describe "Dir#path" do
before :all do
@@ -11,5 +10,28 @@ describe "Dir#path" do
DirSpecs.delete_mock_dirs
end
- it_behaves_like :dir_path, :path
+ it "returns the path that was supplied to .new or .open" do
+ dir = Dir.open DirSpecs.mock_dir
+ begin
+ dir.path.should == DirSpecs.mock_dir
+ ensure
+ dir.close rescue nil
+ end
+ end
+
+ it "returns the path even when called on a closed Dir instance" do
+ dir = Dir.open DirSpecs.mock_dir
+ dir.close
+ dir.path.should == DirSpecs.mock_dir
+ end
+
+ it "returns a String with the same encoding as the argument to .open" do
+ path = DirSpecs.mock_dir.force_encoding Encoding::IBM866
+ dir = Dir.open path
+ begin
+ dir.path.encoding.should.equal?(Encoding::IBM866)
+ ensure
+ dir.close
+ end
+ end
end
diff --git a/spec/ruby/core/dir/pos_spec.rb b/spec/ruby/core/dir/pos_spec.rb
index b382bff81f..f8ca06d778 100644
--- a/spec/ruby/core/dir/pos_spec.rb
+++ b/spec/ruby/core/dir/pos_spec.rb
@@ -1,30 +1,11 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
-require_relative 'shared/closed'
require_relative 'shared/pos'
describe "Dir#pos" do
- before :all do
- DirSpecs.create_mock_dirs
- end
-
- after :all do
- DirSpecs.delete_mock_dirs
- end
-
- it_behaves_like :dir_pos, :pos
-end
-
-describe "Dir#pos" do
- before :all do
- DirSpecs.create_mock_dirs
+ it "is an alias of Dir#tell" do
+ Dir.instance_method(:pos).should == Dir.instance_method(:tell)
end
-
- after :all do
- DirSpecs.delete_mock_dirs
- end
-
- it_behaves_like :dir_closed, :pos
end
describe "Dir#pos=" do
diff --git a/spec/ruby/core/dir/pwd_spec.rb b/spec/ruby/core/dir/pwd_spec.rb
index ad01286c90..70208b03d6 100644
--- a/spec/ruby/core/dir/pwd_spec.rb
+++ b/spec/ruby/core/dir/pwd_spec.rb
@@ -1,7 +1,6 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
require_relative 'fixtures/common'
-require_relative 'shared/pwd'
describe "Dir.pwd" do
before :all do
@@ -12,7 +11,49 @@ describe "Dir.pwd" do
DirSpecs.delete_mock_dirs
end
- it_behaves_like :dir_pwd, :pwd
+ before :each do
+ @fs_encoding = Encoding.find('filesystem')
+ end
+
+ it "returns the current working directory" do
+ pwd = Dir.pwd
+
+ File.directory?(pwd).should == true
+
+ # On ubuntu gutsy, for example, /bin/pwd does not
+ # understand -P. With just `pwd -P`, /bin/pwd is run.
+
+ # The following uses inode rather than file names to account for
+ # case insensitive file systems like default OS/X file systems
+ platform_is_not :windows do
+ File.stat(pwd).ino.should == File.stat(`/bin/sh -c "pwd -P"`.chomp).ino
+ end
+ platform_is :windows do
+ File.stat(pwd).ino.should == File.stat(File.expand_path(`cd`.chomp)).ino
+ end
+ end
+
+ it "returns an absolute path" do
+ pwd = Dir.pwd
+ pwd.should == File.expand_path(pwd)
+ end
+
+ it "returns an absolute path even when chdir to a relative path" do
+ Dir.chdir(".") do
+ pwd = Dir.pwd
+ File.directory?(pwd).should == true
+ pwd.should == File.expand_path(pwd)
+ end
+ end
+
+ it "returns a String with the filesystem encoding" do
+ enc = Dir.pwd.encoding
+ if @fs_encoding == Encoding::US_ASCII
+ [Encoding::US_ASCII, Encoding::BINARY].should.include?(enc)
+ else
+ enc.should.equal?(@fs_encoding)
+ end
+ end
end
describe "Dir.pwd" do
diff --git a/spec/ruby/core/dir/read_spec.rb b/spec/ruby/core/dir/read_spec.rb
index 276930c6b7..3f842457f4 100644
--- a/spec/ruby/core/dir/read_spec.rb
+++ b/spec/ruby/core/dir/read_spec.rb
@@ -15,7 +15,7 @@ describe "Dir#read" do
# an FS does not necessarily impose order
ls = Dir.entries DirSpecs.mock_dir
dir = Dir.open DirSpecs.mock_dir
- ls.should include(dir.read)
+ ls.should.include?(dir.read)
dir.close
end
@@ -61,7 +61,7 @@ describe "Dir#read" do
while entry = d.read
shift_jis_entries << entry
end
- }.should_not raise_error
+ }.should_not.raise
end
ensure
Encoding.default_internal = old_internal_encoding
diff --git a/spec/ruby/core/dir/scan_spec.rb b/spec/ruby/core/dir/scan_spec.rb
new file mode 100644
index 0000000000..3aa071337b
--- /dev/null
+++ b/spec/ruby/core/dir/scan_spec.rb
@@ -0,0 +1,224 @@
+# encoding: utf-8
+
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
+require_relative '../file/fixtures/file_types'
+
+ruby_version_is "4.1" do
+ describe "Dir.scan" do
+ before :all do
+ FileSpecs.configure_types
+ end
+
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
+
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
+
+ before :each do
+ @internal = Encoding.default_internal
+ end
+
+ after :each do
+ Encoding.default_internal = @internal
+ end
+
+ it "returns an Array of filename and type pairs in an existing directory including dotfiles" do
+ a = Dir.scan(DirSpecs.mock_dir).sort
+
+ a.should == DirSpecs.expected_paths_with_type - [[".", :directory], ["..", :directory]]
+
+ a = Dir.scan("#{DirSpecs.mock_dir}/deeply/nested").sort
+ a.should == [[".dotfile.ext", :file], ["directory", :directory]]
+ end
+
+ it "yields filename and type in an existing directory including dotfiles" do
+ a = []
+ Dir.scan(DirSpecs.mock_dir) do |n, t|
+ a << [n, t]
+ end
+ a.sort!
+ a.should == DirSpecs.expected_paths_with_type - [[".", :directory], ["..", :directory]]
+
+ a = []
+ Dir.scan("#{DirSpecs.mock_dir}/deeply/nested") do |n, t|
+ a << [n, t]
+ end
+ a.sort!
+ a.should == [[".dotfile.ext", :file], ["directory", :directory]]
+ end
+
+ it "calls #to_path on non-String arguments" do
+ p = mock('path')
+ p.should_receive(:to_path).and_return(DirSpecs.mock_dir)
+ Dir.scan(p)
+ end
+
+ it "accepts an options Hash" do
+ a = Dir.scan("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").sort
+ a.should == [[".dotfile.ext", :file], ["directory", :directory]]
+ end
+
+ it "returns children names encoded with the filesystem encoding by default" do
+ # This spec depends on the locale not being US-ASCII because if it is, the
+ # children that are not ascii_only? will be BINARY encoded.
+ children = Dir.scan(File.join(DirSpecs.mock_dir, 'special')).sort
+ encoding = Encoding.find("filesystem")
+ encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
+ platform_is_not :windows do
+ children.should.include?(["こんにちは.txt".dup.force_encoding(encoding), :file])
+ end
+ children.first.first.encoding.should.equal?(Encoding.find("filesystem"))
+ end
+
+ it "returns children names encoded with the specified encoding" do
+ dir = File.join(DirSpecs.mock_dir, 'special')
+ children = Dir.scan(dir, encoding: "euc-jp").sort
+ children.first.first.encoding.should.equal?(Encoding::EUC_JP)
+ end
+
+ it "returns children names transcoded to the default internal encoding" do
+ Encoding.default_internal = Encoding::EUC_KR
+ children = Dir.scan(File.join(DirSpecs.mock_dir, 'special')).sort
+ children.first.first.encoding.should.equal?(Encoding::EUC_KR)
+ end
+
+ it "raises a SystemCallError if called with a nonexistent directory" do
+ -> { Dir.scan DirSpecs.nonexistent }.should.raise(SystemCallError)
+ end
+
+ it "handles symlink" do
+ FileSpecs.symlink do |path|
+ Dir.scan(File.dirname(path)).map(&:last).should.include?(:link)
+ end
+ end
+
+ platform_is_not :windows do
+ it "handles socket" do
+ FileSpecs.socket do |path|
+ Dir.scan(File.dirname(path)).map(&:last).should.include?(:socket)
+ end
+ end
+
+ it "handles FIFO" do
+ FileSpecs.fifo do |path|
+ Dir.scan(File.dirname(path)).map(&:last).should.include?(:fifo)
+ end
+ end
+
+ it "handles character devices" do
+ FileSpecs.character_device do |path|
+ Dir.scan(File.dirname(path)).map(&:last).should.include?(:characterSpecial)
+ end
+ end
+ end
+
+ platform_is_not :freebsd, :windows do
+ with_block_device do
+ it "handles block devices" do
+ FileSpecs.block_device do |path|
+ Dir.scan(File.dirname(path)).map(&:last).should.include?(:blockSpecial)
+ end
+ end
+ end
+ end
+ end
+
+ describe "Dir#scan" do
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
+
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
+
+ before :each do
+ @internal = Encoding.default_internal
+ end
+
+ after :each do
+ Encoding.default_internal = @internal
+ @dir.close if @dir
+ end
+
+ it "returns an Array of filenames in an existing directory including dotfiles" do
+ @dir = Dir.new(DirSpecs.mock_dir)
+ a = @dir.scan.sort
+ @dir.close
+
+ a.should == DirSpecs.expected_paths_with_type - [[".", :directory], ["..", :directory]]
+
+ @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested")
+ a = @dir.scan.sort
+ a.should == [[".dotfile.ext", :file], ["directory", :directory]]
+ end
+
+ it "yields filename and type in an existing directory including dotfiles" do
+ @dir = Dir.new(DirSpecs.mock_dir)
+ a = []
+ @dir.scan do |n, t|
+ a << [n, t]
+ end
+ a.sort!
+ a.should == DirSpecs.expected_paths_with_type - [[".", :directory], ["..", :directory]]
+
+ @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested")
+ a = []
+ @dir.scan do |n, t|
+ a << [n, t]
+ end
+ a.sort!
+ a.should == [[".dotfile.ext", :file], ["directory", :directory]]
+ end
+
+ it "accepts an encoding keyword for the encoding of the entries" do
+ @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8")
+ dirs = @dir.to_a.sort
+ dirs.each { |d| d.encoding.should == Encoding::UTF_8 }
+ end
+
+ it "returns children names encoded with the filesystem encoding by default" do
+ # This spec depends on the locale not being US-ASCII because if it is, the
+ # children that are not ascii_only? will be BINARY encoded.
+ @dir = Dir.new(File.join(DirSpecs.mock_dir, 'special'))
+ children = @dir.scan.sort
+ encoding = Encoding.find("filesystem")
+ encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
+ platform_is_not :windows do
+ children.should.include?(["こんにちは.txt".dup.force_encoding(encoding), :file])
+ end
+ children.first.first.encoding.should.equal?(Encoding.find("filesystem"))
+ end
+
+ it "returns children names encoded with the specified encoding" do
+ path = File.join(DirSpecs.mock_dir, 'special')
+ @dir = Dir.new(path, encoding: "euc-jp")
+ children = @dir.children.sort
+ children.first.encoding.should.equal?(Encoding::EUC_JP)
+ end
+
+ it "returns children names transcoded to the default internal encoding" do
+ Encoding.default_internal = Encoding::EUC_KR
+ @dir = Dir.new(File.join(DirSpecs.mock_dir, 'special'))
+ children = @dir.scan.sort
+ children.first.first.encoding.should.equal?(Encoding::EUC_KR)
+ end
+
+ it "returns the same result when called repeatedly" do
+ @dir = Dir.open DirSpecs.mock_dir
+
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/shared/chroot.rb b/spec/ruby/core/dir/shared/chroot.rb
index b14a433670..e4e6103799 100644
--- a/spec/ruby/core/dir/shared/chroot.rb
+++ b/spec/ruby/core/dir/shared/chroot.rb
@@ -2,8 +2,8 @@ describe :dir_chroot_as_root, shared: true do
before :all do
DirSpecs.create_mock_dirs
- @real_root = "../" * (File.dirname(__FILE__).count('/') - 1)
- @ref_dir = File.join("/", Dir.new('/').entries.first)
+ @real_root = "../" * (__dir__.count('/') - 1)
+ @ref_dir = File.join("/", File.basename(Dir["/*"].first))
end
after :all do
@@ -14,24 +14,27 @@ describe :dir_chroot_as_root, shared: true do
DirSpecs.delete_mock_dirs
end
+ # Pending until https://github.com/ruby/ruby/runs/8075149420 is fixed
+ compilations_ci = ENV["GITHUB_WORKFLOW"] == "Compilations"
+
it "can be used to change the process' root directory" do
- -> { Dir.send(@method, File.dirname(__FILE__)) }.should_not raise_error
+ -> { Dir.send(@method, __dir__) }.should_not.raise
File.should.exist?("/#{File.basename(__FILE__)}")
- end
+ end unless compilations_ci
it "returns 0 if successful" do
Dir.send(@method, '/').should == 0
end
it "raises an Errno::ENOENT exception if the directory doesn't exist" do
- -> { Dir.send(@method, 'xgwhwhsjai2222jg') }.should raise_error(Errno::ENOENT)
+ -> { Dir.send(@method, 'xgwhwhsjai2222jg') }.should.raise(Errno::ENOENT)
end
it "can be escaped from with ../" do
Dir.send(@method, @real_root)
File.should.exist?(@ref_dir)
File.should_not.exist?("/#{File.basename(__FILE__)}")
- end
+ end unless compilations_ci
it "calls #to_path on non-String argument" do
p = mock('path')
diff --git a/spec/ruby/core/dir/shared/closed.rb b/spec/ruby/core/dir/shared/closed.rb
index 17d8332c2a..c868fd6e6d 100644
--- a/spec/ruby/core/dir/shared/closed.rb
+++ b/spec/ruby/core/dir/shared/closed.rb
@@ -4,6 +4,6 @@ describe :dir_closed, shared: true do
dir = Dir.open DirSpecs.mock_dir
dir.close
dir.send(@method) {}
- }.should raise_error(IOError)
+ }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/dir/shared/delete.rb b/spec/ruby/core/dir/shared/delete.rb
index 49e88360e8..ba013e8615 100644
--- a/spec/ruby/core/dir/shared/delete.rb
+++ b/spec/ruby/core/dir/shared/delete.rb
@@ -17,26 +17,16 @@ describe :dir_delete, shared: true do
Dir.send(@method, p)
end
- platform_is_not :solaris do
- it "raises an Errno::ENOTEMPTY when trying to remove a nonempty directory" do
- -> do
- Dir.send @method, DirSpecs.mock_rmdir("nonempty")
- end.should raise_error(Errno::ENOTEMPTY)
- end
- end
-
- platform_is :solaris do
- it "raises an Errno::EEXIST when trying to remove a nonempty directory" do
- -> do
- Dir.send @method, DirSpecs.mock_rmdir("nonempty")
- end.should raise_error(Errno::EEXIST)
- end
+ it "raises an Errno::ENOTEMPTY when trying to remove a nonempty directory" do
+ -> do
+ Dir.send @method, DirSpecs.mock_rmdir("nonempty")
+ end.should.raise(Errno::ENOTEMPTY)
end
it "raises an Errno::ENOENT when trying to remove a non-existing directory" do
-> do
Dir.send @method, DirSpecs.nonexistent
- end.should raise_error(Errno::ENOENT)
+ end.should.raise(Errno::ENOENT)
end
it "raises an Errno::ENOTDIR when trying to remove a non-directory" do
@@ -44,7 +34,7 @@ describe :dir_delete, shared: true do
touch(file)
-> do
Dir.send @method, file
- end.should raise_error(Errno::ENOTDIR)
+ end.should.raise(Errno::ENOTDIR)
end
# this won't work on Windows, since chmod(0000) does not remove all permissions
@@ -56,7 +46,7 @@ describe :dir_delete, shared: true do
File.chmod(0000, parent)
-> do
Dir.send @method, child
- end.should raise_error(Errno::EACCES)
+ end.should.raise(Errno::EACCES)
end
end
end
diff --git a/spec/ruby/core/dir/shared/exist.rb b/spec/ruby/core/dir/shared/exist.rb
deleted file mode 100644
index 765d1b656c..0000000000
--- a/spec/ruby/core/dir/shared/exist.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-describe :dir_exist, shared: true do
- it "returns true if the given directory exists" do
- Dir.send(@method, File.dirname(__FILE__)).should be_true
- end
-
- it "returns true for '.'" do
- Dir.send(@method, '.').should be_true
- end
-
- it "returns true for '..'" do
- Dir.send(@method, '..').should be_true
- end
-
- it "understands non-ASCII paths" do
- subdir = File.join(tmp("\u{9876}\u{665}"))
- Dir.send(@method, subdir).should be_false
- Dir.mkdir(subdir)
- Dir.send(@method, subdir).should be_true
- Dir.rmdir(subdir)
- end
-
- it "understands relative paths" do
- Dir.send(@method, File.dirname(__FILE__) + '/../').should be_true
- end
-
- it "returns false if the given directory doesn't exist" do
- Dir.send(@method, 'y26dg27n2nwjs8a/').should be_false
- end
-
- it "doesn't require the name to have a trailing slash" do
- dir = File.dirname(__FILE__)
- dir.sub!(/\/$/,'')
- Dir.send(@method, dir).should be_true
- end
-
- it "doesn't expand paths" do
- Dir.send(@method, File.expand_path('~')).should be_true
- Dir.send(@method, '~').should be_false
- end
-
- it "returns false if the argument exists but is a file" do
- File.should.exist?(__FILE__)
- Dir.send(@method, __FILE__).should be_false
- end
-
- it "doesn't set $! when file doesn't exist" do
- Dir.send(@method, "/path/to/non/existent/dir")
- $!.should be_nil
- end
-
- it "calls #to_path on non String arguments" do
- p = mock('path')
- p.should_receive(:to_path).and_return(File.dirname(__FILE__))
- Dir.send(@method, p)
- end
-end
diff --git a/spec/ruby/core/dir/shared/glob.rb b/spec/ruby/core/dir/shared/glob.rb
index 60d4a8c97a..86aa105259 100644
--- a/spec/ruby/core/dir/shared/glob.rb
+++ b/spec/ruby/core/dir/shared/glob.rb
@@ -12,8 +12,8 @@ describe :dir_glob, shared: true do
end
it "raises an Encoding::CompatibilityError if the argument encoding is not compatible with US-ASCII" do
- pattern = "file*".force_encoding Encoding::UTF_16BE
- -> { Dir.send(@method, pattern) }.should raise_error(Encoding::CompatibilityError)
+ pattern = "files*".dup.force_encoding Encoding::UTF_16BE
+ -> { Dir.send(@method, pattern) }.should.raise(Encoding::CompatibilityError)
end
it "calls #to_path to convert a pattern" do
@@ -24,45 +24,28 @@ describe :dir_glob, shared: true do
end
it "raises an ArgumentError if the string contains \\0" do
- -> {Dir.send(@method, "file_o*\0file_t*")}.should raise_error ArgumentError, /nul-separated/
+ -> {Dir.send(@method, "file_o*\0file_t*")}.should.raise ArgumentError, /nul-separated/
end
- ruby_version_is "3.0" do
- it "result is sorted by default" do
- result = Dir.send(@method, '*')
- result.should == result.sort
- end
-
- it "result is sorted with sort: true" do
- result = Dir.send(@method, '*', sort: true)
- result.should == result.sort
- end
-
- it "sort: false returns same files" do
- result = Dir.send(@method,'*', sort: false)
- result.sort.should == Dir.send(@method, '*').sort
- end
+ it "result is sorted by default" do
+ result = Dir.send(@method, '*')
+ result.should == result.sort
end
- ruby_version_is "3.0"..."3.1" do
- it "result is sorted with any non false value of sort:" do
- result = Dir.send(@method, '*', sort: 0)
- result.should == result.sort
-
- result = Dir.send(@method, '*', sort: nil)
- result.should == result.sort
+ it "result is sorted with sort: true" do
+ result = Dir.send(@method, '*', sort: true)
+ result.should == result.sort
+ end
- result = Dir.send(@method, '*', sort: 'false')
- result.should == result.sort
- end
+ it "sort: false returns same files" do
+ result = Dir.send(@method,'*', sort: false)
+ result.sort.should == Dir.send(@method, '*').sort
end
- ruby_version_is "3.1" do
- it "raises an ArgumentError if sort: is not true or false" do
- -> { Dir.send(@method, '*', sort: 0) }.should raise_error ArgumentError, /expected true or false/
- -> { Dir.send(@method, '*', sort: nil) }.should raise_error ArgumentError, /expected true or false/
- -> { Dir.send(@method, '*', sort: 'false') }.should raise_error ArgumentError, /expected true or false/
- end
+ it "raises an ArgumentError if sort: is not true or false" do
+ -> { Dir.send(@method, '*', sort: 0) }.should.raise ArgumentError, /expected true or false/
+ -> { Dir.send(@method, '*', sort: nil) }.should.raise ArgumentError, /expected true or false/
+ -> { Dir.send(@method, '*', sort: 'false') }.should.raise ArgumentError, /expected true or false/
end
it "matches non-dotfiles with '*'" do
@@ -111,6 +94,10 @@ describe :dir_glob, shared: true do
it "matches files with backslashes in their name" do
Dir.glob('special/\\\\{a,b}').should == ['special/\a']
end
+
+ it "matches directory with special characters in their name in complex patterns" do
+ Dir.glob("special/test +()\\[\\]\\{\\}/hello_world{.{en},}{.{html},}{+{phone},}{.{erb},}").should == ['special/test +()[]{}/hello_world.erb']
+ end
end
it "matches regexp special ^" do
@@ -149,16 +136,8 @@ describe :dir_glob, shared: true do
Dir.send(@method, 'special/test\{1\}/*').should == ['special/test{1}/file[1]']
end
- ruby_version_is ''...'3.1' do
- it "matches dotfiles with '.*'" do
- Dir.send(@method, '.*').sort.should == %w|. .. .dotfile .dotsubdir|.sort
- end
- end
-
- ruby_version_is '3.1' do
- it "matches dotfiles except .. with '.*'" do
- Dir.send(@method, '.*').sort.should == %w|. .dotfile .dotsubdir|.sort
- end
+ it "matches dotfiles except .. with '.*'" do
+ Dir.send(@method, '.*').sort.should == %w|. .dotfile .dotsubdir|.sort
end
it "matches non-dotfiles with '*<non-special characters>'" do
@@ -203,16 +182,8 @@ describe :dir_glob, shared: true do
Dir.send(@method, '**').sort.should == expected
end
- ruby_version_is ''...'3.1' do
- it "matches dotfiles in the current directory with '.**'" do
- Dir.send(@method, '.**').sort.should == %w|. .. .dotsubdir .dotfile|.sort
- end
- end
-
- ruby_version_is '3.1' do
- it "matches dotfiles in the current directory except .. with '.**'" do
- Dir.send(@method, '.**').sort.should == %w|. .dotsubdir .dotfile|.sort
- end
+ it "matches dotfiles in the current directory except .. with '.**'" do
+ Dir.send(@method, '.**').sort.should == %w|. .dotsubdir .dotfile|.sort
end
it "recursively matches any nondot subdirectories with '**/'" do
@@ -225,6 +196,7 @@ describe :dir_glob, shared: true do
dir/
nested/
special/
+ special/test\ +()[]{}/
special/test{1}/
special/{}/
subdir_one/
@@ -242,19 +214,9 @@ describe :dir_glob, shared: true do
Dir.send(@method, '**/*ory', base: 'deeply').sort.should == expected
end
- ruby_version_is ''...'3.1' do
- it "recursively matches any subdirectories including ./ and ../ with '.**/'" do
- Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do
- Dir.send(@method, '.**/').sort.should == %w|./ ../|.sort
- end
- end
- end
-
- ruby_version_is '3.1' do
- it "recursively matches any subdirectories including ./ with '.**/'" do
- Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do
- Dir.send(@method, '.**/').should == ['./']
- end
+ it "recursively matches any subdirectories including ./ with '.**/'" do
+ Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do
+ Dir.send(@method, '.**/').should == ['./']
end
end
@@ -411,7 +373,7 @@ describe :dir_glob, shared: true do
it "raises TypeError when cannot convert value to string" do
-> {
Dir.send(@method, "*", base: [])
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "handles '' as current directory path" do
diff --git a/spec/ruby/core/dir/shared/open.rb b/spec/ruby/core/dir/shared/open.rb
deleted file mode 100644
index 920845cba1..0000000000
--- a/spec/ruby/core/dir/shared/open.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-describe :dir_open, shared: true do
- it "returns a Dir instance representing the specified directory" do
- dir = Dir.send(@method, DirSpecs.mock_dir)
- dir.should be_kind_of(Dir)
- dir.close
- end
-
- it "raises a SystemCallError if the directory does not exist" do
- -> do
- Dir.send @method, DirSpecs.nonexistent
- end.should raise_error(SystemCallError)
- end
-
- it "may take a block which is yielded to with the Dir instance" do
- Dir.send(@method, DirSpecs.mock_dir) {|dir| dir.should be_kind_of(Dir)}
- end
-
- it "returns the value of the block if a block is given" do
- Dir.send(@method, DirSpecs.mock_dir) {|dir| :value }.should == :value
- end
-
- it "closes the Dir instance when the block exits if given a block" do
- closed_dir = Dir.send(@method, DirSpecs.mock_dir) { |dir| dir }
- -> { closed_dir.read }.should raise_error(IOError)
- end
-
- it "closes the Dir instance when the block exits the block even due to an exception" do
- closed_dir = nil
-
- -> do
- Dir.send(@method, DirSpecs.mock_dir) do |dir|
- closed_dir = dir
- raise "dir specs"
- end
- end.should raise_error(RuntimeError, "dir specs")
-
- -> { closed_dir.read }.should raise_error(IOError)
- end
-
- it "calls #to_path on non-String arguments" do
- p = mock('path')
- p.should_receive(:to_path).and_return(DirSpecs.mock_dir)
- Dir.send(@method, p) { true }
- end
-
- it "accepts an options Hash" do
- dir = Dir.send(@method, DirSpecs.mock_dir, encoding: "utf-8") {|d| d }
- dir.should be_kind_of(Dir)
- end
-
- it "calls #to_hash to convert the options object" do
- options = mock("dir_open")
- options.should_receive(:to_hash).and_return({ encoding: Encoding::UTF_8 })
-
- dir = Dir.send(@method, DirSpecs.mock_dir, **options) {|d| d }
- dir.should be_kind_of(Dir)
- end
-
- it "ignores the :encoding option if it is nil" do
- dir = Dir.send(@method, DirSpecs.mock_dir, encoding: nil) {|d| d }
- dir.should be_kind_of(Dir)
- end
-
- platform_is_not :windows do
- it 'sets the close-on-exec flag for the directory file descriptor' do
- Dir.send(@method, DirSpecs.mock_dir) do |dir|
- io = IO.for_fd(dir.fileno)
- io.autoclose = false
- io.should.close_on_exec?
- end
- end
- end
-end
diff --git a/spec/ruby/core/dir/shared/path.rb b/spec/ruby/core/dir/shared/path.rb
deleted file mode 100644
index 494dcca775..0000000000
--- a/spec/ruby/core/dir/shared/path.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require_relative '../../../spec_helper'
-require_relative '../fixtures/common'
-require_relative 'closed'
-
-describe :dir_path, shared: true do
- it "returns the path that was supplied to .new or .open" do
- dir = Dir.open DirSpecs.mock_dir
- begin
- dir.send(@method).should == DirSpecs.mock_dir
- ensure
- dir.close rescue nil
- end
- end
-
- it "returns the path even when called on a closed Dir instance" do
- dir = Dir.open DirSpecs.mock_dir
- dir.close
- dir.send(@method).should == DirSpecs.mock_dir
- end
-
- it "returns a String with the same encoding as the argument to .open" do
- path = DirSpecs.mock_dir.force_encoding Encoding::IBM866
- dir = Dir.open path
- begin
- dir.send(@method).encoding.should equal(Encoding::IBM866)
- ensure
- dir.close
- end
- end
-end
diff --git a/spec/ruby/core/dir/shared/pos.rb b/spec/ruby/core/dir/shared/pos.rb
index 2165932d99..741de8918c 100644
--- a/spec/ruby/core/dir/shared/pos.rb
+++ b/spec/ruby/core/dir/shared/pos.rb
@@ -1,30 +1,3 @@
-describe :dir_pos, shared: true do
- before :each do
- @dir = Dir.open DirSpecs.mock_dir
- end
-
- after :each do
- @dir.close rescue nil
- end
-
- it "returns an Integer representing the current position in the directory" do
- @dir.send(@method).should be_kind_of(Integer)
- @dir.send(@method).should be_kind_of(Integer)
- @dir.send(@method).should be_kind_of(Integer)
- end
-
- it "returns a different Integer if moved from previous position" do
- a = @dir.send(@method)
- @dir.read
- b = @dir.send(@method)
-
- a.should be_kind_of(Integer)
- b.should be_kind_of(Integer)
-
- a.should_not == b
- end
-end
-
describe :dir_pos_set, shared: true do
before :each do
@dir = Dir.open DirSpecs.mock_dir
diff --git a/spec/ruby/core/dir/shared/pwd.rb b/spec/ruby/core/dir/shared/pwd.rb
deleted file mode 100644
index 2a8d7fe790..0000000000
--- a/spec/ruby/core/dir/shared/pwd.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-describe :dir_pwd, shared: true do
- before :each do
- @fs_encoding = Encoding.find('filesystem')
- end
-
- it "returns the current working directory" do
- pwd = Dir.send(@method)
-
- File.directory?(pwd).should == true
-
- # On ubuntu gutsy, for example, /bin/pwd does not
- # understand -P. With just `pwd -P`, /bin/pwd is run.
-
- # The following uses inode rather than file names to account for
- # case insensitive file systems like default OS/X file systems
- platform_is_not :windows do
- File.stat(pwd).ino.should == File.stat(`/bin/sh -c "pwd -P"`.chomp).ino
- end
- platform_is :windows do
- File.stat(pwd).ino.should == File.stat(File.expand_path(`cd`.chomp)).ino
- end
- end
-
- it "returns an absolute path" do
- pwd = Dir.send(@method)
- pwd.should == File.expand_path(pwd)
- end
-
- it "returns an absolute path even when chdir to a relative path" do
- Dir.chdir(".") do
- pwd = Dir.send(@method)
- File.directory?(pwd).should == true
- pwd.should == File.expand_path(pwd)
- end
- end
-
- it "returns a String with the filesystem encoding" do
- enc = Dir.send(@method).encoding
- if @fs_encoding == Encoding::US_ASCII
- [Encoding::US_ASCII, Encoding::BINARY].should include(enc)
- else
- enc.should equal(@fs_encoding)
- end
- end
-end
diff --git a/spec/ruby/core/dir/tell_spec.rb b/spec/ruby/core/dir/tell_spec.rb
index af86dc1598..dcbb40438f 100644
--- a/spec/ruby/core/dir/tell_spec.rb
+++ b/spec/ruby/core/dir/tell_spec.rb
@@ -12,7 +12,30 @@ describe "Dir#tell" do
DirSpecs.delete_mock_dirs
end
- it_behaves_like :dir_pos, :tell
-
it_behaves_like :dir_closed, :tell
+
+ before :each do
+ @dir = Dir.open DirSpecs.mock_dir
+ end
+
+ after :each do
+ @dir.close rescue nil
+ end
+
+ it "returns an Integer representing the current position in the directory" do
+ @dir.tell.should.is_a?(Integer)
+ @dir.tell.should.is_a?(Integer)
+ @dir.tell.should.is_a?(Integer)
+ end
+
+ it "returns a different Integer if moved from previous position" do
+ a = @dir.tell
+ @dir.read
+ b = @dir.tell
+
+ a.should.is_a?(Integer)
+ b.should.is_a?(Integer)
+
+ a.should_not == b
+ end
end
diff --git a/spec/ruby/core/dir/to_path_spec.rb b/spec/ruby/core/dir/to_path_spec.rb
index 77404a3dc8..2ed533e757 100644
--- a/spec/ruby/core/dir/to_path_spec.rb
+++ b/spec/ruby/core/dir/to_path_spec.rb
@@ -1,15 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/common'
-require_relative 'shared/path'
describe "Dir#to_path" do
- before :all do
- DirSpecs.create_mock_dirs
+ it "is an alias of Dir#path" do
+ Dir.instance_method(:to_path).should == Dir.instance_method(:path)
end
-
- after :all do
- DirSpecs.delete_mock_dirs
- end
-
- it_behaves_like :dir_path, :to_path
end
diff --git a/spec/ruby/core/encoding/aliases_spec.rb b/spec/ruby/core/encoding/aliases_spec.rb
index 786157981a..12c6c6cf85 100644
--- a/spec/ruby/core/encoding/aliases_spec.rb
+++ b/spec/ruby/core/encoding/aliases_spec.rb
@@ -2,24 +2,24 @@ require_relative '../../spec_helper'
describe "Encoding.aliases" do
it "returns a Hash" do
- Encoding.aliases.should be_an_instance_of(Hash)
+ Encoding.aliases.should.instance_of?(Hash)
end
it "has Strings as keys" do
Encoding.aliases.keys.each do |key|
- key.should be_an_instance_of(String)
+ key.should.instance_of?(String)
end
end
it "has Strings as values" do
Encoding.aliases.values.each do |value|
- value.should be_an_instance_of(String)
+ value.should.instance_of?(String)
end
end
it "has alias names as its keys" do
- Encoding.aliases.key?('BINARY').should be_true
- Encoding.aliases.key?('ASCII').should be_true
+ Encoding.aliases.key?('BINARY').should == true
+ Encoding.aliases.key?('ASCII').should == true
end
it "has the names of the aliased encoding as its values" do
diff --git a/spec/ruby/core/encoding/ascii_compatible_spec.rb b/spec/ruby/core/encoding/ascii_compatible_spec.rb
index 4804300e85..04fc159bb8 100644
--- a/spec/ruby/core/encoding/ascii_compatible_spec.rb
+++ b/spec/ruby/core/encoding/ascii_compatible_spec.rb
@@ -2,10 +2,21 @@ require_relative '../../spec_helper'
describe "Encoding#ascii_compatible?" do
it "returns true if self represents an ASCII-compatible encoding" do
- Encoding::UTF_8.ascii_compatible?.should be_true
+ Encoding::UTF_8.ascii_compatible?.should == true
end
it "returns false if self does not represent an ASCII-compatible encoding" do
- Encoding::UTF_16LE.ascii_compatible?.should be_false
+ Encoding::UTF_16LE.ascii_compatible?.should == false
+ end
+
+ it "returns false for UTF_16 and UTF_32" do
+ Encoding::UTF_16.should_not.ascii_compatible?
+ Encoding::UTF_32.should_not.ascii_compatible?
+ end
+
+ it "is always false for dummy encodings" do
+ Encoding.list.select(&:dummy?).each do |encoding|
+ encoding.should_not.ascii_compatible?
+ end
end
end
diff --git a/spec/ruby/core/encoding/compatible_spec.rb b/spec/ruby/core/encoding/compatible_spec.rb
index 80ecab6155..0d620e5bf3 100644
--- a/spec/ruby/core/encoding/compatible_spec.rb
+++ b/spec/ruby/core/encoding/compatible_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
@@ -7,7 +7,7 @@ require_relative '../../spec_helper'
describe "Encoding.compatible? String, String" do
describe "when the first's Encoding is valid US-ASCII" do
before :each do
- @str = "abc".force_encoding Encoding::US_ASCII
+ @str = "abc".dup.force_encoding Encoding::US_ASCII
end
it "returns US-ASCII when the second's is US-ASCII" do
@@ -33,29 +33,29 @@ describe "Encoding.compatible? String, String" do
describe "when the first's Encoding is ASCII compatible and ASCII only" do
it "returns the first's Encoding if the second is ASCII compatible and ASCII only" do
- [ [Encoding, "abc".force_encoding("UTF-8"), "123".force_encoding("Shift_JIS"), Encoding::UTF_8],
- [Encoding, "123".force_encoding("Shift_JIS"), "abc".force_encoding("UTF-8"), Encoding::Shift_JIS]
+ [ [Encoding, "abc".dup.force_encoding("UTF-8"), "123".dup.force_encoding("Shift_JIS"), Encoding::UTF_8],
+ [Encoding, "123".dup.force_encoding("Shift_JIS"), "abc".dup.force_encoding("UTF-8"), Encoding::Shift_JIS]
].should be_computed_by(:compatible?)
end
it "returns the first's Encoding if the second is ASCII compatible and ASCII only" do
- [ [Encoding, "abc".force_encoding("BINARY"), "123".force_encoding("US-ASCII"), Encoding::BINARY],
- [Encoding, "123".force_encoding("US-ASCII"), "abc".force_encoding("BINARY"), Encoding::US_ASCII]
+ [ [Encoding, "abc".dup.force_encoding("BINARY"), "123".dup.force_encoding("US-ASCII"), Encoding::BINARY],
+ [Encoding, "123".dup.force_encoding("US-ASCII"), "abc".dup.force_encoding("BINARY"), Encoding::US_ASCII]
].should be_computed_by(:compatible?)
end
it "returns the second's Encoding if the second is ASCII compatible but not ASCII only" do
- [ [Encoding, "abc".force_encoding("UTF-8"), "\xff".force_encoding("Shift_JIS"), Encoding::Shift_JIS],
- [Encoding, "123".force_encoding("Shift_JIS"), "\xff".force_encoding("UTF-8"), Encoding::UTF_8],
- [Encoding, "abc".force_encoding("BINARY"), "\xff".force_encoding("US-ASCII"), Encoding::US_ASCII],
- [Encoding, "123".force_encoding("US-ASCII"), "\xff".force_encoding("BINARY"), Encoding::BINARY],
+ [ [Encoding, "abc".dup.force_encoding("UTF-8"), "\xff".dup.force_encoding("Shift_JIS"), Encoding::Shift_JIS],
+ [Encoding, "123".dup.force_encoding("Shift_JIS"), "\xff".dup.force_encoding("UTF-8"), Encoding::UTF_8],
+ [Encoding, "abc".dup.force_encoding("BINARY"), "\xff".dup.force_encoding("US-ASCII"), Encoding::US_ASCII],
+ [Encoding, "123".dup.force_encoding("US-ASCII"), "\xff".dup.force_encoding("BINARY"), Encoding::BINARY],
].should be_computed_by(:compatible?)
end
it "returns nil if the second's Encoding is not ASCII compatible" do
- a = "abc".force_encoding("UTF-8")
- b = "1234".force_encoding("UTF-16LE")
- Encoding.compatible?(a, b).should be_nil
+ a = "abc".dup.force_encoding("UTF-8")
+ b = "1234".dup.force_encoding("UTF-16LE")
+ Encoding.compatible?(a, b).should == nil
end
end
@@ -69,36 +69,36 @@ describe "Encoding.compatible? String, String" do
end
it "returns nil if the second encoding is ASCII compatible but neither String's encoding is ASCII only" do
- Encoding.compatible?("\xff", "\u3042".encode("utf-8")).should be_nil
+ Encoding.compatible?("\xff", "\u3042".encode("utf-8")).should == nil
end
end
describe "when the first's Encoding is not ASCII compatible" do
before :each do
- @str = "abc".force_encoding Encoding::UTF_7
+ @str = "abc".dup.force_encoding Encoding::UTF_7
end
it "returns nil when the second String is US-ASCII" do
- Encoding.compatible?(@str, "def".encode("us-ascii")).should be_nil
+ Encoding.compatible?(@str, "def".encode("us-ascii")).should == nil
end
it "returns nil when the second String is BINARY and ASCII only" do
- Encoding.compatible?(@str, "\x7f").should be_nil
+ Encoding.compatible?(@str, "\x7f").should == nil
end
it "returns nil when the second String is BINARY but not ASCII only" do
- Encoding.compatible?(@str, "\xff").should be_nil
+ Encoding.compatible?(@str, "\xff").should == nil
end
it "returns the Encoding when the second's Encoding is not ASCII compatible but the same as the first's Encoding" do
- encoding = Encoding.compatible?(@str, "def".force_encoding("utf-7"))
+ encoding = Encoding.compatible?(@str, "def".dup.force_encoding("utf-7"))
encoding.should == Encoding::UTF_7
end
end
describe "when the first's Encoding is invalid" do
before :each do
- @str = "\xff".force_encoding Encoding::UTF_8
+ @str = "\xff".dup.force_encoding Encoding::UTF_8
end
it "returns the first's Encoding when the second's Encoding is US-ASCII" do
@@ -110,15 +110,15 @@ describe "Encoding.compatible? String, String" do
end
it "returns nil when the second's Encoding is BINARY but not ASCII only" do
- Encoding.compatible?(@str, "\xff").should be_nil
+ Encoding.compatible?(@str, "\xff").should == nil
end
it "returns nil when the second's Encoding is invalid and ASCII only" do
- Encoding.compatible?(@str, "\x7f".force_encoding("utf-16be")).should be_nil
+ Encoding.compatible?(@str, "\x7f\x7f".dup.force_encoding("utf-16be")).should == nil
end
it "returns nil when the second's Encoding is invalid and not ASCII only" do
- Encoding.compatible?(@str, "\xff".force_encoding("utf-16be")).should be_nil
+ Encoding.compatible?(@str, "\xff\xff".dup.force_encoding("utf-16be")).should == nil
end
it "returns the Encoding when the second's Encoding is invalid but the same as the first" do
@@ -129,7 +129,7 @@ describe "Encoding.compatible? String, String" do
describe "when the first String is empty and the second is not" do
describe "and the first's Encoding is ASCII compatible" do
before :each do
- @str = "".force_encoding("utf-8")
+ @str = "".dup.force_encoding("utf-8")
end
it "returns the first's encoding when the second String is ASCII only" do
@@ -143,7 +143,7 @@ describe "Encoding.compatible? String, String" do
describe "when the first's Encoding is not ASCII compatible" do
before :each do
- @str = "".force_encoding Encoding::UTF_7
+ @str = "".dup.force_encoding Encoding::UTF_7
end
it "returns the second string's encoding" do
@@ -154,18 +154,391 @@ describe "Encoding.compatible? String, String" do
describe "when the second String is empty" do
before :each do
- @str = "abc".force_encoding("utf-7")
+ @str = "abc".dup.force_encoding("utf-7")
end
it "returns the first Encoding" do
Encoding.compatible?(@str, "").should == Encoding::UTF_7
end
end
+
+ # Encoding negotiation depends on whether encodings are ASCII-compatible, empty
+ # and contain only ASCII characters (that take 7 bits). Check US-ASCII, UTF-8 and
+ # BINARY encodings (as most common) as well as an ASCII-compatible, a non-ASCII-compatible and a dummy
+ # encodings in all possible combinations.
+ describe "compatibility matrix" do
+
+# Use the following script to regenerate the matrix:
+#
+# ```
+# # encoding: binary
+#
+# ENCODINGS = [
+# "US-ASCII",
+# "UTF-8",
+# "ASCII-8BIT",
+# "ISO-8859-1", # ASCII-compatible
+# "UTF-16BE", # non-ASCII-compatible
+# "ISO-2022-JP" # dummy
+# ]
+#
+# TYPES = [:empty, :"7bits", :non7bits]
+#
+# VALUES = {
+# empty: "",
+# :"7bits" => "\x01\x01",
+# non7bits: "\x01\x81"
+# }
+#
+# ENCODINGS.product(TYPES, ENCODINGS, TYPES).each do |encoding1, type1, encoding2, type2|
+# value1 = VALUES[type1].dup.force_encoding(encoding1)
+# value2 = VALUES[type2].dup.force_encoding(encoding2)
+#
+# result_encoding = Encoding.compatible?(value1, value2)
+#
+# puts "[#{encoding1.inspect}, #{value1.inspect}, #{encoding2.inspect}, #{value2.inspect}, #{result_encoding&.name.inspect}],"
+# end
+# ```
+
+ matrix = [
+ ["US-ASCII", "", "US-ASCII", "", "US-ASCII"],
+ ["US-ASCII", "", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["US-ASCII", "", "UTF-8", "", "US-ASCII"],
+ ["US-ASCII", "", "UTF-8", "\u0001\u0001", "US-ASCII"],
+ ["US-ASCII", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["US-ASCII", "", "ASCII-8BIT", "", "US-ASCII"],
+ ["US-ASCII", "", "ASCII-8BIT", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["US-ASCII", "", "ISO-8859-1", "", "US-ASCII"],
+ ["US-ASCII", "", "ISO-8859-1", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["US-ASCII", "", "UTF-16BE", "", "US-ASCII"],
+ ["US-ASCII", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["US-ASCII", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["US-ASCII", "", "ISO-2022-JP", "", "US-ASCII"],
+ ["US-ASCII", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["US-ASCII", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["US-ASCII", "\x01\x01", "US-ASCII", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "UTF-8", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "UTF-8", "\u0001\u0001", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["US-ASCII", "\x01\x01", "ASCII-8BIT", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ASCII-8BIT", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["US-ASCII", "\x01\x01", "ISO-8859-1", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ISO-8859-1", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["US-ASCII", "\x01\x01", "UTF-16BE", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "UTF-16BE", "\u0101", nil],
+ ["US-ASCII", "\x01\x01", "UTF-16BE", "\u0181", nil],
+ ["US-ASCII", "\x01\x01", "ISO-2022-JP", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ISO-2022-JP", "\x01\x01", nil],
+ ["US-ASCII", "\x01\x01", "ISO-2022-JP", "\x01\x81", nil],
+ ["US-ASCII", "\x01\x81", "US-ASCII", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "UTF-8", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "UTF-8", "\u0001\u0001", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "UTF-8", "\u0001\x81", nil],
+ ["US-ASCII", "\x01\x81", "ASCII-8BIT", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ASCII-8BIT", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ASCII-8BIT", "\x01\x81", nil],
+ ["US-ASCII", "\x01\x81", "ISO-8859-1", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ISO-8859-1", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ISO-8859-1", "\x01\x81", nil],
+ ["US-ASCII", "\x01\x81", "UTF-16BE", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "UTF-16BE", "\u0101", nil],
+ ["US-ASCII", "\x01\x81", "UTF-16BE", "\u0181", nil],
+ ["US-ASCII", "\x01\x81", "ISO-2022-JP", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ISO-2022-JP", "\x01\x01", nil],
+ ["US-ASCII", "\x01\x81", "ISO-2022-JP", "\x01\x81", nil],
+ ["UTF-8", "", "US-ASCII", "", "UTF-8"],
+ ["UTF-8", "", "US-ASCII", "\x01\x01", "UTF-8"],
+ ["UTF-8", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["UTF-8", "", "UTF-8", "", "UTF-8"],
+ ["UTF-8", "", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["UTF-8", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["UTF-8", "", "ASCII-8BIT", "", "UTF-8"],
+ ["UTF-8", "", "ASCII-8BIT", "\x01\x01", "UTF-8"],
+ ["UTF-8", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["UTF-8", "", "ISO-8859-1", "", "UTF-8"],
+ ["UTF-8", "", "ISO-8859-1", "\x01\x01", "UTF-8"],
+ ["UTF-8", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["UTF-8", "", "UTF-16BE", "", "UTF-8"],
+ ["UTF-8", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["UTF-8", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["UTF-8", "", "ISO-2022-JP", "", "UTF-8"],
+ ["UTF-8", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["UTF-8", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["UTF-8", "\u0001\u0001", "US-ASCII", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "US-ASCII", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["UTF-8", "\u0001\u0001", "UTF-8", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ASCII-8BIT", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ASCII-8BIT", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["UTF-8", "\u0001\u0001", "ISO-8859-1", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ISO-8859-1", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["UTF-8", "\u0001\u0001", "UTF-16BE", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "UTF-16BE", "\u0101", nil],
+ ["UTF-8", "\u0001\u0001", "UTF-16BE", "\u0181", nil],
+ ["UTF-8", "\u0001\u0001", "ISO-2022-JP", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ISO-2022-JP", "\x01\x01", nil],
+ ["UTF-8", "\u0001\u0001", "ISO-2022-JP", "\x01\x81", nil],
+ ["UTF-8", "\u0001\x81", "US-ASCII", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "US-ASCII", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "US-ASCII", "\x01\x81", nil],
+ ["UTF-8", "\u0001\x81", "UTF-8", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ASCII-8BIT", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ASCII-8BIT", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ASCII-8BIT", "\x01\x81", nil],
+ ["UTF-8", "\u0001\x81", "ISO-8859-1", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ISO-8859-1", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ISO-8859-1", "\x01\x81", nil],
+ ["UTF-8", "\u0001\x81", "UTF-16BE", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "UTF-16BE", "\u0101", nil],
+ ["UTF-8", "\u0001\x81", "UTF-16BE", "\u0181", nil],
+ ["UTF-8", "\u0001\x81", "ISO-2022-JP", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ISO-2022-JP", "\x01\x01", nil],
+ ["UTF-8", "\u0001\x81", "ISO-2022-JP", "\x01\x81", nil],
+ ["ASCII-8BIT", "", "US-ASCII", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "US-ASCII", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ASCII-8BIT", "", "UTF-8", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "UTF-8", "\u0001\u0001", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ASCII-8BIT", "", "ASCII-8BIT", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ISO-8859-1", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ISO-8859-1", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ASCII-8BIT", "", "UTF-16BE", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["ASCII-8BIT", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["ASCII-8BIT", "", "ISO-2022-JP", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ASCII-8BIT", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["ASCII-8BIT", "\x01\x01", "US-ASCII", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "US-ASCII", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-8", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-8", "\u0001\u0001", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ASCII-8BIT", "\x01\x01", "ASCII-8BIT", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ISO-8859-1", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ISO-8859-1", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-16BE", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-16BE", "\u0101", nil],
+ ["ASCII-8BIT", "\x01\x01", "UTF-16BE", "\u0181", nil],
+ ["ASCII-8BIT", "\x01\x01", "ISO-2022-JP", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ISO-2022-JP", "\x01\x01", nil],
+ ["ASCII-8BIT", "\x01\x01", "ISO-2022-JP", "\x01\x81", nil],
+ ["ASCII-8BIT", "\x01\x81", "US-ASCII", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "US-ASCII", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "US-ASCII", "\x01\x81", nil],
+ ["ASCII-8BIT", "\x01\x81", "UTF-8", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "UTF-8", "\u0001\u0001", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "UTF-8", "\u0001\x81", nil],
+ ["ASCII-8BIT", "\x01\x81", "ASCII-8BIT", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ISO-8859-1", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ISO-8859-1", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ISO-8859-1", "\x01\x81", nil],
+ ["ASCII-8BIT", "\x01\x81", "UTF-16BE", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "UTF-16BE", "\u0101", nil],
+ ["ASCII-8BIT", "\x01\x81", "UTF-16BE", "\u0181", nil],
+ ["ASCII-8BIT", "\x01\x81", "ISO-2022-JP", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ISO-2022-JP", "\x01\x01", nil],
+ ["ASCII-8BIT", "\x01\x81", "ISO-2022-JP", "\x01\x81", nil],
+ ["ISO-8859-1", "", "US-ASCII", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "US-ASCII", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ISO-8859-1", "", "UTF-8", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "UTF-8", "\u0001\u0001", "ISO-8859-1"],
+ ["ISO-8859-1", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ISO-8859-1", "", "ASCII-8BIT", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ASCII-8BIT", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ISO-8859-1", "", "ISO-8859-1", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ISO-8859-1", "", "UTF-16BE", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["ISO-8859-1", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["ISO-8859-1", "", "ISO-2022-JP", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ISO-8859-1", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["ISO-8859-1", "\x01\x01", "US-ASCII", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "US-ASCII", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ISO-8859-1", "\x01\x01", "UTF-8", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "UTF-8", "\u0001\u0001", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ISO-8859-1", "\x01\x01", "ASCII-8BIT", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ASCII-8BIT", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ISO-8859-1", "\x01\x01", "ISO-8859-1", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "UTF-16BE", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "UTF-16BE", "\u0101", nil],
+ ["ISO-8859-1", "\x01\x01", "UTF-16BE", "\u0181", nil],
+ ["ISO-8859-1", "\x01\x01", "ISO-2022-JP", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ISO-2022-JP", "\x01\x01", nil],
+ ["ISO-8859-1", "\x01\x01", "ISO-2022-JP", "\x01\x81", nil],
+ ["ISO-8859-1", "\x01\x81", "US-ASCII", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "US-ASCII", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "US-ASCII", "\x01\x81", nil],
+ ["ISO-8859-1", "\x01\x81", "UTF-8", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "UTF-8", "\u0001\u0001", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "UTF-8", "\u0001\x81", nil],
+ ["ISO-8859-1", "\x01\x81", "ASCII-8BIT", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ASCII-8BIT", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ASCII-8BIT", "\x01\x81", nil],
+ ["ISO-8859-1", "\x01\x81", "ISO-8859-1", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "UTF-16BE", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "UTF-16BE", "\u0101", nil],
+ ["ISO-8859-1", "\x01\x81", "UTF-16BE", "\u0181", nil],
+ ["ISO-8859-1", "\x01\x81", "ISO-2022-JP", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ISO-2022-JP", "\x01\x01", nil],
+ ["ISO-8859-1", "\x01\x81", "ISO-2022-JP", "\x01\x81", nil],
+ ["UTF-16BE", "", "US-ASCII", "", "UTF-16BE"],
+ ["UTF-16BE", "", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["UTF-16BE", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["UTF-16BE", "", "UTF-8", "", "UTF-16BE"],
+ ["UTF-16BE", "", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["UTF-16BE", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["UTF-16BE", "", "ASCII-8BIT", "", "UTF-16BE"],
+ ["UTF-16BE", "", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["UTF-16BE", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["UTF-16BE", "", "ISO-8859-1", "", "UTF-16BE"],
+ ["UTF-16BE", "", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["UTF-16BE", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["UTF-16BE", "", "UTF-16BE", "", "UTF-16BE"],
+ ["UTF-16BE", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["UTF-16BE", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["UTF-16BE", "", "ISO-2022-JP", "", "UTF-16BE"],
+ ["UTF-16BE", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["UTF-16BE", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["UTF-16BE", "\u0101", "US-ASCII", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "US-ASCII", "\x01\x01", nil],
+ ["UTF-16BE", "\u0101", "US-ASCII", "\x01\x81", nil],
+ ["UTF-16BE", "\u0101", "UTF-8", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "UTF-8", "\u0001\u0001", nil],
+ ["UTF-16BE", "\u0101", "UTF-8", "\u0001\x81", nil],
+ ["UTF-16BE", "\u0101", "ASCII-8BIT", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "ASCII-8BIT", "\x01\x01", nil],
+ ["UTF-16BE", "\u0101", "ASCII-8BIT", "\x01\x81", nil],
+ ["UTF-16BE", "\u0101", "ISO-8859-1", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "ISO-8859-1", "\x01\x01", nil],
+ ["UTF-16BE", "\u0101", "ISO-8859-1", "\x01\x81", nil],
+ ["UTF-16BE", "\u0101", "UTF-16BE", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "ISO-2022-JP", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "ISO-2022-JP", "\x01\x01", nil],
+ ["UTF-16BE", "\u0101", "ISO-2022-JP", "\x01\x81", nil],
+ ["UTF-16BE", "\u0181", "US-ASCII", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "US-ASCII", "\x01\x01", nil],
+ ["UTF-16BE", "\u0181", "US-ASCII", "\x01\x81", nil],
+ ["UTF-16BE", "\u0181", "UTF-8", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "UTF-8", "\u0001\u0001", nil],
+ ["UTF-16BE", "\u0181", "UTF-8", "\u0001\x81", nil],
+ ["UTF-16BE", "\u0181", "ASCII-8BIT", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "ASCII-8BIT", "\x01\x01", nil],
+ ["UTF-16BE", "\u0181", "ASCII-8BIT", "\x01\x81", nil],
+ ["UTF-16BE", "\u0181", "ISO-8859-1", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "ISO-8859-1", "\x01\x01", nil],
+ ["UTF-16BE", "\u0181", "ISO-8859-1", "\x01\x81", nil],
+ ["UTF-16BE", "\u0181", "UTF-16BE", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "ISO-2022-JP", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "ISO-2022-JP", "\x01\x01", nil],
+ ["UTF-16BE", "\u0181", "ISO-2022-JP", "\x01\x81", nil],
+ ["ISO-2022-JP", "", "US-ASCII", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["ISO-2022-JP", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ISO-2022-JP", "", "UTF-8", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["ISO-2022-JP", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ISO-2022-JP", "", "ASCII-8BIT", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["ISO-2022-JP", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ISO-2022-JP", "", "ISO-8859-1", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["ISO-2022-JP", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ISO-2022-JP", "", "UTF-16BE", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["ISO-2022-JP", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["ISO-2022-JP", "", "ISO-2022-JP", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "US-ASCII", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "US-ASCII", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x01", "US-ASCII", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x01", "UTF-8", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "UTF-8", "\u0001\u0001", nil],
+ ["ISO-2022-JP", "\x01\x01", "UTF-8", "\u0001\x81", nil],
+ ["ISO-2022-JP", "\x01\x01", "ASCII-8BIT", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "ASCII-8BIT", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x01", "ASCII-8BIT", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x01", "ISO-8859-1", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "ISO-8859-1", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x01", "ISO-8859-1", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x01", "UTF-16BE", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "UTF-16BE", "\u0101", nil],
+ ["ISO-2022-JP", "\x01\x01", "UTF-16BE", "\u0181", nil],
+ ["ISO-2022-JP", "\x01\x01", "ISO-2022-JP", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "US-ASCII", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "US-ASCII", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x81", "US-ASCII", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x81", "UTF-8", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "UTF-8", "\u0001\u0001", nil],
+ ["ISO-2022-JP", "\x01\x81", "UTF-8", "\u0001\x81", nil],
+ ["ISO-2022-JP", "\x01\x81", "ASCII-8BIT", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "ASCII-8BIT", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x81", "ASCII-8BIT", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x81", "ISO-8859-1", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "ISO-8859-1", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x81", "ISO-8859-1", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x81", "UTF-16BE", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "UTF-16BE", "\u0101", nil],
+ ["ISO-2022-JP", "\x01\x81", "UTF-16BE", "\u0181", nil],
+ ["ISO-2022-JP", "\x01\x81", "ISO-2022-JP", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ]
+
+ matrix.each do |encoding1, value1, encoding2, value2, compatible_encoding|
+ it "returns #{compatible_encoding} for #{value1.inspect} in #{encoding1} and #{value2.inspect} in #{encoding2}" do
+ actual_encoding = Encoding.compatible?(value1.dup.force_encoding(encoding1), value2.dup.force_encoding(encoding2))
+ actual_encoding&.name.should == compatible_encoding
+ end
+ end
+ end
end
describe "Encoding.compatible? String, Regexp" do
it "returns US-ASCII if both are US-ASCII" do
- str = "abc".force_encoding("us-ascii")
+ str = "abc".dup.force_encoding("us-ascii")
Encoding.compatible?(str, /abc/).should == Encoding::US_ASCII
end
@@ -180,15 +553,20 @@ describe "Encoding.compatible? String, Regexp" do
it "returns the String's Encoding if the String is not ASCII only" do
[ [Encoding, "\xff", Encoding::BINARY],
[Encoding, "\u3042".encode("utf-8"), Encoding::UTF_8],
- [Encoding, "\xa4\xa2".force_encoding("euc-jp"), Encoding::EUC_JP],
- [Encoding, "\x82\xa0".force_encoding("shift_jis"), Encoding::Shift_JIS],
+ [Encoding, "\xa4\xa2".dup.force_encoding("euc-jp"), Encoding::EUC_JP],
+ [Encoding, "\x82\xa0".dup.force_encoding("shift_jis"), Encoding::Shift_JIS],
].should be_computed_by(:compatible?, /abc/)
end
+
+ it "returns the Regexp's Encoding if the String is ASCII only and the Regexp is not" do
+ r = Regexp.new("\xa4\xa2".dup.force_encoding("euc-jp"))
+ Encoding.compatible?("hello".dup.force_encoding("utf-8"), r).should == Encoding::EUC_JP
+ end
end
describe "Encoding.compatible? String, Symbol" do
it "returns US-ASCII if both are ASCII only" do
- str = "abc".force_encoding("us-ascii")
+ str = "abc".dup.force_encoding("us-ascii")
Encoding.compatible?(str, :abc).should == Encoding::US_ASCII
end
@@ -203,26 +581,26 @@ describe "Encoding.compatible? String, Symbol" do
it "returns the String's Encoding if the String is not ASCII only" do
[ [Encoding, "\xff", Encoding::BINARY],
[Encoding, "\u3042".encode("utf-8"), Encoding::UTF_8],
- [Encoding, "\xa4\xa2".force_encoding("euc-jp"), Encoding::EUC_JP],
- [Encoding, "\x82\xa0".force_encoding("shift_jis"), Encoding::Shift_JIS],
+ [Encoding, "\xa4\xa2".dup.force_encoding("euc-jp"), Encoding::EUC_JP],
+ [Encoding, "\x82\xa0".dup.force_encoding("shift_jis"), Encoding::Shift_JIS],
].should be_computed_by(:compatible?, :abc)
end
end
describe "Encoding.compatible? String, Encoding" do
it "returns nil if the String's encoding is not ASCII compatible" do
- Encoding.compatible?("abc".encode("utf-32le"), Encoding::US_ASCII).should be_nil
+ Encoding.compatible?("abc".encode("utf-32le"), Encoding::US_ASCII).should == nil
end
it "returns nil if the Encoding is not ASCII compatible" do
- Encoding.compatible?("abc".encode("us-ascii"), Encoding::UTF_32LE).should be_nil
+ Encoding.compatible?("abc".encode("us-ascii"), Encoding::UTF_32LE).should == nil
end
it "returns the String's encoding if the Encoding is US-ASCII" do
[ [Encoding, "\xff", Encoding::BINARY],
[Encoding, "\u3042".encode("utf-8"), Encoding::UTF_8],
- [Encoding, "\xa4\xa2".force_encoding("euc-jp"), Encoding::EUC_JP],
- [Encoding, "\x82\xa0".force_encoding("shift_jis"), Encoding::Shift_JIS],
+ [Encoding, "\xa4\xa2".dup.force_encoding("euc-jp"), Encoding::EUC_JP],
+ [Encoding, "\x82\xa0".dup.force_encoding("shift_jis"), Encoding::Shift_JIS],
].should be_computed_by(:compatible?, Encoding::US_ASCII)
end
@@ -236,16 +614,25 @@ describe "Encoding.compatible? String, Encoding" do
end
it "returns nil if the String's encoding is ASCII compatible but the string is not ASCII only" do
- Encoding.compatible?("\u3042".encode("utf-8"), Encoding::BINARY).should be_nil
+ Encoding.compatible?("\u3042".encode("utf-8"), Encoding::BINARY).should == nil
end
end
describe "Encoding.compatible? Regexp, String" do
it "returns US-ASCII if both are US-ASCII" do
- str = "abc".force_encoding("us-ascii")
+ str = "abc".dup.force_encoding("us-ascii")
Encoding.compatible?(/abc/, str).should == Encoding::US_ASCII
end
+ it "returns the String's Encoding when the String is ASCII only with a different encoding" do
+ r = Regexp.new("\xa4\xa2".dup.force_encoding("euc-jp"))
+ Encoding.compatible?(r, "hello".dup.force_encoding("utf-8")).should == Encoding::UTF_8
+ end
+
+ it "returns the Regexp's Encoding if the String has the same non-ASCII encoding" do
+ r = Regexp.new("\xa4\xa2".dup.force_encoding("euc-jp"))
+ Encoding.compatible?(r, "hello".dup.force_encoding("euc-jp")).should == Encoding::EUC_JP
+ end
end
describe "Encoding.compatible? Regexp, Regexp" do
@@ -256,8 +643,8 @@ describe "Encoding.compatible? Regexp, Regexp" do
it "returns the first's Encoding if it is not US-ASCII and not ASCII only" do
[ [Encoding, Regexp.new("\xff"), Encoding::BINARY],
[Encoding, Regexp.new("\u3042".encode("utf-8")), Encoding::UTF_8],
- [Encoding, Regexp.new("\xa4\xa2".force_encoding("euc-jp")), Encoding::EUC_JP],
- [Encoding, Regexp.new("\x82\xa0".force_encoding("shift_jis")), Encoding::Shift_JIS],
+ [Encoding, Regexp.new("\xa4\xa2".dup.force_encoding("euc-jp")), Encoding::EUC_JP],
+ [Encoding, Regexp.new("\x82\xa0".dup.force_encoding("shift_jis")), Encoding::Shift_JIS],
].should be_computed_by(:compatible?, /abc/)
end
end
@@ -270,15 +657,15 @@ describe "Encoding.compatible? Regexp, Symbol" do
it "returns the first's Encoding if it is not US-ASCII and not ASCII only" do
[ [Encoding, Regexp.new("\xff"), Encoding::BINARY],
[Encoding, Regexp.new("\u3042".encode("utf-8")), Encoding::UTF_8],
- [Encoding, Regexp.new("\xa4\xa2".force_encoding("euc-jp")), Encoding::EUC_JP],
- [Encoding, Regexp.new("\x82\xa0".force_encoding("shift_jis")), Encoding::Shift_JIS],
+ [Encoding, Regexp.new("\xa4\xa2".dup.force_encoding("euc-jp")), Encoding::EUC_JP],
+ [Encoding, Regexp.new("\x82\xa0".dup.force_encoding("shift_jis")), Encoding::Shift_JIS],
].should be_computed_by(:compatible?, /abc/)
end
end
describe "Encoding.compatible? Symbol, String" do
it "returns US-ASCII if both are ASCII only" do
- str = "abc".force_encoding("us-ascii")
+ str = "abc".dup.force_encoding("us-ascii")
Encoding.compatible?(str, :abc).should == Encoding::US_ASCII
end
end
@@ -291,8 +678,8 @@ describe "Encoding.compatible? Symbol, Regexp" do
it "returns the Regexp's Encoding if it is not US-ASCII and not ASCII only" do
a = Regexp.new("\xff")
b = Regexp.new("\u3042".encode("utf-8"))
- c = Regexp.new("\xa4\xa2".force_encoding("euc-jp"))
- d = Regexp.new("\x82\xa0".force_encoding("shift_jis"))
+ c = Regexp.new("\xa4\xa2".dup.force_encoding("euc-jp"))
+ d = Regexp.new("\x82\xa0".dup.force_encoding("shift_jis"))
[ [Encoding, :abc, a, Encoding::BINARY],
[Encoding, :abc, b, Encoding::UTF_8],
@@ -310,8 +697,8 @@ describe "Encoding.compatible? Symbol, Symbol" do
it "returns the first's Encoding if it is not ASCII only" do
[ [Encoding, "\xff".to_sym, Encoding::BINARY],
[Encoding, "\u3042".encode("utf-8").to_sym, Encoding::UTF_8],
- [Encoding, "\xa4\xa2".force_encoding("euc-jp").to_sym, Encoding::EUC_JP],
- [Encoding, "\x82\xa0".force_encoding("shift_jis").to_sym, Encoding::Shift_JIS],
+ [Encoding, "\xa4\xa2".dup.force_encoding("euc-jp").to_sym, Encoding::EUC_JP],
+ [Encoding, "\x82\xa0".dup.force_encoding("shift_jis").to_sym, Encoding::Shift_JIS],
].should be_computed_by(:compatible?, :abc)
end
end
@@ -354,26 +741,32 @@ end
describe "Encoding.compatible? Object, Object" do
it "returns nil for Object, String" do
- Encoding.compatible?(Object.new, "abc").should be_nil
+ Encoding.compatible?(Object.new, "abc").should == nil
end
it "returns nil for Object, Regexp" do
- Encoding.compatible?(Object.new, /./).should be_nil
+ Encoding.compatible?(Object.new, /./).should == nil
end
it "returns nil for Object, Symbol" do
- Encoding.compatible?(Object.new, :sym).should be_nil
+ Encoding.compatible?(Object.new, :sym).should == nil
end
it "returns nil for String, Object" do
- Encoding.compatible?("abc", Object.new).should be_nil
+ Encoding.compatible?("abc", Object.new).should == nil
end
it "returns nil for Regexp, Object" do
- Encoding.compatible?(/./, Object.new).should be_nil
+ Encoding.compatible?(/./, Object.new).should == nil
end
it "returns nil for Symbol, Object" do
- Encoding.compatible?(:sym, Object.new).should be_nil
+ Encoding.compatible?(:sym, Object.new).should == nil
+ end
+end
+
+describe "Encoding.compatible? nil, nil" do
+ it "returns nil" do
+ Encoding.compatible?(nil, nil).should == nil
end
end
diff --git a/spec/ruby/core/encoding/converter/asciicompat_encoding_spec.rb b/spec/ruby/core/encoding/converter/asciicompat_encoding_spec.rb
index 1beb40af3f..07c7a88356 100644
--- a/spec/ruby/core/encoding/converter/asciicompat_encoding_spec.rb
+++ b/spec/ruby/core/encoding/converter/asciicompat_encoding_spec.rb
@@ -24,14 +24,14 @@ describe "Encoding::Converter.asciicompat_encoding" do
end
it "returns nil when the given encoding is ASCII compatible" do
- Encoding::Converter.asciicompat_encoding('ASCII').should be_nil
- Encoding::Converter.asciicompat_encoding('UTF-8').should be_nil
+ Encoding::Converter.asciicompat_encoding('ASCII').should == nil
+ Encoding::Converter.asciicompat_encoding('UTF-8').should == nil
end
it "handles encoding names who resolve to nil encodings" do
internal = Encoding.default_internal
Encoding.default_internal = nil
- Encoding::Converter.asciicompat_encoding('internal').should be_nil
+ Encoding::Converter.asciicompat_encoding('internal').should == nil
Encoding.default_internal = internal
end
end
diff --git a/spec/ruby/core/encoding/converter/constants_spec.rb b/spec/ruby/core/encoding/converter/constants_spec.rb
index 7d29bdb278..e2d21b5429 100644
--- a/spec/ruby/core/encoding/converter/constants_spec.rb
+++ b/spec/ruby/core/encoding/converter/constants_spec.rb
@@ -2,130 +2,130 @@ require_relative '../../../spec_helper'
describe "Encoding::Converter::INVALID_MASK" do
it "exists" do
- Encoding::Converter.should have_constant(:INVALID_MASK)
+ Encoding::Converter.should.const_defined?(:INVALID_MASK, false)
end
it "has an Integer value" do
- Encoding::Converter::INVALID_MASK.should be_an_instance_of(Integer)
+ Encoding::Converter::INVALID_MASK.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::INVALID_REPLACE" do
it "exists" do
- Encoding::Converter.should have_constant(:INVALID_REPLACE)
+ Encoding::Converter.should.const_defined?(:INVALID_REPLACE, false)
end
it "has an Integer value" do
- Encoding::Converter::INVALID_REPLACE.should be_an_instance_of(Integer)
+ Encoding::Converter::INVALID_REPLACE.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::UNDEF_MASK" do
it "exists" do
- Encoding::Converter.should have_constant(:UNDEF_MASK)
+ Encoding::Converter.should.const_defined?(:UNDEF_MASK, false)
end
it "has an Integer value" do
- Encoding::Converter::UNDEF_MASK.should be_an_instance_of(Integer)
+ Encoding::Converter::UNDEF_MASK.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::UNDEF_REPLACE" do
it "exists" do
- Encoding::Converter.should have_constant(:UNDEF_REPLACE)
+ Encoding::Converter.should.const_defined?(:UNDEF_REPLACE, false)
end
it "has an Integer value" do
- Encoding::Converter::UNDEF_REPLACE.should be_an_instance_of(Integer)
+ Encoding::Converter::UNDEF_REPLACE.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::UNDEF_HEX_CHARREF" do
it "exists" do
- Encoding::Converter.should have_constant(:UNDEF_HEX_CHARREF)
+ Encoding::Converter.should.const_defined?(:UNDEF_HEX_CHARREF, false)
end
it "has an Integer value" do
- Encoding::Converter::UNDEF_HEX_CHARREF.should be_an_instance_of(Integer)
+ Encoding::Converter::UNDEF_HEX_CHARREF.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::PARTIAL_INPUT" do
it "exists" do
- Encoding::Converter.should have_constant(:PARTIAL_INPUT)
+ Encoding::Converter.should.const_defined?(:PARTIAL_INPUT, false)
end
it "has an Integer value" do
- Encoding::Converter::PARTIAL_INPUT.should be_an_instance_of(Integer)
+ Encoding::Converter::PARTIAL_INPUT.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::AFTER_OUTPUT" do
it "exists" do
- Encoding::Converter.should have_constant(:AFTER_OUTPUT)
+ Encoding::Converter.should.const_defined?(:AFTER_OUTPUT, false)
end
it "has an Integer value" do
- Encoding::Converter::AFTER_OUTPUT.should be_an_instance_of(Integer)
+ Encoding::Converter::AFTER_OUTPUT.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR" do
it "exists" do
- Encoding::Converter.should have_constant(:UNIVERSAL_NEWLINE_DECORATOR)
+ Encoding::Converter.should.const_defined?(:UNIVERSAL_NEWLINE_DECORATOR, false)
end
it "has an Integer value" do
- Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR.should be_an_instance_of(Integer)
+ Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::CRLF_NEWLINE_DECORATOR" do
it "exists" do
- Encoding::Converter.should have_constant(:CRLF_NEWLINE_DECORATOR)
+ Encoding::Converter.should.const_defined?(:CRLF_NEWLINE_DECORATOR, false)
end
it "has an Integer value" do
- Encoding::Converter::CRLF_NEWLINE_DECORATOR.should be_an_instance_of(Integer)
+ Encoding::Converter::CRLF_NEWLINE_DECORATOR.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::CR_NEWLINE_DECORATOR" do
it "exists" do
- Encoding::Converter.should have_constant(:CR_NEWLINE_DECORATOR)
+ Encoding::Converter.should.const_defined?(:CR_NEWLINE_DECORATOR, false)
end
it "has an Integer value" do
- Encoding::Converter::CR_NEWLINE_DECORATOR.should be_an_instance_of(Integer)
+ Encoding::Converter::CR_NEWLINE_DECORATOR.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::XML_TEXT_DECORATOR" do
it "exists" do
- Encoding::Converter.should have_constant(:XML_TEXT_DECORATOR)
+ Encoding::Converter.should.const_defined?(:XML_TEXT_DECORATOR, false)
end
it "has an Integer value" do
- Encoding::Converter::XML_TEXT_DECORATOR.should be_an_instance_of(Integer)
+ Encoding::Converter::XML_TEXT_DECORATOR.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::XML_ATTR_CONTENT_DECORATOR" do
it "exists" do
- Encoding::Converter.should have_constant(:XML_ATTR_CONTENT_DECORATOR)
+ Encoding::Converter.should.const_defined?(:XML_ATTR_CONTENT_DECORATOR, false)
end
it "has an Integer value" do
- Encoding::Converter::XML_ATTR_CONTENT_DECORATOR.should be_an_instance_of(Integer)
+ Encoding::Converter::XML_ATTR_CONTENT_DECORATOR.should.instance_of?(Integer)
end
end
describe "Encoding::Converter::XML_ATTR_QUOTE_DECORATOR" do
it "exists" do
- Encoding::Converter.should have_constant(:XML_ATTR_QUOTE_DECORATOR)
+ Encoding::Converter.should.const_defined?(:XML_ATTR_QUOTE_DECORATOR, false)
end
it "has an Integer value" do
- Encoding::Converter::XML_ATTR_QUOTE_DECORATOR.should be_an_instance_of(Integer)
+ Encoding::Converter::XML_ATTR_QUOTE_DECORATOR.should.instance_of?(Integer)
end
end
diff --git a/spec/ruby/core/encoding/converter/convert_spec.rb b/spec/ruby/core/encoding/converter/convert_spec.rb
index 95a9e0b758..c95e88a491 100644
--- a/spec/ruby/core/encoding/converter/convert_spec.rb
+++ b/spec/ruby/core/encoding/converter/convert_spec.rb
@@ -1,45 +1,45 @@
-# -*- encoding: binary -*-
+# encoding: binary
+# frozen_string_literal: true
require_relative '../../../spec_helper'
describe "Encoding::Converter#convert" do
it "returns a String" do
ec = Encoding::Converter.new('ascii', 'utf-8')
- ec.convert('glark').should be_an_instance_of(String)
+ ec.convert('glark').should.instance_of?(String)
end
it "sets the encoding of the result to the target encoding" do
ec = Encoding::Converter.new('ascii', 'utf-8')
- str = 'glark'.force_encoding('ascii')
+ str = 'glark'.dup.force_encoding('ascii')
ec.convert(str).encoding.should == Encoding::UTF_8
end
it "transcodes the given String to the target encoding" do
ec = Encoding::Converter.new("utf-8", "euc-jp")
- ec.convert("\u3042".force_encoding('UTF-8')).should == \
- "\xA4\xA2".force_encoding('EUC-JP')
+ ec.convert("\u3042".dup.force_encoding('UTF-8')).should == \
+ "\xA4\xA2".dup.force_encoding('EUC-JP')
end
it "allows Strings of different encodings to the source encoding" do
ec = Encoding::Converter.new('ascii', 'utf-8')
- str = 'glark'.force_encoding('SJIS')
+ str = 'glark'.dup.force_encoding('SJIS')
ec.convert(str).encoding.should == Encoding::UTF_8
end
it "reuses the given encoding pair if called multiple times" do
ec = Encoding::Converter.new('ascii', 'SJIS')
- ec.convert('a'.force_encoding('ASCII')).should == 'a'.force_encoding('SJIS')
- ec.convert('b'.force_encoding('ASCII')).should == 'b'.force_encoding('SJIS')
+ ec.convert('a'.dup.force_encoding('ASCII')).should == 'a'.dup.force_encoding('SJIS')
+ ec.convert('b'.dup.force_encoding('ASCII')).should == 'b'.dup.force_encoding('SJIS')
end
it "raises UndefinedConversionError if the String contains characters invalid for the target encoding" do
ec = Encoding::Converter.new('UTF-8', Encoding.find('macCyrillic'))
- -> { ec.convert("\u{6543}".force_encoding('UTF-8')) }.should \
- raise_error(Encoding::UndefinedConversionError)
+ -> { ec.convert("\u{6543}".dup.force_encoding('UTF-8')) }.should.raise(Encoding::UndefinedConversionError)
end
it "raises an ArgumentError if called on a finished stream" do
ec = Encoding::Converter.new('UTF-8', Encoding.find('macCyrillic'))
ec.finish
- -> { ec.convert("\u{65}") }.should raise_error(ArgumentError)
+ -> { ec.convert("\u{65}") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/encoding/converter/finish_spec.rb b/spec/ruby/core/encoding/converter/finish_spec.rb
index 11ca7e8510..e13b7415f8 100644
--- a/spec/ruby/core/encoding/converter/finish_spec.rb
+++ b/spec/ruby/core/encoding/converter/finish_spec.rb
@@ -7,7 +7,7 @@ describe "Encoding::Converter#finish" do
it "returns a String" do
@ec.convert('foo')
- @ec.finish.should be_an_instance_of(String)
+ @ec.finish.should.instance_of?(String)
end
it "returns an empty String if there is nothing more to convert" do
@@ -16,8 +16,8 @@ describe "Encoding::Converter#finish" do
end
it "returns the last part of the converted String if it hasn't already" do
- @ec.convert("\u{9999}").should == "\e$B9a".force_encoding('iso-2022-jp')
- @ec.finish.should == "\e(B".force_encoding('iso-2022-jp')
+ @ec.convert("\u{9999}").should == "\e$B9a".dup.force_encoding('iso-2022-jp')
+ @ec.finish.should == "\e(B".dup.force_encoding('iso-2022-jp')
end
it "returns a String in the destination encoding" do
diff --git a/spec/ruby/core/encoding/converter/last_error_spec.rb b/spec/ruby/core/encoding/converter/last_error_spec.rb
index 68567737b7..3984a628f5 100644
--- a/spec/ruby/core/encoding/converter/last_error_spec.rb
+++ b/spec/ruby/core/encoding/converter/last_error_spec.rb
@@ -1,54 +1,54 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe "Encoding::Converter#last_error" do
it "returns nil when the no conversion has been attempted" do
ec = Encoding::Converter.new('ascii','utf-8')
- ec.last_error.should be_nil
+ ec.last_error.should == nil
end
it "returns nil when the last conversion did not produce an error" do
ec = Encoding::Converter.new('ascii','utf-8')
- ec.convert('a'.force_encoding('ascii'))
- ec.last_error.should be_nil
+ ec.convert('a'.dup.force_encoding('ascii'))
+ ec.last_error.should == nil
end
it "returns 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) \
+ ec.primitive_convert(+"\u{9999}", +"", 0, 0, partial_input: false) \
.should == :destination_buffer_full
- ec.last_error.should be_nil
+ ec.last_error.should == nil
end
it "returns nil when #primitive_convert last returned :finished" do
ec = Encoding::Converter.new("utf-8", "iso-8859-1")
- ec.primitive_convert("glark".force_encoding('utf-8'),"").should == :finished
- ec.last_error.should be_nil
+ ec.primitive_convert("glark".dup.force_encoding('utf-8'), +"").should == :finished
+ ec.last_error.should == nil
end
it "returns nil if the last conversion succeeded but the penultimate failed" do
ec = Encoding::Converter.new("utf-8", "iso-8859-1")
- ec.primitive_convert("\xf1abcd","").should == :invalid_byte_sequence
- ec.primitive_convert("glark".force_encoding('utf-8'),"").should == :finished
- ec.last_error.should be_nil
+ ec.primitive_convert(+"\xf1abcd", +"").should == :invalid_byte_sequence
+ ec.primitive_convert("glark".dup.force_encoding('utf-8'), +"").should == :finished
+ ec.last_error.should == nil
end
it "returns an Encoding::InvalidByteSequenceError when #primitive_convert last returned :invalid_byte_sequence" do
ec = Encoding::Converter.new("utf-8", "iso-8859-1")
- ec.primitive_convert("\xf1abcd","").should == :invalid_byte_sequence
- ec.last_error.should be_an_instance_of(Encoding::InvalidByteSequenceError)
+ ec.primitive_convert(+"\xf1abcd", +"").should == :invalid_byte_sequence
+ ec.last_error.should.instance_of?(Encoding::InvalidByteSequenceError)
end
it "returns an Encoding::UndefinedConversionError when #primitive_convert last returned :undefined_conversion" do
ec = Encoding::Converter.new("utf-8", "iso-8859-1")
- ec.primitive_convert("\u{9876}","").should == :undefined_conversion
- ec.last_error.should be_an_instance_of(Encoding::UndefinedConversionError)
+ ec.primitive_convert(+"\u{9876}", +"").should == :undefined_conversion
+ ec.last_error.should.instance_of?(Encoding::UndefinedConversionError)
end
it "returns an Encoding::InvalidByteSequenceError when #primitive_convert last returned :incomplete_input" do
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
- ec.primitive_convert("\xa4", "", nil, 10).should == :incomplete_input
- ec.last_error.should be_an_instance_of(Encoding::InvalidByteSequenceError)
+ ec.primitive_convert(+"\xa4", +"", nil, 10).should == :incomplete_input
+ ec.last_error.should.instance_of?(Encoding::InvalidByteSequenceError)
end
it "returns an Encoding::InvalidByteSequenceError when the last call to #convert produced one" do
@@ -56,10 +56,10 @@ describe "Encoding::Converter#last_error" do
exception = nil
-> {
ec.convert("\xf1abcd")
- }.should raise_error(Encoding::InvalidByteSequenceError) { |e|
+ }.should.raise(Encoding::InvalidByteSequenceError) { |e|
exception = e
}
- ec.last_error.should be_an_instance_of(Encoding::InvalidByteSequenceError)
+ ec.last_error.should.instance_of?(Encoding::InvalidByteSequenceError)
ec.last_error.message.should == exception.message
end
@@ -68,12 +68,12 @@ describe "Encoding::Converter#last_error" do
exception = nil
-> {
ec.convert("\u{9899}")
- }.should raise_error(Encoding::UndefinedConversionError) { |e|
+ }.should.raise(Encoding::UndefinedConversionError) { |e|
exception = e
}
- ec.last_error.should be_an_instance_of(Encoding::UndefinedConversionError)
+ ec.last_error.should.instance_of?(Encoding::UndefinedConversionError)
ec.last_error.message.should == exception.message
- ec.last_error.message.should include "from UTF-8 to ISO-8859-1"
+ ec.last_error.message.should.include? "from UTF-8 to ISO-8859-1"
end
it "returns the last error of #convert with a message showing the transcoding path" do
@@ -81,11 +81,11 @@ describe "Encoding::Converter#last_error" do
exception = nil
-> {
ec.convert("\xE9") # é in ISO-8859-1
- }.should raise_error(Encoding::UndefinedConversionError) { |e|
+ }.should.raise(Encoding::UndefinedConversionError) { |e|
exception = e
}
- ec.last_error.should be_an_instance_of(Encoding::UndefinedConversionError)
+ ec.last_error.should.instance_of?(Encoding::UndefinedConversionError)
ec.last_error.message.should == exception.message
- ec.last_error.message.should include "from ISO-8859-1 to UTF-8 to Big5"
+ ec.last_error.message.should.include? "from ISO-8859-1 to UTF-8 to Big5"
end
end
diff --git a/spec/ruby/core/encoding/converter/new_spec.rb b/spec/ruby/core/encoding/converter/new_spec.rb
index 1f7affc72b..bbdfb48bce 100644
--- a/spec/ruby/core/encoding/converter/new_spec.rb
+++ b/spec/ruby/core/encoding/converter/new_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe "Encoding::Converter.new" do
@@ -25,7 +25,7 @@ describe "Encoding::Converter.new" do
it "raises an Encoding::ConverterNotFoundError if both encodings are the same" do
-> do
Encoding::Converter.new "utf-8", "utf-8"
- end.should raise_error(Encoding::ConverterNotFoundError)
+ end.should.raise(Encoding::ConverterNotFoundError)
end
it "calls #to_str to convert the source encoding argument to an encoding name" do
@@ -67,25 +67,25 @@ describe "Encoding::Converter.new" do
-> do
Encoding::Converter.new("us-ascii", "utf-8", replace: obj)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed true for the replacement object" do
-> do
Encoding::Converter.new("us-ascii", "utf-8", replace: true)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed false for the replacement object" do
-> do
Encoding::Converter.new("us-ascii", "utf-8", replace: false)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed an Integer for the replacement object" do
-> do
Encoding::Converter.new("us-ascii", "utf-8", replace: 1)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "accepts an empty String for the replacement object" do
@@ -107,7 +107,7 @@ describe "Encoding::Converter.new" do
it "sets the replacement String to '\\uFFFD'" do
conv = Encoding::Converter.new("us-ascii", "utf-8", replace: nil)
- conv.replacement.should == "\u{fffd}".force_encoding("utf-8")
+ conv.replacement.should == "\u{fffd}".dup.force_encoding("utf-8")
end
it "sets the replacement String encoding to UTF-8" do
diff --git a/spec/ruby/core/encoding/converter/primitive_convert_spec.rb b/spec/ruby/core/encoding/converter/primitive_convert_spec.rb
index 802d8e7cb1..ab9ce6a992 100644
--- a/spec/ruby/core/encoding/converter/primitive_convert_spec.rb
+++ b/spec/ruby/core/encoding/converter/primitive_convert_spec.rb
@@ -1,4 +1,5 @@
-# -*- encoding: binary -*-
+# encoding: binary
+# frozen_string_literal: false
require_relative '../../../spec_helper'
describe "Encoding::Converter#primitive_convert" do
@@ -7,19 +8,23 @@ describe "Encoding::Converter#primitive_convert" do
end
it "accepts a nil source buffer" do
- -> { @ec.primitive_convert(nil,"") }.should_not raise_error
+ -> { @ec.primitive_convert(nil,"") }.should_not.raise
end
it "accepts a String as the source buffer" do
- -> { @ec.primitive_convert("","") }.should_not raise_error
+ -> { @ec.primitive_convert("","") }.should_not.raise
+ end
+
+ it "raises FrozenError when the destination buffer is a frozen String" do
+ -> { @ec.primitive_convert("", "".freeze) }.should.raise(FrozenError)
end
it "accepts nil for the destination byte offset" do
- -> { @ec.primitive_convert("","", nil) }.should_not raise_error
+ -> { @ec.primitive_convert("","", nil) }.should_not.raise
end
it "accepts an integer for the destination byte offset" do
- -> { @ec.primitive_convert("","a", 1) }.should_not raise_error
+ -> { @ec.primitive_convert("","a", 1) }.should_not.raise
end
it "calls #to_int to convert the destination byte offset" do
@@ -30,10 +35,10 @@ describe "Encoding::Converter#primitive_convert" do
end
it "raises an ArgumentError if the destination byte offset is greater than the bytesize of the destination buffer" do
- -> { @ec.primitive_convert("","am", 0) }.should_not raise_error
- -> { @ec.primitive_convert("","am", 1) }.should_not raise_error
- -> { @ec.primitive_convert("","am", 2) }.should_not raise_error
- -> { @ec.primitive_convert("","am", 3) }.should raise_error(ArgumentError)
+ -> { @ec.primitive_convert("","am", 0) }.should_not.raise
+ -> { @ec.primitive_convert("","am", 1) }.should_not.raise
+ -> { @ec.primitive_convert("","am", 2) }.should_not.raise
+ -> { @ec.primitive_convert("","am", 3) }.should.raise(ArgumentError)
end
it "uses the destination byte offset to determine where to write the result in the destination buffer" do
@@ -49,19 +54,19 @@ describe "Encoding::Converter#primitive_convert" do
end
it "accepts nil for the destination bytesize" do
- -> { @ec.primitive_convert("","", nil, nil) }.should_not raise_error
+ -> { @ec.primitive_convert("","", nil, nil) }.should_not.raise
end
it "accepts an integer for the destination bytesize" do
- -> { @ec.primitive_convert("","", nil, 0) }.should_not raise_error
+ -> { @ec.primitive_convert("","", nil, 0) }.should_not.raise
end
it "allows a destination bytesize value greater than the bytesize of the source buffer" do
- -> { @ec.primitive_convert("am","", nil, 3) }.should_not raise_error
+ -> { @ec.primitive_convert("am","", nil, 3) }.should_not.raise
end
it "allows a destination bytesize value less than the bytesize of the source buffer" do
- -> { @ec.primitive_convert("am","", nil, 1) }.should_not raise_error
+ -> { @ec.primitive_convert("am","", nil, 1) }.should_not.raise
end
it "calls #to_int to convert the destination byte size" do
diff --git a/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb b/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
index 1f836b259f..580e2e37e1 100644
--- a/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
+++ b/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
@@ -1,4 +1,5 @@
-# -*- encoding: binary -*-
+# encoding: binary
+# frozen_string_literal: false
require_relative '../../../spec_helper'
describe "Encoding::Converter#primitive_errinfo" do
@@ -54,7 +55,7 @@ describe "Encoding::Converter#primitive_errinfo" do
it "returns the state, source encoding, target encoding, erroneous bytes, and the read-again bytes when #convert last raised InvalidByteSequenceError" do
ec = Encoding::Converter.new("utf-8", "iso-8859-1")
- -> { ec.convert("\xf1abcd") }.should raise_error(Encoding::InvalidByteSequenceError)
+ -> { ec.convert("\xf1abcd") }.should.raise(Encoding::InvalidByteSequenceError)
ec.primitive_errinfo.should ==
[:invalid_byte_sequence, "UTF-8", "ISO-8859-1", "\xF1", "a"]
end
@@ -62,7 +63,7 @@ describe "Encoding::Converter#primitive_errinfo" do
it "returns the state, source encoding, target encoding, erroneous bytes, and the read-again bytes when #finish last raised InvalidByteSequenceError" do
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
ec.convert("\xa4")
- -> { ec.finish }.should raise_error(Encoding::InvalidByteSequenceError)
+ -> { ec.finish }.should.raise(Encoding::InvalidByteSequenceError)
ec.primitive_errinfo.should == [:incomplete_input, "EUC-JP", "UTF-8", "\xA4", ""]
end
end
diff --git a/spec/ruby/core/encoding/converter/putback_spec.rb b/spec/ruby/core/encoding/converter/putback_spec.rb
index c4e0a5da21..a85cec5145 100644
--- a/spec/ruby/core/encoding/converter/putback_spec.rb
+++ b/spec/ruby/core/encoding/converter/putback_spec.rb
@@ -1,14 +1,14 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe "Encoding::Converter#putback" do
before :each do
@ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
- @ret = @ec.primitive_convert(@src="abc\xa1def", @dst="", nil, 10)
+ @ret = @ec.primitive_convert(@src=+"abc\xa1def", @dst=+"", nil, 10)
end
it "returns a String" do
- @ec.putback.should be_an_instance_of(String)
+ @ec.putback.should.instance_of?(String)
end
it "returns a String in the source encoding" do
@@ -36,21 +36,21 @@ describe "Encoding::Converter#putback" do
it "returns the problematic bytes for UTF-16LE" do
ec = Encoding::Converter.new("utf-16le", "iso-8859-1")
- src = "\x00\xd8\x61\x00"
- dst = ""
+ src = +"\x00\xd8\x61\x00"
+ dst = +""
ec.primitive_convert(src, dst).should == :invalid_byte_sequence
ec.primitive_errinfo.should == [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"]
- ec.putback.should == "a\x00".force_encoding("utf-16le")
+ ec.putback.should == "a\x00".dup.force_encoding("utf-16le")
ec.putback.should == ""
end
it "accepts an integer argument corresponding to the number of bytes to be put back" do
ec = Encoding::Converter.new("utf-16le", "iso-8859-1")
- src = "\x00\xd8\x61\x00"
- dst = ""
+ src = +"\x00\xd8\x61\x00"
+ dst = +""
ec.primitive_convert(src, dst).should == :invalid_byte_sequence
ec.primitive_errinfo.should == [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"]
- ec.putback(2).should == "a\x00".force_encoding("utf-16le")
+ ec.putback(2).should == "a\x00".dup.force_encoding("utf-16le")
ec.putback.should == ""
end
end
diff --git a/spec/ruby/core/encoding/converter/replacement_spec.rb b/spec/ruby/core/encoding/converter/replacement_spec.rb
index 5ca42e7e5a..c25ec36517 100644
--- a/spec/ruby/core/encoding/converter/replacement_spec.rb
+++ b/spec/ruby/core/encoding/converter/replacement_spec.rb
@@ -13,7 +13,7 @@ describe "Encoding::Converter#replacement" do
it "returns \\uFFFD when the destination encoding is UTF-8" do
ec = Encoding::Converter.new("us-ascii", "utf-8")
- ec.replacement.should == "\u{fffd}".force_encoding('utf-8')
+ ec.replacement.should == "\u{fffd}".dup.force_encoding('utf-8')
ec.replacement.encoding.should == Encoding::UTF_8
end
end
@@ -33,38 +33,36 @@ describe "Encoding::Converter#replacement=" do
it "raises a TypeError if assigned a non-String argument" do
ec = Encoding::Converter.new("utf-8", "us-ascii")
- -> { ec.replacement = nil }.should raise_error(TypeError)
+ -> { ec.replacement = nil }.should.raise(TypeError)
end
it "sets #replacement" do
ec = Encoding::Converter.new("us-ascii", "utf-8")
- ec.replacement.should == "\u{fffd}".force_encoding('utf-8')
+ ec.replacement.should == "\u{fffd}".dup.force_encoding('utf-8')
ec.replacement = '?'.encode('utf-8')
- ec.replacement.should == '?'.force_encoding('utf-8')
+ ec.replacement.should == '?'.dup.force_encoding('utf-8')
end
it "raises an UndefinedConversionError is the argument cannot be converted into the destination encoding" do
ec = Encoding::Converter.new("sjis", "ascii")
- utf8_q = "\u{986}".force_encoding('utf-8')
- ec.primitive_convert(utf8_q.dup, "").should == :undefined_conversion
- -> { ec.replacement = utf8_q }.should \
- raise_error(Encoding::UndefinedConversionError)
+ utf8_q = "\u{986}".dup.force_encoding('utf-8')
+ ec.primitive_convert(utf8_q.dup, +"").should == :undefined_conversion
+ -> { ec.replacement = utf8_q }.should.raise(Encoding::UndefinedConversionError)
end
it "does not change the replacement character if the argument cannot be converted into the destination encoding" do
ec = Encoding::Converter.new("sjis", "ascii")
- utf8_q = "\u{986}".force_encoding('utf-8')
- ec.primitive_convert(utf8_q.dup, "").should == :undefined_conversion
- -> { ec.replacement = utf8_q }.should \
- raise_error(Encoding::UndefinedConversionError)
- ec.replacement.should == "?".force_encoding('us-ascii')
+ utf8_q = "\u{986}".dup.force_encoding('utf-8')
+ ec.primitive_convert(utf8_q.dup, +"").should == :undefined_conversion
+ -> { ec.replacement = utf8_q }.should.raise(Encoding::UndefinedConversionError)
+ ec.replacement.should == "?".dup.force_encoding('us-ascii')
end
it "uses the replacement character" do
ec = Encoding::Converter.new("utf-8", "us-ascii", :invalid => :replace, :undef => :replace)
ec.replacement = "!"
- dest = ""
- status = ec.primitive_convert "中文123", dest
+ dest = +""
+ status = ec.primitive_convert(+"中文123", dest)
status.should == :finished
dest.should == "!!123"
diff --git a/spec/ruby/core/encoding/converter/search_convpath_spec.rb b/spec/ruby/core/encoding/converter/search_convpath_spec.rb
index 0882af5539..cac44765f8 100644
--- a/spec/ruby/core/encoding/converter/search_convpath_spec.rb
+++ b/spec/ruby/core/encoding/converter/search_convpath_spec.rb
@@ -23,8 +23,8 @@ describe "Encoding::Converter.search_convpath" do
end
it "raises an Encoding::ConverterNotFoundError if no conversion path exists" do
- -> do
- Encoding::Converter.search_convpath(Encoding::BINARY, Encoding::Emacs_Mule)
- end.should raise_error(Encoding::ConverterNotFoundError)
+ -> do
+ Encoding::Converter.search_convpath(Encoding::BINARY, Encoding::Emacs_Mule)
+ end.should.raise(Encoding::ConverterNotFoundError)
end
end
diff --git a/spec/ruby/core/encoding/default_external_spec.rb b/spec/ruby/core/encoding/default_external_spec.rb
index 682d49d37c..2a2bd7f6ae 100644
--- a/spec/ruby/core/encoding/default_external_spec.rb
+++ b/spec/ruby/core/encoding/default_external_spec.rb
@@ -10,7 +10,7 @@ describe "Encoding.default_external" do
end
it "returns an Encoding object" do
- Encoding.default_external.should be_an_instance_of(Encoding)
+ Encoding.default_external.should.instance_of?(Encoding)
end
it "returns the default external encoding" do
@@ -18,11 +18,9 @@ describe "Encoding.default_external" do
Encoding.default_external.should == Encoding::SHIFT_JIS
end
- ruby_version_is "3.0" do
- platform_is :windows do
- it 'is UTF-8 by default on Windows' do
- Encoding.default_external.should == Encoding::UTF_8
- end
+ platform_is :windows do
+ it 'is UTF-8 by default on Windows' do
+ Encoding.default_external.should == Encoding::UTF_8
end
end
end
@@ -62,10 +60,10 @@ describe "Encoding.default_external=" do
end
it "raises a TypeError unless the argument is an Encoding or convertible to a String" do
- -> { Encoding.default_external = [] }.should raise_error(TypeError)
+ -> { Encoding.default_external = [] }.should.raise(TypeError)
end
it "raises an ArgumentError if the argument is nil" do
- -> { Encoding.default_external = nil }.should raise_error(ArgumentError)
+ -> { Encoding.default_external = nil }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/encoding/default_internal_spec.rb b/spec/ruby/core/encoding/default_internal_spec.rb
index 855f4e9f32..38aef9dce9 100644
--- a/spec/ruby/core/encoding/default_internal_spec.rb
+++ b/spec/ruby/core/encoding/default_internal_spec.rb
@@ -10,17 +10,17 @@ describe "Encoding.default_internal" do
end
it "is nil by default" do
- Encoding.default_internal.should be_nil
+ Encoding.default_internal.should == nil
end
it "returns an Encoding object if a default internal encoding is set" do
Encoding.default_internal = Encoding::ASCII
- Encoding.default_internal.should be_an_instance_of(Encoding)
+ Encoding.default_internal.should.instance_of?(Encoding)
end
it "returns nil if no default internal encoding is set" do
Encoding.default_internal = nil
- Encoding.default_internal.should be_nil
+ Encoding.default_internal.should == nil
end
it "returns the default internal encoding" do
@@ -60,15 +60,15 @@ describe "Encoding.default_internal=" do
obj = mock('string')
obj.should_receive(:to_str).at_least(1).times.and_return(1)
- -> { Encoding.default_internal = obj }.should raise_error(TypeError)
+ -> { Encoding.default_internal = obj }.should.raise(TypeError)
end
it "raises a TypeError when passed an object not providing #to_str" do
- -> { Encoding.default_internal = mock("encoding") }.should raise_error(TypeError)
+ -> { Encoding.default_internal = mock("encoding") }.should.raise(TypeError)
end
it "accepts an argument of nil to unset the default internal encoding" do
Encoding.default_internal = nil
- Encoding.default_internal.should be_nil
+ Encoding.default_internal.should == nil
end
end
diff --git a/spec/ruby/core/encoding/dummy_spec.rb b/spec/ruby/core/encoding/dummy_spec.rb
index 75ffcd5a4e..05530a8186 100644
--- a/spec/ruby/core/encoding/dummy_spec.rb
+++ b/spec/ruby/core/encoding/dummy_spec.rb
@@ -2,13 +2,24 @@ require_relative '../../spec_helper'
describe "Encoding#dummy?" do
it "returns false for proper encodings" do
- Encoding::UTF_8.dummy?.should be_false
- Encoding::ASCII.dummy?.should be_false
+ Encoding::UTF_8.dummy?.should == false
+ Encoding::ASCII.dummy?.should == false
end
it "returns true for dummy encodings" do
- Encoding::ISO_2022_JP.dummy?.should be_true
- Encoding::CP50221.dummy?.should be_true
- Encoding::UTF_7.dummy?.should be_true
+ Encoding::ISO_2022_JP.dummy?.should == true
+ Encoding::CP50221.dummy?.should == true
+ Encoding::UTF_7.dummy?.should == true
+ end
+
+ it "returns true for UTF_16 and UTF_32" do
+ Encoding::UTF_16.should.dummy?
+ Encoding::UTF_32.should.dummy?
+ end
+
+ it "implies not #ascii_compatible?" do
+ Encoding.list.select(&:dummy?).each do |encoding|
+ encoding.should_not.ascii_compatible?
+ end
end
end
diff --git a/spec/ruby/core/encoding/find_spec.rb b/spec/ruby/core/encoding/find_spec.rb
index 8a0873070f..c5356560eb 100644
--- a/spec/ruby/core/encoding/find_spec.rb
+++ b/spec/ruby/core/encoding/find_spec.rb
@@ -7,18 +7,18 @@ describe "Encoding.find" do
it "returns the corresponding Encoding object if given a valid encoding name" do
@encodings.each do |enc|
- Encoding.find(enc).should be_an_instance_of(Encoding)
+ Encoding.find(enc).should.instance_of?(Encoding)
end
end
it "returns the corresponding Encoding object if given a valid alias name" do
Encoding.aliases.keys.each do |enc_alias|
- Encoding.find(enc_alias).should be_an_instance_of(Encoding)
+ Encoding.find(enc_alias).should.instance_of?(Encoding)
end
end
it "raises a TypeError if passed a Symbol" do
- -> { Encoding.find(:"utf-8") }.should raise_error(TypeError)
+ -> { Encoding.find(:"utf-8") }.should.raise(TypeError)
end
it "returns the passed Encoding object" do
@@ -50,7 +50,7 @@ describe "Encoding.find" do
end
it "raises an ArgumentError if the given encoding does not exist" do
- -> { Encoding.find('dh2dh278d') }.should raise_error(ArgumentError)
+ -> { Encoding.find('dh2dh278d') }.should.raise(ArgumentError, 'unknown encoding name - dh2dh278d')
end
# Not sure how to do a better test, since locale depends on weird platform-specific stuff
diff --git a/spec/ruby/core/encoding/fixtures/classes.rb b/spec/ruby/core/encoding/fixtures/classes.rb
index 12e9a4f348..943865e8d8 100644
--- a/spec/ruby/core/encoding/fixtures/classes.rb
+++ b/spec/ruby/core/encoding/fixtures/classes.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
module EncodingSpecs
class UndefinedConversionError
def self.exception
diff --git a/spec/ruby/core/encoding/inspect_spec.rb b/spec/ruby/core/encoding/inspect_spec.rb
index 9a930b2a77..ab7f8cf9fc 100644
--- a/spec/ruby/core/encoding/inspect_spec.rb
+++ b/spec/ruby/core/encoding/inspect_spec.rb
@@ -2,12 +2,26 @@ require_relative '../../spec_helper'
describe "Encoding#inspect" do
it "returns a String" do
- Encoding::UTF_8.inspect.should be_an_instance_of(String)
+ Encoding::UTF_8.inspect.should.instance_of?(String)
end
- it "returns #<Encoding:name> for a non-dummy encoding named 'name'" do
- Encoding.list.to_a.reject {|e| e.dummy? }.each do |enc|
- enc.inspect.should =~ /#<Encoding:#{enc.name}>/
+ ruby_version_is ""..."3.4" do
+ it "returns #<Encoding:name> for a non-dummy encoding named 'name'" do
+ Encoding.list.to_a.reject {|e| e.dummy? }.each do |enc|
+ enc.inspect.should =~ /#<Encoding:#{enc.name}>/
+ end
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "returns #<Encoding:name> for a non-dummy encoding named 'name'" do
+ Encoding.list.to_a.reject {|e| e.dummy? }.each do |enc|
+ if enc.name == "ASCII-8BIT"
+ enc.inspect.should == "#<Encoding:BINARY (ASCII-8BIT)>"
+ else
+ enc.inspect.should =~ /#<Encoding:#{enc.name}>/
+ end
+ end
end
end
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_name_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_name_spec.rb
index f5fa6f55e3..7d3cc77c0b 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_name_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_name_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::InvalidByteSequenceError#destination_encoding_name" do
@@ -7,8 +8,8 @@ describe "Encoding::InvalidByteSequenceError#destination_encoding_name" do
end
it "returns a String" do
- @exception.destination_encoding_name.should be_an_instance_of(String)
- @exception2.destination_encoding_name.should be_an_instance_of(String)
+ @exception.destination_encoding_name.should.instance_of?(String)
+ @exception2.destination_encoding_name.should.instance_of?(String)
end
it "is equal to the destination encoding name of the object that raised it" do
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_spec.rb
index 43be3ddd71..264c409b1c 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/destination_encoding_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::InvalidByteSequenceError#destination_encoding" do
@@ -7,8 +8,8 @@ describe "Encoding::InvalidByteSequenceError#destination_encoding" do
end
it "returns an Encoding object" do
- @exception.destination_encoding.should be_an_instance_of(Encoding)
- @exception2.destination_encoding.should be_an_instance_of(Encoding)
+ @exception.destination_encoding.should.instance_of?(Encoding)
+ @exception2.destination_encoding.should.instance_of?(Encoding)
end
it "is equal to the destination encoding of the object that raised it" do
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb
index a8f7354b16..40a9a35caf 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb
@@ -1,4 +1,5 @@
-# -*- encoding: binary -*-
+# encoding: binary
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::InvalidByteSequenceError#error_bytes" do
@@ -8,8 +9,8 @@ describe "Encoding::InvalidByteSequenceError#error_bytes" do
end
it "returns a String" do
- @exception.error_bytes.should be_an_instance_of(String)
- @exception2.error_bytes.should be_an_instance_of(String)
+ @exception.error_bytes.should.instance_of?(String)
+ @exception2.error_bytes.should.instance_of?(String)
end
it "returns the bytes that caused the exception" do
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb
index 94201a9b15..143db7b6da 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb
@@ -1,28 +1,28 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe "Encoding::InvalidByteSequenceError#incomplete_input?" do
it "returns nil by default" do
- Encoding::InvalidByteSequenceError.new.incomplete_input?.should be_nil
+ Encoding::InvalidByteSequenceError.new.incomplete_input?.should == nil
end
it "returns true if #primitive_convert returned :incomplete_input for the same data" do
ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
- ec.primitive_convert("\xA1",'').should == :incomplete_input
+ ec.primitive_convert(+"\xA1", +'').should == :incomplete_input
begin
ec.convert("\xA1")
rescue Encoding::InvalidByteSequenceError => e
- e.incomplete_input?.should be_true
+ e.incomplete_input?.should == true
end
end
it "returns false if #primitive_convert returned :invalid_byte_sequence for the same data" do
ec = Encoding::Converter.new("ascii", "utf-8")
- ec.primitive_convert("\xfffffffff",'').should == :invalid_byte_sequence
+ ec.primitive_convert(+"\xfffffffff", +'').should == :invalid_byte_sequence
begin
ec.convert("\xfffffffff")
rescue Encoding::InvalidByteSequenceError => e
- e.incomplete_input?.should be_false
+ e.incomplete_input?.should == false
end
end
end
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb
index 93823b5db4..e4fc81aac6 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb
@@ -1,4 +1,5 @@
-# -*- encoding: binary -*-
+# encoding: binary
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::InvalidByteSequenceError#readagain_bytes" do
@@ -8,17 +9,17 @@ describe "Encoding::InvalidByteSequenceError#readagain_bytes" do
end
it "returns a String" do
- @exception.readagain_bytes.should be_an_instance_of(String)
- @exception2.readagain_bytes.should be_an_instance_of(String)
+ @exception.readagain_bytes.should.instance_of?(String)
+ @exception2.readagain_bytes.should.instance_of?(String)
end
it "returns the bytes to be read again" do
@exception.readagain_bytes.size.should == 1
- @exception.readagain_bytes.should == "a".force_encoding('binary')
+ @exception.readagain_bytes.should == "a".dup.force_encoding('binary')
@exception.readagain_bytes.should == @errinfo[-1]
@exception2.readagain_bytes.size.should == 1
- @exception2.readagain_bytes.should == "\xFF".force_encoding('binary')
+ @exception2.readagain_bytes.should == "\xFF".dup.force_encoding('binary')
@exception2.readagain_bytes.should == @errinfo2[-1]
end
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 bd3a51cbc5..b00e1ad4e8 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
@@ -1,3 +1,4 @@
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::UndefinedConversionError#source_encoding_name" do
@@ -7,7 +8,7 @@ describe "Encoding::UndefinedConversionError#source_encoding_name" do
end
it "returns a String" do
- @exception.source_encoding_name.should be_an_instance_of(String)
+ @exception.source_encoding_name.should.instance_of?(String)
end
it "is equal to the source encoding name of the object that raised it" do
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 f43d6d5830..32ad25dbb5 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
@@ -1,3 +1,4 @@
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::InvalidByteSequenceError#source_encoding" do
@@ -7,8 +8,8 @@ describe "Encoding::InvalidByteSequenceError#source_encoding" do
end
it "returns an Encoding object" do
- @exception.source_encoding.should be_an_instance_of(Encoding)
- @exception2.source_encoding.should be_an_instance_of(Encoding)
+ @exception.source_encoding.should.instance_of?(Encoding)
+ @exception2.source_encoding.should.instance_of?(Encoding)
end
it "is equal to the source encoding of the object that raised it" do
diff --git a/spec/ruby/core/encoding/list_spec.rb b/spec/ruby/core/encoding/list_spec.rb
index bd3d5b7bc0..9fe336c608 100644
--- a/spec/ruby/core/encoding/list_spec.rb
+++ b/spec/ruby/core/encoding/list_spec.rb
@@ -2,12 +2,12 @@ require_relative '../../spec_helper'
describe "Encoding.list" do
it "returns an Array" do
- Encoding.list.should be_an_instance_of(Array)
+ Encoding.list.should.instance_of?(Array)
end
it "returns an Array of Encoding objects" do
Encoding.list.each do |enc|
- enc.should be_an_instance_of(Encoding)
+ enc.should.instance_of?(Encoding)
end
end
@@ -17,18 +17,18 @@ describe "Encoding.list" do
end
it "includes the default external encoding" do
- Encoding.list.include?(Encoding.default_external).should be_true
+ Encoding.list.include?(Encoding.default_external).should == true
end
it "does not include any alias names" do
Encoding.aliases.keys.each do |enc_alias|
- Encoding.list.include?(enc_alias).should be_false
+ Encoding.list.include?(enc_alias).should == false
end
end
it "includes all aliased encodings" do
Encoding.aliases.values.each do |enc_alias|
- Encoding.list.include?(Encoding.find(enc_alias)).should be_true
+ Encoding.list.include?(Encoding.find(enc_alias)).should == true
end
end
diff --git a/spec/ruby/core/encoding/locale_charmap_spec.rb b/spec/ruby/core/encoding/locale_charmap_spec.rb
index 8143b9083a..0d77bf227b 100644
--- a/spec/ruby/core/encoding/locale_charmap_spec.rb
+++ b/spec/ruby/core/encoding/locale_charmap_spec.rb
@@ -2,55 +2,55 @@ require_relative '../../spec_helper'
describe "Encoding.locale_charmap" do
it "returns a String" do
- Encoding.locale_charmap.should be_an_instance_of(String)
+ Encoding.locale_charmap.should.instance_of?(String)
end
- # FIXME: Get this working on Windows
- platform_is :linux do
- platform_is_not :android do
- it "returns a value based on the LC_ALL environment variable" do
- old_lc_all = ENV['LC_ALL']
- ENV['LC_ALL'] = 'C'
- ruby_exe("print Encoding.locale_charmap").should == 'ANSI_X3.4-1968'
- ENV['LC_ALL'] = old_lc_all
+ describe "when setting LC_ALL=C" do
+ before :each do
+ @old_lc_all = ENV['LC_ALL']
+ end
+
+ after :each do
+ ENV['LC_ALL'] = @old_lc_all
+ end
+
+ # FIXME: Get this working on Windows
+ platform_is :linux do
+ platform_is_not :android do
+ it "returns a value based on the LC_ALL environment variable" do
+ ENV['LC_ALL'] = 'C'
+ ruby_exe("print Encoding.locale_charmap").should == 'ANSI_X3.4-1968'
+ end
end
end
- end
- platform_is :freebsd, :openbsd, :darwin do
- it "returns a value based on the LC_ALL environment variable" do
- old_lc_all = ENV['LC_ALL']
- ENV['LC_ALL'] = 'C'
- ruby_exe("print Encoding.locale_charmap").should == 'US-ASCII'
- ENV['LC_ALL'] = old_lc_all
+ platform_is :freebsd, :openbsd, :darwin do
+ it "returns a value based on the LC_ALL environment variable" do
+ ENV['LC_ALL'] = 'C'
+ ruby_exe("print Encoding.locale_charmap").should == 'US-ASCII'
+ end
end
- end
- platform_is :netbsd do
- it "returns a value based on the LC_ALL environment variable" do
- old_lc_all = ENV['LC_ALL']
- ENV['LC_ALL'] = 'C'
- ruby_exe("print Encoding.locale_charmap").should == '646'
- ENV['LC_ALL'] = old_lc_all
+ platform_is :netbsd do
+ it "returns a value based on the LC_ALL environment variable" do
+ ENV['LC_ALL'] = 'C'
+ ruby_exe("print Encoding.locale_charmap").should == '646'
+ end
end
- end
- platform_is :android do
- it "always returns UTF-8" do
- old_lc_all = ENV['LC_ALL']
- ENV['LC_ALL'] = 'C'
- ruby_exe("print Encoding.locale_charmap").should == 'UTF-8'
- ENV['LC_ALL'] = old_lc_all
+ platform_is :android do
+ it "always returns UTF-8" do
+ ENV['LC_ALL'] = 'C'
+ ruby_exe("print Encoding.locale_charmap").should == 'UTF-8'
+ end
end
- end
- platform_is :bsd, :darwin, :linux do
- it "is unaffected by assigning to ENV['LC_ALL'] in the same process" do
- old_charmap = Encoding.locale_charmap
- old_lc_all = ENV['LC_ALL']
- ENV['LC_ALL'] = 'C'
- Encoding.locale_charmap.should == old_charmap
- ENV['LC_ALL'] = old_lc_all
+ platform_is :bsd, :darwin, :linux do
+ it "is unaffected by assigning to ENV['LC_ALL'] in the same process" do
+ old_charmap = Encoding.locale_charmap
+ ENV['LC_ALL'] = 'C'
+ Encoding.locale_charmap.should == old_charmap
+ end
end
end
end
diff --git a/spec/ruby/core/encoding/name_list_spec.rb b/spec/ruby/core/encoding/name_list_spec.rb
index 836381c4d8..1ba8d383bc 100644
--- a/spec/ruby/core/encoding/name_list_spec.rb
+++ b/spec/ruby/core/encoding/name_list_spec.rb
@@ -2,22 +2,22 @@ require_relative '../../spec_helper'
describe "Encoding.name_list" do
it "returns an Array" do
- Encoding.name_list.should be_an_instance_of(Array)
+ Encoding.name_list.should.instance_of?(Array)
end
it "returns encoding names as Strings" do
- Encoding.name_list.each {|e| e.should be_an_instance_of(String) }
+ Encoding.name_list.each {|e| e.should.instance_of?(String) }
end
it "includes all aliases" do
Encoding.aliases.keys.each do |enc_alias|
- Encoding.name_list.include?(enc_alias).should be_true
+ Encoding.name_list.include?(enc_alias).should == true
end
end
it "includes all non-dummy encodings" do
Encoding.list.each do |enc|
- Encoding.name_list.include?(enc.name).should be_true
+ Encoding.name_list.include?(enc.name).should == true
end
end
end
diff --git a/spec/ruby/core/encoding/name_spec.rb b/spec/ruby/core/encoding/name_spec.rb
index 5eadb1d2f5..1d625c9379 100644
--- a/spec/ruby/core/encoding/name_spec.rb
+++ b/spec/ruby/core/encoding/name_spec.rb
@@ -1,5 +1,15 @@
-require_relative 'shared/name'
+require_relative "../../spec_helper"
describe "Encoding#name" do
- it_behaves_like :encoding_name, :name
+ it "returns a String" do
+ Encoding.list.each do |e|
+ e.name.should.instance_of?(String)
+ end
+ end
+
+ it "uniquely identifies an encoding" do
+ Encoding.list.each do |e|
+ e.should == Encoding.find(e.name)
+ end
+ end
end
diff --git a/spec/ruby/core/encoding/names_spec.rb b/spec/ruby/core/encoding/names_spec.rb
index 9ded043bbb..e6bcbf474a 100644
--- a/spec/ruby/core/encoding/names_spec.rb
+++ b/spec/ruby/core/encoding/names_spec.rb
@@ -4,7 +4,7 @@ describe "Encoding#names" do
it "returns an Array" do
Encoding.name_list.each do |name|
e = Encoding.find(name) or next
- e.names.should be_an_instance_of(Array)
+ e.names.should.instance_of?(Array)
end
end
@@ -12,7 +12,7 @@ describe "Encoding#names" do
Encoding.name_list.each do |name|
e = Encoding.find(name) or next
e.names.each do |this_name|
- this_name.should be_an_instance_of(String)
+ this_name.should.instance_of?(String)
end
end
end
@@ -29,7 +29,7 @@ describe "Encoding#names" do
e = Encoding.find(name) or next
aliases = Encoding.aliases.select{|a,n| n == name}.keys
names = e.names
- aliases.each {|a| names.include?(a).should be_true}
+ aliases.each {|a| names.include?(a).should == true}
end
end
end
diff --git a/spec/ruby/core/encoding/replicate_spec.rb b/spec/ruby/core/encoding/replicate_spec.rb
index 45727a5c0d..9fe0ba8747 100644
--- a/spec/ruby/core/encoding/replicate_spec.rb
+++ b/spec/ruby/core/encoding/replicate_spec.rb
@@ -1,67 +1,8 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
describe "Encoding#replicate" do
- before :all do
- @i = 0
- end
-
- before :each do
- @i += 1
- @prefix = "RS#{@i}"
- end
-
- it "returns a replica of ASCII" do
- name = @prefix + '-ASCII'
- e = Encoding::ASCII.replicate(name)
- e.name.should == name
- Encoding.find(name).should == e
-
- "a".force_encoding(e).valid_encoding?.should be_true
- "\x80".force_encoding(e).valid_encoding?.should be_false
- end
-
- it "returns a replica of UTF-8" do
- name = @prefix + 'UTF-8'
- e = Encoding::UTF_8.replicate(name)
- e.name.should == name
- Encoding.find(name).should == e
-
- "a".force_encoding(e).valid_encoding?.should be_true
- "\u3042".force_encoding(e).valid_encoding?.should be_true
- "\x80".force_encoding(e).valid_encoding?.should be_false
- end
-
- it "returns a replica of UTF-16BE" do
- name = @prefix + 'UTF-16-BE'
- e = Encoding::UTF_16BE.replicate(name)
- e.name.should == name
- Encoding.find(name).should == e
-
- "a".force_encoding(e).valid_encoding?.should be_false
- "\x30\x42".force_encoding(e).valid_encoding?.should be_true
- "\x80".force_encoding(e).valid_encoding?.should be_false
- end
-
- it "returns a replica of ISO-2022-JP" do
- name = @prefix + 'ISO-2022-JP'
- e = Encoding::ISO_2022_JP.replicate(name)
- Encoding.find(name).should == e
-
- e.name.should == name
- e.dummy?.should be_true
- end
-
- # NOTE: it's unclear of the value of this (for the complexity cost of it),
- # but it is the current CRuby behavior.
- it "can be associated with a String" do
- name = @prefix + '-US-ASCII'
- e = Encoding::US_ASCII.replicate(name)
- e.name.should == name
- Encoding.find(name).should == e
-
- s = "abc".force_encoding(e)
- s.encoding.should == e
- s.encoding.name.should == name
+ it "has been removed" do
+ Encoding::US_ASCII.should_not.respond_to?(:replicate, true)
end
end
diff --git a/spec/ruby/core/encoding/shared/name.rb b/spec/ruby/core/encoding/shared/name.rb
deleted file mode 100644
index cd37ea06db..0000000000
--- a/spec/ruby/core/encoding/shared/name.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require_relative '../../../spec_helper'
-
-describe :encoding_name, shared: true do
- it "returns a String" do
- Encoding.list.each do |e|
- e.send(@method).should be_an_instance_of(String)
- end
- end
-
- it "uniquely identifies an encoding" do
- Encoding.list.each do |e|
- e.should == Encoding.find(e.send(@method))
- end
- end
-end
diff --git a/spec/ruby/core/encoding/to_s_spec.rb b/spec/ruby/core/encoding/to_s_spec.rb
index 82d282386b..ee5e3b4abe 100644
--- a/spec/ruby/core/encoding/to_s_spec.rb
+++ b/spec/ruby/core/encoding/to_s_spec.rb
@@ -1,5 +1,7 @@
-require_relative 'shared/name'
+require_relative "../../spec_helper"
describe "Encoding#to_s" do
- it_behaves_like :encoding_name, :to_s
+ it "is an alias of Encoding#name" do
+ Encoding.instance_method(:to_s).should == Encoding.instance_method(:name)
+ end
end
diff --git a/spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_name_spec.rb b/spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_name_spec.rb
index 106fc7ecac..bc36695ca7 100644
--- a/spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_name_spec.rb
+++ b/spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_name_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::UndefinedConversionError#destination_encoding_name" do
@@ -6,7 +7,7 @@ describe "Encoding::UndefinedConversionError#destination_encoding_name" do
end
it "returns a String" do
- @exception.destination_encoding_name.should be_an_instance_of(String)
+ @exception.destination_encoding_name.should.instance_of?(String)
end
it "is equal to the destination encoding name of the object that raised it" do
diff --git a/spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_spec.rb b/spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_spec.rb
index c6e24732fd..c0fcf8de58 100644
--- a/spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_spec.rb
+++ b/spec/ruby/core/encoding/undefined_conversion_error/destination_encoding_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::UndefinedConversionError#destination_encoding" do
@@ -6,7 +7,7 @@ describe "Encoding::UndefinedConversionError#destination_encoding" do
end
it "returns an Encoding object" do
- @exception.destination_encoding.should be_an_instance_of(Encoding)
+ @exception.destination_encoding.should.instance_of?(Encoding)
end
it "is equal to the destination encoding of the object that raised it" do
diff --git a/spec/ruby/core/encoding/undefined_conversion_error/error_char_spec.rb b/spec/ruby/core/encoding/undefined_conversion_error/error_char_spec.rb
index 780d81c1ee..333acf5ee6 100644
--- a/spec/ruby/core/encoding/undefined_conversion_error/error_char_spec.rb
+++ b/spec/ruby/core/encoding/undefined_conversion_error/error_char_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::UndefinedConversionError#error_char" do
@@ -7,8 +8,8 @@ describe "Encoding::UndefinedConversionError#error_char" do
end
it "returns a String" do
- @exception.error_char.should be_an_instance_of(String)
- @exception2.error_char.should be_an_instance_of(String)
+ @exception.error_char.should.instance_of?(String)
+ @exception2.error_char.should.instance_of?(String)
end
it "returns the one-character String that caused the exception" do
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 3b697cb82f..4932a25ed7 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
@@ -1,3 +1,4 @@
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::UndefinedConversionError#source_encoding_name" do
@@ -7,7 +8,7 @@ describe "Encoding::UndefinedConversionError#source_encoding_name" do
end
it "returns a String" do
- @exception.source_encoding_name.should be_an_instance_of(String)
+ @exception.source_encoding_name.should.instance_of?(String)
end
it "is equal to the source encoding name of the object that raised it" do
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 9101d51e11..cf12020ad2 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
@@ -1,3 +1,4 @@
+require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
describe "Encoding::UndefinedConversionError#source_encoding" do
@@ -7,8 +8,8 @@ describe "Encoding::UndefinedConversionError#source_encoding" do
end
it "returns an Encoding object" do
- @exception.source_encoding.should be_an_instance_of(Encoding)
- @exception2.source_encoding.should be_an_instance_of(Encoding)
+ @exception.source_encoding.should.instance_of?(Encoding)
+ @exception2.source_encoding.should.instance_of?(Encoding)
end
it "is equal to the source encoding of the object that raised it" do
diff --git a/spec/ruby/core/enumerable/all_spec.rb b/spec/ruby/core/enumerable/all_spec.rb
index 0ded1e8eba..cbdd63f86a 100644
--- a/spec/ruby/core/enumerable/all_spec.rb
+++ b/spec/ruby/core/enumerable/all_spec.rb
@@ -21,19 +21,19 @@ describe "Enumerable#all?" do
end
it "raises an ArgumentError when more than 1 argument is provided" do
- -> { @enum.all?(1, 2, 3) }.should raise_error(ArgumentError)
- -> { [].all?(1, 2, 3) }.should raise_error(ArgumentError)
- -> { {}.all?(1, 2, 3) }.should raise_error(ArgumentError)
+ -> { @enum.all?(1, 2, 3) }.should.raise(ArgumentError)
+ -> { [].all?(1, 2, 3) }.should.raise(ArgumentError)
+ -> { {}.all?(1, 2, 3) }.should.raise(ArgumentError)
end
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.all?
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
-> {
EnumerableSpecs::ThrowingEach.new.all? { false }
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
describe "with no block" do
@@ -60,7 +60,7 @@ describe "Enumerable#all?" do
it "gathers whole arrays as elements when each yields multiple" do
multi = EnumerableSpecs::YieldsMultiWithFalse.new
- multi.all?.should be_true
+ multi.all?.should == true
end
end
@@ -106,7 +106,7 @@ describe "Enumerable#all?" do
it "does not hide exceptions out of the block" do
-> {
@enum.all? { raise "from block" }
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "gathers initial args as elements when each yields multiple" do
@@ -125,7 +125,7 @@ describe "Enumerable#all?" do
end
describe 'when given a pattern argument' do
- it "calls `===` on the pattern the return value " do
+ it "calls `===` on the pattern the return value" do
pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 }
@enum1.all?(pattern).should == false
pattern.yielded.should == [[0], [1], [2], [-1]]
@@ -140,7 +140,7 @@ describe "Enumerable#all?" do
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.all?(Integer)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "returns true if the pattern never returns false or nil" do
@@ -168,7 +168,7 @@ describe "Enumerable#all?" do
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
-> {
@enum.all?(pattern)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "calls the pattern with gathered array when yielded with multiple arguments" do
@@ -177,5 +177,11 @@ describe "Enumerable#all?" do
multi.all?(pattern).should == true
pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
end
+
+ it "ignores the block if there is an argument" do
+ -> {
+ EnumerableSpecs::Numerous.new(1, 2, 3, 4, 5).all?(String) { true }.should == false
+ }.should complain(/given block not used/)
+ end
end
end
diff --git a/spec/ruby/core/enumerable/any_spec.rb b/spec/ruby/core/enumerable/any_spec.rb
index 355cd0c290..4405d4740a 100644
--- a/spec/ruby/core/enumerable/any_spec.rb
+++ b/spec/ruby/core/enumerable/any_spec.rb
@@ -21,19 +21,19 @@ describe "Enumerable#any?" do
end
it "raises an ArgumentError when more than 1 argument is provided" do
- -> { @enum.any?(1, 2, 3) }.should raise_error(ArgumentError)
- -> { [].any?(1, 2, 3) }.should raise_error(ArgumentError)
- -> { {}.any?(1, 2, 3) }.should raise_error(ArgumentError)
+ -> { @enum.any?(1, 2, 3) }.should.raise(ArgumentError)
+ -> { [].any?(1, 2, 3) }.should.raise(ArgumentError)
+ -> { {}.any?(1, 2, 3) }.should.raise(ArgumentError)
end
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.any?
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
-> {
EnumerableSpecs::ThrowingEach.new.any? { false }
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
describe "with no block" do
@@ -60,7 +60,7 @@ describe "Enumerable#any?" do
it "gathers whole arrays as elements when each yields multiple" do
multi = EnumerableSpecs::YieldsMultiWithFalse.new
- multi.any?.should be_true
+ multi.any?.should == true
end
end
@@ -120,7 +120,7 @@ describe "Enumerable#any?" do
it "does not hide exceptions out of the block" do
-> {
@enum.any? { raise "from block" }
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "gathers initial args as elements when each yields multiple" do
@@ -139,7 +139,7 @@ describe "Enumerable#any?" do
end
describe 'when given a pattern argument' do
- it "calls `===` on the pattern the return value " do
+ it "calls `===` on the pattern the return value" do
pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
@enum1.any?(pattern).should == true
pattern.yielded.should == [[0], [1], [2]]
@@ -154,7 +154,7 @@ describe "Enumerable#any?" do
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.any?(Integer)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "returns true if the pattern ever returns a truthy value" do
@@ -181,7 +181,7 @@ describe "Enumerable#any?" do
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
-> {
@enum.any?(pattern)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "calls the pattern with gathered array when yielded with multiple arguments" do
@@ -190,5 +190,11 @@ describe "Enumerable#any?" do
multi.any?(pattern).should == false
pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
end
+
+ it "ignores the block if there is an argument" do
+ -> {
+ EnumerableSpecs::Numerous.new(1, 2, 3, 4, 5).any?(String) { true }.should == false
+ }.should complain(/given block not used/)
+ end
end
end
diff --git a/spec/ruby/core/enumerable/chain_spec.rb b/spec/ruby/core/enumerable/chain_spec.rb
index 5e2105d294..a0597e46a1 100644
--- a/spec/ruby/core/enumerable/chain_spec.rb
+++ b/spec/ruby/core/enumerable/chain_spec.rb
@@ -18,6 +18,6 @@ describe "Enumerable#chain" do
end
it "returns an Enumerator::Chain if given a block" do
- EnumerableSpecs::Numerous.new.chain.should be_an_instance_of(Enumerator::Chain)
+ EnumerableSpecs::Numerous.new.chain.should.instance_of?(Enumerator::Chain)
end
end
diff --git a/spec/ruby/core/enumerable/chunk_spec.rb b/spec/ruby/core/enumerable/chunk_spec.rb
index c5579d67fa..7c9b31c991 100644
--- a/spec/ruby/core/enumerable/chunk_spec.rb
+++ b/spec/ruby/core/enumerable/chunk_spec.rb
@@ -8,13 +8,13 @@ describe "Enumerable#chunk" do
it "returns an Enumerator if called without a block" do
chunk = EnumerableSpecs::Numerous.new(1, 2, 3, 1, 2).chunk
- chunk.should be_an_instance_of(Enumerator)
+ chunk.should.instance_of?(Enumerator)
result = chunk.with_index {|elt, i| elt - i }.to_a
result.should == [[1, [1, 2, 3]], [-2, [1, 2]]]
end
it "returns an Enumerator if given a block" do
- EnumerableSpecs::Numerous.new.chunk {}.should be_an_instance_of(Enumerator)
+ EnumerableSpecs::Numerous.new.chunk {}.should.instance_of?(Enumerator)
end
it "yields the current element and the current chunk to the block" do
@@ -29,6 +29,11 @@ describe "Enumerable#chunk" do
result.should == [[1, [1, 2]], [0, [3]], [1, [2]], [0, [3]], [1, [2, 1]]]
end
+ it "returns a partitioned Array of values" do
+ e = EnumerableSpecs::Numerous.new(1,2,3)
+ e.chunk { |x| x > 2 }.map(&:last).should == [[1, 2], [3]]
+ end
+
it "returns elements for which the block returns :_alone in separate Arrays" do
e = EnumerableSpecs::Numerous.new(1, 2, 3, 2, 1)
result = e.chunk { |x| x < 2 && :_alone }.to_a
@@ -54,14 +59,14 @@ describe "Enumerable#chunk" do
it "raises a RuntimeError if the block returns a Symbol starting with an underscore other than :_alone or :_separator" do
e = EnumerableSpecs::Numerous.new(1, 2, 3, 2, 1)
- -> { e.chunk { |x| :_arbitrary }.to_a }.should raise_error(RuntimeError)
+ -> { e.chunk { |x| :_arbitrary }.to_a }.should.raise(RuntimeError)
end
it "does not accept arguments" do
e = EnumerableSpecs::Numerous.new(1, 2, 3)
-> {
e.chunk(1) {}
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it 'returned Enumerator size returns nil' do
diff --git a/spec/ruby/core/enumerable/chunk_while_spec.rb b/spec/ruby/core/enumerable/chunk_while_spec.rb
index 26bcc983db..286f717442 100644
--- a/spec/ruby/core/enumerable/chunk_while_spec.rb
+++ b/spec/ruby/core/enumerable/chunk_while_spec.rb
@@ -11,7 +11,7 @@ describe "Enumerable#chunk_while" do
context "when given a block" do
it "returns an enumerator" do
- @result.should be_an_instance_of(Enumerator)
+ @result.should.instance_of?(Enumerator)
end
it "splits chunks between adjacent elements i and j where the block returns false" do
@@ -30,7 +30,7 @@ describe "Enumerable#chunk_while" do
context "when not given a block" do
it "raises an ArgumentError" do
- -> { @enum.chunk_while }.should raise_error(ArgumentError)
+ -> { @enum.chunk_while }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/enumerable/collect_concat_spec.rb b/spec/ruby/core/enumerable/collect_concat_spec.rb
index 6e34c9eb93..59317cfe34 100644
--- a/spec/ruby/core/enumerable/collect_concat_spec.rb
+++ b/spec/ruby/core/enumerable/collect_concat_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/collect_concat'
describe "Enumerable#collect_concat" do
- it_behaves_like :enumerable_collect_concat , :collect_concat
+ it_behaves_like :enumerable_collect_concat, :collect_concat
end
diff --git a/spec/ruby/core/enumerable/collect_spec.rb b/spec/ruby/core/enumerable/collect_spec.rb
index 1016b67798..cfa2895cce 100644
--- a/spec/ruby/core/enumerable/collect_spec.rb
+++ b/spec/ruby/core/enumerable/collect_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/collect'
describe "Enumerable#collect" do
- it_behaves_like :enumerable_collect , :collect
+ it_behaves_like :enumerable_collect, :collect
end
diff --git a/spec/ruby/core/enumerable/compact_spec.rb b/spec/ruby/core/enumerable/compact_spec.rb
index 86e95dce08..1895430c4e 100644
--- a/spec/ruby/core/enumerable/compact_spec.rb
+++ b/spec/ruby/core/enumerable/compact_spec.rb
@@ -1,11 +1,9 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is '3.1' do
- describe "Enumerable#compact" do
- it 'returns array without nil elements' do
- arr = EnumerableSpecs::Numerous.new(nil, 1, 2, nil, true)
- arr.compact.should == [1, 2, true]
- end
+describe "Enumerable#compact" do
+ it 'returns array without nil elements' do
+ arr = EnumerableSpecs::Numerous.new(nil, 1, 2, nil, true)
+ arr.compact.should == [1, 2, true]
end
end
diff --git a/spec/ruby/core/enumerable/cycle_spec.rb b/spec/ruby/core/enumerable/cycle_spec.rb
index 487086cba3..1fb3cc3d41 100644
--- a/spec/ruby/core/enumerable/cycle_spec.rb
+++ b/spec/ruby/core/enumerable/cycle_spec.rb
@@ -17,7 +17,7 @@ describe "Enumerable#cycle" do
it "returns nil if there are no elements" do
out = EnumerableSpecs::Empty.new.cycle { break :nope }
- out.should be_nil
+ out.should == nil
end
it "yields successive elements of the array repeatedly" do
@@ -44,8 +44,8 @@ describe "Enumerable#cycle" do
describe "passed a number n as an argument" do
it "returns nil and does nothing for non positive n" do
- EnumerableSpecs::ThrowingEach.new.cycle(0) {}.should be_nil
- EnumerableSpecs::NoEach.new.cycle(-22) {}.should be_nil
+ EnumerableSpecs::ThrowingEach.new.cycle(0) {}.should == nil
+ EnumerableSpecs::NoEach.new.cycle(-22) {}.should == nil
end
it "calls each at most once" do
@@ -71,12 +71,12 @@ describe "Enumerable#cycle" do
it "raises a TypeError when the passed n cannot be coerced to Integer" do
enum = EnumerableSpecs::Numerous.new
- ->{ enum.cycle("cat"){} }.should raise_error(TypeError)
+ ->{ enum.cycle("cat"){} }.should.raise(TypeError)
end
it "raises an ArgumentError if more arguments are passed" do
enum = EnumerableSpecs::Numerous.new
- ->{ enum.cycle(1, 2) {} }.should raise_error(ArgumentError)
+ ->{ enum.cycle(1, 2) {} }.should.raise(ArgumentError)
end
it "gathers whole arrays as elements when each yields multiple" do
diff --git a/spec/ruby/core/enumerable/detect_spec.rb b/spec/ruby/core/enumerable/detect_spec.rb
index e912134fed..6959aadc44 100644
--- a/spec/ruby/core/enumerable/detect_spec.rb
+++ b/spec/ruby/core/enumerable/detect_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find'
describe "Enumerable#detect" do
- it_behaves_like :enumerable_find , :detect
+ it_behaves_like :enumerable_find, :detect
end
diff --git a/spec/ruby/core/enumerable/drop_spec.rb b/spec/ruby/core/enumerable/drop_spec.rb
index 423cc0088b..8d95f464b3 100644
--- a/spec/ruby/core/enumerable/drop_spec.rb
+++ b/spec/ruby/core/enumerable/drop_spec.rb
@@ -7,13 +7,13 @@ describe "Enumerable#drop" do
end
it "requires exactly one argument" do
- ->{ @enum.drop{} }.should raise_error(ArgumentError)
- ->{ @enum.drop(1, 2){} }.should raise_error(ArgumentError)
+ ->{ @enum.drop{} }.should.raise(ArgumentError)
+ ->{ @enum.drop(1, 2){} }.should.raise(ArgumentError)
end
describe "passed a number n as an argument" do
it "raises ArgumentError if n < 0" do
- ->{ @enum.drop(-1) }.should raise_error(ArgumentError)
+ ->{ @enum.drop(-1) }.should.raise(ArgumentError)
end
it "tries to convert n to an Integer using #to_int" do
@@ -35,8 +35,8 @@ describe "Enumerable#drop" do
end
it "raises a TypeError when the passed n cannot be coerced to Integer" do
- ->{ @enum.drop("hat") }.should raise_error(TypeError)
- ->{ @enum.drop(nil) }.should raise_error(TypeError)
+ ->{ @enum.drop("hat") }.should.raise(TypeError)
+ ->{ @enum.drop(nil) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/enumerable/drop_while_spec.rb b/spec/ruby/core/enumerable/drop_while_spec.rb
index 636c3d284a..4b4fdf2d4f 100644
--- a/spec/ruby/core/enumerable/drop_while_spec.rb
+++ b/spec/ruby/core/enumerable/drop_while_spec.rb
@@ -8,7 +8,7 @@ describe "Enumerable#drop_while" do
end
it "returns an Enumerator if no block given" do
- @enum.drop_while.should be_an_instance_of(Enumerator)
+ @enum.drop_while.should.instance_of?(Enumerator)
end
it "returns no/all elements for {true/false} block" do
@@ -38,7 +38,7 @@ describe "Enumerable#drop_while" do
it "doesn't return self when it could" do
a = [1,2,3]
- a.drop_while{false}.should_not equal(a)
+ a.drop_while{false}.should_not.equal?(a)
end
it "gathers whole arrays as elements when each yields multiple" do
diff --git a/spec/ruby/core/enumerable/each_cons_spec.rb b/spec/ruby/core/enumerable/each_cons_spec.rb
index ba658203a2..c5e299fd00 100644
--- a/spec/ruby/core/enumerable/each_cons_spec.rb
+++ b/spec/ruby/core/enumerable/each_cons_spec.rb
@@ -15,14 +15,14 @@ describe "Enumerable#each_cons" do
end
it "raises an ArgumentError if there is not a single parameter > 0" do
- ->{ @enum.each_cons(0){} }.should raise_error(ArgumentError)
- ->{ @enum.each_cons(-2){} }.should raise_error(ArgumentError)
- ->{ @enum.each_cons{} }.should raise_error(ArgumentError)
- ->{ @enum.each_cons(2,2){} }.should raise_error(ArgumentError)
- ->{ @enum.each_cons(0) }.should raise_error(ArgumentError)
- ->{ @enum.each_cons(-2) }.should raise_error(ArgumentError)
- ->{ @enum.each_cons }.should raise_error(ArgumentError)
- ->{ @enum.each_cons(2,2) }.should raise_error(ArgumentError)
+ ->{ @enum.each_cons(0){} }.should.raise(ArgumentError)
+ ->{ @enum.each_cons(-2){} }.should.raise(ArgumentError)
+ ->{ @enum.each_cons{} }.should.raise(ArgumentError)
+ ->{ @enum.each_cons(2,2){} }.should.raise(ArgumentError)
+ ->{ @enum.each_cons(0) }.should.raise(ArgumentError)
+ ->{ @enum.each_cons(-2) }.should.raise(ArgumentError)
+ ->{ @enum.each_cons }.should.raise(ArgumentError)
+ ->{ @enum.each_cons(2,2) }.should.raise(ArgumentError)
end
it "tries to convert n to an Integer using #to_int" do
@@ -56,10 +56,14 @@ describe "Enumerable#each_cons" do
multi.each_cons(2).to_a.should == [[[1, 2], [3, 4, 5]], [[3, 4, 5], [6, 7, 8, 9]]]
end
+ it "returns self when a block is given" do
+ @enum.each_cons(3){}.should == @enum
+ end
+
describe "when no block is given" do
it "returns an enumerator" do
e = @enum.each_cons(3)
- e.should be_an_instance_of(Enumerator)
+ e.should.instance_of?(Enumerator)
e.to_a.should == @in_threes
end
diff --git a/spec/ruby/core/enumerable/each_entry_spec.rb b/spec/ruby/core/enumerable/each_entry_spec.rb
index edf00f3137..9dc89ec28e 100644
--- a/spec/ruby/core/enumerable/each_entry_spec.rb
+++ b/spec/ruby/core/enumerable/each_entry_spec.rb
@@ -11,13 +11,13 @@ describe "Enumerable#each_entry" do
it "yields multiple arguments as an array" do
acc = []
- @enum.each_entry {|g| acc << g}.should equal(@enum)
+ @enum.each_entry {|g| acc << g}.should.equal?(@enum)
acc.should == @entries
end
it "returns an enumerator if no block" do
e = @enum.each_entry
- e.should be_an_instance_of(Enumerator)
+ e.should.instance_of?(Enumerator)
e.to_a.should == @entries
end
@@ -27,8 +27,8 @@ describe "Enumerable#each_entry" do
end
it "raises an ArgumentError when extra arguments" do
- -> { @enum.each_entry("one").to_a }.should raise_error(ArgumentError)
- -> { @enum.each_entry("one"){}.to_a }.should raise_error(ArgumentError)
+ -> { @enum.each_entry("one").to_a }.should.raise(ArgumentError)
+ -> { @enum.each_entry("one"){}.to_a }.should.raise(ArgumentError)
end
it "passes extra arguments to #each" do
diff --git a/spec/ruby/core/enumerable/each_slice_spec.rb b/spec/ruby/core/enumerable/each_slice_spec.rb
index 2ea89f5e72..d05abad1e9 100644
--- a/spec/ruby/core/enumerable/each_slice_spec.rb
+++ b/spec/ruby/core/enumerable/each_slice_spec.rb
@@ -15,14 +15,14 @@ describe "Enumerable#each_slice" do
end
it "raises an ArgumentError if there is not a single parameter > 0" do
- ->{ @enum.each_slice(0){} }.should raise_error(ArgumentError)
- ->{ @enum.each_slice(-2){} }.should raise_error(ArgumentError)
- ->{ @enum.each_slice{} }.should raise_error(ArgumentError)
- ->{ @enum.each_slice(2,2){} }.should raise_error(ArgumentError)
- ->{ @enum.each_slice(0) }.should raise_error(ArgumentError)
- ->{ @enum.each_slice(-2) }.should raise_error(ArgumentError)
- ->{ @enum.each_slice }.should raise_error(ArgumentError)
- ->{ @enum.each_slice(2,2) }.should raise_error(ArgumentError)
+ ->{ @enum.each_slice(0){} }.should.raise(ArgumentError)
+ ->{ @enum.each_slice(-2){} }.should.raise(ArgumentError)
+ ->{ @enum.each_slice{} }.should.raise(ArgumentError)
+ ->{ @enum.each_slice(2,2){} }.should.raise(ArgumentError)
+ ->{ @enum.each_slice(0) }.should.raise(ArgumentError)
+ ->{ @enum.each_slice(-2) }.should.raise(ArgumentError)
+ ->{ @enum.each_slice }.should.raise(ArgumentError)
+ ->{ @enum.each_slice(2,2) }.should.raise(ArgumentError)
end
it "tries to convert n to an Integer using #to_int" do
@@ -53,10 +53,14 @@ describe "Enumerable#each_slice" do
it "returns an enumerator if no block" do
e = @enum.each_slice(3)
- e.should be_an_instance_of(Enumerator)
+ e.should.instance_of?(Enumerator)
e.to_a.should == @sliced
end
+ it "returns self when a block is given" do
+ @enum.each_slice(3){}.should == @enum
+ end
+
it "gathers whole arrays as elements when each yields multiple" do
multi = EnumerableSpecs::YieldsMulti.new
multi.each_slice(2).to_a.should == [[[1, 2], [3, 4, 5]], [[6, 7, 8, 9]]]
@@ -65,7 +69,7 @@ describe "Enumerable#each_slice" do
describe "when no block is given" do
it "returns an enumerator" do
e = @enum.each_slice(3)
- e.should be_an_instance_of(Enumerator)
+ e.should.instance_of?(Enumerator)
e.to_a.should == @sliced
end
diff --git a/spec/ruby/core/enumerable/each_with_index_spec.rb b/spec/ruby/core/enumerable/each_with_index_spec.rb
index 122e88eab7..fcb2f82f84 100644
--- a/spec/ruby/core/enumerable/each_with_index_spec.rb
+++ b/spec/ruby/core/enumerable/each_with_index_spec.rb
@@ -26,19 +26,19 @@ describe "Enumerable#each_with_index" do
acc = []
res = @b.each_with_index {|a,i| acc << [a,i]}
[[2, 0], [5, 1], [3, 2], [6, 3], [1, 4], [4, 5]].should == acc
- res.should eql(@b)
+ res.should.eql?(@b)
end
it "binds splat arguments properly" do
acc = []
res = @b.each_with_index { |*b| c,d = b; acc << c; acc << d }
[2, 0, 5, 1, 3, 2, 6, 3, 1, 4, 4, 5].should == acc
- res.should eql(@b)
+ res.should.eql?(@b)
end
it "returns an enumerator if no block" do
e = @b.each_with_index
- e.should be_an_instance_of(Enumerator)
+ e.should.instance_of?(Enumerator)
e.to_a.should == [[2, 0], [5, 1], [3, 2], [6, 3], [1, 4], [4, 5]]
end
diff --git a/spec/ruby/core/enumerable/each_with_object_spec.rb b/spec/ruby/core/enumerable/each_with_object_spec.rb
index 35665e7019..1760d3b267 100644
--- a/spec/ruby/core/enumerable/each_with_object_spec.rb
+++ b/spec/ruby/core/enumerable/each_with_object_spec.rb
@@ -12,10 +12,10 @@ describe "Enumerable#each_with_object" do
it "passes each element and its argument to the block" do
acc = []
@enum.each_with_object(@initial) do |elem, obj|
- obj.should equal(@initial)
+ obj.should.equal?(@initial)
obj = 42
acc << elem
- end.should equal(@initial)
+ end.should.equal?(@initial)
acc.should == @values
end
@@ -23,10 +23,10 @@ describe "Enumerable#each_with_object" do
acc = []
e = @enum.each_with_object(@initial)
e.each do |elem, obj|
- obj.should equal(@initial)
+ obj.should.equal?(@initial)
obj = 42
acc << elem
- end.should equal(@initial)
+ end.should.equal?(@initial)
acc.should == @values
end
diff --git a/spec/ruby/core/enumerable/entries_spec.rb b/spec/ruby/core/enumerable/entries_spec.rb
index 83232cfa06..2de4fc756a 100644
--- a/spec/ruby/core/enumerable/entries_spec.rb
+++ b/spec/ruby/core/enumerable/entries_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/entries'
describe "Enumerable#entries" do
- it_behaves_like :enumerable_entries , :entries
+ it_behaves_like :enumerable_entries, :entries
end
diff --git a/spec/ruby/core/enumerable/filter_map_spec.rb b/spec/ruby/core/enumerable/filter_map_spec.rb
index aa4894230b..1ed131a960 100644
--- a/spec/ruby/core/enumerable/filter_map_spec.rb
+++ b/spec/ruby/core/enumerable/filter_map_spec.rb
@@ -19,6 +19,6 @@ describe 'Enumerable#filter_map' do
end
it 'returns an enumerator when no block given' do
- @numerous.filter_map.should be_an_instance_of(Enumerator)
+ @numerous.filter_map.should.instance_of?(Enumerator)
end
end
diff --git a/spec/ruby/core/enumerable/filter_spec.rb b/spec/ruby/core/enumerable/filter_spec.rb
index 7e4f8c0b50..1c3a7e9ff5 100644
--- a/spec/ruby/core/enumerable/filter_spec.rb
+++ b/spec/ruby/core/enumerable/filter_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find_all'
describe "Enumerable#filter" do
- it_behaves_like(:enumerable_find_all , :filter)
+ it_behaves_like :enumerable_find_all, :filter
end
diff --git a/spec/ruby/core/enumerable/find_all_spec.rb b/spec/ruby/core/enumerable/find_all_spec.rb
index ce9058fe77..9cd635f247 100644
--- a/spec/ruby/core/enumerable/find_all_spec.rb
+++ b/spec/ruby/core/enumerable/find_all_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find_all'
describe "Enumerable#find_all" do
- it_behaves_like :enumerable_find_all , :find_all
+ it_behaves_like :enumerable_find_all, :find_all
end
diff --git a/spec/ruby/core/enumerable/find_index_spec.rb b/spec/ruby/core/enumerable/find_index_spec.rb
index 542660fe04..2e714367ba 100644
--- a/spec/ruby/core/enumerable/find_index_spec.rb
+++ b/spec/ruby/core/enumerable/find_index_spec.rb
@@ -47,7 +47,7 @@ describe "Enumerable#find_index" do
end
it "returns an Enumerator if no block given" do
- @numerous.find_index.should be_an_instance_of(Enumerator)
+ @numerous.find_index.should.instance_of?(Enumerator)
end
it "uses #== for testing equality" do
diff --git a/spec/ruby/core/enumerable/find_spec.rb b/spec/ruby/core/enumerable/find_spec.rb
index 25aa3bf103..5ddebc05f8 100644
--- a/spec/ruby/core/enumerable/find_spec.rb
+++ b/spec/ruby/core/enumerable/find_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find'
describe "Enumerable#find" do
- it_behaves_like :enumerable_find , :find
+ it_behaves_like :enumerable_find, :find
end
diff --git a/spec/ruby/core/enumerable/first_spec.rb b/spec/ruby/core/enumerable/first_spec.rb
index ed1ba599b4..592dff1ebc 100644
--- a/spec/ruby/core/enumerable/first_spec.rb
+++ b/spec/ruby/core/enumerable/first_spec.rb
@@ -19,7 +19,7 @@ describe "Enumerable#first" do
it "raises a RangeError when passed a Bignum" do
enum = EnumerableSpecs::Empty.new
- -> { enum.first(bignum_value) }.should raise_error(RangeError)
+ -> { enum.first(bignum_value) }.should.raise(RangeError)
end
describe "when passed an argument" do
diff --git a/spec/ruby/core/enumerable/fixtures/classes.rb b/spec/ruby/core/enumerable/fixtures/classes.rb
index fb4951c6e6..b5feafcfb7 100644
--- a/spec/ruby/core/enumerable/fixtures/classes.rb
+++ b/spec/ruby/core/enumerable/fixtures/classes.rb
@@ -38,12 +38,14 @@ module EnumerableSpecs
class Empty
include Enumerable
def each
+ self
end
end
class EmptyWithSize
include Enumerable
def each
+ self
end
def size
0
@@ -342,4 +344,7 @@ module EnumerableSpecs
@block.call(*args)
end
end
+
+ class SetSubclass < Set
+ end
end # EnumerableSpecs utility classes
diff --git a/spec/ruby/core/enumerable/flat_map_spec.rb b/spec/ruby/core/enumerable/flat_map_spec.rb
index a294b9ddad..bd07eab6c5 100644
--- a/spec/ruby/core/enumerable/flat_map_spec.rb
+++ b/spec/ruby/core/enumerable/flat_map_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/collect_concat'
describe "Enumerable#flat_map" do
- it_behaves_like :enumerable_collect_concat , :flat_map
+ it_behaves_like :enumerable_collect_concat, :flat_map
end
diff --git a/spec/ruby/core/enumerable/grep_spec.rb b/spec/ruby/core/enumerable/grep_spec.rb
index b81075291f..965e183766 100644
--- a/spec/ruby/core/enumerable/grep_spec.rb
+++ b/spec/ruby/core/enumerable/grep_spec.rb
@@ -40,43 +40,28 @@ describe "Enumerable#grep" do
$~.should == nil
end
- ruby_version_is ""..."3.0.0" do
- it "sets $~ to the last match when given no block" do
- "z" =~ /z/ # Reset $~
- ["abc", "def"].grep(/b/).should == ["abc"]
-
- # Set by the failed match of "def"
- $~.should == nil
-
- ["abc", "def"].grep(/e/)
- $&.should == "e"
- end
+ it "does not set $~ when given no block" do
+ "z" =~ /z/ # Reset $~
+ ["abc", "def"].grep(/b/).should == ["abc"]
+ $&.should == "z"
end
- ruby_version_is "3.0.0" do
- it "does not set $~ when given no block" do
- "z" =~ /z/ # Reset $~
- ["abc", "def"].grep(/b/).should == ["abc"]
- $&.should == "z"
- end
-
- it "does not modify Regexp.last_match without block" do
- "z" =~ /z/ # Reset last match
- ["abc", "def"].grep(/b/).should == ["abc"]
- Regexp.last_match[0].should == "z"
- end
+ it "does not modify Regexp.last_match without block" do
+ "z" =~ /z/ # Reset last match
+ ["abc", "def"].grep(/b/).should == ["abc"]
+ Regexp.last_match[0].should == "z"
+ end
- it "correctly handles non-string elements" do
- 'set last match' =~ /set last (.*)/
- [:a, 'b', 'z', :c, 42, nil].grep(/[a-d]/).should == [:a, 'b', :c]
- $1.should == 'match'
+ it "correctly handles non-string elements" do
+ 'set last match' =~ /set last (.*)/
+ [:a, 'b', 'z', :c, 42, nil].grep(/[a-d]/).should == [:a, 'b', :c]
+ $1.should == 'match'
- o = Object.new
- def o.to_str
- 'hello'
- end
- [o].grep(/ll/).first.should.equal?(o)
+ o = Object.new
+ def o.to_str
+ 'hello'
end
+ [o].grep(/ll/).first.should.equal?(o)
end
describe "with a block" do
@@ -96,7 +81,7 @@ describe "Enumerable#grep" do
end
it "raises an ArgumentError when not given a pattern" do
- -> { @numerous.grep { |e| e } }.should raise_error(ArgumentError)
+ -> { @numerous.grep { |e| e } }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/enumerable/grep_v_spec.rb b/spec/ruby/core/enumerable/grep_v_spec.rb
index 35fde27eb6..ee99a77ac1 100644
--- a/spec/ruby/core/enumerable/grep_v_spec.rb
+++ b/spec/ruby/core/enumerable/grep_v_spec.rb
@@ -20,43 +20,28 @@ describe "Enumerable#grep_v" do
$&.should == "e"
end
- ruby_version_is ""..."3.0.0" do
- it "sets $~ to the last match when given no block" do
- "z" =~ /z/ # Reset $~
- ["abc", "def"].grep_v(/e/).should == ["abc"]
-
- # Set by the match of "def"
- $&.should == "e"
-
- ["abc", "def"].grep_v(/b/)
- $&.should == nil
- end
+ it "does not set $~ when given no block" do
+ "z" =~ /z/ # Reset $~
+ ["abc", "def"].grep_v(/e/).should == ["abc"]
+ $&.should == "z"
end
- ruby_version_is "3.0.0" do
- it "does not set $~ when given no block" do
- "z" =~ /z/ # Reset $~
- ["abc", "def"].grep_v(/e/).should == ["abc"]
- $&.should == "z"
- end
-
- it "does not modify Regexp.last_match without block" do
- "z" =~ /z/ # Reset last match
- ["abc", "def"].grep_v(/e/).should == ["abc"]
- Regexp.last_match[0].should == "z"
- end
+ it "does not modify Regexp.last_match without block" do
+ "z" =~ /z/ # Reset last match
+ ["abc", "def"].grep_v(/e/).should == ["abc"]
+ Regexp.last_match[0].should == "z"
+ end
- it "correctly handles non-string elements" do
- 'set last match' =~ /set last (.*)/
- [:a, 'b', 'z', :c, 42, nil].grep_v(/[a-d]/).should == ['z', 42, nil]
- $1.should == 'match'
+ it "correctly handles non-string elements" do
+ 'set last match' =~ /set last (.*)/
+ [:a, 'b', 'z', :c, 42, nil].grep_v(/[a-d]/).should == ['z', 42, nil]
+ $1.should == 'match'
- o = Object.new
- def o.to_str
- 'hello'
- end
- [o].grep_v(/mm/).first.should.equal?(o)
+ o = Object.new
+ def o.to_str
+ 'hello'
end
+ [o].grep_v(/mm/).first.should.equal?(o)
end
describe "without block" do
@@ -70,7 +55,7 @@ describe "Enumerable#grep_v" do
end
it "raises an ArgumentError when not given a pattern" do
- -> { @numerous.grep_v }.should raise_error(ArgumentError)
+ -> { @numerous.grep_v }.should.raise(ArgumentError)
end
end
@@ -85,7 +70,7 @@ describe "Enumerable#grep_v" do
end
it "raises an ArgumentError when not given a pattern" do
- -> { @numerous.grep_v { |e| e } }.should raise_error(ArgumentError)
+ -> { @numerous.grep_v { |e| e } }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/enumerable/group_by_spec.rb b/spec/ruby/core/enumerable/group_by_spec.rb
index 4fd1603819..904e5d6c68 100644
--- a/spec/ruby/core/enumerable/group_by_spec.rb
+++ b/spec/ruby/core/enumerable/group_by_spec.rb
@@ -16,13 +16,13 @@ describe "Enumerable#group_by" do
it "returns a hash without default_proc" do
e = EnumerableSpecs::Numerous.new("foo", "bar", "baz")
h = e.group_by { |word| word[0..0].to_sym }
- h[:some].should be_nil
- h.default_proc.should be_nil
- h.default.should be_nil
+ h[:some].should == nil
+ h.default_proc.should == nil
+ h.default.should == nil
end
it "returns an Enumerator if called without a block" do
- EnumerableSpecs::Numerous.new.group_by.should be_an_instance_of(Enumerator)
+ EnumerableSpecs::Numerous.new.group_by.should.instance_of?(Enumerator)
end
it "gathers whole arrays as elements when each yields multiple" do
diff --git a/spec/ruby/core/enumerable/lazy_spec.rb b/spec/ruby/core/enumerable/lazy_spec.rb
index 9a9ead81a0..935e574067 100644
--- a/spec/ruby/core/enumerable/lazy_spec.rb
+++ b/spec/ruby/core/enumerable/lazy_spec.rb
@@ -5,6 +5,6 @@ require_relative 'fixtures/classes'
describe "Enumerable#lazy" do
it "returns an instance of Enumerator::Lazy" do
- EnumerableSpecs::Numerous.new.lazy.should be_an_instance_of(Enumerator::Lazy)
+ EnumerableSpecs::Numerous.new.lazy.should.instance_of?(Enumerator::Lazy)
end
end
diff --git a/spec/ruby/core/enumerable/map_spec.rb b/spec/ruby/core/enumerable/map_spec.rb
index d65aec238c..98a70781cf 100644
--- a/spec/ruby/core/enumerable/map_spec.rb
+++ b/spec/ruby/core/enumerable/map_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/collect'
describe "Enumerable#map" do
- it_behaves_like :enumerable_collect , :map
+ it_behaves_like :enumerable_collect, :map
end
diff --git a/spec/ruby/core/enumerable/max_by_spec.rb b/spec/ruby/core/enumerable/max_by_spec.rb
index ec1738ea3b..f67b5d15ea 100644
--- a/spec/ruby/core/enumerable/max_by_spec.rb
+++ b/spec/ruby/core/enumerable/max_by_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/enumerable_enumeratorized'
describe "Enumerable#max_by" do
it "returns an enumerator if no block" do
- EnumerableSpecs::Numerous.new(42).max_by.should be_an_instance_of(Enumerator)
+ EnumerableSpecs::Numerous.new(42).max_by.should.instance_of?(Enumerator)
end
it "returns nil if #each yields no objects" do
@@ -18,7 +18,7 @@ describe "Enumerable#max_by" do
it "returns the object that appears first in #each in case of a tie" do
a, b, c = '1', '2', '2'
- EnumerableSpecs::Numerous.new(a, b, c).max_by {|obj| obj.to_i }.should equal(b)
+ EnumerableSpecs::Numerous.new(a, b, c).max_by {|obj| obj.to_i }.should.equal?(b)
end
it "uses max.<=>(current) to determine order" do
@@ -48,7 +48,7 @@ describe "Enumerable#max_by" do
context "without a block" do
it "returns an enumerator" do
- @enum.max_by(2).should be_an_instance_of(Enumerator)
+ @enum.max_by(2).should.instance_of?(Enumerator)
end
end
@@ -67,7 +67,7 @@ describe "Enumerable#max_by" do
context "when n is negative" do
it "raises an ArgumentError" do
- -> { @enum.max_by(-1) { |i| i.to_s } }.should raise_error(ArgumentError)
+ -> { @enum.max_by(-1) { |i| i.to_s } }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/enumerable/max_spec.rb b/spec/ruby/core/enumerable/max_spec.rb
index 0c11ca0969..d92700258b 100644
--- a/spec/ruby/core/enumerable/max_spec.rb
+++ b/spec/ruby/core/enumerable/max_spec.rb
@@ -38,16 +38,16 @@ describe "Enumerable#max" do
it "raises a NoMethodError for elements without #<=>" do
-> do
EnumerableSpecs::EachDefiner.new(BasicObject.new, BasicObject.new).max
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
it "raises an ArgumentError for incomparable elements" do
-> do
EnumerableSpecs::EachDefiner.new(11,"22").max
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
-> do
EnumerableSpecs::EachDefiner.new(11,12,22,33).max{|a, b| nil}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
context "when passed a block" do
@@ -106,7 +106,7 @@ describe "Enumerable#max" do
context "that is negative" do
it "raises an ArgumentError" do
- -> { @e_ints.max(-1) }.should raise_error(ArgumentError)
+ -> { @e_ints.max(-1) }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/enumerable/min_by_spec.rb b/spec/ruby/core/enumerable/min_by_spec.rb
index 3ff87e49d8..4f949e2130 100644
--- a/spec/ruby/core/enumerable/min_by_spec.rb
+++ b/spec/ruby/core/enumerable/min_by_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/enumerable_enumeratorized'
describe "Enumerable#min_by" do
it "returns an enumerator if no block" do
- EnumerableSpecs::Numerous.new(42).min_by.should be_an_instance_of(Enumerator)
+ EnumerableSpecs::Numerous.new(42).min_by.should.instance_of?(Enumerator)
end
it "returns nil if #each yields no objects" do
@@ -18,7 +18,7 @@ describe "Enumerable#min_by" do
it "returns the object that appears first in #each in case of a tie" do
a, b, c = '2', '1', '1'
- EnumerableSpecs::Numerous.new(a, b, c).min_by {|obj| obj.to_i }.should equal(b)
+ EnumerableSpecs::Numerous.new(a, b, c).min_by {|obj| obj.to_i }.should.equal?(b)
end
it "uses min.<=>(current) to determine order" do
@@ -48,7 +48,7 @@ describe "Enumerable#min_by" do
context "without a block" do
it "returns an enumerator" do
- @enum.min_by(2).should be_an_instance_of(Enumerator)
+ @enum.min_by(2).should.instance_of?(Enumerator)
end
end
@@ -67,7 +67,7 @@ describe "Enumerable#min_by" do
context "when n is negative" do
it "raises an ArgumentError" do
- -> { @enum.min_by(-1) { |i| i.to_s } }.should raise_error(ArgumentError)
+ -> { @enum.min_by(-1) { |i| i.to_s } }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/enumerable/min_spec.rb b/spec/ruby/core/enumerable/min_spec.rb
index 4b6ae248fa..f05d59c2c9 100644
--- a/spec/ruby/core/enumerable/min_spec.rb
+++ b/spec/ruby/core/enumerable/min_spec.rb
@@ -32,22 +32,22 @@ describe "Enumerable#min" do
end
it "returns nil for an empty Enumerable" do
- EnumerableSpecs::EachDefiner.new.min.should be_nil
+ EnumerableSpecs::EachDefiner.new.min.should == nil
end
it "raises a NoMethodError for elements without #<=>" do
-> do
EnumerableSpecs::EachDefiner.new(BasicObject.new, BasicObject.new).min
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
it "raises an ArgumentError for incomparable elements" do
-> do
EnumerableSpecs::EachDefiner.new(11,"22").min
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
-> do
EnumerableSpecs::EachDefiner.new(11,12,22,33).min{|a, b| nil}
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "returns the minimum when using a block rule" do
@@ -110,7 +110,7 @@ describe "Enumerable#min" do
context "that is negative" do
it "raises an ArgumentError" do
- -> { @e_ints.min(-1) }.should raise_error(ArgumentError)
+ -> { @e_ints.min(-1) }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/enumerable/minmax_by_spec.rb b/spec/ruby/core/enumerable/minmax_by_spec.rb
index a6a9249270..30c88cfcfb 100644
--- a/spec/ruby/core/enumerable/minmax_by_spec.rb
+++ b/spec/ruby/core/enumerable/minmax_by_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/enumerable_enumeratorized'
describe "Enumerable#minmax_by" do
it "returns an enumerator if no block" do
- EnumerableSpecs::Numerous.new(42).minmax_by.should be_an_instance_of(Enumerator)
+ EnumerableSpecs::Numerous.new(42).minmax_by.should.instance_of?(Enumerator)
end
it "returns nil if #each yields no objects" do
@@ -19,8 +19,8 @@ describe "Enumerable#minmax_by" do
it "returns the object that appears first in #each in case of a tie" do
a, b, c, d = '1', '1', '2', '2'
mm = EnumerableSpecs::Numerous.new(a, b, c, d).minmax_by {|obj| obj.to_i }
- mm[0].should equal(a)
- mm[1].should equal(c)
+ mm[0].should.equal?(a)
+ mm[1].should.equal?(c)
end
it "uses min/max.<=>(current) to determine order" do
diff --git a/spec/ruby/core/enumerable/none_spec.rb b/spec/ruby/core/enumerable/none_spec.rb
index 99bb7f7a4e..d9ee0b441e 100644
--- a/spec/ruby/core/enumerable/none_spec.rb
+++ b/spec/ruby/core/enumerable/none_spec.rb
@@ -15,35 +15,35 @@ describe "Enumerable#none?" do
end
it "raises an ArgumentError when more than 1 argument is provided" do
- -> { @enum.none?(1, 2, 3) }.should raise_error(ArgumentError)
- -> { [].none?(1, 2, 3) }.should raise_error(ArgumentError)
- -> { {}.none?(1, 2, 3) }.should raise_error(ArgumentError)
+ -> { @enum.none?(1, 2, 3) }.should.raise(ArgumentError)
+ -> { [].none?(1, 2, 3) }.should.raise(ArgumentError)
+ -> { {}.none?(1, 2, 3) }.should.raise(ArgumentError)
end
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.none?
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
-> {
EnumerableSpecs::ThrowingEach.new.none? { false }
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
describe "with no block" do
it "returns true if none of the elements in self are true" do
e = EnumerableSpecs::Numerous.new(false, nil, false)
- e.none?.should be_true
+ e.none?.should == true
end
it "returns false if at least one of the elements in self are true" do
e = EnumerableSpecs::Numerous.new(false, nil, true, false)
- e.none?.should be_false
+ e.none?.should == false
end
it "gathers whole arrays as elements when each yields multiple" do
multi = EnumerableSpecs::YieldsMultiWithFalse.new
- multi.none?.should be_false
+ multi.none?.should == false
end
end
@@ -65,17 +65,17 @@ describe "Enumerable#none?" do
end
it "returns true if the block never returns true" do
- @e.none? {|e| false }.should be_true
+ @e.none? {|e| false }.should == true
end
it "returns false if the block ever returns true" do
- @e.none? {|e| e == 3 ? true : false }.should be_false
+ @e.none? {|e| e == 3 ? true : false }.should == false
end
it "does not hide exceptions out of the block" do
-> {
@enum.none? { raise "from block" }
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "gathers initial args as elements when each yields multiple" do
@@ -94,7 +94,7 @@ describe "Enumerable#none?" do
end
describe 'when given a pattern argument' do
- it "calls `===` on the pattern the return value " do
+ it "calls `===` on the pattern the return value" do
pattern = EnumerableSpecs::Pattern.new { |x| x == 3 }
@enum1.none?(pattern).should == true
pattern.yielded.should == [[0], [1], [2], [-1]]
@@ -109,7 +109,7 @@ describe "Enumerable#none?" do
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.none?(Integer)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "returns true if the pattern never returns a truthy value" do
@@ -134,7 +134,7 @@ describe "Enumerable#none?" do
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
-> {
@enum.none?(pattern)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "calls the pattern with gathered array when yielded with multiple arguments" do
@@ -143,5 +143,11 @@ describe "Enumerable#none?" do
multi.none?(pattern).should == true
pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
end
+
+ it "ignores the block if there is an argument" do
+ -> {
+ EnumerableSpecs::Numerous.new(1, 2, 3, 4, 5).none?(String) { true }.should == true
+ }.should complain(/given block not used/)
+ end
end
end
diff --git a/spec/ruby/core/enumerable/one_spec.rb b/spec/ruby/core/enumerable/one_spec.rb
index 47bfd65a0f..cf966d4a9b 100644
--- a/spec/ruby/core/enumerable/one_spec.rb
+++ b/spec/ruby/core/enumerable/one_spec.rb
@@ -15,57 +15,57 @@ describe "Enumerable#one?" do
end
it "raises an ArgumentError when more than 1 argument is provided" do
- -> { @enum.one?(1, 2, 3) }.should raise_error(ArgumentError)
- -> { [].one?(1, 2, 3) }.should raise_error(ArgumentError)
- -> { {}.one?(1, 2, 3) }.should raise_error(ArgumentError)
+ -> { @enum.one?(1, 2, 3) }.should.raise(ArgumentError)
+ -> { [].one?(1, 2, 3) }.should.raise(ArgumentError)
+ -> { {}.one?(1, 2, 3) }.should.raise(ArgumentError)
end
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.one?
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
-> {
EnumerableSpecs::ThrowingEach.new.one? { false }
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
describe "with no block" do
it "returns true if only one element evaluates to true" do
- [false, nil, true].one?.should be_true
+ [false, nil, true].one?.should == true
end
it "returns false if two elements evaluate to true" do
- [false, :value, nil, true].one?.should be_false
+ [false, :value, nil, true].one?.should == false
end
it "returns false if all elements evaluate to false" do
- [false, nil, false].one?.should be_false
+ [false, nil, false].one?.should == false
end
it "gathers whole arrays as elements when each yields multiple" do
multi = EnumerableSpecs::YieldsMultiWithSingleTrue.new
- multi.one?.should be_false
+ multi.one?.should == false
end
end
describe "with a block" do
it "returns true if block returns true once" do
- [:a, :b, :c].one? { |s| s == :a }.should be_true
+ [:a, :b, :c].one? { |s| s == :a }.should == true
end
it "returns false if the block returns true more than once" do
- [:a, :b, :c].one? { |s| s == :a || s == :b }.should be_false
+ [:a, :b, :c].one? { |s| s == :a || s == :b }.should == false
end
it "returns false if the block only returns false" do
- [:a, :b, :c].one? { |s| s == :d }.should be_false
+ [:a, :b, :c].one? { |s| s == :d }.should == false
end
it "does not hide exceptions out of the block" do
-> {
@enum.one? { raise "from block" }
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "gathers initial args as elements when each yields multiple" do
@@ -83,9 +83,8 @@ describe "Enumerable#one?" do
end
end
-
describe 'when given a pattern argument' do
- it "calls `===` on the pattern the return value " do
+ it "calls `===` on the pattern the return value" do
pattern = EnumerableSpecs::Pattern.new { |x| x == 1 }
@enum1.one?(pattern).should == true
pattern.yielded.should == [[0], [1], [2], [-1]]
@@ -100,7 +99,7 @@ describe "Enumerable#one?" do
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.one?(Integer)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "returns true if the pattern returns a truthy value only once" do
@@ -136,7 +135,7 @@ describe "Enumerable#one?" do
pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
-> {
@enum.one?(pattern)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
it "calls the pattern with gathered array when yielded with multiple arguments" do
@@ -145,5 +144,11 @@ describe "Enumerable#one?" do
multi.one?(pattern).should == false
pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
end
+
+ it "ignores the block if there is an argument" do
+ -> {
+ EnumerableSpecs::Numerous.new(1, 2, 3, 4, "5").one?(String) { false }.should == true
+ }.should complain(/given block not used/)
+ end
end
end
diff --git a/spec/ruby/core/enumerable/partition_spec.rb b/spec/ruby/core/enumerable/partition_spec.rb
index d3d220b4b4..8272ee189e 100644
--- a/spec/ruby/core/enumerable/partition_spec.rb
+++ b/spec/ruby/core/enumerable/partition_spec.rb
@@ -8,7 +8,7 @@ describe "Enumerable#partition" do
end
it "returns an Enumerator if called without a block" do
- EnumerableSpecs::Numerous.new.partition.should be_an_instance_of(Enumerator)
+ EnumerableSpecs::Numerous.new.partition.should.instance_of?(Enumerator)
end
it "gathers whole arrays as elements when each yields multiple" do
diff --git a/spec/ruby/core/enumerable/reject_spec.rb b/spec/ruby/core/enumerable/reject_spec.rb
index 0d86b49ea2..31e89f5b0e 100644
--- a/spec/ruby/core/enumerable/reject_spec.rb
+++ b/spec/ruby/core/enumerable/reject_spec.rb
@@ -13,7 +13,7 @@ describe "Enumerable#reject" do
end
it "returns an Enumerator if called without a block" do
- EnumerableSpecs::Numerous.new.reject.should be_an_instance_of(Enumerator)
+ EnumerableSpecs::Numerous.new.reject.should.instance_of?(Enumerator)
end
it "gathers whole arrays as elements when each yields multiple" do
diff --git a/spec/ruby/core/enumerable/reverse_each_spec.rb b/spec/ruby/core/enumerable/reverse_each_spec.rb
index 2b1c233488..4753956724 100644
--- a/spec/ruby/core/enumerable/reverse_each_spec.rb
+++ b/spec/ruby/core/enumerable/reverse_each_spec.rb
@@ -11,7 +11,7 @@ describe "Enumerable#reverse_each" do
it "returns an Enumerator if no block given" do
enum = EnumerableSpecs::Numerous.new.reverse_each
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.should == [4, 1, 6, 3, 5, 2]
end
diff --git a/spec/ruby/core/enumerable/select_spec.rb b/spec/ruby/core/enumerable/select_spec.rb
index 11168eb42e..7fc61926f9 100644
--- a/spec/ruby/core/enumerable/select_spec.rb
+++ b/spec/ruby/core/enumerable/select_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find_all'
describe "Enumerable#select" do
- it_behaves_like :enumerable_find_all , :select
+ it_behaves_like :enumerable_find_all, :select
end
diff --git a/spec/ruby/core/enumerable/shared/collect.rb b/spec/ruby/core/enumerable/shared/collect.rb
index 6df1a616eb..4696d32454 100644
--- a/spec/ruby/core/enumerable/shared/collect.rb
+++ b/spec/ruby/core/enumerable/shared/collect.rb
@@ -30,7 +30,7 @@ describe :enumerable_collect, shared: true do
it "returns an enumerator when no block given" do
enum = EnumerableSpecs::Numerous.new.send(@method)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.each { |i| -i }.should == [-2, -5, -3, -6, -1, -4]
end
@@ -86,7 +86,7 @@ describe :enumerable_collect, shared: true do
-> do
{ 1 => 'a', 2 => 'b' }.map(&m)
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "calls the each method on sub-classes" do
diff --git a/spec/ruby/core/enumerable/shared/collect_concat.rb b/spec/ruby/core/enumerable/shared/collect_concat.rb
index ddd431baeb..1694e3fdce 100644
--- a/spec/ruby/core/enumerable/shared/collect_concat.rb
+++ b/spec/ruby/core/enumerable/shared/collect_concat.rb
@@ -41,12 +41,12 @@ describe :enumerable_collect_concat, shared: true do
obj = mock("to_ary defined")
obj.should_receive(:to_ary).and_return("array")
- -> { [1, obj, 3].send(@method) { |i| i } }.should raise_error(TypeError)
+ -> { [1, obj, 3].send(@method) { |i| i } }.should.raise(TypeError)
end
it "returns an enumerator when no block given" do
enum = EnumerableSpecs::Numerous.new(1, 2).send(@method)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.each{ |i| [i] * i }.should == [1, 2, 2]
end
diff --git a/spec/ruby/core/enumerable/shared/find.rb b/spec/ruby/core/enumerable/shared/find.rb
index 61d63ba3d5..cdff640415 100644
--- a/spec/ruby/core/enumerable/shared/find.rb
+++ b/spec/ruby/core/enumerable/shared/find.rb
@@ -59,7 +59,7 @@ describe :enumerable_find, shared: true do
end
it "returns an enumerator when no block given" do
- @numerous.send(@method).should be_an_instance_of(Enumerator)
+ @numerous.send(@method).should.instance_of?(Enumerator)
end
it "passes the ifnone proc to the enumerator" do
diff --git a/spec/ruby/core/enumerable/shared/find_all.rb b/spec/ruby/core/enumerable/shared/find_all.rb
index 1bbe71f372..27f01de6e0 100644
--- a/spec/ruby/core/enumerable/shared/find_all.rb
+++ b/spec/ruby/core/enumerable/shared/find_all.rb
@@ -14,7 +14,7 @@ describe :enumerable_find_all, shared: true do
end
it "returns an enumerator when no block given" do
- @numerous.send(@method).should be_an_instance_of(Enumerator)
+ @numerous.send(@method).should.instance_of?(Enumerator)
end
it "passes through the values yielded by #each_with_index" do
diff --git a/spec/ruby/core/enumerable/shared/include.rb b/spec/ruby/core/enumerable/shared/include.rb
index 569f350fd5..ea250f032b 100644
--- a/spec/ruby/core/enumerable/shared/include.rb
+++ b/spec/ruby/core/enumerable/shared/include.rb
@@ -28,7 +28,7 @@ describe :enumerable_include, shared: true do
it "gathers whole arrays as elements when each yields multiple" do
multi = EnumerableSpecs::YieldsMulti.new
- multi.send(@method, [1,2]).should be_true
+ multi.send(@method, [1,2]).should == true
end
end
diff --git a/spec/ruby/core/enumerable/shared/inject.rb b/spec/ruby/core/enumerable/shared/inject.rb
index c5907f92d8..7da4f0ca99 100644
--- a/spec/ruby/core/enumerable/shared/inject.rb
+++ b/spec/ruby/core/enumerable/shared/inject.rb
@@ -1,3 +1,5 @@
+require_relative '../../array/shared/iterable_and_tolerating_size_increasing'
+
describe :enumerable_inject, shared: true do
it "with argument takes a block with an accumulator (with argument as initial value) and the current element. Value of block becomes new accumulator" do
a = []
@@ -14,15 +16,65 @@ describe :enumerable_inject, shared: true do
it "can take two argument" do
EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-).should == 4
+ EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, "-").should == 4
+
+ [1, 2, 3].send(@method, 10, :-).should == 4
+ [1, 2, 3].send(@method, 10, "-").should == 4
+ end
+
+ it "converts non-Symbol method name argument to String with #to_str if two arguments" do
+ name = Object.new
+ def name.to_str; "-"; end
+
+ EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, name).should == 4
+ [1, 2, 3].send(@method, 10, name).should == 4
+ end
+
+ it "raises TypeError when the second argument is not Symbol or String and it cannot be converted to String if two arguments" do
+ -> { EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, Object.new) }.should.raise(TypeError, /is not a symbol nor a string/)
+ -> { [1, 2, 3].send(@method, 10, Object.new) }.should.raise(TypeError, /is not a symbol nor a string/)
end
it "ignores the block if two arguments" do
- EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-) { raise "we never get here"}.should == 4
- [].send(@method, 3, :+) { raise "we never get here"}.should == 3
+ -> {
+ EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-) { raise "we never get here"}.should == 4
+ }.should complain(/#{__FILE__}:#{__LINE__-1}: warning: given block not used/, verbose: true)
+
+ -> {
+ [1, 2, 3].send(@method, 10, :-) { raise "we never get here"}.should == 4
+ }.should complain(/#{__FILE__}:#{__LINE__-1}: warning: given block not used/, verbose: true)
+ end
+
+ it "does not warn when given a Symbol with $VERBOSE true" do
+ -> {
+ [1, 2].send(@method, 0, :+)
+ [1, 2].send(@method, :+)
+ EnumerableSpecs::Numerous.new(1, 2).send(@method, 0, :+)
+ EnumerableSpecs::Numerous.new(1, 2).send(@method, :+)
+ }.should_not complain(verbose: true)
end
it "can take a symbol argument" do
EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, :-).should == 4
+ [10, 1, 2, 3].send(@method, :-).should == 4
+ end
+
+ it "can take a String argument" do
+ EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, "-").should == 4
+ [10, 1, 2, 3].send(@method, "-").should == 4
+ end
+
+ it "converts non-Symbol method name argument to String with #to_str" do
+ name = Object.new
+ def name.to_str; "-"; end
+
+ EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, name).should == 4
+ [10, 1, 2, 3].send(@method, name).should == 4
+ end
+
+ it "raises TypeError when passed not Symbol or String method name argument and it cannot be converted to String" do
+ -> { EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, Object.new) }.should.raise(TypeError, /is not a symbol nor a string/)
+ -> { [10, 1, 2, 3].send(@method, Object.new) }.should.raise(TypeError, /is not a symbol nor a string/)
end
it "without argument takes a block with an accumulator (with first element as initial value) and the current element. Value of block becomes new accumulator" do
@@ -31,10 +83,10 @@ describe :enumerable_inject, shared: true do
a.should == [[2, 5], [5, 3], [3, 6], [6, 1], [1, 4]]
end
- it "gathers whole arrays as elements when each yields multiple" do
- multi = EnumerableSpecs::YieldsMulti.new
- multi.send(@method, []) {|acc, e| acc << e }.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
- end
+ it "gathers whole arrays as elements when each yields multiple" do
+ multi = EnumerableSpecs::YieldsMulti.new
+ multi.send(@method, []) {|acc, e| acc << e }.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
+ end
it "with inject arguments(legacy rubycon)" do
# with inject argument
@@ -51,7 +103,7 @@ describe :enumerable_inject, shared: true do
it "without inject arguments(legacy rubycon)" do
# no inject argument
- EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| 999 } .should == 2
+ EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| 999 }.should == 2
EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| acc }.should == 2
EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| x }.should == 2
@@ -61,17 +113,30 @@ describe :enumerable_inject, shared: true do
EnumerableSpecs::EachDefiner.new('a','b','c').send(@method) {|result, i| i+result}.should == "cba"
EnumerableSpecs::EachDefiner.new(3, 4, 5).send(@method) {|result, i| result*i}.should == 60
EnumerableSpecs::EachDefiner.new([1], 2, 'a','b').send(@method){|r,i| r<<i}.should == [1, 2, 'a', 'b']
-
end
it "returns nil when fails(legacy rubycon)" do
EnumerableSpecs::EachDefiner.new().send(@method) {|acc,x| 999 }.should == nil
end
- ruby_bug '#18635', ''...'3.2' do
- it "raises an ArgumentError when no parameters or block is given" do
- -> { [1,2].send(@method) }.should raise_error(ArgumentError)
- -> { {one: 1, two: 2}.send(@method) }.should raise_error(ArgumentError)
+ it "tolerates increasing a collection size during iterating Array" do
+ array = [:a, :b, :c]
+ ScratchPad.record []
+ i = 0
+
+ array.send(@method, nil) do |_, e|
+ ScratchPad << e
+ array << i if i < 100
+ i += 1
end
+
+ actual = ScratchPad.recorded
+ expected = [:a, :b, :c] + (0..99).to_a
+ actual.sort_by(&:to_s).should == expected.sort_by(&:to_s)
+ end
+
+ it "raises an ArgumentError when no parameters or block is given" do
+ -> { [1,2].send(@method) }.should.raise(ArgumentError)
+ -> { {one: 1, two: 2}.send(@method) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/enumerable/shared/take.rb b/spec/ruby/core/enumerable/shared/take.rb
index ce2ace20fa..a6da06325f 100644
--- a/spec/ruby/core/enumerable/shared/take.rb
+++ b/spec/ruby/core/enumerable/shared/take.rb
@@ -25,7 +25,7 @@ describe :enumerable_take, shared: true do
end
it "raises an ArgumentError when count is negative" do
- -> { @enum.send(@method, -1) }.should raise_error(ArgumentError)
+ -> { @enum.send(@method, -1) }.should.raise(ArgumentError)
end
it "returns the entire array when count > length" do
@@ -40,11 +40,11 @@ describe :enumerable_take, shared: true do
end
it "raises a TypeError if the passed argument is not numeric" do
- -> { @enum.send(@method, nil) }.should raise_error(TypeError)
- -> { @enum.send(@method, "a") }.should raise_error(TypeError)
+ -> { @enum.send(@method, nil) }.should.raise(TypeError)
+ -> { @enum.send(@method, "a") }.should.raise(TypeError)
obj = mock("nonnumeric")
- -> { @enum.send(@method, obj) }.should raise_error(TypeError)
+ -> { @enum.send(@method, obj) }.should.raise(TypeError)
end
it "gathers whole arrays as elements when each yields multiple" do
diff --git a/spec/ruby/core/enumerable/shared/value_packing.rb b/spec/ruby/core/enumerable/shared/value_packing.rb
new file mode 100644
index 0000000000..ff77f45cdf
--- /dev/null
+++ b/spec/ruby/core/enumerable/shared/value_packing.rb
@@ -0,0 +1,26 @@
+# This is the behavior of rb_enum_values_pack() in CRuby
+describe :enumerable_value_packing, shared: true do
+ # @take must be set to a Proc that returns the take-result whose #each
+ # yields packed values (e.g. -> e { e.take(1) } or -> e { e.lazy.take(1) }).
+
+ it "yields a single nil for a zero-argument source yield" do
+ e = Enumerator.new { |y| y.yield }
+ args = nil
+ @take.call(e).each { |*a| args = a }
+ args.should == [nil]
+ end
+
+ it "yields the value for a single-argument source yield" do
+ e = Enumerator.new { |y| y.yield :v }
+ args = nil
+ @take.call(e).each { |*a| args = a }
+ args.should == [:v]
+ end
+
+ it "yields a packed Array for a multi-argument source yield" do
+ e = Enumerator.new { |y| y.yield 1, 2 }
+ args = nil
+ @take.call(e).each { |*a| args = a }
+ args.should == [[1, 2]]
+ end
+end
diff --git a/spec/ruby/core/enumerable/slice_after_spec.rb b/spec/ruby/core/enumerable/slice_after_spec.rb
index 0e46688db1..1ef37195e5 100644
--- a/spec/ruby/core/enumerable/slice_after_spec.rb
+++ b/spec/ruby/core/enumerable/slice_after_spec.rb
@@ -11,7 +11,7 @@ describe "Enumerable#slice_after" do
arg = mock("filter")
arg.should_receive(:===).and_return(false, true, false, false, false, true, false)
e = @enum.slice_after(arg)
- e.should be_an_instance_of(Enumerator)
+ e.should.instance_of?(Enumerator)
e.to_a.should == [[7, 6], [5, 4, 3, 2], [1]]
end
@@ -34,21 +34,21 @@ describe "Enumerable#slice_after" do
describe "and no argument" do
it "calls the block to determine when to yield" do
e = @enum.slice_after{ |i| i == 6 || i == 2 }
- e.should be_an_instance_of(Enumerator)
+ e.should.instance_of?(Enumerator)
e.to_a.should == [[7, 6], [5, 4, 3, 2], [1]]
end
end
describe "and an argument" do
it "raises an ArgumentError" do
- -> { @enum.slice_after(42) { |i| i == 6 } }.should raise_error(ArgumentError)
+ -> { @enum.slice_after(42) { |i| i == 6 } }.should.raise(ArgumentError)
end
end
end
it "raises an ArgumentError when given an incorrect number of arguments" do
- -> { @enum.slice_after("one", "two") }.should raise_error(ArgumentError)
- -> { @enum.slice_after }.should raise_error(ArgumentError)
+ -> { @enum.slice_after("one", "two") }.should.raise(ArgumentError)
+ -> { @enum.slice_after }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/enumerable/slice_before_spec.rb b/spec/ruby/core/enumerable/slice_before_spec.rb
index f9b33f7b28..7eb4410a25 100644
--- a/spec/ruby/core/enumerable/slice_before_spec.rb
+++ b/spec/ruby/core/enumerable/slice_before_spec.rb
@@ -12,7 +12,7 @@ describe "Enumerable#slice_before" do
arg = mock "filter"
arg.should_receive(:===).and_return(false, true, false, false, false, true, false)
e = @enum.slice_before(arg)
- e.should be_an_instance_of(Enumerator)
+ e.should.instance_of?(Enumerator)
e.to_a.should == [[7], [6, 5, 4, 3], [2, 1]]
end
@@ -35,7 +35,7 @@ describe "Enumerable#slice_before" do
describe "and no argument" do
it "calls the block to determine when to yield" do
e = @enum.slice_before{|i| i == 6 || i == 2}
- e.should be_an_instance_of(Enumerator)
+ e.should.instance_of?(Enumerator)
e.to_a.should == [[7], [6, 5, 4, 3], [2, 1]]
end
end
@@ -43,13 +43,13 @@ describe "Enumerable#slice_before" do
it "does not accept arguments" do
-> {
@enum.slice_before(1) {}
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
end
it "raises an ArgumentError when given an incorrect number of arguments" do
- -> { @enum.slice_before("one", "two") }.should raise_error(ArgumentError)
- -> { @enum.slice_before }.should raise_error(ArgumentError)
+ -> { @enum.slice_before("one", "two") }.should.raise(ArgumentError)
+ -> { @enum.slice_before }.should.raise(ArgumentError)
end
describe "when an iterator method yields more than one value" do
diff --git a/spec/ruby/core/enumerable/slice_when_spec.rb b/spec/ruby/core/enumerable/slice_when_spec.rb
index 6b8ea0923e..fe1ecd31e2 100644
--- a/spec/ruby/core/enumerable/slice_when_spec.rb
+++ b/spec/ruby/core/enumerable/slice_when_spec.rb
@@ -11,7 +11,7 @@ describe "Enumerable#slice_when" do
context "when given a block" do
it "returns an enumerator" do
- @result.should be_an_instance_of(Enumerator)
+ @result.should.instance_of?(Enumerator)
end
it "splits chunks between adjacent elements i and j where the block returns true" do
@@ -39,7 +39,7 @@ describe "Enumerable#slice_when" do
context "when not given a block" do
it "raises an ArgumentError" do
- -> { @enum.slice_when }.should raise_error(ArgumentError)
+ -> { @enum.slice_when }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/enumerable/sort_by_spec.rb b/spec/ruby/core/enumerable/sort_by_spec.rb
index 8fdd923fb4..62cf38ce3e 100644
--- a/spec/ruby/core/enumerable/sort_by_spec.rb
+++ b/spec/ruby/core/enumerable/sort_by_spec.rb
@@ -18,7 +18,7 @@ describe "Enumerable#sort_by" do
it "returns an Enumerator when a block is not supplied" do
a = EnumerableSpecs::Numerous.new("a","b")
- a.sort_by.should be_an_instance_of(Enumerator)
+ a.sort_by.should.instance_of?(Enumerator)
a.to_a.should == ["a", "b"]
end
diff --git a/spec/ruby/core/enumerable/sort_spec.rb b/spec/ruby/core/enumerable/sort_spec.rb
index 6fc64f325e..427b1cd8f1 100644
--- a/spec/ruby/core/enumerable/sort_spec.rb
+++ b/spec/ruby/core/enumerable/sort_spec.rb
@@ -16,7 +16,7 @@ describe "Enumerable#sort" do
it "raises a NoMethodError if elements do not define <=>" do
-> do
EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new, BasicObject.new).sort
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
it "sorts enumerables that contain nils" do
@@ -35,12 +35,12 @@ describe "Enumerable#sort" do
}.should == [6, 5, 4, 3, 2, 1]
-> {
EnumerableSpecs::Numerous.new.sort { |n, m| (n <=> m).to_s }
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises an error if objects can't be compared" do
a=EnumerableSpecs::Numerous.new(EnumerableSpecs::Uncomparable.new, EnumerableSpecs::Uncomparable.new)
- -> {a.sort}.should raise_error(ArgumentError)
+ -> {a.sort}.should.raise(ArgumentError)
end
it "gathers whole arrays as elements when each yields multiple" do
diff --git a/spec/ruby/core/enumerable/sum_spec.rb b/spec/ruby/core/enumerable/sum_spec.rb
index 4a978794e5..2eb74db6ac 100644
--- a/spec/ruby/core/enumerable/sum_spec.rb
+++ b/spec/ruby/core/enumerable/sum_spec.rb
@@ -22,12 +22,25 @@ describe 'Enumerable#sum' do
@enum.sum.should == 5/3r
end
- it 'takes a block to transform the elements' do
- @enum.sum { |element| element * 2 }.should == 10/3r
+ context 'with a block' do
+ it 'transforms the elements' do
+ @enum.sum { |element| element * 2 }.should == 10/3r
+ end
+
+ it 'does not destructure array elements' do
+ class << @enum
+ def each
+ yield [1,2]
+ yield [3]
+ end
+ end
+
+ @enum.sum(&:last).should == 5
+ end
end
# https://bugs.ruby-lang.org/issues/12217
- # https://github.com/ruby/ruby/blob/master/doc/ChangeLog-2.4.0#L6208-L6214
+ # https://github.com/ruby/ruby/blob/master/doc/ChangeLog/ChangeLog-2.4.0#L6208-L6214
it "uses Kahan's compensated summation algorithm for precise sum of float numbers" do
floats = [2.7800000000000002, 5.0, 2.5, 4.44, 3.89, 3.89, 4.44, 7.78, 5.0, 2.7800000000000002, 5.0, 2.5].to_enum
naive_sum = floats.reduce { |sum, e| sum + e }
diff --git a/spec/ruby/core/enumerable/take_spec.rb b/spec/ruby/core/enumerable/take_spec.rb
index 41a7438330..ca439b750d 100644
--- a/spec/ruby/core/enumerable/take_spec.rb
+++ b/spec/ruby/core/enumerable/take_spec.rb
@@ -1,13 +1,21 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/take'
+require_relative 'shared/value_packing'
describe "Enumerable#take" do
it "requires an argument" do
- ->{ EnumerableSpecs::Numerous.new.take}.should raise_error(ArgumentError)
+ ->{ EnumerableSpecs::Numerous.new.take}.should.raise(ArgumentError)
end
describe "when passed an argument" do
it_behaves_like :enumerable_take, :take
end
+
+ describe "value packing of source yields" do
+ before :each do
+ @take = -> e { e.take(1) }
+ end
+ it_behaves_like :enumerable_value_packing, nil
+ end
end
diff --git a/spec/ruby/core/enumerable/take_while_spec.rb b/spec/ruby/core/enumerable/take_while_spec.rb
index 26db39ac4b..918bfc897d 100644
--- a/spec/ruby/core/enumerable/take_while_spec.rb
+++ b/spec/ruby/core/enumerable/take_while_spec.rb
@@ -8,7 +8,7 @@ describe "Enumerable#take_while" do
end
it "returns an Enumerator if no block given" do
- @enum.take_while.should be_an_instance_of(Enumerator)
+ @enum.take_while.should.instance_of?(Enumerator)
end
it "returns no/all elements for {true/false} block" do
@@ -38,7 +38,7 @@ describe "Enumerable#take_while" do
it "doesn't return self when it could" do
a = [1,2,3]
- a.take_while{true}.should_not equal(a)
+ a.take_while{true}.should_not.equal?(a)
end
it "calls the block with initial args when yielded with multiple arguments" do
diff --git a/spec/ruby/core/enumerable/tally_spec.rb b/spec/ruby/core/enumerable/tally_spec.rb
index f09a8f533a..deef741407 100644
--- a/spec/ruby/core/enumerable/tally_spec.rb
+++ b/spec/ruby/core/enumerable/tally_spec.rb
@@ -13,8 +13,8 @@ describe "Enumerable#tally" do
it "returns a hash without default" do
hash = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz').tally
- hash.default_proc.should be_nil
- hash.default.should be_nil
+ hash.default_proc.should == nil
+ hash.default.should == nil
end
it "returns an empty hash for empty enumerables" do
@@ -32,49 +32,60 @@ describe "Enumerable#tally" do
end
end
-ruby_version_is "3.1" do
- describe "Enumerable#tally with a hash" do
- before :each do
- ScratchPad.record []
- end
-
- it "returns a hash with counts according to the value" do
- enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
- enum.tally({ 'foo' => 1 }).should == { 'foo' => 3, 'bar' => 1, 'baz' => 1}
- end
-
- it "returns the given hash" do
- enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
- hash = { 'foo' => 1 }
- enum.tally(hash).should equal(hash)
- end
-
- it "raises a FrozenError and does not update the given hash when the hash is frozen" do
- enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
- hash = { 'foo' => 1 }.freeze
- -> { enum.tally(hash) }.should raise_error(FrozenError)
- hash.should == { 'foo' => 1 }
- end
-
- it "does not call given block" do
- enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
- enum.tally({ 'foo' => 1 }) { |v| ScratchPad << v }
- ScratchPad.recorded.should == []
- end
-
- it "ignores the default value" do
- enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
- enum.tally(Hash.new(100)).should == { 'foo' => 2, 'bar' => 1, 'baz' => 1}
- end
-
- it "ignores the default proc" do
- enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
- enum.tally(Hash.new {100}).should == { 'foo' => 2, 'bar' => 1, 'baz' => 1}
- end
-
- it "needs the values counting each elements to be an integer" do
- enum = EnumerableSpecs::Numerous.new('foo')
- -> { enum.tally({ 'foo' => 'bar' }) }.should raise_error(TypeError)
- end
+describe "Enumerable#tally with a hash" do
+ before :each do
+ ScratchPad.record []
+ end
+
+ it "returns a hash with counts according to the value" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ enum.tally({ 'foo' => 1 }).should == { 'foo' => 3, 'bar' => 1, 'baz' => 1}
+ end
+
+ it "returns the given hash" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ hash = { 'foo' => 1 }
+ enum.tally(hash).should.equal?(hash)
+ end
+
+ it "calls #to_hash to convert argument to Hash implicitly if passed not a Hash" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ object = Object.new
+ def object.to_hash; { 'foo' => 1 }; end
+ enum.tally(object).should == { 'foo' => 3, 'bar' => 1, 'baz' => 1}
+ end
+
+ it "raises a FrozenError and does not update the given hash when the hash is frozen" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ hash = { 'foo' => 1 }.freeze
+ -> { enum.tally(hash) }.should.raise(FrozenError)
+ hash.should == { 'foo' => 1 }
+ end
+
+ it "raises a FrozenError even if enumerable is empty" do
+ enum = EnumerableSpecs::Numerous.new()
+ hash = { 'foo' => 1 }.freeze
+ -> { enum.tally(hash) }.should.raise(FrozenError)
+ end
+
+ it "does not call given block" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ enum.tally({ 'foo' => 1 }) { |v| ScratchPad << v }
+ ScratchPad.recorded.should == []
+ end
+
+ it "ignores the default value" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ enum.tally(Hash.new(100)).should == { 'foo' => 2, 'bar' => 1, 'baz' => 1}
+ end
+
+ it "ignores the default proc" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ enum.tally(Hash.new {100}).should == { 'foo' => 2, 'bar' => 1, 'baz' => 1}
+ end
+
+ it "needs the values counting each elements to be an integer" do
+ enum = EnumerableSpecs::Numerous.new('foo')
+ -> { enum.tally({ 'foo' => 'bar' }) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/enumerable/to_a_spec.rb b/spec/ruby/core/enumerable/to_a_spec.rb
index 0f3060dc48..723f922574 100644
--- a/spec/ruby/core/enumerable/to_a_spec.rb
+++ b/spec/ruby/core/enumerable/to_a_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/entries'
describe "Enumerable#to_a" do
- it_behaves_like :enumerable_entries , :to_a
+ it_behaves_like :enumerable_entries, :to_a
end
diff --git a/spec/ruby/core/enumerable/to_h_spec.rb b/spec/ruby/core/enumerable/to_h_spec.rb
index 0489134552..38847eccfb 100644
--- a/spec/ruby/core/enumerable/to_h_spec.rb
+++ b/spec/ruby/core/enumerable/to_h_spec.rb
@@ -36,12 +36,12 @@ describe "Enumerable#to_h" do
it "raises TypeError if an element is not an array" do
enum = EnumerableSpecs::EachDefiner.new(:x)
- -> { enum.to_h }.should raise_error(TypeError)
+ -> { enum.to_h }.should.raise(TypeError)
end
it "raises ArgumentError if an element is not a [key, value] pair" do
enum = EnumerableSpecs::EachDefiner.new([:x])
- -> { enum.to_h }.should raise_error(ArgumentError)
+ -> { enum.to_h }.should.raise(ArgumentError)
end
context "with block" do
@@ -53,20 +53,28 @@ describe "Enumerable#to_h" do
@enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
end
+ it "passes to a block each element as a single argument" do
+ enum_of_arrays = EnumerableSpecs::EachDefiner.new([:a, 1], [:b, 2])
+
+ ScratchPad.record []
+ enum_of_arrays.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
+ end
+
it "raises ArgumentError if block returns longer or shorter array" do
-> do
@enum.to_h { |k| [k, k.to_s, 1] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
+ end.should.raise(ArgumentError, /element has wrong array length/)
-> do
@enum.to_h { |k| [k] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
+ end.should.raise(ArgumentError, /element has wrong array length/)
end
it "raises TypeError if block returns something other than Array" do
-> do
@enum.to_h { |k| "not-array" }
- end.should raise_error(TypeError, /wrong element type String/)
+ end.should.raise(TypeError, /wrong element type String/)
end
it "coerces returned pair to Array with #to_ary" do
@@ -82,7 +90,7 @@ describe "Enumerable#to_h" do
-> do
@enum.to_h { |k| x }
- end.should raise_error(TypeError, /wrong element type MockObject/)
+ end.should.raise(TypeError, /wrong element type MockObject/)
end
end
end
diff --git a/spec/ruby/core/enumerable/to_set_spec.rb b/spec/ruby/core/enumerable/to_set_spec.rb
new file mode 100644
index 0000000000..7b04c72bce
--- /dev/null
+++ b/spec/ruby/core/enumerable/to_set_spec.rb
@@ -0,0 +1,30 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Enumerable#to_set" do
+ it "returns a new Set created from self" do
+ [1, 2, 3].to_set.should == Set[1, 2, 3]
+ {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]]
+ end
+
+ it "passes down passed blocks" do
+ [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9]
+ end
+
+ ruby_version_is "4.0"..."4.1" do
+ it "instantiates an object of provided as the first argument set class" do
+ set = nil
+ proc{set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)}.should complain(/Enumerable#to_set/)
+ set.should.is_a?(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "instantiates an object of provided as the first argument set class" do
+ set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)
+ set.should.is_a?(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerable/zip_spec.rb b/spec/ruby/core/enumerable/zip_spec.rb
index 9ec15aa030..c5f9a3e4d4 100644
--- a/spec/ruby/core/enumerable/zip_spec.rb
+++ b/spec/ruby/core/enumerable/zip_spec.rb
@@ -38,4 +38,9 @@ describe "Enumerable#zip" do
multi.zip(multi).should == [[[1, 2], [1, 2]], [[3, 4, 5], [3, 4, 5]], [[6, 7, 8, 9], [6, 7, 8, 9]]]
end
+ it "raises TypeError when some argument isn't Array and doesn't respond to #to_ary and #to_enum" do
+ -> { EnumerableSpecs::Numerous.new(1,2,3).zip(Object.new) }.should.raise(TypeError, "wrong argument type Object (must respond to :each)")
+ -> { EnumerableSpecs::Numerous.new(1,2,3).zip(1) }.should.raise(TypeError, "wrong argument type Integer (must respond to :each)")
+ -> { EnumerableSpecs::Numerous.new(1,2,3).zip(true) }.should.raise(TypeError, "wrong argument type TrueClass (must respond to :each)")
+ end
end
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb
index d4fff3e01f..0a83019d49 100644
--- a/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb
@@ -12,6 +12,6 @@ describe "Enumerator::ArithmeticSequence#each" do
end
it "returns self" do
- @seq.each { |item| }.should equal(@seq)
+ @seq.each { |item| }.should.equal?(@seq)
end
end
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb
index bdb308074b..a18c554fb3 100644
--- a/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../../spec_helper'
describe "Enumerator::ArithmeticSequence#hash" do
it "is based on begin, end, step and exclude_end?" do
- 1.step(10).hash.should be_an_instance_of(Integer)
+ 1.step(10).hash.should.instance_of?(Integer)
1.step(10).hash.should == 1.step(10).hash
1.step(10, 5).hash.should == 1.step(10, 5).hash
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb
index 2015983826..1bd2f7f0f7 100644
--- a/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb
@@ -4,7 +4,7 @@ describe "Enumerator::ArithmeticSequence.new" do
it "is not defined" do
-> {
Enumerator::ArithmeticSequence.new
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
end
@@ -12,6 +12,6 @@ describe "Enumerator::ArithmeticSequence.allocate" do
it "is not defined" do
-> {
Enumerator::ArithmeticSequence.allocate
- }.should raise_error(TypeError, 'allocator undefined for Enumerator::ArithmeticSequence')
+ }.should.raise(TypeError, 'allocator undefined for Enumerator::ArithmeticSequence')
end
end
diff --git a/spec/ruby/core/enumerator/chain/initialize_spec.rb b/spec/ruby/core/enumerator/chain/initialize_spec.rb
index 69484dfcb4..1df1dec5f8 100644
--- a/spec/ruby/core/enumerator/chain/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/chain/initialize_spec.rb
@@ -6,26 +6,26 @@ describe "Enumerator::Chain#initialize" do
end
it "is a private method" do
- Enumerator::Chain.should have_private_instance_method(:initialize, false)
+ Enumerator::Chain.private_instance_methods(false).should.include?(:initialize)
end
it "returns self" do
- @uninitialized.send(:initialize).should equal(@uninitialized)
+ @uninitialized.send(:initialize).should.equal?(@uninitialized)
end
it "accepts many arguments" do
- @uninitialized.send(:initialize, 0..1, 2..3, 4..5).should equal(@uninitialized)
+ @uninitialized.send(:initialize, 0..1, 2..3, 4..5).should.equal?(@uninitialized)
end
it "accepts arguments that are not Enumerable nor responding to :each" do
- @uninitialized.send(:initialize, Object.new).should equal(@uninitialized)
+ @uninitialized.send(:initialize, Object.new).should.equal?(@uninitialized)
end
describe "on frozen instance" do
- it "raises a RuntimeError" do
+ it "raises a FrozenError" do
-> {
@uninitialized.freeze.send(:initialize)
- }.should raise_error(RuntimeError)
+ }.should.raise(FrozenError)
end
end
end
diff --git a/spec/ruby/core/enumerator/chain/inspect_spec.rb b/spec/ruby/core/enumerator/chain/inspect_spec.rb
index a0450c808a..9b5a442b75 100644
--- a/spec/ruby/core/enumerator/chain/inspect_spec.rb
+++ b/spec/ruby/core/enumerator/chain/inspect_spec.rb
@@ -11,4 +11,8 @@ describe "Enumerator::Chain#inspect" do
obj.should_receive(:inspect).and_return('some desc')
Enumerator::Chain.new(obj).inspect.should == "#<Enumerator::Chain: [some desc]>"
end
+
+ it "returns a not initialized representation if #initialized is not called yet" do
+ Enumerator::Chain.allocate.inspect.should == "#<Enumerator::Chain: uninitialized>"
+ end
end
diff --git a/spec/ruby/core/enumerator/chain/rewind_spec.rb b/spec/ruby/core/enumerator/chain/rewind_spec.rb
index 5f51ce2cf1..4525b82f7b 100644
--- a/spec/ruby/core/enumerator/chain/rewind_spec.rb
+++ b/spec/ruby/core/enumerator/chain/rewind_spec.rb
@@ -10,7 +10,7 @@ describe "Enumerator::Chain#rewind" do
end
it "returns self" do
- @enum.rewind.should equal @enum
+ @enum.rewind.should.equal? @enum
end
it "does nothing if receiver has not been iterated" do
@@ -35,7 +35,7 @@ describe "Enumerator::Chain#rewind" do
@obj.should_not_receive(:rewind)
@second.should_receive(:rewind).and_raise(RuntimeError)
@enum.each {}
- -> { @enum.rewind }.should raise_error(RuntimeError)
+ -> { @enum.rewind }.should.raise(RuntimeError)
end
it "calls rewind only for objects that have actually been iterated on" do
@@ -45,7 +45,7 @@ describe "Enumerator::Chain#rewind" do
@obj.should_receive(:rewind)
@second.should_not_receive(:rewind)
- -> { @enum.each {} }.should raise_error(RuntimeError)
+ -> { @enum.each {} }.should.raise(RuntimeError)
@enum.rewind
end
end
diff --git a/spec/ruby/core/enumerator/each_spec.rb b/spec/ruby/core/enumerator/each_spec.rb
index 99ac3120af..03be53fe05 100644
--- a/spec/ruby/core/enumerator/each_spec.rb
+++ b/spec/ruby/core/enumerator/each_spec.rb
@@ -10,58 +10,58 @@ describe "Enumerator#each" do
@enum_with_arguments = object_each_with_arguments.to_enum(:each_with_arguments, :arg0, :arg1, :arg2)
- @enum_with_yielder = Enumerator.new {|y| y.yield :ok}
+ @enum_with_yielder = Enumerator.new { |y| y.yield :ok }
end
it "yields each element of self to the given block" do
acc = []
- [1,2,3].to_enum.each {|e| acc << e }
- acc.should == [1,2,3]
+ [1, 2, 3].to_enum.each { |e| acc << e }
+ acc.should == [1, 2, 3]
end
it "calls #each on the object given in the constructor by default" do
each = mock('each')
each.should_receive(:each)
- each.to_enum.each {|e| e }
+ each.to_enum.each { |e| e }
end
it "calls #each on the underlying object until it's exhausted" do
each = mock('each')
each.should_receive(:each).and_yield(1).and_yield(2).and_yield(3)
acc = []
- each.to_enum.each {|e| acc << e }
- acc.should == [1,2,3]
+ each.to_enum.each { |e| acc << e }
+ acc.should == [1, 2, 3]
end
it "calls the method given in the constructor instead of #each" do
each = mock('peach')
each.should_receive(:peach)
- each.to_enum(:peach).each {|e| e }
+ each.to_enum(:peach).each { |e| e }
end
it "calls the method given in the constructor until it's exhausted" do
each = mock('peach')
each.should_receive(:peach).and_yield(1).and_yield(2).and_yield(3)
acc = []
- each.to_enum(:peach).each {|e| acc << e }
- acc.should == [1,2,3]
+ each.to_enum(:peach).each { |e| acc << e }
+ acc.should == [1, 2, 3]
end
it "raises a NoMethodError if the object doesn't respond to #each" do
enum = Object.new.to_enum
-> do
enum.each { |e| e }
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
it "returns self if not given arguments and not given a block" do
- @enum_with_arguments.each.should equal(@enum_with_arguments)
+ @enum_with_arguments.each.should.equal?(@enum_with_arguments)
- @enum_with_yielder.each.should equal(@enum_with_yielder)
+ @enum_with_yielder.each.should.equal?(@enum_with_yielder)
end
it "returns the same value from receiver.each if block is given" do
- @enum_with_arguments.each {}.should equal(:method_returned)
+ @enum_with_arguments.each {}.should.equal?(:method_returned)
end
it "passes given arguments at initialized to receiver.each" do
@@ -78,12 +78,27 @@ describe "Enumerator#each" do
end
it "returns the same value from receiver.each if block and arguments are given" do
- @enum_with_arguments.each(:each1, :each2) {}.should equal(:method_returned)
+ @enum_with_arguments.each(:each1, :each2) {}.should.equal?(:method_returned)
end
it "returns new Enumerator if given arguments but not given a block" do
ret = @enum_with_arguments.each 1
- ret.should be_an_instance_of(Enumerator)
- ret.should_not equal(@enum_with_arguments)
+ ret.should.instance_of?(Enumerator)
+ ret.should_not.equal?(@enum_with_arguments)
+ end
+
+ it "does not destructure yielded array values when chaining each.map" do
+ result = [[[1]]].each.map { |a, b| [a, b] }
+ result.should == [[[1], nil]]
+ end
+
+ it "preserves array values yielded from the enumerator" do
+ result = [[1, 2]].each.map { |a| a }
+ result.should == [[1, 2]]
+ end
+
+ it "allows destructuring to occur in the block, not the enumerator" do
+ result = [[1, 2]].each.map { |a, b| a }
+ result.should == [1]
end
end
diff --git a/spec/ruby/core/enumerator/each_with_index_spec.rb b/spec/ruby/core/enumerator/each_with_index_spec.rb
index 96e53a2804..0630b7045e 100644
--- a/spec/ruby/core/enumerator/each_with_index_spec.rb
+++ b/spec/ruby/core/enumerator/each_with_index_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/with_index'
+require_relative 'shared/with_index'
require_relative '../enumerable/shared/enumeratorized'
describe "Enumerator#each_with_index" do
@@ -9,28 +9,28 @@ describe "Enumerator#each_with_index" do
it "returns a new Enumerator when no block is given" do
enum1 = [1,2,3].select
enum2 = enum1.each_with_index
- enum2.should be_an_instance_of(Enumerator)
+ enum2.should.instance_of?(Enumerator)
enum1.should_not == enum2
end
it "raises an ArgumentError if passed extra arguments" do
-> do
[1].to_enum.each_with_index(:glark)
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "passes on the given block's return value" do
arr = [1,2,3]
- arr.delete_if.with_index { |a,b| false }
+ arr.delete_if.each_with_index { |a,b| false }
arr.should == [1,2,3]
end
it "returns the iterator's return value" do
- [1,2,3].select.with_index { |a,b| false }.should == []
+ [1,2,3].select.each_with_index { |a,b| false }.should == []
+ [1,2,3].select.each_with_index { |a,b| true }.should == [1,2,3]
end
it "returns the correct value if chained with itself" do
[:a].each_with_index.each_with_index.to_a.should == [[[:a,0],0]]
- [:a].each.with_index.with_index.to_a.should == [[[:a,0],0]]
end
end
diff --git a/spec/ruby/core/enumerator/each_with_object_spec.rb b/spec/ruby/core/enumerator/each_with_object_spec.rb
index 68524dc74a..84a45ae89d 100644
--- a/spec/ruby/core/enumerator/each_with_object_spec.rb
+++ b/spec/ruby/core/enumerator/each_with_object_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/with_object'
+require_relative 'shared/with_object'
describe "Enumerator#each_with_object" do
it_behaves_like :enum_with_object, :each_with_object
diff --git a/spec/ruby/core/enumerator/enum_for_spec.rb b/spec/ruby/core/enumerator/enum_for_spec.rb
index fd33f463bf..fbdf98545a 100644
--- a/spec/ruby/core/enumerator/enum_for_spec.rb
+++ b/spec/ruby/core/enumerator/enum_for_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/enum_for'
+require_relative 'shared/enum_for'
describe "Enumerator#enum_for" do
it_behaves_like :enum_for, :enum_for
diff --git a/spec/ruby/core/enumerator/feed_spec.rb b/spec/ruby/core/enumerator/feed_spec.rb
index e387c6cd39..781947a8c7 100644
--- a/spec/ruby/core/enumerator/feed_spec.rb
+++ b/spec/ruby/core/enumerator/feed_spec.rb
@@ -33,20 +33,20 @@ describe "Enumerator#feed" do
end
it "returns nil" do
- @enum.feed(:a).should be_nil
+ @enum.feed(:a).should == nil
end
it "raises a TypeError if called more than once without advancing the enumerator" do
@enum.feed :a
@enum.next
- -> { @enum.feed :b }.should raise_error(TypeError)
+ -> { @enum.feed :b }.should.raise(TypeError)
end
it "sets the return value of Yielder#yield" do
enum = Enumerator.new { |y| ScratchPad << y.yield }
enum.next
enum.feed :a
- -> { enum.next }.should raise_error(StopIteration)
+ -> { enum.next }.should.raise(StopIteration)
ScratchPad.recorded.should == [:a]
end
end
diff --git a/spec/ruby/fixtures/enumerator/classes.rb b/spec/ruby/core/enumerator/fixtures/classes.rb
index 6f285b8efa..6f285b8efa 100644
--- a/spec/ruby/fixtures/enumerator/classes.rb
+++ b/spec/ruby/core/enumerator/fixtures/classes.rb
diff --git a/spec/ruby/core/enumerator/generator/each_spec.rb b/spec/ruby/core/enumerator/generator/each_spec.rb
deleted file mode 100644
index a43805dd16..0000000000
--- a/spec/ruby/core/enumerator/generator/each_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require_relative '../../../spec_helper'
-
-describe "Enumerator::Generator#each" do
- before :each do
- @generator = Enumerator::Generator.new do |y, *args|
- y << 3 << 2 << 1
- y << args unless args.empty?
- :block_returned
- end
- end
-
- it "is an enumerable" do
- @generator.should be_kind_of(Enumerable)
- end
-
- it "supports enumeration with a block" do
- r = []
- @generator.each { |v| r << v }
-
- r.should == [3, 2, 1]
- end
-
- it "raises a LocalJumpError if no block given" do
- -> { @generator.each }.should raise_error(LocalJumpError)
- end
-
- it "returns the block returned value" do
- @generator.each {}.should equal(:block_returned)
- end
-
- it "requires multiple arguments" do
- Enumerator::Generator.instance_method(:each).arity.should < 0
- end
-
- it "appends given arguments to receiver.each" do
- yields = []
- @generator.each(:each0, :each1) { |yielded| yields << yielded }
- yields.should == [3, 2, 1, [:each0, :each1]]
- end
-end
diff --git a/spec/ruby/core/enumerator/generator/initialize_spec.rb b/spec/ruby/core/enumerator/generator/initialize_spec.rb
deleted file mode 100644
index f75c7d6f26..0000000000
--- a/spec/ruby/core/enumerator/generator/initialize_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- encoding: us-ascii -*-
-
-require_relative '../../../spec_helper'
-
-describe "Enumerator::Generator#initialize" do
- before :each do
- @class = Enumerator::Generator
- @uninitialized = @class.allocate
- end
-
- it "is a private method" do
- @class.should have_private_instance_method(:initialize, false)
- end
-
- it "returns self when given a block" do
- @uninitialized.send(:initialize) {}.should equal(@uninitialized)
- end
-
- describe "on frozen instance" do
- it "raises a RuntimeError" do
- -> {
- @uninitialized.freeze.send(:initialize) {}
- }.should raise_error(RuntimeError)
- end
- end
-end
diff --git a/spec/ruby/core/enumerator/initialize_spec.rb b/spec/ruby/core/enumerator/initialize_spec.rb
index 217af1d3bc..9929494b5a 100644
--- a/spec/ruby/core/enumerator/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/initialize_spec.rb
@@ -8,19 +8,11 @@ describe "Enumerator#initialize" do
end
it "is a private method" do
- Enumerator.should have_private_instance_method(:initialize, false)
- end
-
- ruby_version_is ''...'3.0' do
- it "returns self when given an object" do
- suppress_warning do
- @uninitialized.send(:initialize, Object.new).should equal(@uninitialized)
- end
- end
+ Enumerator.private_instance_methods(false).should.include?(:initialize)
end
it "returns self when given a block" do
- @uninitialized.send(:initialize) {}.should equal(@uninitialized)
+ @uninitialized.send(:initialize) {}.should.equal?(@uninitialized)
end
# Maybe spec should be broken up?
@@ -29,22 +21,22 @@ describe "Enumerator#initialize" do
r = yielder.yield 3
yielder << r << 2 << 1
end
- @uninitialized.should be_an_instance_of(Enumerator)
+ @uninitialized.should.instance_of?(Enumerator)
r = []
@uninitialized.each{|x| r << x; x * 2}
r.should == [3, 6, 2, 1]
end
it "sets size to nil if size is not given" do
- @uninitialized.send(:initialize) {}.size.should be_nil
+ @uninitialized.send(:initialize) {}.size.should == nil
end
it "sets size to nil if the given size is nil" do
- @uninitialized.send(:initialize, nil) {}.size.should be_nil
+ @uninitialized.send(:initialize, nil) {}.size.should == nil
end
it "sets size to the given size if the given size is Float::INFINITY" do
- @uninitialized.send(:initialize, Float::INFINITY) {}.size.should equal(Float::INFINITY)
+ @uninitialized.send(:initialize, Float::INFINITY) {}.size.should.equal?(Float::INFINITY)
end
it "sets size to the given size if the given size is an Integer" do
@@ -56,10 +48,10 @@ describe "Enumerator#initialize" do
end
describe "on frozen instance" do
- it "raises a RuntimeError" do
+ it "raises a FrozenError" do
-> {
@uninitialized.freeze.send(:initialize) {}
- }.should raise_error(RuntimeError)
+ }.should.raise(FrozenError)
end
end
end
diff --git a/spec/ruby/core/enumerator/inspect_spec.rb b/spec/ruby/core/enumerator/inspect_spec.rb
index 3bcf07e754..7e97864246 100644
--- a/spec/ruby/core/enumerator/inspect_spec.rb
+++ b/spec/ruby/core/enumerator/inspect_spec.rb
@@ -14,4 +14,9 @@ describe "Enumerator#inspect" do
(1..3).each.each_slice(2).inspect.should == "#<Enumerator: #<Enumerator: 1..3:each>:each_slice(2)>"
end
end
+
+ it "returns a not initialized representation if #initialized is not called yet" do
+ Enumerator.allocate.inspect.should == "#<Enumerator: uninitialized>"
+ Enumerator::Lazy.allocate.inspect.should == "#<Enumerator::Lazy: uninitialized>"
+ end
end
diff --git a/spec/ruby/core/enumerator/lazy/chunk_spec.rb b/spec/ruby/core/enumerator/lazy/chunk_spec.rb
index 87d2b0c206..d0179d32b6 100644
--- a/spec/ruby/core/enumerator/lazy/chunk_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/chunk_spec.rb
@@ -17,8 +17,8 @@ describe "Enumerator::Lazy#chunk" do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.chunk {}
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets #size to nil" do
@@ -27,7 +27,7 @@ describe "Enumerator::Lazy#chunk" do
it "returns an Enumerator if called without a block" do
chunk = @yieldsmixed.chunk
- chunk.should be_an_instance_of(Enumerator::Lazy)
+ chunk.should.instance_of?(Enumerator::Lazy)
res = chunk.each { |v| true }.force
res.should == [[true, EnumeratorLazySpecs::YieldsMixed.gathered_yields]]
diff --git a/spec/ruby/core/enumerator/lazy/chunk_while_spec.rb b/spec/ruby/core/enumerator/lazy/chunk_while_spec.rb
index 772bd42de9..edba8e1363 100644
--- a/spec/ruby/core/enumerator/lazy/chunk_while_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/chunk_while_spec.rb
@@ -9,6 +9,6 @@ describe "Enumerator::Lazy#chunk_while" do
it "should return a lazy enumerator" do
s = 0..Float::INFINITY
- s.lazy.chunk_while { |a, b| false }.should be_kind_of(Enumerator::Lazy)
+ s.lazy.chunk_while { |a, b| false }.should.is_a?(Enumerator::Lazy)
end
end
diff --git a/spec/ruby/core/enumerator/lazy/compact_spec.rb b/spec/ruby/core/enumerator/lazy/compact_spec.rb
new file mode 100644
index 0000000000..7305e1c9c4
--- /dev/null
+++ b/spec/ruby/core/enumerator/lazy/compact_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Enumerator::Lazy#compact" do
+ it 'returns array without nil elements' do
+ arr = [1, nil, 3, false, 5].to_enum.lazy.compact
+ arr.should.instance_of?(Enumerator::Lazy)
+ arr.force.should == [1, 3, false, 5]
+ end
+
+ it "sets #size to nil" do
+ Enumerator::Lazy.new(Object.new, 100) {}.compact.size.should == nil
+ end
+end
diff --git a/spec/ruby/core/enumerator/lazy/drop_spec.rb b/spec/ruby/core/enumerator/lazy/drop_spec.rb
index 822b8034fb..95ac7e9ecc 100644
--- a/spec/ruby/core/enumerator/lazy/drop_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/drop_spec.rb
@@ -16,8 +16,8 @@ describe "Enumerator::Lazy#drop" do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.drop(1)
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets difference of given count with old size to new size" do
diff --git a/spec/ruby/core/enumerator/lazy/drop_while_spec.rb b/spec/ruby/core/enumerator/lazy/drop_while_spec.rb
index 4f6e366f88..65f3007dec 100644
--- a/spec/ruby/core/enumerator/lazy/drop_while_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/drop_while_spec.rb
@@ -16,8 +16,8 @@ describe "Enumerator::Lazy#drop_while" do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.drop_while {}
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets #size to nil" do
@@ -40,7 +40,7 @@ describe "Enumerator::Lazy#drop_while" do
end
it "raises an ArgumentError when not given a block" do
- -> { @yieldsmixed.drop_while }.should raise_error(ArgumentError)
+ -> { @yieldsmixed.drop_while }.should.raise(ArgumentError)
end
describe "on a nested Lazy" do
diff --git a/spec/ruby/core/enumerator/lazy/grep_spec.rb b/spec/ruby/core/enumerator/lazy/grep_spec.rb
index e67686c9a3..383f80a918 100644
--- a/spec/ruby/core/enumerator/lazy/grep_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/grep_spec.rb
@@ -20,12 +20,12 @@ describe "Enumerator::Lazy#grep" do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.grep(Object) {}
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
ret = @yieldsmixed.grep(Object)
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets #size to nil" do
diff --git a/spec/ruby/core/enumerator/lazy/grep_v_spec.rb b/spec/ruby/core/enumerator/lazy/grep_v_spec.rb
index 67173021bb..19c917f254 100644
--- a/spec/ruby/core/enumerator/lazy/grep_v_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/grep_v_spec.rb
@@ -18,12 +18,12 @@ describe "Enumerator::Lazy#grep_v" do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.grep_v(Object) {}
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
ret = @yieldsmixed.grep_v(Object)
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets #size to nil" do
diff --git a/spec/ruby/core/enumerator/lazy/initialize_spec.rb b/spec/ruby/core/enumerator/lazy/initialize_spec.rb
index f23018d010..47765d32c3 100644
--- a/spec/ruby/core/enumerator/lazy/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/initialize_spec.rb
@@ -16,11 +16,11 @@ describe "Enumerator::Lazy#initialize" do
end
it "is a private method" do
- Enumerator::Lazy.should have_private_instance_method(:initialize, false)
+ Enumerator::Lazy.private_instance_methods(false).should.include?(:initialize)
end
it "returns self" do
- @uninitialized.send(:initialize, @receiver) {}.should equal(@uninitialized)
+ @uninitialized.send(:initialize, @receiver) {}.should.equal?(@uninitialized)
end
describe "when the returned lazy enumerator is evaluated by Enumerable#first" do
@@ -32,15 +32,15 @@ describe "Enumerator::Lazy#initialize" do
end
it "sets #size to nil if not given a size" do
- @uninitialized.send(:initialize, @receiver) {}.size.should be_nil
+ @uninitialized.send(:initialize, @receiver) {}.size.should == nil
end
it "sets #size to nil if given size is nil" do
- @uninitialized.send(:initialize, @receiver, nil) {}.size.should be_nil
+ @uninitialized.send(:initialize, @receiver, nil) {}.size.should == nil
end
it "sets given size to own size if the given size is Float::INFINITY" do
- @uninitialized.send(:initialize, @receiver, Float::INFINITY) {}.size.should equal(Float::INFINITY)
+ @uninitialized.send(:initialize, @receiver, Float::INFINITY) {}.size.should.equal?(Float::INFINITY)
end
it "sets given size to own size if the given size is an Integer" do
@@ -52,12 +52,12 @@ describe "Enumerator::Lazy#initialize" do
end
it "raises an ArgumentError when block is not given" do
- -> { @uninitialized.send :initialize, @receiver }.should raise_error(ArgumentError)
+ -> { @uninitialized.send :initialize, @receiver }.should.raise(ArgumentError)
end
describe "on frozen instance" do
- it "raises a RuntimeError" do
- -> { @uninitialized.freeze.send(:initialize, @receiver) {} }.should raise_error(RuntimeError)
+ it "raises a FrozenError" do
+ -> { @uninitialized.freeze.send(:initialize, @receiver) {} }.should.raise(FrozenError)
end
end
end
diff --git a/spec/ruby/core/enumerator/lazy/lazy_spec.rb b/spec/ruby/core/enumerator/lazy/lazy_spec.rb
index 683dfb81d7..12107383d6 100644
--- a/spec/ruby/core/enumerator/lazy/lazy_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/lazy_spec.rb
@@ -4,39 +4,24 @@ require_relative '../../../spec_helper'
describe "Enumerator::Lazy" do
it "is a subclass of Enumerator" do
- Enumerator::Lazy.superclass.should equal(Enumerator)
+ Enumerator::Lazy.superclass.should.equal?(Enumerator)
end
it "defines lazy versions of a whitelist of Enumerator methods" do
- lazy_methods = [
- :chunk, :collect, :collect_concat, :drop, :drop_while, :enum_for,
+ lazy_methods = Set[
+ :chunk, :chunk_while, :collect, :collect_concat, :compact, :drop, :drop_while, :enum_for,
:find_all, :flat_map, :force, :grep, :grep_v, :lazy, :map, :reject,
:select, :slice_after, :slice_before, :slice_when, :take, :take_while,
- :to_enum, :zip
+ :to_enum, :uniq, :zip
]
- lazy_methods += [:chunk_while, :uniq]
- ruby_version_is '3.1' do
- lazy_methods += [:compact]
- end
-
- Enumerator::Lazy.instance_methods(false).should include(*lazy_methods)
+ Enumerator::Lazy.instance_methods(false).to_set.should >= lazy_methods
end
end
describe "Enumerator::Lazy#lazy" do
it "returns self" do
lazy = (1..3).to_enum.lazy
- lazy.lazy.should equal(lazy)
- end
-end
-
-ruby_version_is '3.1' do
- describe "Enumerator::Lazy#compact" do
- it 'returns array without nil elements' do
- arr = [1, nil, 3, false, 5].to_enum.lazy.compact
- arr.should be_an_instance_of(Enumerator::Lazy)
- arr.force.should == [1, 3, false, 5]
- end
+ lazy.lazy.should.equal?(lazy)
end
end
diff --git a/spec/ruby/core/enumerator/lazy/reject_spec.rb b/spec/ruby/core/enumerator/lazy/reject_spec.rb
index 0e1632d667..374d4df14e 100644
--- a/spec/ruby/core/enumerator/lazy/reject_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/reject_spec.rb
@@ -16,8 +16,8 @@ describe "Enumerator::Lazy#reject" do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.reject {}
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets #size to nil" do
@@ -42,7 +42,7 @@ describe "Enumerator::Lazy#reject" do
-> {
lazy.first
- }.should raise_error(RuntimeError, "foo")
+ }.should.raise(RuntimeError, "foo")
end
it "calls the block with a gathered array when yield with multiple arguments" do
@@ -52,7 +52,7 @@ describe "Enumerator::Lazy#reject" do
end
it "raises an ArgumentError when not given a block" do
- -> { @yieldsmixed.reject }.should raise_error(ArgumentError)
+ -> { @yieldsmixed.reject }.should.raise(ArgumentError)
end
describe "on a nested Lazy" do
diff --git a/spec/ruby/core/enumerator/lazy/shared/collect.rb b/spec/ruby/core/enumerator/lazy/shared/collect.rb
index 5690255a0c..0ed04c8e02 100644
--- a/spec/ruby/core/enumerator/lazy/shared/collect.rb
+++ b/spec/ruby/core/enumerator/lazy/shared/collect.rb
@@ -16,8 +16,8 @@ describe :enumerator_lazy_collect, shared: true do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.send(@method) {}
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "keeps size" do
diff --git a/spec/ruby/core/enumerator/lazy/shared/collect_concat.rb b/spec/ruby/core/enumerator/lazy/shared/collect_concat.rb
index 00d7941a61..685e6d0594 100644
--- a/spec/ruby/core/enumerator/lazy/shared/collect_concat.rb
+++ b/spec/ruby/core/enumerator/lazy/shared/collect_concat.rb
@@ -16,8 +16,8 @@ describe :enumerator_lazy_collect_concat, shared: true do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.send(@method) {}
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets #size to nil" do
@@ -34,7 +34,7 @@ describe :enumerator_lazy_collect_concat, shared: true do
it "flattens elements when the given block returned an array or responding to .each and .force" do
(0..Float::INFINITY).lazy.send(@method) { |n| (n * 10).to_s.chars }.first(6).should == %w[0 1 0 2 0 3]
- (0..Float::INFINITY).lazy.send(@method) { |n| (n * 10).to_s.each_char }.first(6).all? { |o| o.instance_of? Enumerator }.should be_true
+ (0..Float::INFINITY).lazy.send(@method) { |n| (n * 10).to_s.each_char }.first(6).all? { |o| o.instance_of? Enumerator }.should == true
(0..Float::INFINITY).lazy.send(@method) { |n| (n * 10).to_s.each_char.lazy }.first(6).should == %w[0 1 0 2 0 3]
end
end
@@ -46,7 +46,7 @@ describe :enumerator_lazy_collect_concat, shared: true do
end
it "raises an ArgumentError when not given a block" do
- -> { @yieldsmixed.send(@method) }.should raise_error(ArgumentError)
+ -> { @yieldsmixed.send(@method) }.should.raise(ArgumentError)
end
describe "on a nested Lazy" do
@@ -64,7 +64,7 @@ describe :enumerator_lazy_collect_concat, shared: true do
it "flattens elements when the given block returned an array or responding to .each and .force" do
(0..Float::INFINITY).lazy.map {|n| n * 10 }.send(@method) { |n| n.to_s.chars }.first(6).should == %w[0 1 0 2 0 3]
- (0..Float::INFINITY).lazy.map {|n| n * 10 }.send(@method) { |n| n.to_s.each_char }.first(6).all? { |o| o.instance_of? Enumerator }.should be_true
+ (0..Float::INFINITY).lazy.map {|n| n * 10 }.send(@method) { |n| n.to_s.each_char }.first(6).all? { |o| o.instance_of? Enumerator }.should == true
(0..Float::INFINITY).lazy.map {|n| n * 10 }.send(@method) { |n| n.to_s.each_char.lazy }.first(6).should == %w[0 1 0 2 0 3]
end
end
diff --git a/spec/ruby/core/enumerator/lazy/shared/select.rb b/spec/ruby/core/enumerator/lazy/shared/select.rb
index 50a00bcbf4..2d15176620 100644
--- a/spec/ruby/core/enumerator/lazy/shared/select.rb
+++ b/spec/ruby/core/enumerator/lazy/shared/select.rb
@@ -16,8 +16,8 @@ describe :enumerator_lazy_select, shared: true do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.send(@method) {}
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets #size to nil" do
@@ -40,7 +40,7 @@ describe :enumerator_lazy_select, shared: true do
end
it "raises an ArgumentError when not given a block" do
- -> { @yieldsmixed.send(@method) }.should raise_error(ArgumentError)
+ -> { @yieldsmixed.send(@method) }.should.raise(ArgumentError)
end
describe "on a nested Lazy" do
diff --git a/spec/ruby/core/enumerator/lazy/shared/to_enum.rb b/spec/ruby/core/enumerator/lazy/shared/to_enum.rb
index 0c91ea55b9..75b9aefe8c 100644
--- a/spec/ruby/core/enumerator/lazy/shared/to_enum.rb
+++ b/spec/ruby/core/enumerator/lazy/shared/to_enum.rb
@@ -13,8 +13,8 @@ describe :enumerator_lazy_to_enum, shared: true do
it "returns a new instance of Enumerator::Lazy" do
ret = @infinite.send @method
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@infinite)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@infinite)
end
it "sets #size to nil when not given a block" do
@@ -43,7 +43,7 @@ describe :enumerator_lazy_to_enum, shared: true do
each_entry: [],
each_cons: [2]
}.each_pair do |method, args|
- @infinite.send(method, *args).should be_an_instance_of(Enumerator::Lazy)
+ @infinite.send(method, *args).should.instance_of?(Enumerator::Lazy)
end
end
diff --git a/spec/ruby/core/enumerator/lazy/slice_after_spec.rb b/spec/ruby/core/enumerator/lazy/slice_after_spec.rb
index 8b08a1ecfd..f8cd97178f 100644
--- a/spec/ruby/core/enumerator/lazy/slice_after_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/slice_after_spec.rb
@@ -9,6 +9,6 @@ describe "Enumerator::Lazy#slice_after" do
it "should return a lazy enumerator" do
s = 0..Float::INFINITY
- s.lazy.slice_after { |n| true }.should be_kind_of(Enumerator::Lazy)
+ s.lazy.slice_after { |n| true }.should.is_a?(Enumerator::Lazy)
end
end
diff --git a/spec/ruby/core/enumerator/lazy/slice_before_spec.rb b/spec/ruby/core/enumerator/lazy/slice_before_spec.rb
index 9c1ec9ba4a..192e853343 100644
--- a/spec/ruby/core/enumerator/lazy/slice_before_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/slice_before_spec.rb
@@ -9,6 +9,6 @@ describe "Enumerator::Lazy#slice_before" do
it "should return a lazy enumerator" do
s = 0..Float::INFINITY
- s.lazy.slice_before { |n| true }.should be_kind_of(Enumerator::Lazy)
+ s.lazy.slice_before { |n| true }.should.is_a?(Enumerator::Lazy)
end
end
diff --git a/spec/ruby/core/enumerator/lazy/slice_when_spec.rb b/spec/ruby/core/enumerator/lazy/slice_when_spec.rb
index f83403425d..fc9d5f5069 100644
--- a/spec/ruby/core/enumerator/lazy/slice_when_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/slice_when_spec.rb
@@ -9,6 +9,6 @@ describe "Enumerator::Lazy#slice_when" do
it "should return a lazy enumerator" do
s = 0..Float::INFINITY
- s.lazy.slice_when { |a, b| true }.should be_kind_of(Enumerator::Lazy)
+ s.lazy.slice_when { |a, b| true }.should.is_a?(Enumerator::Lazy)
end
end
diff --git a/spec/ruby/core/enumerator/lazy/take_spec.rb b/spec/ruby/core/enumerator/lazy/take_spec.rb
index 9fc17e969f..2dd5b939e2 100644
--- a/spec/ruby/core/enumerator/lazy/take_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/take_spec.rb
@@ -2,8 +2,16 @@
require_relative '../../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../../enumerable/shared/value_packing'
describe "Enumerator::Lazy#take" do
+ describe "value packing of source yields (matches Enumerable#take)" do
+ before :each do
+ @take = -> e { e.lazy.take(1) }
+ end
+ it_behaves_like :enumerable_value_packing, nil
+ end
+
before :each do
@yieldsmixed = EnumeratorLazySpecs::YieldsMixed.new.to_enum.lazy
@eventsmixed = EnumeratorLazySpecs::EventsMixed.new.to_enum.lazy
@@ -16,8 +24,8 @@ describe "Enumerator::Lazy#take" do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.take(1)
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets given count to size if the given count is less than old size" do
diff --git a/spec/ruby/core/enumerator/lazy/take_while_spec.rb b/spec/ruby/core/enumerator/lazy/take_while_spec.rb
index bcea0b1419..c369712c56 100644
--- a/spec/ruby/core/enumerator/lazy/take_while_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/take_while_spec.rb
@@ -16,8 +16,8 @@ describe "Enumerator::Lazy#take_while" do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.take_while {}
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "sets #size to nil" do
@@ -40,7 +40,7 @@ describe "Enumerator::Lazy#take_while" do
end
it "raises an ArgumentError when not given a block" do
- -> { @yieldsmixed.take_while }.should raise_error(ArgumentError)
+ -> { @yieldsmixed.take_while }.should.raise(ArgumentError)
end
describe "on a nested Lazy" do
diff --git a/spec/ruby/core/enumerator/lazy/uniq_spec.rb b/spec/ruby/core/enumerator/lazy/uniq_spec.rb
index ce67ace5ab..d30ed8df2f 100644
--- a/spec/ruby/core/enumerator/lazy/uniq_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/uniq_spec.rb
@@ -8,7 +8,7 @@ describe 'Enumerator::Lazy#uniq' do
end
it 'returns a lazy enumerator' do
- @lazy.should be_an_instance_of(Enumerator::Lazy)
+ @lazy.should.instance_of?(Enumerator::Lazy)
@lazy.force.should == [0, 1]
end
@@ -28,7 +28,7 @@ describe 'Enumerator::Lazy#uniq' do
end
it 'returns a lazy enumerator' do
- @lazy.should be_an_instance_of(Enumerator::Lazy)
+ @lazy.should.instance_of?(Enumerator::Lazy)
@lazy.force.should == [0, 1]
end
diff --git a/spec/ruby/core/enumerator/lazy/with_index_spec.rb b/spec/ruby/core/enumerator/lazy/with_index_spec.rb
index a6b5c38777..2e983fd3b1 100644
--- a/spec/ruby/core/enumerator/lazy/with_index_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/with_index_spec.rb
@@ -17,7 +17,7 @@ describe "Enumerator::Lazy#with_index" do
end
it "raises TypeError when offset does not convert to Integer" do
- -> { (0..Float::INFINITY).lazy.with_index(false).map { |i, idx| i }.first(3) }.should raise_error(TypeError)
+ -> { (0..Float::INFINITY).lazy.with_index(false).map { |i, idx| i }.first(3) }.should.raise(TypeError)
end
it "enumerates with a given block" do
diff --git a/spec/ruby/core/enumerator/lazy/zip_spec.rb b/spec/ruby/core/enumerator/lazy/zip_spec.rb
index 5a828c1dcc..9f612542d7 100644
--- a/spec/ruby/core/enumerator/lazy/zip_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/zip_spec.rb
@@ -16,8 +16,8 @@ describe "Enumerator::Lazy#zip" do
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.zip []
- ret.should be_an_instance_of(Enumerator::Lazy)
- ret.should_not equal(@yieldsmixed)
+ ret.should.instance_of?(Enumerator::Lazy)
+ ret.should_not.equal?(@yieldsmixed)
end
it "keeps size" do
@@ -40,11 +40,11 @@ describe "Enumerator::Lazy#zip" do
end
it "returns a Lazy when no arguments given" do
- @yieldsmixed.zip.should be_an_instance_of(Enumerator::Lazy)
+ @yieldsmixed.zip.should.instance_of?(Enumerator::Lazy)
end
it "raises a TypeError if arguments contain non-list object" do
- -> { @yieldsmixed.zip [], Object.new, [] }.should raise_error(TypeError)
+ -> { @yieldsmixed.zip [], Object.new, [] }.should.raise(TypeError)
end
describe "on a nested Lazy" do
diff --git a/spec/ruby/core/enumerator/new_spec.rb b/spec/ruby/core/enumerator/new_spec.rb
index c439469525..eb6c13759e 100644
--- a/spec/ruby/core/enumerator/new_spec.rb
+++ b/spec/ruby/core/enumerator/new_spec.rb
@@ -2,51 +2,8 @@ require_relative '../../spec_helper'
describe "Enumerator.new" do
context "no block given" do
- ruby_version_is '3.0' do
- it "raises" do
- -> { Enumerator.new(1, :upto, 3) }.should raise_error(ArgumentError)
- end
- end
-
- ruby_version_is ''...'3.0' do
- it "creates a new custom enumerator with the given object, iterator and arguments" do
- enum = suppress_warning { Enumerator.new(1, :upto, 3) }
- enum.should be_an_instance_of(Enumerator)
- end
-
- it "creates a new custom enumerator that responds to #each" do
- enum = suppress_warning { Enumerator.new(1, :upto, 3) }
- enum.respond_to?(:each).should == true
- end
-
- it "creates a new custom enumerator that runs correctly" do
- suppress_warning { Enumerator.new(1, :upto, 3) }.map{ |x| x }.should == [1,2,3]
- end
-
- it "aliases the second argument to :each" do
- suppress_warning { Enumerator.new(1..2) }.to_a.should ==
- suppress_warning { Enumerator.new(1..2, :each) }.to_a
- end
-
- it "doesn't check for the presence of the iterator method" do
- suppress_warning { Enumerator.new(nil) }.should be_an_instance_of(Enumerator)
- end
-
- it "uses the latest define iterator method" do
- class StrangeEach
- def each
- yield :foo
- end
- end
- enum = suppress_warning { Enumerator.new(StrangeEach.new) }
- enum.to_a.should == [:foo]
- class StrangeEach
- def each
- yield :bar
- end
- end
- enum.to_a.should == [:bar]
- end
+ it "raises" do
+ -> { Enumerator.new(1, :upto, 3) }.should.raise(ArgumentError)
end
end
@@ -85,35 +42,74 @@ describe "Enumerator.new" do
enum.to_a.should == ["a\n", "b\n", "c"]
end
- describe 'yielded values' do
- it 'handles yield arguments properly' do
+ describe '#yield' do
+ it 'accepts a single argument' do
Enumerator.new { |y| y.yield(1) }.to_a.should == [1]
Enumerator.new { |y| y.yield(1) }.first.should == 1
+ end
- Enumerator.new { |y| y.yield([1]) }.to_a.should == [[1]]
- Enumerator.new { |y| y.yield([1]) }.first.should == [1]
-
+ it 'accepts multiple arguments' do
Enumerator.new { |y| y.yield(1, 2) }.to_a.should == [[1, 2]]
Enumerator.new { |y| y.yield(1, 2) }.first.should == [1, 2]
+ end
+
+ it "doesn't double-wrap arrays" do
+ Enumerator.new { |y| y.yield([1]) }.to_a.should == [[1]]
+ Enumerator.new { |y| y.yield([1]) }.first.should == [1]
Enumerator.new { |y| y.yield([1, 2]) }.to_a.should == [[1, 2]]
Enumerator.new { |y| y.yield([1, 2]) }.first.should == [1, 2]
end
- it 'handles << arguments properly' do
+ it 'returns nil' do
+ ScratchPad.record []
+ Enumerator.new do |y|
+ ScratchPad << y.yield(1)
+ end.to_a
+
+ ScratchPad.recorded.should == [nil]
+ end
+
+ it 'accepts keyword arguments and treats them as a positional hash' do
+ Enumerator.new { |y| y.yield(foo: 42) }.to_a.should == [{ foo: 42 }]
+ Enumerator.new { |y| y.yield(foo: 42) }.first.should == { foo: 42 }
+
+ Enumerator.new { |y| y.yield(123, foo: 42) }.to_a.should == [[123, { foo: 42 }]]
+ Enumerator.new { |y| y.yield(123, foo: 42) }.first.should == [123, { foo: 42 }]
+ end
+ end
+
+ describe '#<<' do
+ it 'accepts a single argument' do
Enumerator.new { |y| y.<<(1) }.to_a.should == [1]
Enumerator.new { |y| y.<<(1) }.first.should == 1
+ end
+ it "doesn't double-wrap arrays" do
Enumerator.new { |y| y.<<([1]) }.to_a.should == [[1]]
Enumerator.new { |y| y.<<([1]) }.first.should == [1]
- # << doesn't accept multiple arguments
- # Enumerator.new { |y| y.<<(1, 2) }.to_a.should == [[1, 2]]
- # Enumerator.new { |y| y.<<(1, 2) }.first.should == [1, 2]
-
Enumerator.new { |y| y.<<([1, 2]) }.to_a.should == [[1, 2]]
Enumerator.new { |y| y.<<([1, 2]) }.first.should == [1, 2]
end
+
+ it 'accepts keyword arguments and treats them as a positional hash' do
+ Enumerator.new { |y| y.<<(foo: 42) }.to_a.should == [{ foo: 42 }]
+ Enumerator.new { |y| y.<<(foo: 42) }.first.should == { foo: 42 }
+ end
+
+ it 'can be chained' do
+ enum = Enumerator.new do |y|
+ y << 1 << 2
+ end
+ enum.to_a.should == [1, 2]
+ end
+
+ it 'raises ArgumentError when given more than one argument' do
+ -> {
+ Enumerator.new { |y| y.<<(1, 2) }.to_a
+ }.should.raise(ArgumentError, "wrong number of arguments (given 2, expected 1)")
+ end
end
end
end
diff --git a/spec/ruby/core/enumerator/next_spec.rb b/spec/ruby/core/enumerator/next_spec.rb
index a5e01a399d..77e79185a9 100644
--- a/spec/ruby/core/enumerator/next_spec.rb
+++ b/spec/ruby/core/enumerator/next_spec.rb
@@ -13,14 +13,14 @@ describe "Enumerator#next" do
it "raises a StopIteration exception at the end of the stream" do
3.times { @enum.next }
- -> { @enum.next }.should raise_error(StopIteration)
+ -> { @enum.next }.should.raise(StopIteration)
end
it "cannot be called again until the enumerator is rewound" do
3.times { @enum.next }
- -> { @enum.next }.should raise_error(StopIteration)
- -> { @enum.next }.should raise_error(StopIteration)
- -> { @enum.next }.should raise_error(StopIteration)
+ -> { @enum.next }.should.raise(StopIteration)
+ -> { @enum.next }.should.raise(StopIteration)
+ -> { @enum.next }.should.raise(StopIteration)
@enum.rewind
@enum.next.should == 1
end
diff --git a/spec/ruby/core/enumerator/next_values_spec.rb b/spec/ruby/core/enumerator/next_values_spec.rb
index 201b5d323f..63e024e2b4 100644
--- a/spec/ruby/core/enumerator/next_values_spec.rb
+++ b/spec/ruby/core/enumerator/next_values_spec.rb
@@ -11,6 +11,7 @@ describe "Enumerator#next_values" do
yield :e1, :e2, :e3
yield nil
yield
+ yield [:f1, :f2]
end
@e = o.to_enum
@@ -48,8 +49,13 @@ describe "Enumerator#next_values" do
@e.next_values.should == []
end
- it "raises StopIteration if called on a finished enumerator" do
+ it "returns an array of array if yield is called with an array" do
7.times { @e.next }
- -> { @e.next_values }.should raise_error(StopIteration)
+ @e.next_values.should == [[:f1, :f2]]
+ end
+
+ it "raises StopIteration if called on a finished enumerator" do
+ 8.times { @e.next }
+ -> { @e.next_values }.should.raise(StopIteration)
end
end
diff --git a/spec/ruby/core/enumerator/peek_spec.rb b/spec/ruby/core/enumerator/peek_spec.rb
index 2334385437..096fd2b10c 100644
--- a/spec/ruby/core/enumerator/peek_spec.rb
+++ b/spec/ruby/core/enumerator/peek_spec.rb
@@ -31,6 +31,6 @@ describe "Enumerator#peek" do
it "raises StopIteration if called on a finished enumerator" do
5.times { @e.next }
- -> { @e.peek }.should raise_error(StopIteration)
+ -> { @e.peek }.should.raise(StopIteration)
end
end
diff --git a/spec/ruby/core/enumerator/peek_values_spec.rb b/spec/ruby/core/enumerator/peek_values_spec.rb
index 7865546515..63f7988bcd 100644
--- a/spec/ruby/core/enumerator/peek_values_spec.rb
+++ b/spec/ruby/core/enumerator/peek_values_spec.rb
@@ -11,6 +11,7 @@ describe "Enumerator#peek_values" do
yield :e1, :e2, :e3
yield nil
yield
+ yield [:f1, :f2]
end
@e = o.to_enum
@@ -50,8 +51,13 @@ describe "Enumerator#peek_values" do
@e.peek_values.should == []
end
- it "raises StopIteration if called on a finished enumerator" do
+ it "returns an array of array if yield is called with an array" do
7.times { @e.next }
- -> { @e.peek_values }.should raise_error(StopIteration)
+ @e.peek_values.should == [[:f1, :f2]]
+ end
+
+ it "raises StopIteration if called on a finished enumerator" do
+ 8.times { @e.next }
+ -> { @e.peek_values }.should.raise(StopIteration)
end
end
diff --git a/spec/ruby/core/enumerator/plus_spec.rb b/spec/ruby/core/enumerator/plus_spec.rb
index 755be5b4eb..d6c0fa93ac 100644
--- a/spec/ruby/core/enumerator/plus_spec.rb
+++ b/spec/ruby/core/enumerator/plus_spec.rb
@@ -12,7 +12,7 @@ describe "Enumerator#+" do
chain = one + two + three
- chain.should be_an_instance_of(Enumerator::Chain)
+ chain.should.instance_of?(Enumerator::Chain)
chain.each { |item| ScratchPad << item }
ScratchPad.recorded.should == [1, 2, 3]
end
diff --git a/spec/ruby/core/enumerator/produce_spec.rb b/spec/ruby/core/enumerator/produce_spec.rb
index c69fb49303..eb1b09294e 100644
--- a/spec/ruby/core/enumerator/produce_spec.rb
+++ b/spec/ruby/core/enumerator/produce_spec.rb
@@ -3,6 +3,8 @@ require_relative '../../spec_helper'
describe "Enumerator.produce" do
it "creates an infinite enumerator" do
enum = Enumerator.produce(0) { |prev| prev + 1 }
+
+ enum.size.should == Float::INFINITY
enum.take(5).should == [0, 1, 2, 3, 4]
end
@@ -31,4 +33,46 @@ describe "Enumerator.produce" do
lines.should == ["a\n", "b\n", "c\n", "d"]
end
end
+
+ it "raises ArgumentError when no block is given" do
+ -> { Enumerator.produce }.should.raise(ArgumentError, "no block given")
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "accepts keyword arguments as the initial value" do
+ enum = Enumerator.produce(a: 1, b: 1) {}
+ enum.take(1).should == [{a: 1, b: 1}]
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "raises ArgumentError for unknown keyword arguments" do
+ -> { Enumerator.produce(a: 1, b: 1) {} }.should.raise(ArgumentError, /unknown keywords/)
+ end
+ end
+
+ ruby_version_is "4.0" do
+ context "with size keyword argument" do
+ it "sets the size of the enumerator" do
+ enum = Enumerator.produce(0, size: 10) { |n| n + 1 }
+
+ enum.size.should == 10
+ enum.take(5).should == [0, 1, 2, 3, 4]
+ end
+
+ it "accepts a callable" do
+ enum = Enumerator.produce(0, size: -> { 5 * 5 }) { |n| n + 1 }
+
+ enum.size.should == 25
+ enum.take(5).should == [0, 1, 2, 3, 4]
+ end
+
+ it "accepts nil" do
+ enum = Enumerator.produce(0, size: nil) { |n| n + 1 }
+
+ enum.size.should == nil
+ enum.take(5).should == [0, 1, 2, 3, 4]
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/enumerator/product/each_spec.rb b/spec/ruby/core/enumerator/product/each_spec.rb
new file mode 100644
index 0000000000..a5dced4db1
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/each_spec.rb
@@ -0,0 +1,85 @@
+require_relative '../../../spec_helper'
+require_relative '../../enumerable/shared/enumeratorized'
+
+describe "Enumerator::Product#each" do
+ it_behaves_like :enumeratorized_with_origin_size, :each, Enumerator::Product.new([1, 2], [:a, :b])
+
+ it "yields each element of Cartesian product of enumerators" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ acc = []
+ enum.each { |e| acc << e }
+ acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
+
+ it "calls #each_entry method on enumerators" do
+ object1 = Object.new
+ def object1.each_entry
+ yield 1
+ yield 2
+ end
+
+ object2 = Object.new
+ def object2.each_entry
+ yield :a
+ yield :b
+ end
+
+ enum = Enumerator::Product.new(object1, object2)
+ acc = []
+ enum.each { |e| acc << e }
+ acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
+
+ it "raises a NoMethodError if the object doesn't respond to #each_entry" do
+ -> {
+ Enumerator::Product.new(Object.new).each {}
+ }.should.raise(NoMethodError, /undefined method [`']each_entry' for/)
+ end
+
+ it "returns enumerator if not given a block" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ enum.each.should.kind_of?(Enumerator)
+
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
+
+ it "returns self if given a block" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ enum.each {}.should.equal?(enum)
+ end
+
+ it "doesn't accept arguments" do
+ Enumerator::Product.instance_method(:each).arity.should == 0
+ end
+
+ it "yields each element to a block that takes multiple arguments" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+
+ acc = []
+ enum.each { |x, y| acc << x }
+ acc.should == [1, 1, 2, 2]
+
+ acc = []
+ enum.each { |x, y| acc << y }
+ acc.should == [:a, :b, :a, :b]
+
+ acc = []
+ enum.each { |x, y, z| acc << z }
+ acc.should == [nil, nil, nil, nil]
+ end
+
+ it "yields no element when any enumerable is empty" do
+ enum = Enumerator::Product.new([], [1])
+
+ acc = []
+ enum.each { |x| acc << x }
+ acc.should == []
+
+ enum = Enumerator::Product.new([1], [])
+
+ acc = []
+ enum.each { |x| acc << x }
+ acc.should == []
+ end
+end
diff --git a/spec/ruby/core/enumerator/product/initialize_copy_spec.rb b/spec/ruby/core/enumerator/product/initialize_copy_spec.rb
new file mode 100644
index 0000000000..b5d2b345a9
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/initialize_copy_spec.rb
@@ -0,0 +1,52 @@
+require_relative '../../../spec_helper'
+
+describe "Enumerator::Product#initialize_copy" do
+ it "replaces content of the receiver with content of the other object" do
+ enum = Enumerator::Product.new([true, false])
+ enum2 = Enumerator::Product.new([1, 2], [:a, :b])
+
+ enum.send(:initialize_copy, enum2)
+ enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
+
+ it "returns self" do
+ enum = Enumerator::Product.new([true, false])
+ enum2 = Enumerator::Product.new([1, 2], [:a, :b])
+
+ enum.send(:initialize_copy, enum2).should.equal?(enum)
+ end
+
+ it "is a private method" do
+ Enumerator::Product.private_instance_methods(false).should.include?(:initialize_copy)
+ end
+
+ it "does nothing if the argument is the same as the receiver" do
+ enum = Enumerator::Product.new(1..2)
+ enum.send(:initialize_copy, enum).should.equal?(enum)
+
+ enum.freeze
+ enum.send(:initialize_copy, enum).should.equal?(enum)
+ end
+
+ it "raises FrozenError if the receiver is frozen" do
+ enum = Enumerator::Product.new(1..2)
+ enum2 = Enumerator::Product.new(3..4)
+
+ -> { enum.freeze.send(:initialize_copy, enum2) }.should.raise(FrozenError)
+ end
+
+ it "raises TypeError if the objects are of different class" do
+ enum = Enumerator::Product.new(1..2)
+ enum2 = Class.new(Enumerator::Product).new(3..4)
+
+ -> { enum.send(:initialize_copy, enum2) }.should.raise(TypeError, 'initialize_copy should take same class object')
+ -> { enum2.send(:initialize_copy, enum) }.should.raise(TypeError, 'initialize_copy should take same class object')
+ end
+
+ it "raises ArgumentError if the argument is not initialized yet" do
+ enum = Enumerator::Product.new(1..2)
+ enum2 = Enumerator::Product.allocate
+
+ -> { enum.send(:initialize_copy, enum2) }.should.raise(ArgumentError, 'uninitialized product')
+ end
+end
diff --git a/spec/ruby/core/enumerator/product/initialize_spec.rb b/spec/ruby/core/enumerator/product/initialize_spec.rb
new file mode 100644
index 0000000000..8814f9d3c7
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/initialize_spec.rb
@@ -0,0 +1,31 @@
+require_relative '../../../spec_helper'
+
+describe "Enumerator::Product#initialize" do
+ before :each do
+ @uninitialized = Enumerator::Product.allocate
+ end
+
+ it "is a private method" do
+ Enumerator::Product.private_instance_methods(false).should.include?(:initialize)
+ end
+
+ it "returns self" do
+ @uninitialized.send(:initialize).should.equal?(@uninitialized)
+ end
+
+ it "accepts many arguments" do
+ @uninitialized.send(:initialize, 0..1, 2..3, 4..5).should.equal?(@uninitialized)
+ end
+
+ it "accepts arguments that are not Enumerable nor responding to :each_entry" do
+ @uninitialized.send(:initialize, Object.new).should.equal?(@uninitialized)
+ end
+
+ describe "on frozen instance" do
+ it "raises a FrozenError" do
+ -> {
+ @uninitialized.freeze.send(:initialize, 0..1)
+ }.should.raise(FrozenError)
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/product/inspect_spec.rb b/spec/ruby/core/enumerator/product/inspect_spec.rb
new file mode 100644
index 0000000000..e0d7441f26
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/inspect_spec.rb
@@ -0,0 +1,20 @@
+require_relative '../../../spec_helper'
+
+describe "Enumerator::Product#inspect" do
+ it "returns a String including enumerators" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ enum.inspect.should == "#<Enumerator::Product: [[1, 2], [:a, :b]]>"
+ end
+
+ it "represents a recursive element with '[...]'" do
+ enum = [1, 2]
+ enum_recursive = Enumerator::Product.new(enum)
+
+ enum << enum_recursive
+ enum_recursive.inspect.should == "#<Enumerator::Product: [[1, 2, #<Enumerator::Product: ...>]]>"
+ end
+
+ it "returns a not initialized representation if #initialized is not called yet" do
+ Enumerator::Product.allocate.inspect.should == "#<Enumerator::Product: uninitialized>"
+ end
+end
diff --git a/spec/ruby/core/enumerator/product/rewind_spec.rb b/spec/ruby/core/enumerator/product/rewind_spec.rb
new file mode 100644
index 0000000000..2beffaf5c1
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/rewind_spec.rb
@@ -0,0 +1,62 @@
+require_relative '../../../spec_helper'
+
+describe "Enumerator::Product#rewind" do
+ before :each do
+ @enum = Enumerator::Product.new([1, 2].each.to_enum, [:a, :b].each.to_enum)
+ end
+
+ it "resets the enumerator to its initial state" do
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ @enum.rewind
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
+
+ it "returns self" do
+ @enum.rewind.should.equal? @enum
+ end
+
+ it "has no effect on a new enumerator" do
+ @enum.rewind
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
+
+ it "has no effect if called multiple, consecutive times" do
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ @enum.rewind
+ @enum.rewind
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
+
+ it "calls the enclosed object's rewind method if one exists" do
+ obj = mock('rewinder')
+ enum = Enumerator::Product.new(obj.to_enum)
+
+ obj.should_receive(:rewind)
+ enum.rewind
+ end
+
+ it "does nothing if the object doesn't have a #rewind method" do
+ obj = mock('rewinder')
+ enum = Enumerator::Product.new(obj.to_enum)
+
+ enum.rewind.should == enum
+ end
+
+ it "calls a rewind method on each enumerable in direct order" do
+ ScratchPad.record []
+
+ object1 = Object.new
+ def object1.rewind; ScratchPad << :object1; end
+
+ object2 = Object.new
+ def object2.rewind; ScratchPad << :object2; end
+
+ object3 = Object.new
+ def object3.rewind; ScratchPad << :object3; end
+
+ enum = Enumerator::Product.new(object1, object2, object3)
+ enum.rewind
+
+ ScratchPad.recorded.should == [:object1, :object2, :object3]
+ end
+end
diff --git a/spec/ruby/core/enumerator/product/size_spec.rb b/spec/ruby/core/enumerator/product/size_spec.rb
new file mode 100644
index 0000000000..0ba427af9a
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/size_spec.rb
@@ -0,0 +1,64 @@
+require_relative '../../../spec_helper'
+
+describe "Enumerator::Product#size" do
+ it "returns the total size of the enumerator product calculated by multiplying the sizes of enumerables in the product" do
+ product = Enumerator::Product.new(1..2, 1..3, 1..4)
+ product.size.should == 24 # 2 * 3 * 4
+ end
+
+ it "returns nil if any enumerable reports its size as nil" do
+ enum = Object.new
+ def enum.size; nil; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
+ end
+
+ it "returns Float::INFINITY if any enumerable reports its size as Float::INFINITY" do
+ enum = Object.new
+ def enum.size; Float::INFINITY; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == Float::INFINITY
+ end
+
+ it "returns nil if any enumerable reports its size as Float::NAN" do
+ enum = Object.new
+ def enum.size; Float::NAN; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
+ end
+
+ it "returns nil if any enumerable doesn't respond to #size" do
+ enum = Object.new
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
+ end
+
+ it "returns nil if any enumerable reports a not-convertible to Integer" do
+ enum = Object.new
+ def enum.size; :symbol; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
+ end
+
+ it "returns nil if any enumerable reports a non-Integer but convertible to Integer size" do
+ enum = Object.new
+ def enum.size; 1.0; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
+ end
+
+ ruby_version_is "3.4" do
+ it "returns zero when any enumerable reports zero" do
+ enum = Enumerator::Product.new(1...1, ["A", "B"])
+ enum.size.should == 0
+
+ enum = Enumerator::Product.new(["A", "B"], 1...1)
+ enum.size.should == 0
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/product_spec.rb b/spec/ruby/core/enumerator/product_spec.rb
new file mode 100644
index 0000000000..0f37ef76e7
--- /dev/null
+++ b/spec/ruby/core/enumerator/product_spec.rb
@@ -0,0 +1,91 @@
+require_relative '../../spec_helper'
+
+describe "Enumerator.product" do
+ it "returns a Cartesian product of enumerators" do
+ enum = Enumerator.product(1..2, ["A", "B"])
+ enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
+ end
+
+ it "accepts a list of enumerators of any length" do
+ enum = Enumerator.product(1..2)
+ enum.to_a.should == [[1], [2]]
+
+ enum = Enumerator.product(1..2, ["A"])
+ enum.to_a.should == [[1, "A"], [2, "A"]]
+
+ enum = Enumerator.product(1..2, ["A"], ["B"])
+ enum.to_a.should == [[1, "A", "B"], [2, "A", "B"]]
+
+ enum = Enumerator.product(2..3, ["A"], ["B"], ["C"])
+ enum.to_a.should == [[2, "A", "B", "C"], [3, "A", "B", "C"]]
+ end
+
+ it "returns an enumerator with an empty array when no arguments passed" do
+ enum = Enumerator.product
+ enum.to_a.should == [[]]
+ end
+
+ it "returns an instance of Enumerator::Product" do
+ enum = Enumerator.product
+ enum.class.should == Enumerator::Product
+ end
+
+ it "accepts infinite enumerators and returns infinite enumerator" do
+ enum = Enumerator.product(1.., ["A", "B"])
+ enum.take(5).should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"]]
+ enum.size.should == Float::INFINITY
+ end
+
+ it "accepts a block" do
+ elems = []
+ enum = Enumerator.product(1..2, ["X", "Y"]) { elems << _1 }
+
+ elems.should == [[1, "X"], [1, "Y"], [2, "X"], [2, "Y"]]
+ end
+
+ it "returns nil when a block passed" do
+ Enumerator.product(1..2) {}.should == nil
+ end
+
+ # https://bugs.ruby-lang.org/issues/19829
+ it "reject keyword arguments" do
+ -> {
+ Enumerator.product(1..3, foo: 1, bar: 2)
+ }.should.raise(ArgumentError, "unknown keywords: :foo, :bar")
+ end
+
+ it "calls only #each_entry method on arguments" do
+ object = Object.new
+ def object.each_entry
+ yield 1
+ yield 2
+ end
+
+ enum = Enumerator.product(object, ["A", "B"])
+ enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
+ end
+
+ it "raises NoMethodError when argument doesn't respond to #each_entry" do
+ -> {
+ Enumerator.product(Object.new).to_a
+ }.should.raise(NoMethodError, /undefined method [`']each_entry' for/)
+ end
+
+ it "calls #each_entry lazily" do
+ Enumerator.product(Object.new).should.is_a?(Enumerator)
+ end
+
+ it "iterates through consuming enumerator elements only once" do
+ a = [1, 2, 3]
+ i = 0
+
+ enum = Enumerator.new do |y|
+ while i < a.size
+ y << a[i]
+ i += 1
+ end
+ end
+
+ Enumerator.product(['a', 'b'], enum).to_a.should == [["a", 1], ["a", 2], ["a", 3]]
+ end
+end
diff --git a/spec/ruby/core/enumerator/rewind_spec.rb b/spec/ruby/core/enumerator/rewind_spec.rb
index a105f2c619..6ba0edf174 100644
--- a/spec/ruby/core/enumerator/rewind_spec.rb
+++ b/spec/ruby/core/enumerator/rewind_spec.rb
@@ -14,7 +14,7 @@ describe "Enumerator#rewind" do
end
it "returns self" do
- @enum.rewind.should == @enum
+ @enum.rewind.should.equal? @enum
end
it "has no effect on a new enumerator" do
@@ -49,7 +49,7 @@ describe "Enumerator#rewind" do
obj = mock('rewinder')
enum = obj.to_enum
obj.should_receive(:each).at_most(1)
- -> { enum.rewind.should == enum }.should_not raise_error
+ enum.rewind.should == enum
end
end
diff --git a/spec/ruby/core/enumerator/shared/enum_for.rb b/spec/ruby/core/enumerator/shared/enum_for.rb
new file mode 100644
index 0000000000..4388103ecf
--- /dev/null
+++ b/spec/ruby/core/enumerator/shared/enum_for.rb
@@ -0,0 +1,57 @@
+describe :enum_for, shared: true do
+ it "is defined in Kernel" do
+ Kernel.method_defined?(@method).should == true
+ end
+
+ it "returns a new enumerator" do
+ "abc".send(@method).should.instance_of?(Enumerator)
+ end
+
+ it "defaults the first argument to :each" do
+ enum = [1,2].send(@method)
+ enum.map { |v| v }.should == [1,2].each { |v| v }
+ end
+
+ it "sets regexp matches in the caller" do
+ "wawa".send(@method, :scan, /./).map {|o| $& }.should == ["w", "a", "w", "a"]
+ a = []
+ "wawa".send(@method, :scan, /./).each {|o| a << $& }
+ a.should == ["w", "a", "w", "a"]
+ end
+
+ it "exposes multi-arg yields as an array" do
+ o = Object.new
+ def o.each
+ yield :a
+ yield :b1, :b2
+ yield [:c]
+ yield :d1, :d2
+ yield :e1, :e2, :e3
+ end
+
+ enum = o.send(@method)
+ enum.next.should == :a
+ enum.next.should == [:b1, :b2]
+ enum.next.should == [:c]
+ enum.next.should == [:d1, :d2]
+ enum.next.should == [:e1, :e2, :e3]
+ end
+
+ it "uses the passed block's value to calculate the size of the enumerator" do
+ Object.new.enum_for { 100 }.size.should == 100
+ end
+
+ it "defers the evaluation of the passed block until #size is called" do
+ ScratchPad.record []
+
+ enum = Object.new.enum_for do
+ ScratchPad << :called
+ 100
+ end
+
+ ScratchPad.recorded.should.empty?
+
+ enum.size
+ ScratchPad.recorded.should == [:called]
+ end
+end
diff --git a/spec/ruby/core/enumerator/shared/with_index.rb b/spec/ruby/core/enumerator/shared/with_index.rb
new file mode 100644
index 0000000000..0992397e95
--- /dev/null
+++ b/spec/ruby/core/enumerator/shared/with_index.rb
@@ -0,0 +1,33 @@
+require_relative '../../../spec_helper'
+
+describe :enum_with_index, shared: true do
+
+ require_relative '../fixtures/classes'
+
+ before :each do
+ @origin = [1, 2, 3, 4]
+ @enum = @origin.to_enum
+ end
+
+ it "passes each element and its index to block" do
+ a = []
+ @enum.send(@method) { |o, i| a << [o, i] }
+ a.should == [[1, 0], [2, 1], [3, 2], [4, 3]]
+ end
+
+ it "returns the object being enumerated when given a block" do
+ @enum.send(@method) { |o, i| :glark }.should.equal?(@origin)
+ end
+
+ it "binds splat arguments properly" do
+ acc = []
+ @enum.send(@method) { |*b| c,d = b; acc << c; acc << d }
+ [1, 0, 2, 1, 3, 2, 4, 3].should == acc
+ end
+
+ it "returns an enumerator if no block is supplied" do
+ ewi = @enum.send(@method)
+ ewi.should.instance_of?(Enumerator)
+ ewi.to_a.should == [[1, 0], [2, 1], [3, 2], [4, 3]]
+ end
+end
diff --git a/spec/ruby/core/enumerator/shared/with_object.rb b/spec/ruby/core/enumerator/shared/with_object.rb
new file mode 100644
index 0000000000..50d4f24eb3
--- /dev/null
+++ b/spec/ruby/core/enumerator/shared/with_object.rb
@@ -0,0 +1,42 @@
+require_relative '../../../spec_helper'
+
+describe :enum_with_object, shared: true do
+ before :each do
+ @enum = [:a, :b].to_enum
+ @memo = ''
+ @block_params = @enum.send(@method, @memo).to_a
+ end
+
+ it "receives an argument" do
+ @enum.method(@method).arity.should == 1
+ end
+
+ context "with block" do
+ it "returns the given object" do
+ ret = @enum.send(@method, @memo) do |elm, memo|
+ # nothing
+ end
+ ret.should.equal?(@memo)
+ end
+
+ context "the block parameter" do
+ it "passes each element to first parameter" do
+ @block_params[0][0].should.equal?(:a)
+ @block_params[1][0].should.equal?(:b)
+ end
+
+ it "passes the given object to last parameter" do
+ @block_params[0][1].should.equal?(@memo)
+ @block_params[1][1].should.equal?(@memo)
+ end
+ end
+ end
+
+ context "without block" do
+ it "returns new Enumerator" do
+ ret = @enum.send(@method, @memo)
+ ret.should.instance_of?(Enumerator)
+ ret.should_not.equal?(@enum)
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/size_spec.rb b/spec/ruby/core/enumerator/size_spec.rb
index 6accd26a4e..4b2beffbbe 100644
--- a/spec/ruby/core/enumerator/size_spec.rb
+++ b/spec/ruby/core/enumerator/size_spec.rb
@@ -6,7 +6,7 @@ describe "Enumerator#size" do
end
it "returns nil if set size is nil" do
- Enumerator.new(nil) {}.size.should be_nil
+ Enumerator.new(nil) {}.size.should == nil
end
it "returns returning value from size.call if set size is a Proc" do
diff --git a/spec/ruby/core/enumerator/to_enum_spec.rb b/spec/ruby/core/enumerator/to_enum_spec.rb
index cadfcf6314..7fb73d0c3c 100644
--- a/spec/ruby/core/enumerator/to_enum_spec.rb
+++ b/spec/ruby/core/enumerator/to_enum_spec.rb
@@ -1,6 +1,6 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/enum_for'
+require_relative 'shared/enum_for'
describe "Enumerator#to_enum" do
- it_behaves_like :enum_for, :enum_for
+ it_behaves_like :enum_for, :to_enum
end
diff --git a/spec/ruby/core/enumerator/with_index_spec.rb b/spec/ruby/core/enumerator/with_index_spec.rb
index ac37cee508..ca90fd18f7 100644
--- a/spec/ruby/core/enumerator/with_index_spec.rb
+++ b/spec/ruby/core/enumerator/with_index_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/with_index'
+require_relative 'shared/with_index'
require_relative '../enumerable/shared/enumeratorized'
describe "Enumerator#with_index" do
@@ -9,20 +9,20 @@ describe "Enumerator#with_index" do
it "returns a new Enumerator when no block is given" do
enum1 = [1,2,3].select
enum2 = enum1.with_index
- enum2.should be_an_instance_of(Enumerator)
+ enum2.should.instance_of?(Enumerator)
enum1.should_not === enum2
end
it "accepts an optional argument when given a block" do
-> do
@enum.with_index(1) { |f| f}
- end.should_not raise_error(ArgumentError)
+ end.should_not.raise(ArgumentError)
end
it "accepts an optional argument when not given a block" do
-> do
@enum.with_index(1)
- end.should_not raise_error(ArgumentError)
+ end.should_not.raise(ArgumentError)
end
it "numbers indices from the given index when given an offset but no block" do
@@ -38,7 +38,7 @@ describe "Enumerator#with_index" do
it "raises a TypeError when the argument cannot be converted to numeric" do
-> do
@enum.with_index('1') {|*i| i}
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "converts non-numeric arguments to Integer via #to_int" do
@@ -69,4 +69,21 @@ describe "Enumerator#with_index" do
@enum.with_index(-1) { |*x| res << x}
res.should == [[1,-1], [2,0], [3,1], [4,2]]
end
+
+ it "passes on the given block's return value" do
+ arr = [1,2,3]
+ arr.delete_if.with_index { |a,b| false }
+ arr.should == [1,2,3]
+
+ arr.delete_if.with_index { |a,b| true }
+ arr.should == []
+ end
+
+ it "returns the iterator's return value" do
+ @enum.select.with_index { |a,b| false }.should == []
+ end
+
+ it "returns the correct value if chained with itself" do
+ [:a].each.with_index.with_index.to_a.should == [[[:a,0],0]]
+ end
end
diff --git a/spec/ruby/core/enumerator/with_object_spec.rb b/spec/ruby/core/enumerator/with_object_spec.rb
index e7ba83fd9f..58031fd765 100644
--- a/spec/ruby/core/enumerator/with_object_spec.rb
+++ b/spec/ruby/core/enumerator/with_object_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/with_object'
+require_relative 'shared/with_object'
describe "Enumerator#with_object" do
it_behaves_like :enum_with_object, :with_object
diff --git a/spec/ruby/core/enumerator/yielder/append_spec.rb b/spec/ruby/core/enumerator/yielder/append_spec.rb
deleted file mode 100644
index a36e5d64b6..0000000000
--- a/spec/ruby/core/enumerator/yielder/append_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-require_relative '../../../spec_helper'
-
-describe "Enumerator::Yielder#<<" do
- # TODO: There's some common behavior between yield and <<; move to a shared spec
- it "yields the value to the block" do
- ary = []
- y = Enumerator::Yielder.new {|x| ary << x}
- y << 1
-
- ary.should == [1]
- end
-
- it "doesn't double-wrap Arrays" do
- yields = []
- y = Enumerator::Yielder.new {|args| yields << args }
- y << [1]
- yields.should == [[1]]
- end
-
- it "returns self" do
- y = Enumerator::Yielder.new {|x| x + 1}
- (y << 1).should equal(y)
- end
-
- context "when multiple arguments passed" do
- it "raises an ArgumentError" do
- ary = []
- y = Enumerator::Yielder.new { |*x| ary << x }
-
- -> {
- y.<<(1, 2)
- }.should raise_error(ArgumentError, /wrong number of arguments/)
- end
- end
-end
diff --git a/spec/ruby/core/enumerator/yielder/initialize_spec.rb b/spec/ruby/core/enumerator/yielder/initialize_spec.rb
deleted file mode 100644
index 5a6eee2d0f..0000000000
--- a/spec/ruby/core/enumerator/yielder/initialize_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- encoding: us-ascii -*-
-
-require_relative '../../../spec_helper'
-
-describe "Enumerator::Yielder#initialize" do
- before :each do
- @class = Enumerator::Yielder
- @uninitialized = @class.allocate
- end
-
- it "is a private method" do
- @class.should have_private_instance_method(:initialize, false)
- end
-
- it "returns self when given a block" do
- @uninitialized.send(:initialize) {}.should equal(@uninitialized)
- end
-end
diff --git a/spec/ruby/core/enumerator/yielder/to_proc_spec.rb b/spec/ruby/core/enumerator/yielder/to_proc_spec.rb
deleted file mode 100644
index 1d3681ab50..0000000000
--- a/spec/ruby/core/enumerator/yielder/to_proc_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require_relative '../../../spec_helper'
-
-describe "Enumerator::Yielder#to_proc" do
- it "returns a Proc object that takes an argument and yields it to the block" do
- ScratchPad.record []
- y = Enumerator::Yielder.new { |*args| ScratchPad << args; "foobar" }
-
- callable = y.to_proc
- callable.class.should == Proc
-
- result = callable.call(1, 2)
- ScratchPad.recorded.should == [[1, 2]]
-
- result.should == "foobar"
- end
-end
diff --git a/spec/ruby/core/enumerator/yielder/yield_spec.rb b/spec/ruby/core/enumerator/yielder/yield_spec.rb
deleted file mode 100644
index acfdf114b6..0000000000
--- a/spec/ruby/core/enumerator/yielder/yield_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require_relative '../../../spec_helper'
-
-describe "Enumerator::Yielder#yield" do
- it "yields the value to the block" do
- ary = []
- y = Enumerator::Yielder.new {|x| ary << x}
- y.yield 1
-
- ary.should == [1]
- end
-
- it "yields with passed arguments" do
- yields = []
- y = Enumerator::Yielder.new {|*args| yields << args }
- y.yield 1, 2
- yields.should == [[1, 2]]
- end
-
- it "returns the result of the block for the given value" do
- y = Enumerator::Yielder.new {|x| x + 1}
- y.yield(1).should == 2
- end
-
- context "when multiple arguments passed" do
- it "yields the arguments list to the block" do
- ary = []
- y = Enumerator::Yielder.new { |*x| ary << x }
- y.yield(1, 2)
-
- ary.should == [[1, 2]]
- end
- end
-end
diff --git a/spec/ruby/core/env/assoc_spec.rb b/spec/ruby/core/env/assoc_spec.rb
index c7a388db75..b81be7ddf2 100644
--- a/spec/ruby/core/env/assoc_spec.rb
+++ b/spec/ruby/core/env/assoc_spec.rb
@@ -26,6 +26,6 @@ describe "ENV.assoc" do
end
it "raises TypeError if the argument is not a String and does not respond to #to_str" do
- -> { ENV.assoc(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.assoc(Object.new) }.should.raise(TypeError, "no implicit conversion of Object into String")
end
end
diff --git a/spec/ruby/core/env/clear_spec.rb b/spec/ruby/core/env/clear_spec.rb
index 48b034ba1d..c0d20193ad 100644
--- a/spec/ruby/core/env/clear_spec.rb
+++ b/spec/ruby/core/env/clear_spec.rb
@@ -4,7 +4,7 @@ describe "ENV.clear" do
it "deletes all environment variables" do
orig = ENV.to_hash
begin
- ENV.clear.should equal(ENV)
+ ENV.clear.should.equal?(ENV)
# This used 'env' the helper before. That shells out to 'env' which
# itself sets up certain environment variables before it runs, because
diff --git a/spec/ruby/core/env/clone_spec.rb b/spec/ruby/core/env/clone_spec.rb
new file mode 100644
index 0000000000..bb3c7ff2f8
--- /dev/null
+++ b/spec/ruby/core/env/clone_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+
+describe "ENV#clone" do
+ it "raises ArgumentError when keyword argument 'freeze' is neither nil nor boolean" do
+ -> {
+ ENV.clone(freeze: 1)
+ }.should.raise(ArgumentError)
+ end
+
+ it "raises ArgumentError when keyword argument is not 'freeze'" do
+ -> {
+ ENV.clone(foo: nil)
+ }.should.raise(ArgumentError)
+ end
+
+ it "raises TypeError" do
+ -> {
+ ENV.clone
+ }.should.raise(TypeError, /Cannot clone ENV, use ENV.to_h to get a copy of ENV as a hash/)
+ end
+end
diff --git a/spec/ruby/core/env/delete_if_spec.rb b/spec/ruby/core/env/delete_if_spec.rb
index d2de51c225..4b05064eba 100644
--- a/spec/ruby/core/env/delete_if_spec.rb
+++ b/spec/ruby/core/env/delete_if_spec.rb
@@ -22,15 +22,15 @@ describe "ENV.delete_if" do
end
it "returns ENV when block given" do
- ENV.delete_if { |k, v| ["foo", "bar"].include?(k) }.should equal(ENV)
+ ENV.delete_if { |k, v| ["foo", "bar"].include?(k) }.should.equal?(ENV)
end
it "returns ENV even if nothing deleted" do
- ENV.delete_if { false }.should equal(ENV)
+ ENV.delete_if { false }.should.equal?(ENV)
end
it "returns an Enumerator if no block given" do
- ENV.delete_if.should be_an_instance_of(Enumerator)
+ ENV.delete_if.should.instance_of?(Enumerator)
end
it "deletes pairs through enumerator" do
@@ -42,12 +42,12 @@ describe "ENV.delete_if" do
it "returns ENV from enumerator" do
enum = ENV.delete_if
- enum.each { |k, v| ["foo", "bar"].include?(k) }.should equal(ENV)
+ enum.each { |k, v| ["foo", "bar"].include?(k) }.should.equal?(ENV)
end
it "returns ENV from enumerator even if nothing deleted" do
enum = ENV.delete_if
- enum.each { false }.should equal(ENV)
+ enum.each { false }.should.equal?(ENV)
end
it_behaves_like :enumeratorized_with_origin_size, :delete_if, ENV
diff --git a/spec/ruby/core/env/delete_spec.rb b/spec/ruby/core/env/delete_spec.rb
index 5e7891f74d..db6d07b057 100644
--- a/spec/ruby/core/env/delete_spec.rb
+++ b/spec/ruby/core/env/delete_spec.rb
@@ -30,11 +30,9 @@ describe "ENV.delete" do
ScratchPad.recorded.should == "foo"
end
- ruby_version_is "3.0" do
- it "returns the result of given block if the named environment variable does not exist" do
- ENV.delete("foo")
- ENV.delete("foo") { |name| "bar" }.should == "bar"
- end
+ it "returns the result of given block if the named environment variable does not exist" do
+ ENV.delete("foo")
+ ENV.delete("foo") { |name| "bar" }.should == "bar"
end
it "does not evaluate the block if the environment variable exists" do
@@ -43,7 +41,15 @@ describe "ENV.delete" do
ENV["foo"].should == nil
end
+ it "removes the variable coerced with #to_str" do
+ ENV["foo"] = "bar"
+ k = mock('key')
+ k.should_receive(:to_str).and_return("foo")
+ ENV.delete(k)
+ ENV["foo"].should == nil
+ end
+
it "raises TypeError if the argument is not a String and does not respond to #to_str" do
- -> { ENV.delete(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.delete(Object.new) }.should.raise(TypeError, "no implicit conversion of Object into String")
end
end
diff --git a/spec/ruby/core/env/dup_spec.rb b/spec/ruby/core/env/dup_spec.rb
new file mode 100644
index 0000000000..d8cfac891d
--- /dev/null
+++ b/spec/ruby/core/env/dup_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+
+describe "ENV#dup" do
+ it "raises TypeError" do
+ -> {
+ ENV.dup
+ }.should.raise(TypeError, /Cannot dup ENV, use ENV.to_h to get a copy of ENV as a hash/)
+ end
+end
diff --git a/spec/ruby/core/env/each_key_spec.rb b/spec/ruby/core/env/each_key_spec.rb
index 0efcb09900..ad2cb560a0 100644
--- a/spec/ruby/core/env/each_key_spec.rb
+++ b/spec/ruby/core/env/each_key_spec.rb
@@ -10,9 +10,9 @@ describe "ENV.each_key" do
ENV.clear
ENV["1"] = "3"
ENV["2"] = "4"
- ENV.each_key { |k| e << k }.should equal(ENV)
- e.should include("1")
- e.should include("2")
+ ENV.each_key { |k| e << k }.should.equal?(ENV)
+ e.should.include?("1")
+ e.should.include?("2")
ensure
ENV.replace orig
end
@@ -20,7 +20,7 @@ describe "ENV.each_key" do
it "returns an Enumerator if called without a block" do
enum = ENV.each_key
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.should == ENV.keys
end
diff --git a/spec/ruby/core/env/each_value_spec.rb b/spec/ruby/core/env/each_value_spec.rb
index cc3c9ebfb8..6f65e923e6 100644
--- a/spec/ruby/core/env/each_value_spec.rb
+++ b/spec/ruby/core/env/each_value_spec.rb
@@ -10,9 +10,9 @@ describe "ENV.each_value" do
ENV.clear
ENV["1"] = "3"
ENV["2"] = "4"
- ENV.each_value { |v| e << v }.should equal(ENV)
- e.should include("3")
- e.should include("4")
+ ENV.each_value { |v| e << v }.should.equal?(ENV)
+ e.should.include?("3")
+ e.should.include?("4")
ensure
ENV.replace orig
end
@@ -20,7 +20,7 @@ describe "ENV.each_value" do
it "returns an Enumerator if called without a block" do
enum = ENV.each_value
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.should == ENV.values
end
diff --git a/spec/ruby/core/env/element_reference_spec.rb b/spec/ruby/core/env/element_reference_spec.rb
index 560c127a9c..e3ac979418 100644
--- a/spec/ruby/core/env/element_reference_spec.rb
+++ b/spec/ruby/core/env/element_reference_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'fixtures/common'
@@ -28,7 +28,7 @@ describe "ENV.[]" do
end
it "raises TypeError if the argument is not a String and does not respond to #to_str" do
- -> { ENV[Object.new] }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV[Object.new] }.should.raise(TypeError, "no implicit conversion of Object into String")
end
platform_is :windows do
@@ -71,6 +71,6 @@ describe "ENV.[]" do
ENV[@variable] = ""
Encoding.default_internal = Encoding::IBM437
- ENV[@variable].encoding.should equal(Encoding::IBM437)
+ ENV[@variable].encoding.should.equal?(Encoding::IBM437)
end
end
diff --git a/spec/ruby/core/env/except_spec.rb b/spec/ruby/core/env/except_spec.rb
index cfe5865abe..fb8f3b7536 100644
--- a/spec/ruby/core/env/except_spec.rb
+++ b/spec/ruby/core/env/except_spec.rb
@@ -1,36 +1,34 @@
require_relative 'spec_helper'
require_relative 'shared/to_hash'
-ruby_version_is "3.0" do
- describe "ENV.except" do
- before do
- @orig_hash = ENV.to_hash
- end
+describe "ENV.except" do
+ before do
+ @orig_hash = ENV.to_hash
+ end
- after do
- ENV.replace @orig_hash
- end
+ after do
+ ENV.replace @orig_hash
+ end
- # Testing the method without arguments is covered via
- it_behaves_like :env_to_hash, :except
+ # Testing the method without arguments is covered via
+ it_behaves_like :env_to_hash, :except
- it "returns a hash without the requested subset" do
- ENV.clear
+ it "returns a hash without the requested subset" do
+ ENV.clear
- ENV['one'] = '1'
- ENV['two'] = '2'
- ENV['three'] = '3'
+ ENV['one'] = '1'
+ ENV['two'] = '2'
+ ENV['three'] = '3'
- ENV.except('one', 'three').should == { 'two' => '2' }
- end
+ ENV.except('one', 'three').should == { 'two' => '2' }
+ end
- it "ignores keys not present in the original hash" do
- ENV.clear
+ it "ignores keys not present in the original hash" do
+ ENV.clear
- ENV['one'] = '1'
- ENV['two'] = '2'
+ ENV['one'] = '1'
+ ENV['two'] = '2'
- ENV.except('one', 'three').should == { 'two' => '2' }
- end
+ ENV.except('one', 'three').should == { 'two' => '2' }
end
end
diff --git a/spec/ruby/core/env/fetch_spec.rb b/spec/ruby/core/env/fetch_spec.rb
index b2e7a88cab..a2ec79c62b 100644
--- a/spec/ruby/core/env/fetch_spec.rb
+++ b/spec/ruby/core/env/fetch_spec.rb
@@ -16,7 +16,7 @@ describe "ENV.fetch" do
end
it "raises a TypeError if the key is not a String" do
- -> { ENV.fetch Object.new }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.fetch Object.new }.should.raise(TypeError, "no implicit conversion of Object into String")
end
context "when the key is not found" do
@@ -25,7 +25,7 @@ describe "ENV.fetch" do
it "formats the object with #inspect in the KeyError message" do
-> {
ENV.fetch('foo')
- }.should raise_error(KeyError, 'key not found: "foo"')
+ }.should.raise(KeyError, 'key not found: "foo"')
end
end
@@ -47,7 +47,7 @@ describe "ENV.fetch" do
it "warns on block and default parameter given" do
-> do
- ENV.fetch("foo", "default") { "bar" }.should == "bar"
+ ENV.fetch("foo", "default") { "bar" }.should == "bar"
end.should complain(/block supersedes default value argument/)
end
diff --git a/spec/ruby/core/env/fetch_values_spec.rb b/spec/ruby/core/env/fetch_values_spec.rb
new file mode 100644
index 0000000000..302cde2fd1
--- /dev/null
+++ b/spec/ruby/core/env/fetch_values_spec.rb
@@ -0,0 +1,51 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
+
+ruby_version_is "4.1" do
+ describe "ENV.fetch_values" do
+ before :each do
+ @saved_foo = ENV["foo"]
+ @saved_bar = ENV["bar"]
+ ENV.delete("foo")
+ ENV.delete("bar")
+ end
+
+ after :each do
+ ENV["foo"] = @saved_foo
+ ENV["bar"] = @saved_bar
+ end
+
+ it "returns an array of the values corresponding to the given keys" do
+ ENV["foo"] = "oof"
+ ENV["bar"] = "rab"
+ ENV.fetch_values("bar", "foo").should == ["rab", "oof"]
+ end
+
+ it "returns the default value from block" do
+ ENV["foo"] = "oof"
+ ENV.fetch_values("bar") { |key| "`#{key}' is not found" }.should == ["`bar' is not found"]
+ ENV.fetch_values("bar", "foo") { |key| "`#{key}' is not found" }.should == ["`bar' is not found", "oof"]
+ end
+
+ it "returns an empty array if no keys specified" do
+ ENV.fetch_values.should == []
+ end
+
+ it "raises KeyError when there is no matching key" do
+ ENV["foo"] = "oof"
+ ENV["bar"] = "rab"
+ -> {
+ ENV.fetch_values("bar", "y", "foo", "z")
+ }.should.raise(KeyError, 'key not found: "y"')
+ end
+
+ it "uses the locale encoding" do
+ ENV.fetch_values(ENV.keys.first).first.encoding.should == ENVSpecs.encoding
+ end
+
+ it "raises TypeError when a key is not coercible to String" do
+ ENV["foo"] = "oof"
+ -> { ENV.fetch_values("foo", Object.new) }.should.raise(TypeError, "no implicit conversion of Object into String")
+ end
+ end
+end
diff --git a/spec/ruby/core/env/index_spec.rb b/spec/ruby/core/env/index_spec.rb
deleted file mode 100644
index 301a66ab4e..0000000000
--- a/spec/ruby/core/env/index_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/key'
-
-ruby_version_is ''...'3.0' do
- describe "ENV.index" do
- it_behaves_like :env_key, :index
-
- it "warns about deprecation" do
- -> do
- ENV.index("foo")
- end.should complain(/warning: ENV.index is deprecated; use ENV.key/)
- end
- end
-end
diff --git a/spec/ruby/core/env/indexes_spec.rb b/spec/ruby/core/env/indexes_spec.rb
deleted file mode 100644
index e724feaa39..0000000000
--- a/spec/ruby/core/env/indexes_spec.rb
+++ /dev/null
@@ -1 +0,0 @@
-require_relative '../../spec_helper'
diff --git a/spec/ruby/core/env/indices_spec.rb b/spec/ruby/core/env/indices_spec.rb
deleted file mode 100644
index e724feaa39..0000000000
--- a/spec/ruby/core/env/indices_spec.rb
+++ /dev/null
@@ -1 +0,0 @@
-require_relative '../../spec_helper'
diff --git a/spec/ruby/core/env/inspect_spec.rb b/spec/ruby/core/env/inspect_spec.rb
index 3c611c24a1..7dd92b120f 100644
--- a/spec/ruby/core/env/inspect_spec.rb
+++ b/spec/ruby/core/env/inspect_spec.rb
@@ -4,7 +4,7 @@ describe "ENV.inspect" do
it "returns a String that looks like a Hash with real data" do
ENV["foo"] = "bar"
- ENV.inspect.should =~ /\{.*"foo"=>"bar".*\}/
+ ENV.inspect.should =~ /\{.*"foo" *=> *"bar".*\}/
ENV.delete "foo"
end
diff --git a/spec/ruby/core/env/keep_if_spec.rb b/spec/ruby/core/env/keep_if_spec.rb
index 64b6a207d0..f24981e216 100644
--- a/spec/ruby/core/env/keep_if_spec.rb
+++ b/spec/ruby/core/env/keep_if_spec.rb
@@ -22,15 +22,15 @@ describe "ENV.keep_if" do
end
it "returns ENV when block given" do
- ENV.keep_if { |k, v| !["foo", "bar"].include?(k) }.should equal(ENV)
+ ENV.keep_if { |k, v| !["foo", "bar"].include?(k) }.should.equal?(ENV)
end
it "returns ENV even if nothing deleted" do
- ENV.keep_if { true }.should equal(ENV)
+ ENV.keep_if { true }.should.equal?(ENV)
end
it "returns an Enumerator if no block given" do
- ENV.keep_if.should be_an_instance_of(Enumerator)
+ ENV.keep_if.should.instance_of?(Enumerator)
end
it "deletes pairs through enumerator" do
@@ -42,12 +42,12 @@ describe "ENV.keep_if" do
it "returns ENV from enumerator" do
enum = ENV.keep_if
- enum.each { |k, v| !["foo", "bar"].include?(k) }.should equal(ENV)
+ enum.each { |k, v| !["foo", "bar"].include?(k) }.should.equal?(ENV)
end
it "returns ENV from enumerator even if nothing deleted" do
enum = ENV.keep_if
- enum.each { true }.should equal(ENV)
+ enum.each { true }.should.equal?(ENV)
end
it_behaves_like :enumeratorized_with_origin_size, :keep_if, ENV
diff --git a/spec/ruby/core/env/key_spec.rb b/spec/ruby/core/env/key_spec.rb
index 82cfbefa39..677cf35216 100644
--- a/spec/ruby/core/env/key_spec.rb
+++ b/spec/ruby/core/env/key_spec.rb
@@ -1,11 +1,39 @@
require_relative '../../spec_helper'
require_relative 'shared/include'
-require_relative 'shared/key'
describe "ENV.key?" do
it_behaves_like :env_include, :key?
end
describe "ENV.key" do
- it_behaves_like :env_key, :key
+ before :each do
+ @saved_foo = ENV["foo"]
+ end
+
+ after :each do
+ ENV["foo"] = @saved_foo
+ end
+
+ it "returns the index associated with the passed value" do
+ ENV["foo"] = "bar"
+ ENV.key("bar").should == "foo"
+ end
+
+ it "returns nil if the passed value is not found" do
+ ENV.delete("foo")
+ ENV.key("foo").should == nil
+ end
+
+ it "coerces the key element with #to_str" do
+ ENV["foo"] = "bar"
+ k = mock('key')
+ k.should_receive(:to_str).and_return("bar")
+ ENV.key(k).should == "foo"
+ end
+
+ it "raises TypeError if the argument is not a String and does not respond to #to_str" do
+ -> {
+ ENV.key(Object.new)
+ }.should.raise(TypeError, "no implicit conversion of Object into String")
+ end
end
diff --git a/spec/ruby/core/env/length_spec.rb b/spec/ruby/core/env/length_spec.rb
index 536af9edf5..c6f9062892 100644
--- a/spec/ruby/core/env/length_spec.rb
+++ b/spec/ruby/core/env/length_spec.rb
@@ -2,5 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/length'
describe "ENV.length" do
- it_behaves_like :env_length, :length
+ it_behaves_like :env_length, :length
end
diff --git a/spec/ruby/core/env/rassoc_spec.rb b/spec/ruby/core/env/rassoc_spec.rb
index ab9fe68088..e4ac5ce5e2 100644
--- a/spec/ruby/core/env/rassoc_spec.rb
+++ b/spec/ruby/core/env/rassoc_spec.rb
@@ -22,7 +22,7 @@ describe "ENV.rassoc" do
[
["foo", "bar"],
["baz", "bar"],
- ].should include(ENV.rassoc("bar"))
+ ].should.include?(ENV.rassoc("bar"))
end
it "returns nil if no environment variable with the given value exists" do
diff --git a/spec/ruby/core/env/reject_spec.rb b/spec/ruby/core/env/reject_spec.rb
index 6a9794925d..4df864493d 100644
--- a/spec/ruby/core/env/reject_spec.rb
+++ b/spec/ruby/core/env/reject_spec.rb
@@ -25,15 +25,15 @@ describe "ENV.reject!" do
it "returns itself or nil" do
ENV.reject! { false }.should == nil
ENV["foo"] = "bar"
- ENV.reject! { |k, v| k == "foo" }.should equal(ENV)
+ ENV.reject! { |k, v| k == "foo" }.should.equal?(ENV)
ENV["foo"].should == nil
end
it "returns an Enumerator if called without a block" do
ENV["foo"] = "bar"
enum = ENV.reject!
- enum.should be_an_instance_of(Enumerator)
- enum.each { |k, v| k == "foo" }.should equal(ENV)
+ enum.should.instance_of?(Enumerator)
+ enum.each { |k, v| k == "foo" }.should.equal?(ENV)
ENV["foo"].should == nil
end
@@ -41,7 +41,7 @@ describe "ENV.reject!" do
orig = ENV.to_hash
begin
ENV.clear
- -> { ENV.reject! }.should_not raise_error(LocalJumpError)
+ -> { ENV.reject! }.should_not.raise(LocalJumpError)
ensure
ENV.replace orig
end
@@ -76,13 +76,13 @@ describe "ENV.reject" do
end
it "returns a Hash" do
- ENV.reject { false }.should be_kind_of(Hash)
+ ENV.reject { false }.should.is_a?(Hash)
end
it "returns an Enumerator if called without a block" do
ENV["foo"] = "bar"
enum = ENV.reject
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.each { |k, v| k == "foo"}
ENV["foo"] = nil
end
@@ -91,7 +91,7 @@ describe "ENV.reject" do
orig = ENV.to_hash
begin
ENV.clear
- -> { ENV.reject }.should_not raise_error(LocalJumpError)
+ -> { ENV.reject }.should_not.raise(LocalJumpError)
ensure
ENV.replace orig
end
diff --git a/spec/ruby/core/env/replace_spec.rb b/spec/ruby/core/env/replace_spec.rb
index 9fc67643d1..27eb3e45dd 100644
--- a/spec/ruby/core/env/replace_spec.rb
+++ b/spec/ruby/core/env/replace_spec.rb
@@ -11,41 +11,41 @@ describe "ENV.replace" do
end
it "replaces ENV with a Hash" do
- ENV.replace("foo" => "0", "bar" => "1").should equal(ENV)
+ ENV.replace("foo" => "0", "bar" => "1").should.equal?(ENV)
ENV.size.should == 2
ENV["foo"].should == "0"
ENV["bar"].should == "1"
end
it "raises TypeError if the argument is not a Hash" do
- -> { ENV.replace(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into Hash")
+ -> { ENV.replace(Object.new) }.should.raise(TypeError, "no implicit conversion of Object into Hash")
ENV.to_hash.should == @orig
end
it "raises TypeError if a key is not a String" do
- -> { ENV.replace(Object.new => "0") }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.replace(Object.new => "0") }.should.raise(TypeError, "no implicit conversion of Object into String")
ENV.to_hash.should == @orig
end
it "raises TypeError if a value is not a String" do
- -> { ENV.replace("foo" => Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.replace("foo" => Object.new) }.should.raise(TypeError, "no implicit conversion of Object into String")
ENV.to_hash.should == @orig
end
it "raises Errno::EINVAL when the key contains the '=' character" do
- -> { ENV.replace("foo=" =>"bar") }.should raise_error(Errno::EINVAL)
+ -> { ENV.replace("foo=" =>"bar") }.should.raise(Errno::EINVAL)
end
it "raises Errno::EINVAL when the key is an empty string" do
- -> { ENV.replace("" => "bar") }.should raise_error(Errno::EINVAL)
+ -> { ENV.replace("" => "bar") }.should.raise(Errno::EINVAL)
end
it "does not accept good data preceding an error" do
- -> { ENV.replace("foo" => "1", Object.new => Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.replace("foo" => "1", Object.new => Object.new) }.should.raise(TypeError, "no implicit conversion of Object into String")
end
it "does not accept good data following an error" do
- -> { ENV.replace(Object.new => Object.new, "foo" => "0") }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.replace(Object.new => Object.new, "foo" => "0") }.should.raise(TypeError, "no implicit conversion of Object into String")
ENV.to_hash.should == @orig
end
end
diff --git a/spec/ruby/core/env/shared/each.rb b/spec/ruby/core/env/shared/each.rb
index d901b854c4..0661ca924c 100644
--- a/spec/ruby/core/env/shared/each.rb
+++ b/spec/ruby/core/env/shared/each.rb
@@ -8,9 +8,9 @@ describe :env_each, shared: true do
ENV.clear
ENV["foo"] = "bar"
ENV["baz"] = "boo"
- ENV.send(@method) { |k, v| e << [k, v] }.should equal(ENV)
- e.should include(["foo", "bar"])
- e.should include(["baz", "boo"])
+ ENV.send(@method) { |k, v| e << [k, v] }.should.equal?(ENV)
+ e.should.include?(["foo", "bar"])
+ e.should.include?(["baz", "boo"])
ensure
ENV.replace orig
end
@@ -18,7 +18,7 @@ describe :env_each, shared: true do
it "returns an Enumerator if called without a block" do
enum = ENV.send(@method)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.each do |name, value|
ENV[name].should == value
end
@@ -55,9 +55,9 @@ describe :env_each, shared: true do
Encoding.default_internal = internal = Encoding::IBM437
ENV.send(@method) do |key, value|
- key.encoding.should equal(internal)
+ key.encoding.should.equal?(internal)
if value.ascii_only?
- value.encoding.should equal(internal)
+ value.encoding.should.equal?(internal)
end
end
end
diff --git a/spec/ruby/core/env/shared/include.rb b/spec/ruby/core/env/shared/include.rb
index 3efcd523d6..ceca02e3eb 100644
--- a/spec/ruby/core/env/shared/include.rb
+++ b/spec/ruby/core/env/shared/include.rb
@@ -17,7 +17,14 @@ describe :env_include, shared: true do
ENV.send(@method, "foo").should == false
end
+ it "coerces the key with #to_str" do
+ ENV["foo"] = "bar"
+ k = mock('key')
+ k.should_receive(:to_str).and_return("foo")
+ ENV.send(@method, k).should == true
+ end
+
it "raises TypeError if the argument is not a String and does not respond to #to_str" do
- -> { ENV.send(@method, Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.send(@method, Object.new) }.should.raise(TypeError, "no implicit conversion of Object into String")
end
end
diff --git a/spec/ruby/core/env/shared/key.rb b/spec/ruby/core/env/shared/key.rb
deleted file mode 100644
index 93396d2aca..0000000000
--- a/spec/ruby/core/env/shared/key.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-describe :env_key, shared: true do
- before :each do
- @saved_foo = ENV["foo"]
- end
-
- after :each do
- ENV["foo"] = @saved_foo
- end
-
- it "returns the index associated with the passed value" do
- ENV["foo"] = "bar"
- suppress_warning {
- ENV.send(@method, "bar").should == "foo"
- }
- end
-
- it "returns nil if the passed value is not found" do
- ENV.delete("foo")
- suppress_warning {
- ENV.send(@method, "foo").should be_nil
- }
- end
-
- it "raises TypeError if the argument is not a String and does not respond to #to_str" do
- -> {
- suppress_warning {
- ENV.send(@method, Object.new)
- }
- }.should raise_error(TypeError, "no implicit conversion of Object into String")
- end
-end
diff --git a/spec/ruby/core/env/shared/select.rb b/spec/ruby/core/env/shared/select.rb
index 75ba112a32..8ec648a637 100644
--- a/spec/ruby/core/env/shared/select.rb
+++ b/spec/ruby/core/env/shared/select.rb
@@ -14,7 +14,7 @@ describe :env_select, shared: true do
it "returns an Enumerator when no block is given" do
enum = ENV.send(@method)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
end
it "selects via the enumerator" do
@@ -49,7 +49,7 @@ describe :env_select!, shared: true do
end
it "returns an Enumerator if called without a block" do
- ENV.send(@method).should be_an_instance_of(Enumerator)
+ ENV.send(@method).should.instance_of?(Enumerator)
end
it "selects via the enumerator" do
diff --git a/spec/ruby/core/env/shared/store.rb b/spec/ruby/core/env/shared/store.rb
index d6265c66a5..388208a8ac 100644
--- a/spec/ruby/core/env/shared/store.rb
+++ b/spec/ruby/core/env/shared/store.rb
@@ -14,13 +14,13 @@ describe :env_store, shared: true do
it "returns the value" do
value = "bar"
- ENV.send(@method, "foo", value).should equal(value)
+ ENV.send(@method, "foo", value).should.equal?(value)
end
it "deletes the environment variable when the value is nil" do
ENV["foo"] = "bar"
ENV.send(@method, "foo", nil)
- ENV.key?("foo").should be_false
+ ENV.key?("foo").should == false
end
it "coerces the key argument with #to_str" do
@@ -38,23 +38,23 @@ describe :env_store, shared: true do
end
it "raises TypeError when the key is not coercible to String" do
- -> { ENV.send(@method, Object.new, "bar") }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.send(@method, Object.new, "bar") }.should.raise(TypeError, "no implicit conversion of Object into String")
end
it "raises TypeError when the value is not coercible to String" do
- -> { ENV.send(@method, "foo", Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.send(@method, "foo", Object.new) }.should.raise(TypeError, "no implicit conversion of Object into String")
end
it "raises Errno::EINVAL when the key contains the '=' character" do
- -> { ENV.send(@method, "foo=", "bar") }.should raise_error(Errno::EINVAL)
+ -> { ENV.send(@method, "foo=", "bar") }.should.raise(Errno::EINVAL)
end
it "raises Errno::EINVAL when the key is an empty string" do
- -> { ENV.send(@method, "", "bar") }.should raise_error(Errno::EINVAL)
+ -> { ENV.send(@method, "", "bar") }.should.raise(Errno::EINVAL)
end
it "does nothing when the key is not a valid environment variable key and the value is nil" do
ENV.send(@method, "foo=", nil)
- ENV.key?("foo=").should be_false
+ ENV.key?("foo=").should == false
end
end
diff --git a/spec/ruby/core/env/shared/to_hash.rb b/spec/ruby/core/env/shared/to_hash.rb
index a0d4d7ce69..7868690c38 100644
--- a/spec/ruby/core/env/shared/to_hash.rb
+++ b/spec/ruby/core/env/shared/to_hash.rb
@@ -10,7 +10,7 @@ describe :env_to_hash, shared: true do
it "returns the ENV as a hash" do
ENV["foo"] = "bar"
h = ENV.send(@method)
- h.should be_an_instance_of(Hash)
+ h.should.instance_of?(Hash)
h["foo"].should == "bar"
end
@@ -24,7 +24,7 @@ describe :env_to_hash, shared: true do
it "duplicates the ENV when converting to a Hash" do
h = ENV.send(@method)
- h.should_not equal ENV
+ h.should_not.equal? ENV
h.size.should == ENV.size
h.each_pair do |k, v|
ENV[k].should == v
diff --git a/spec/ruby/core/env/shared/update.rb b/spec/ruby/core/env/shared/update.rb
index 3101f9c561..112cc2505d 100644
--- a/spec/ruby/core/env/shared/update.rb
+++ b/spec/ruby/core/env/shared/update.rb
@@ -10,22 +10,19 @@ describe :env_update, shared: true do
end
it "adds the parameter hash to ENV, returning ENV" do
- ENV.send(@method, "foo" => "0", "bar" => "1").should equal(ENV)
+ ENV.send(@method, "foo" => "0", "bar" => "1").should.equal?(ENV)
ENV["foo"].should == "0"
ENV["bar"].should == "1"
end
- ruby_version_is "3.2" do
- it "adds the multiple parameter hashes to ENV, returning ENV" do
- ENV.send(@method, {"foo" => "0", "bar" => "1"}, {"baz" => "2"}).should equal(ENV)
- ENV["foo"].should == "0"
- ENV["bar"].should == "1"
- ENV["baz"].should == "2"
- end
+ it "adds the multiple parameter hashes to ENV, returning ENV" do
+ ENV.send(@method, {"foo" => "multi1"}, {"bar" => "multi2"}).should.equal?(ENV)
+ ENV["foo"].should == "multi1"
+ ENV["bar"].should == "multi2"
end
it "returns ENV when no block given" do
- ENV.send(@method, {"foo" => "0", "bar" => "1"}).should equal(ENV)
+ ENV.send(@method, {"foo" => "0", "bar" => "1"}).should.equal?(ENV)
end
it "yields key, the old value and the new value when replacing an entry" do
@@ -66,23 +63,23 @@ describe :env_update, shared: true do
end
it "returns ENV when block given" do
- ENV.send(@method, {"foo" => "0", "bar" => "1"}){}.should equal(ENV)
+ ENV.send(@method, {"foo" => "0", "bar" => "1"}){}.should.equal?(ENV)
end
it "raises TypeError when a name is not coercible to String" do
- -> { ENV.send @method, Object.new => "0" }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.send @method, Object.new => "0" }.should.raise(TypeError, "no implicit conversion of Object into String")
end
it "raises TypeError when a value is not coercible to String" do
- -> { ENV.send @method, "foo" => Object.new }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.send @method, "foo" => Object.new }.should.raise(TypeError, "no implicit conversion of Object into String")
end
it "raises Errno::EINVAL when a name contains the '=' character" do
- -> { ENV.send(@method, "foo=" => "bar") }.should raise_error(Errno::EINVAL)
+ -> { ENV.send(@method, "foo=" => "bar") }.should.raise(Errno::EINVAL)
end
it "raises Errno::EINVAL when a name is an empty string" do
- -> { ENV.send(@method, "" => "bar") }.should raise_error(Errno::EINVAL)
+ -> { ENV.send(@method, "" => "bar") }.should.raise(Errno::EINVAL)
end
it "updates good data preceding an error" do
diff --git a/spec/ruby/core/env/shared/value.rb b/spec/ruby/core/env/shared/value.rb
index bef96b5fef..c2b5025465 100644
--- a/spec/ruby/core/env/shared/value.rb
+++ b/spec/ruby/core/env/shared/value.rb
@@ -16,6 +16,13 @@ describe :env_value, shared: true do
ENV.send(@method, "foo").should == false
end
+ it "coerces the value element with #to_str" do
+ ENV["foo"] = "bar"
+ v = mock('value')
+ v.should_receive(:to_str).and_return("bar")
+ ENV.send(@method, v).should == true
+ end
+
it "returns nil if the argument is not a String and does not respond to #to_str" do
ENV.send(@method, Object.new).should == nil
end
diff --git a/spec/ruby/core/env/shift_spec.rb b/spec/ruby/core/env/shift_spec.rb
index 1b92e5d1e4..52bd0f9139 100644
--- a/spec/ruby/core/env/shift_spec.rb
+++ b/spec/ruby/core/env/shift_spec.rb
@@ -33,15 +33,15 @@ describe "ENV.shift" do
Encoding.default_internal = nil
pair = ENV.shift
- pair.first.encoding.should equal(ENVSpecs.encoding)
- pair.last.encoding.should equal(ENVSpecs.encoding)
+ pair.first.encoding.should.equal?(ENVSpecs.encoding)
+ pair.last.encoding.should.equal?(ENVSpecs.encoding)
end
it "transcodes from the locale encoding to Encoding.default_internal if set" do
Encoding.default_internal = Encoding::IBM437
pair = ENV.shift
- pair.first.encoding.should equal(Encoding::IBM437)
- pair.last.encoding.should equal(Encoding::IBM437)
+ pair.first.encoding.should.equal?(Encoding::IBM437)
+ pair.last.encoding.should.equal?(Encoding::IBM437)
end
end
diff --git a/spec/ruby/core/env/size_spec.rb b/spec/ruby/core/env/size_spec.rb
index f050e9e5a9..7c8072481e 100644
--- a/spec/ruby/core/env/size_spec.rb
+++ b/spec/ruby/core/env/size_spec.rb
@@ -2,5 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/length'
describe "ENV.size" do
- it_behaves_like :env_length, :size
+ it_behaves_like :env_length, :size
end
diff --git a/spec/ruby/core/env/slice_spec.rb b/spec/ruby/core/env/slice_spec.rb
index e3b6020391..4c0416547d 100644
--- a/spec/ruby/core/env/slice_spec.rb
+++ b/spec/ruby/core/env/slice_spec.rb
@@ -21,7 +21,17 @@ describe "ENV.slice" do
ENV.slice("foo", "boo", "bar").should == {"foo" => "0", "bar" => "1"}
end
+ it "returns the values for the keys coerced with #to_str, but keeps the original objects as result keys" do
+ foo = mock('key 1')
+ foo.should_receive(:to_str).and_return("foo")
+ boo = mock('key 2')
+ boo.should_receive(:to_str).and_return("boo")
+ bar = mock('key 3')
+ bar.should_receive(:to_str).and_return("bar")
+ ENV.slice(foo, boo, bar).should == {foo => "0", bar => "1"}
+ end
+
it "raises TypeError if any argument is not a String and does not respond to #to_str" do
- -> { ENV.slice(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.slice(Object.new) }.should.raise(TypeError, "no implicit conversion of Object into String")
end
end
diff --git a/spec/ruby/core/env/to_a_spec.rb b/spec/ruby/core/env/to_a_spec.rb
index 39e3877b48..2b1649281f 100644
--- a/spec/ruby/core/env/to_a_spec.rb
+++ b/spec/ruby/core/env/to_a_spec.rb
@@ -6,7 +6,10 @@ describe "ENV.to_a" do
a = ENV.to_a
a.is_a?(Array).should == true
a.size.should == ENV.size
- ENV.each_pair { |k, v| a.should include([k, v])}
+ a.each { |k,v| ENV[k].should == v }
+
+ a.first.should.is_a?(Array)
+ a.first.size.should == 2
end
it "returns the entries in the locale encoding" do
diff --git a/spec/ruby/core/env/to_h_spec.rb b/spec/ruby/core/env/to_h_spec.rb
index 3c4a92aa57..7e0fef2120 100644
--- a/spec/ruby/core/env/to_h_spec.rb
+++ b/spec/ruby/core/env/to_h_spec.rb
@@ -18,6 +18,18 @@ describe "ENV.to_h" do
ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" }
end
+ it "passes to a block each pair's key and value as separate arguments" do
+ ENV.replace("a" => "b", "c" => "d")
+
+ ScratchPad.record []
+ ENV.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
+ ScratchPad.recorded.sort.should == [["a", "b"], ["c", "d"]]
+
+ ScratchPad.record []
+ ENV.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [["a", "b"], ["c", "d"]]
+ end
+
it "does not require the array elements to be strings" do
ENV.replace("a" => "b", "c" => "d")
ENV.to_h { |k, v| [k.to_sym, v.to_sym] }.should == { :a => :b, :c => :d }
@@ -26,17 +38,17 @@ describe "ENV.to_h" do
it "raises ArgumentError if block returns longer or shorter array" do
-> do
ENV.to_h { |k, v| [k, v.upcase, 1] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
+ end.should.raise(ArgumentError, /element has wrong array length/)
-> do
ENV.to_h { |k, v| [k] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
+ end.should.raise(ArgumentError, /element has wrong array length/)
end
it "raises TypeError if block returns something other than Array" do
-> do
ENV.to_h { |k, v| "not-array" }
- end.should raise_error(TypeError, /wrong element type String/)
+ end.should.raise(TypeError, /wrong element type String/)
end
it "coerces returned pair to Array with #to_ary" do
@@ -52,7 +64,7 @@ describe "ENV.to_h" do
-> do
ENV.to_h { |k| x }
- end.should raise_error(TypeError, /wrong element type MockObject/)
+ end.should.raise(TypeError, /wrong element type MockObject/)
end
end
end
diff --git a/spec/ruby/core/env/values_at_spec.rb b/spec/ruby/core/env/values_at_spec.rb
index 338680e820..4a733f4ed5 100644
--- a/spec/ruby/core/env/values_at_spec.rb
+++ b/spec/ruby/core/env/values_at_spec.rb
@@ -33,6 +33,6 @@ describe "ENV.values_at" do
end
it "raises TypeError when a key is not coercible to String" do
- -> { ENV.values_at("foo", Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> { ENV.values_at("foo", Object.new) }.should.raise(TypeError, "no implicit conversion of Object into String")
end
end
diff --git a/spec/ruby/core/exception/backtrace_locations_spec.rb b/spec/ruby/core/exception/backtrace_locations_spec.rb
index 86eb9d3413..62eab8a0f3 100644
--- a/spec/ruby/core/exception/backtrace_locations_spec.rb
+++ b/spec/ruby/core/exception/backtrace_locations_spec.rb
@@ -7,15 +7,15 @@ describe "Exception#backtrace_locations" do
end
it "returns nil if no backtrace was set" do
- Exception.new.backtrace_locations.should be_nil
+ Exception.new.backtrace_locations.should == nil
end
it "returns an Array" do
- @backtrace.should be_an_instance_of(Array)
+ @backtrace.should.instance_of?(Array)
end
it "sets each element to a Thread::Backtrace::Location" do
- @backtrace.each {|l| l.should be_an_instance_of(Thread::Backtrace::Location)}
+ @backtrace.each {|l| l.should.instance_of?(Thread::Backtrace::Location)}
end
it "produces a backtrace for an exception captured using $!" do
diff --git a/spec/ruby/core/exception/backtrace_spec.rb b/spec/ruby/core/exception/backtrace_spec.rb
index 3f74c4cefe..a4a8272030 100644
--- a/spec/ruby/core/exception/backtrace_spec.rb
+++ b/spec/ruby/core/exception/backtrace_spec.rb
@@ -7,15 +7,15 @@ describe "Exception#backtrace" do
end
it "returns nil if no backtrace was set" do
- Exception.new.backtrace.should be_nil
+ Exception.new.backtrace.should == nil
end
it "returns an Array" do
- @backtrace.should be_an_instance_of(Array)
+ @backtrace.should.instance_of?(Array)
end
it "sets each element to a String" do
- @backtrace.each {|l| l.should be_an_instance_of(String)}
+ @backtrace.each {|l| l.should.instance_of?(String)}
end
it "includes the filename of the location where self raised in the first element" do
@@ -27,7 +27,7 @@ describe "Exception#backtrace" do
end
it "includes the name of the method from where self raised in the first element" do
- @backtrace.first.should =~ /in `backtrace'/
+ @backtrace.first.should =~ /in [`'](?:ExceptionSpecs::Backtrace\.)?backtrace'/
end
it "includes the filename of the location immediately prior to where self raised in the second element" do
@@ -38,12 +38,25 @@ describe "Exception#backtrace" do
@backtrace[1].should =~ /:6(:in )?/
end
- it "contains lines of the same format for each prior position in the stack" do
- @backtrace[2..-1].each do |line|
- # This regexp is deliberately imprecise to account for the need to abstract out
- # the paths of the included mspec files and the desire to avoid specifying in any
- # detail what the in `...' portion looks like.
- line.should =~ /^.+:\d+:in `[^`]+'$/
+ ruby_version_is ""..."3.4" do
+ it "contains lines of the same format for each prior position in the stack" do
+ @backtrace[2..-1].each do |line|
+ # This regexp is deliberately imprecise to account for the need to abstract out
+ # the paths of the included mspec files and the desire to avoid specifying in any
+ # detail what the in `...' portion looks like.
+ line.should =~ /^.+:\d+:in `[^`]+'$/
+ end
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "contains lines of the same format for each prior position in the stack" do
+ @backtrace[2..-1].each do |line|
+ # This regexp is deliberately imprecise to account for the need to abstract out
+ # the paths of the included mspec files and the desire to avoid specifying in any
+ # detail what the in '...' portion looks like.
+ line.should =~ /^.+:\d+:in '[^`]+'$/
+ end
end
end
@@ -81,13 +94,13 @@ describe "Exception#backtrace" do
raise
rescue RuntimeError => err
bt = err.backtrace
- err.dup.backtrace.should equal(bt)
+ err.dup.backtrace.should.equal?(bt)
new_bt = ['hi']
err.set_backtrace new_bt
err.backtrace.should == new_bt
- err.dup.backtrace.should equal(new_bt)
+ err.dup.backtrace.should.equal?(new_bt)
end
end
end
diff --git a/spec/ruby/core/exception/case_compare_spec.rb b/spec/ruby/core/exception/case_compare_spec.rb
index 87b9dee3ca..5fd11ae741 100644
--- a/spec/ruby/core/exception/case_compare_spec.rb
+++ b/spec/ruby/core/exception/case_compare_spec.rb
@@ -26,13 +26,11 @@ describe "SystemCallError.===" do
end
it "returns true if receiver is generic and arg is kind of SystemCallError" do
- unknown_error_number = Errno.constants.size
e = SystemCallError.new('foo', @example_errno)
SystemCallError.===(e).should == true
end
it "returns false if receiver is generic and arg is not kind of SystemCallError" do
- unknown_error_number = Errno.constants.size
e = Object.new
SystemCallError.===(e).should == false
end
diff --git a/spec/ruby/core/exception/cause_spec.rb b/spec/ruby/core/exception/cause_spec.rb
index cf4aaeb188..cfc15bdda3 100644
--- a/spec/ruby/core/exception/cause_spec.rb
+++ b/spec/ruby/core/exception/cause_spec.rb
@@ -4,53 +4,35 @@ describe "Exception#cause" do
it "returns the active exception when an exception is raised" do
begin
raise Exception, "the cause"
- rescue Exception
- begin
+ rescue Exception => cause
+ -> {
raise RuntimeError, "the consequence"
- rescue RuntimeError => e
- e.should be_an_instance_of(RuntimeError)
- e.message.should == "the consequence"
-
- e.cause.should be_an_instance_of(Exception)
- e.cause.message.should == "the cause"
- end
+ }.should.raise(RuntimeError, "the consequence", cause:)
end
end
it "is set for user errors caused by internal errors" do
- -> {
- begin
- 1 / 0
- rescue
- raise "foo"
- end
- }.should raise_error(RuntimeError) { |e|
- e.cause.should be_kind_of(ZeroDivisionError)
- }
+ begin
+ 1 / 0
+ rescue => cause
+ -> { raise "foo" }.should.raise(RuntimeError, cause:)
+ end
end
it "is set for internal errors caused by user errors" do
cause = RuntimeError.new "cause"
- -> {
- begin
- raise cause
- rescue
- 1 / 0
- end
- }.should raise_error(ZeroDivisionError) { |e|
- e.cause.should equal(cause)
- }
+ begin
+ raise cause
+ rescue
+ -> { 1 / 0 }.should.raise(ZeroDivisionError, cause:)
+ end
end
it "is not set to the exception itself when it is re-raised" do
- -> {
- begin
- raise RuntimeError
- rescue RuntimeError => e
- raise e
- end
- }.should raise_error(RuntimeError) { |e|
- e.cause.should == nil
- }
+ begin
+ raise RuntimeError
+ rescue RuntimeError => e
+ -> { raise e }.should.raise(RuntimeError, cause: nil)
+ end
end
end
diff --git a/spec/ruby/core/exception/detailed_message_spec.rb b/spec/ruby/core/exception/detailed_message_spec.rb
new file mode 100644
index 0000000000..9df164a1cf
--- /dev/null
+++ b/spec/ruby/core/exception/detailed_message_spec.rb
@@ -0,0 +1,50 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
+
+describe "Exception#detailed_message" do
+ it "returns decorated message" do
+ RuntimeError.new("new error").detailed_message.should == "new error (RuntimeError)"
+ end
+
+ it "is called by #full_message to allow message customization" do
+ exception = Exception.new("new error")
+ def exception.detailed_message(**)
+ "<prefix>#{message}<suffix>"
+ end
+ exception.full_message(highlight: false).should.include? "<prefix>new error<suffix>"
+ end
+
+ it "returns just a message if exception class is anonymous" do
+ Class.new(RuntimeError).new("message").detailed_message.should == "message"
+ end
+
+ it "returns 'unhandled exception' for an instance of RuntimeError with empty message" do
+ RuntimeError.new("").detailed_message.should == "unhandled exception"
+ end
+
+ it "returns just class name for an instance other than RuntimeError with empty message" do
+ DetailedMessageSpec::C.new("").detailed_message.should == "DetailedMessageSpec::C"
+ StandardError.new("").detailed_message.should == "StandardError"
+ end
+
+ it "returns a generated class name for an instance of RuntimeError anonymous subclass with empty message" do
+ klass = Class.new(RuntimeError)
+ klass.new("").detailed_message.should =~ /\A#<Class:0x\h+>\z/
+ end
+
+ it "accepts highlight keyword argument and adds escape control sequences" do
+ RuntimeError.new("new error").detailed_message(highlight: true).should == "\e[1mnew error (\e[1;4mRuntimeError\e[m\e[1m)\e[m"
+ end
+
+ it "accepts highlight keyword argument and adds escape control sequences for an instance of RuntimeError with empty message" do
+ RuntimeError.new("").detailed_message(highlight: true).should == "\e[1;4munhandled exception\e[m"
+ end
+
+ it "accepts highlight keyword argument and adds escape control sequences for an instance other than RuntimeError with empty message" do
+ StandardError.new("").detailed_message(highlight: true).should == "\e[1;4mStandardError\e[m"
+ end
+
+ it "allows and ignores other keyword arguments" do
+ RuntimeError.new("new error").detailed_message(foo: true).should == "new error (RuntimeError)"
+ end
+end
diff --git a/spec/ruby/core/exception/dup_spec.rb b/spec/ruby/core/exception/dup_spec.rb
index edd54bfb37..b53ad79bf3 100644
--- a/spec/ruby/core/exception/dup_spec.rb
+++ b/spec/ruby/core/exception/dup_spec.rb
@@ -20,7 +20,7 @@ describe "Exception#dup" do
it "does not copy singleton methods" do
def @obj.special() :the_one end
dup = @obj.dup
- -> { dup.special }.should raise_error(NameError)
+ -> { dup.special }.should.raise(NameError)
end
it "does not copy modules included in the singleton class" do
@@ -29,7 +29,7 @@ describe "Exception#dup" do
end
dup = @obj.dup
- -> { dup.repr }.should raise_error(NameError)
+ -> { dup.repr }.should.raise(NameError)
end
it "does not copy constants defined in the singleton class" do
@@ -38,7 +38,7 @@ describe "Exception#dup" do
end
dup = @obj.dup
- -> { class << dup; CLONE; end }.should raise_error(NameError)
+ -> { class << dup; CLONE; end }.should.raise(NameError)
end
it "does copy the message" do
@@ -61,13 +61,13 @@ describe "Exception#dup" do
it "does copy the cause" do
begin
- raise StandardError, "the cause"
+ raise StandardError
rescue StandardError => cause
begin
- raise RuntimeError, "the consequence"
+ raise RuntimeError
rescue RuntimeError => e
- e.cause.should equal(cause)
- e.dup.cause.should equal(cause)
+ e.cause.should.equal?(cause)
+ e.dup.cause.should.equal?(cause)
end
end
end
diff --git a/spec/ruby/core/exception/equal_value_spec.rb b/spec/ruby/core/exception/equal_value_spec.rb
index 7f2065511a..b76b3bcd4a 100644
--- a/spec/ruby/core/exception/equal_value_spec.rb
+++ b/spec/ruby/core/exception/equal_value_spec.rb
@@ -22,19 +22,19 @@ describe "Exception#==" do
it "returns true if both exceptions have the same class, the same message, and the same backtrace" do
one = TypeError.new("message")
- one.set_backtrace [File.dirname(__FILE__)]
+ one.set_backtrace [__dir__]
two = TypeError.new("message")
- two.set_backtrace [File.dirname(__FILE__)]
+ two.set_backtrace [__dir__]
one.should == two
end
it "returns false if the two exceptions inherit from Exception but have different classes" do
one = RuntimeError.new("message")
- one.set_backtrace [File.dirname(__FILE__)]
- one.should be_kind_of(Exception)
+ one.set_backtrace [__dir__]
+ one.should.is_a?(Exception)
two = TypeError.new("message")
- two.set_backtrace [File.dirname(__FILE__)]
- two.should be_kind_of(Exception)
+ two.set_backtrace [__dir__]
+ two.should.is_a?(Exception)
one.should_not == two
end
@@ -52,7 +52,7 @@ describe "Exception#==" do
it "returns false if the two exceptions differ only in their backtrace" do
one = RuntimeError.new("message")
- one.set_backtrace [File.dirname(__FILE__)]
+ one.set_backtrace [__dir__]
two = RuntimeError.new("message")
two.set_backtrace nil
one.should_not == two
@@ -60,9 +60,9 @@ describe "Exception#==" do
it "returns false if the two exceptions differ only in their message" do
one = RuntimeError.new("message")
- one.set_backtrace [File.dirname(__FILE__)]
+ one.set_backtrace [__dir__]
two = RuntimeError.new("message2")
- two.set_backtrace [File.dirname(__FILE__)]
+ two.set_backtrace [__dir__]
one.should_not == two
end
end
diff --git a/spec/ruby/core/exception/errno_spec.rb b/spec/ruby/core/exception/errno_spec.rb
index a063e522ea..36beae9976 100644
--- a/spec/ruby/core/exception/errno_spec.rb
+++ b/spec/ruby/core/exception/errno_spec.rb
@@ -4,21 +4,21 @@ require_relative 'fixtures/common'
describe "Errno::EINVAL.new" do
it "can be called with no arguments" do
exc = Errno::EINVAL.new
- exc.should be_an_instance_of(Errno::EINVAL)
+ exc.should.instance_of?(Errno::EINVAL)
exc.errno.should == Errno::EINVAL::Errno
exc.message.should == "Invalid argument"
end
it "accepts an optional custom message" do
exc = Errno::EINVAL.new('custom message')
- exc.should be_an_instance_of(Errno::EINVAL)
+ exc.should.instance_of?(Errno::EINVAL)
exc.errno.should == Errno::EINVAL::Errno
exc.message.should == "Invalid argument - custom message"
end
it "accepts an optional custom message and location" do
exc = Errno::EINVAL.new('custom message', 'location')
- exc.should be_an_instance_of(Errno::EINVAL)
+ exc.should.instance_of?(Errno::EINVAL)
exc.errno.should == Errno::EINVAL::Errno
exc.message.should == "Invalid argument @ location - custom message"
end
@@ -28,7 +28,9 @@ describe "Errno::EMFILE" do
it "can be subclassed" do
ExceptionSpecs::EMFILESub = Class.new(Errno::EMFILE)
exc = ExceptionSpecs::EMFILESub.new
- exc.should be_an_instance_of(ExceptionSpecs::EMFILESub)
+ exc.should.instance_of?(ExceptionSpecs::EMFILESub)
+ ensure
+ ExceptionSpecs.send(:remove_const, :EMFILESub)
end
end
@@ -45,7 +47,7 @@ end
describe "Errno::ENOTSUP" do
it "is defined" do
- Errno.should have_constant(:ENOTSUP)
+ Errno.should.const_defined?(:ENOTSUP, false)
end
it "is the same class as Errno::EOPNOTSUPP if they represent the same errno value" do
diff --git a/spec/ruby/core/exception/exception_spec.rb b/spec/ruby/core/exception/exception_spec.rb
index d6f5283bd9..f5424cdabd 100644
--- a/spec/ruby/core/exception/exception_spec.rb
+++ b/spec/ruby/core/exception/exception_spec.rb
@@ -20,7 +20,7 @@ describe "Exception#exception" do
it "returns an exception of the same class as self with the message given as argument" do
e = RuntimeError.new
e2 = e.exception("message")
- e2.should be_an_instance_of(RuntimeError)
+ e2.should.instance_of?(RuntimeError)
e2.message.should == "message"
end
@@ -62,7 +62,7 @@ describe "Exception#exception" do
it "returns an exception of the same class as self with the message given as argument, but without reinitializing" do
e = CustomArgumentError.new(:boom)
e2 = e.exception("message")
- e2.should be_an_instance_of(CustomArgumentError)
+ e2.should.instance_of?(CustomArgumentError)
e2.val.should == :boom
e2.message.should == "message"
end
diff --git a/spec/ruby/core/exception/exit_value_spec.rb b/spec/ruby/core/exception/exit_value_spec.rb
index 99987dd1bc..bb6cff1831 100644
--- a/spec/ruby/core/exception/exit_value_spec.rb
+++ b/spec/ruby/core/exception/exit_value_spec.rb
@@ -6,7 +6,7 @@ describe "LocalJumpError#exit_value" do
end
it "returns the value given to return" do
- -> { get_me_a_return.call }.should raise_error(LocalJumpError) { |e|
+ -> { get_me_a_return.call }.should.raise(LocalJumpError) { |e|
e.exit_value.should == 42
}
end
diff --git a/spec/ruby/core/exception/fixtures/common.rb b/spec/ruby/core/exception/fixtures/common.rb
index 0ffb3ed855..3d8a3c3430 100644
--- a/spec/ruby/core/exception/fixtures/common.rb
+++ b/spec/ruby/core/exception/fixtures/common.rb
@@ -84,6 +84,9 @@ module NoMethodErrorSpecs
class InstanceException < Exception
end
+
+ class AClass; end
+ module AModule; end
end
class NameErrorSpecs
@@ -93,3 +96,7 @@ class NameErrorSpecs
end
end
end
+
+module DetailedMessageSpec
+ C = Class.new(RuntimeError)
+end
diff --git a/spec/ruby/core/exception/fixtures/syntax_error.rb b/spec/ruby/core/exception/fixtures/syntax_error.rb
new file mode 100644
index 0000000000..ccec62f7a1
--- /dev/null
+++ b/spec/ruby/core/exception/fixtures/syntax_error.rb
@@ -0,0 +1,3 @@
+# rubocop:disable Lint/Syntax
+1+1=2
+# rubocop:enable Lint/Syntax
diff --git a/spec/ruby/core/exception/fixtures/thread_fiber_ensure.rb b/spec/ruby/core/exception/fixtures/thread_fiber_ensure.rb
new file mode 100644
index 0000000000..c109ec6247
--- /dev/null
+++ b/spec/ruby/core/exception/fixtures/thread_fiber_ensure.rb
@@ -0,0 +1,22 @@
+ready = false
+t = Thread.new do
+ f = Fiber.new do
+ begin
+ Fiber.yield
+ ensure
+ STDERR.puts "suspended fiber ensure"
+ end
+ end
+ f.resume
+
+ begin
+ ready = true
+ sleep
+ ensure
+ STDERR.puts "current fiber ensure"
+ end
+end
+
+Thread.pass until ready && t.stop?
+
+# let the program end, it's the same as #exit or an exception for this behavior
diff --git a/spec/ruby/core/exception/fixtures/thread_fiber_ensure_non_root_fiber.rb b/spec/ruby/core/exception/fixtures/thread_fiber_ensure_non_root_fiber.rb
new file mode 100644
index 0000000000..3364ed06d0
--- /dev/null
+++ b/spec/ruby/core/exception/fixtures/thread_fiber_ensure_non_root_fiber.rb
@@ -0,0 +1,25 @@
+ready = false
+t = Thread.new do
+ f = Fiber.new do
+ begin
+ Fiber.yield
+ ensure
+ STDERR.puts "suspended fiber ensure"
+ end
+ end
+ f.resume
+
+ f2 = Fiber.new do
+ begin
+ ready = true
+ sleep
+ ensure
+ STDERR.puts "current fiber ensure"
+ end
+ end
+ f2.resume
+end
+
+Thread.pass until ready && t.stop?
+
+# let the program end, it's the same as #exit or an exception for this behavior
diff --git a/spec/ruby/core/exception/frozen_error_spec.rb b/spec/ruby/core/exception/frozen_error_spec.rb
index 2efdc239d8..a28f524b54 100644
--- a/spec/ruby/core/exception/frozen_error_spec.rb
+++ b/spec/ruby/core/exception/frozen_error_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "FrozenError.new" do
it "should take optional receiver argument" do
o = Object.new
- FrozenError.new("msg", receiver: o).receiver.should equal(o)
+ FrozenError.new("msg", receiver: o).receiver.should.equal?(o)
end
end
@@ -13,10 +13,42 @@ describe "FrozenError#receiver" do
begin
def o.x; end
rescue => e
- e.should be_kind_of(FrozenError)
- e.receiver.should equal(o)
+ e.should.is_a?(FrozenError)
+ e.receiver.should.equal?(o)
else
raise
end
end
end
+
+describe "FrozenError#message" do
+ it "includes a receiver" do
+ object = Object.new
+ object.freeze
+
+ msg_class = ruby_version_is("4.0") ? "Object" : "object"
+
+ -> {
+ def object.x; end
+ }.should.raise(FrozenError, "can't modify frozen #{msg_class}: #{object}")
+
+ object = [].freeze
+ -> { object << nil }.should.raise(FrozenError, "can't modify frozen Array: []")
+ end
+end
+
+describe "Modifying a frozen object" do
+ context "#inspect is redefined and modifies the object" do
+ it "returns ... instead of String representation of object" do
+ object = Object.new
+ def object.inspect; @a = 1 end
+ def object.modify; @a = 2 end
+
+ object.freeze
+
+ # CRuby's message contains multiple whitespaces before '...'.
+ # So handle both multiple and single whitespace.
+ -> { object.modify }.should.raise(FrozenError, /can't modify frozen .*?: \s*.../)
+ end
+ end
+end
diff --git a/spec/ruby/core/exception/full_message_spec.rb b/spec/ruby/core/exception/full_message_spec.rb
index 9757a2f407..5a5e0a2b3a 100644
--- a/spec/ruby/core/exception/full_message_spec.rb
+++ b/spec/ruby/core/exception/full_message_spec.rb
@@ -6,10 +6,10 @@ describe "Exception#full_message" do
e.set_backtrace(["a.rb:1", "b.rb:2"])
full_message = e.full_message
- full_message.should include "RuntimeError"
- full_message.should include "Some runtime error"
- full_message.should include "a.rb:1"
- full_message.should include "b.rb:2"
+ full_message.should.include? "RuntimeError"
+ full_message.should.include? "Some runtime error"
+ full_message.should.include? "a.rb:1"
+ full_message.should.include? "b.rb:2"
end
it "supports :highlight option and adds escape sequences to highlight some strings" do
@@ -42,16 +42,77 @@ describe "Exception#full_message" do
e = RuntimeError.new("Some runtime error")
e.backtrace.should == nil
full_message = e.full_message(highlight: false, order: :top).lines
- full_message[0].should.start_with?("#{__FILE__}:#{__LINE__-1}:in `")
+ full_message[0].should.start_with?("#{__FILE__}:#{__LINE__-1}:in ")
full_message[0].should.end_with?("': Some runtime error (RuntimeError)\n")
end
+ describe "includes details about whether an exception was handled" do
+ describe "RuntimeError" do
+ it "should report as unhandled if message is empty" do
+ err = RuntimeError.new("")
+
+ err.full_message.should =~ /unhandled exception/
+ err.full_message(highlight: true).should =~ /unhandled exception/
+ err.full_message(highlight: false).should =~ /unhandled exception/
+ end
+
+ it "should not report as unhandled if the message is not empty" do
+ err = RuntimeError.new("non-empty")
+
+ err.full_message.should !~ /unhandled exception/
+ err.full_message(highlight: true).should !~ /unhandled exception/
+ err.full_message(highlight: false).should !~ /unhandled exception/
+ end
+
+ it "should not report as unhandled if the message is nil" do
+ err = RuntimeError.new(nil)
+
+ err.full_message.should !~ /unhandled exception/
+ err.full_message(highlight: true).should !~ /unhandled exception/
+ err.full_message(highlight: false).should !~ /unhandled exception/
+ end
+
+ it "should not report as unhandled if the message is not specified" do
+ err = RuntimeError.new()
+
+ err.full_message.should !~ /unhandled exception/
+ err.full_message(highlight: true).should !~ /unhandled exception/
+ err.full_message(highlight: false).should !~ /unhandled exception/
+ end
+
+ it "adds escape sequences to highlight some strings if the message is not specified and :highlight option is specified" do
+ e = RuntimeError.new("")
+
+ full_message = e.full_message(highlight: true, order: :top).lines
+ full_message[0].should.end_with? "\e[1;4munhandled exception\e[m\n"
+
+ full_message = e.full_message(highlight: true, order: :bottom).lines
+ full_message[0].should == "\e[1mTraceback\e[m (most recent call last):\n"
+ full_message[-1].should.end_with? "\e[1;4munhandled exception\e[m\n"
+
+ full_message = e.full_message(highlight: false, order: :top).lines
+ full_message[0].should.end_with? "unhandled exception\n"
+
+ full_message = e.full_message(highlight: false, order: :bottom).lines
+ full_message[0].should == "Traceback (most recent call last):\n"
+ full_message[-1].should.end_with? "unhandled exception\n"
+ end
+ end
+
+ describe "generic Error" do
+ it "should not report as unhandled in any event" do
+ StandardError.new("").full_message.should !~ /unhandled exception/
+ StandardError.new("non-empty").full_message.should !~ /unhandled exception/
+ end
+ end
+ end
+
it "shows the exception class at the end of the first line of the message when the message contains multiple lines" do
begin
line = __LINE__; raise "first line\nsecond line"
rescue => e
full_message = e.full_message(highlight: false, order: :top).lines
- full_message[0].should.start_with?("#{__FILE__}:#{line}:in `")
+ full_message[0].should.start_with?("#{__FILE__}:#{line}:in ")
full_message[0].should.end_with?(": first line (RuntimeError)\n")
full_message[1].should == "second line\n"
end
@@ -62,7 +123,7 @@ describe "Exception#full_message" do
line = __LINE__; raise "first line\nsecond line\nthird line"
rescue => e
full_message = e.full_message(highlight: true, order: :top).lines
- full_message[0].should.start_with?("#{__FILE__}:#{line}:in `")
+ full_message[0].should.start_with?("#{__FILE__}:#{line}:in ")
full_message[0].should.end_with?(": \e[1mfirst line (\e[1;4mRuntimeError\e[m\e[1m)\e[m\n")
full_message[1].should == "\e[1msecond line\e[m\n"
full_message[2].should == "\e[1mthird line\e[m\n"
@@ -80,8 +141,8 @@ describe "Exception#full_message" do
exception = e
end
- exception.full_message.should include "main exception"
- exception.full_message.should include "the cause"
+ exception.full_message.should.include? "main exception"
+ exception.full_message.should.include? "the cause"
end
it 'contains all the chain of exceptions' do
@@ -99,8 +160,67 @@ describe "Exception#full_message" do
exception = e
end
- exception.full_message.should include "last exception"
- exception.full_message.should include "intermediate exception"
- exception.full_message.should include "origin exception"
+ exception.full_message.should.include? "last exception"
+ exception.full_message.should.include? "intermediate exception"
+ exception.full_message.should.include? "origin exception"
+ end
+
+ it "relies on #detailed_message" do
+ e = RuntimeError.new("new error")
+ e.define_singleton_method(:detailed_message) { |**| "DETAILED MESSAGE" }
+
+ e.full_message.lines.first.should =~ /DETAILED MESSAGE/
+ end
+
+ it "passes all its own keyword arguments (with :highlight default value and without :order default value) to #detailed_message" do
+ e = RuntimeError.new("new error")
+ options_passed = nil
+ e.define_singleton_method(:detailed_message) do |**options|
+ options_passed = options
+ "DETAILED MESSAGE"
+ end
+
+ e.full_message(foo: "bar")
+ options_passed.should == { foo: "bar", highlight: Exception.to_tty? }
+ end
+
+ it "converts #detailed_message returned value to String if it isn't a String" do
+ message = Object.new
+ def message.to_str; "DETAILED MESSAGE"; end
+
+ e = RuntimeError.new("new error")
+ e.define_singleton_method(:detailed_message) { |**| message }
+
+ e.full_message.lines.first.should =~ /DETAILED MESSAGE/
+ end
+
+ it "uses class name if #detailed_message returns nil" do
+ e = RuntimeError.new("new error")
+ e.define_singleton_method(:detailed_message) { |**| nil }
+
+ e.full_message(highlight: false).lines.first.should =~ /RuntimeError/
+ e.full_message(highlight: true).lines.first.should =~ /#{Regexp.escape("\e[1;4mRuntimeError\e[m")}/
+ end
+
+ it "uses class name if exception object doesn't respond to #detailed_message" do
+ e = RuntimeError.new("new error")
+ class << e
+ undef :detailed_message
+ end
+
+ e.full_message(highlight: false).lines.first.should =~ /RuntimeError/
+ e.full_message(highlight: true).lines.first.should =~ /#{Regexp.escape("\e[1;4mRuntimeError\e[m")}/
+ end
+
+ it "allows cause with empty backtrace" do
+ begin
+ raise RuntimeError.new("Some runtime error"), cause: RuntimeError.new("Some other runtime error")
+ rescue => e
+ end
+
+ full_message = e.full_message
+ full_message.should.include? "RuntimeError"
+ full_message.should.include? "Some runtime error"
+ full_message.should.include? "Some other runtime error"
end
end
diff --git a/spec/ruby/core/exception/interrupt_spec.rb b/spec/ruby/core/exception/interrupt_spec.rb
index 299b5b81f3..90d261e470 100644
--- a/spec/ruby/core/exception/interrupt_spec.rb
+++ b/spec/ruby/core/exception/interrupt_spec.rb
@@ -54,7 +54,7 @@ describe "Interrupt" do
err = IO.popen([*ruby_exe, '-e', 'Process.kill :INT, Process.pid; sleep'], err: [:child, :out], &:read)
$?.termsig.should == Signal.list.fetch('INT')
err.should.include? ': Interrupt'
- err.should.include? "from -e:1:in `<main>'"
+ err.should =~ /from -e:1:in [`']<main>'/
end
end
end
diff --git a/spec/ruby/core/exception/io_error_spec.rb b/spec/ruby/core/exception/io_error_spec.rb
index ab8a72518f..940d5be876 100644
--- a/spec/ruby/core/exception/io_error_spec.rb
+++ b/spec/ruby/core/exception/io_error_spec.rb
@@ -3,14 +3,14 @@ require_relative '../../spec_helper'
describe "IO::EAGAINWaitReadable" do
it "combines Errno::EAGAIN and IO::WaitReadable" do
IO::EAGAINWaitReadable.superclass.should == Errno::EAGAIN
- IO::EAGAINWaitReadable.ancestors.should include IO::WaitReadable
+ IO::EAGAINWaitReadable.ancestors.should.include? IO::WaitReadable
end
it "is the same as IO::EWOULDBLOCKWaitReadable if Errno::EAGAIN is the same as Errno::EWOULDBLOCK" do
if Errno::EAGAIN.equal? Errno::EWOULDBLOCK
- IO::EAGAINWaitReadable.should equal IO::EWOULDBLOCKWaitReadable
+ IO::EAGAINWaitReadable.should.equal? IO::EWOULDBLOCKWaitReadable
else
- IO::EAGAINWaitReadable.should_not equal IO::EWOULDBLOCKWaitReadable
+ IO::EAGAINWaitReadable.should_not.equal? IO::EWOULDBLOCKWaitReadable
end
end
end
@@ -18,21 +18,21 @@ end
describe "IO::EWOULDBLOCKWaitReadable" do
it "combines Errno::EWOULDBLOCK and IO::WaitReadable" do
IO::EWOULDBLOCKWaitReadable.superclass.should == Errno::EWOULDBLOCK
- IO::EAGAINWaitReadable.ancestors.should include IO::WaitReadable
+ IO::EAGAINWaitReadable.ancestors.should.include? IO::WaitReadable
end
end
describe "IO::EAGAINWaitWritable" do
it "combines Errno::EAGAIN and IO::WaitWritable" do
IO::EAGAINWaitWritable.superclass.should == Errno::EAGAIN
- IO::EAGAINWaitWritable.ancestors.should include IO::WaitWritable
+ IO::EAGAINWaitWritable.ancestors.should.include? IO::WaitWritable
end
it "is the same as IO::EWOULDBLOCKWaitWritable if Errno::EAGAIN is the same as Errno::EWOULDBLOCK" do
if Errno::EAGAIN.equal? Errno::EWOULDBLOCK
- IO::EAGAINWaitWritable.should equal IO::EWOULDBLOCKWaitWritable
+ IO::EAGAINWaitWritable.should.equal? IO::EWOULDBLOCKWaitWritable
else
- IO::EAGAINWaitWritable.should_not equal IO::EWOULDBLOCKWaitWritable
+ IO::EAGAINWaitWritable.should_not.equal? IO::EWOULDBLOCKWaitWritable
end
end
end
@@ -40,6 +40,6 @@ end
describe "IO::EWOULDBLOCKWaitWritable" do
it "combines Errno::EWOULDBLOCK and IO::WaitWritable" do
IO::EWOULDBLOCKWaitWritable.superclass.should == Errno::EWOULDBLOCK
- IO::EAGAINWaitWritable.ancestors.should include IO::WaitWritable
+ IO::EAGAINWaitWritable.ancestors.should.include? IO::WaitWritable
end
end
diff --git a/spec/ruby/core/exception/name_spec.rb b/spec/ruby/core/exception/name_spec.rb
index c8a49b40e2..6e0e99d194 100644
--- a/spec/ruby/core/exception/name_spec.rb
+++ b/spec/ruby/core/exception/name_spec.rb
@@ -4,25 +4,25 @@ describe "NameError#name" do
it "returns a method name as a symbol" do
-> {
doesnt_exist
- }.should raise_error(NameError) {|e| e.name.should == :doesnt_exist }
+ }.should.raise(NameError) {|e| e.name.should == :doesnt_exist }
end
it "returns a constant name as a symbol" do
-> {
DoesntExist
- }.should raise_error(NameError) {|e| e.name.should == :DoesntExist }
+ }.should.raise(NameError) {|e| e.name.should == :DoesntExist }
end
it "returns a constant name without namespace as a symbol" do
-> {
Object::DoesntExist
- }.should raise_error(NameError) {|e| e.name.should == :DoesntExist }
+ }.should.raise(NameError) {|e| e.name.should == :DoesntExist }
end
it "returns a class variable name as a symbol" do
-> {
eval("class singleton_class::A; @@doesnt_exist end", binding, __FILE__, __LINE__)
- }.should raise_error(NameError) { |e| e.name.should == :@@doesnt_exist }
+ }.should.raise(NameError) { |e| e.name.should == :@@doesnt_exist }
end
it "returns the first argument passed to the method when a NameError is raised from #instance_variable_get" do
@@ -30,7 +30,7 @@ describe "NameError#name" do
-> {
Object.new.instance_variable_get(invalid_ivar_name)
- }.should raise_error(NameError) {|e| e.name.should equal(invalid_ivar_name) }
+ }.should.raise(NameError) {|e| e.name.should.equal?(invalid_ivar_name) }
end
it "returns the first argument passed to the method when a NameError is raised from #class_variable_get" do
@@ -38,6 +38,6 @@ describe "NameError#name" do
-> {
Object.class_variable_get(invalid_cvar_name)
- }.should raise_error(NameError) {|e| e.name.should equal(invalid_cvar_name) }
+ }.should.raise(NameError) {|e| e.name.should.equal?(invalid_cvar_name) }
end
end
diff --git a/spec/ruby/core/exception/no_method_error_spec.rb b/spec/ruby/core/exception/no_method_error_spec.rb
index 8428ba0382..9f92104082 100644
--- a/spec/ruby/core/exception/no_method_error_spec.rb
+++ b/spec/ruby/core/exception/no_method_error_spec.rb
@@ -35,7 +35,7 @@ describe "NoMethodError#args" do
NoMethodErrorSpecs::NoMethodErrorB.new.foo(1,a)
rescue Exception => e
e.args.should == [1,a]
- e.args[1].should equal a
+ e.args[1].should.equal? a
end
end
end
@@ -45,7 +45,7 @@ describe "NoMethodError#message" do
begin
NoMethodErrorSpecs::NoMethodErrorD.new.foo
rescue Exception => e
- e.should be_kind_of(NoMethodError)
+ e.should.is_a?(NoMethodError)
end
end
@@ -53,7 +53,7 @@ describe "NoMethodError#message" do
begin
NoMethodErrorSpecs::NoMethodErrorC.new.a_protected_method
rescue Exception => e
- e.should be_kind_of(NoMethodError)
+ e.should.is_a?(NoMethodError)
end
end
@@ -61,62 +61,150 @@ describe "NoMethodError#message" do
begin
NoMethodErrorSpecs::NoMethodErrorC.new.a_private_method
rescue Exception => e
- e.should be_kind_of(NoMethodError)
- e.message.lines[0].should =~ /private method `a_private_method' called for #<NoMethodErrorSpecs::NoMethodErrorC:0x[\h]+>/
+ e.should.is_a?(NoMethodError)
+ e.message.lines[0].should =~ /private method [`']a_private_method' called for /
end
end
- it "calls receiver.inspect only when calling Exception#message" do
- ScratchPad.record []
- test_class = Class.new do
- def inspect
- ScratchPad << :inspect_called
- "<inspect>"
- end
+ it "uses a literal name when receiver is nil" do
+ begin
+ nil.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for nil\Z/
end
- instance = test_class.new
+ end
+
+ it "uses a literal name when receiver is true" do
+ begin
+ true.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for true\Z/
+ end
+ end
+
+ it "uses a literal name when receiver is false" do
+ begin
+ false.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for false\Z/
+ end
+ end
+
+ it "uses #name when receiver is a class" do
+ klass = Class.new { def self.name; "MyClass"; end }
+
+ begin
+ klass.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for class MyClass\Z/
+ end
+ end
+
+ it "uses class' string representation when receiver is an anonymous class" do
+ klass = Class.new
+
+ begin
+ klass.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for class #<Class:0x\h+>\Z/
+ end
+ end
+
+ it "uses class' string representation when receiver is a singleton class" do
+ obj = Object.new
+ singleton_class = obj.singleton_class
+
+ begin
+ singleton_class.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for class #<Class:#<Object:0x\h+>>\Z/
+ end
+ end
+
+ it "uses #name when receiver is a module" do
+ mod = Module.new { def self.name; "MyModule"; end }
+
+ begin
+ mod.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for module MyModule\Z/
+ end
+ end
+
+ it "uses module's string representation when receiver is an anonymous module" do
+ m = Module.new
+
+ begin
+ m.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for module #<Module:0x\h+>\Z/
+ end
+ end
+
+ it "uses class #name when receiver is an ordinary object" do
+ klass = Class.new { def self.name; "MyClass"; end }
+ instance = klass.new
+
begin
instance.bar
- rescue Exception => e
- e.name.should == :bar
- ScratchPad.recorded.should == []
- e.message.should =~ /undefined method.+\bbar\b/
- ScratchPad.recorded.should == [:inspect_called]
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']bar' for an instance of MyClass\Z/
+ end
+ end
+
+ it "uses class string representation when receiver is an instance of anonymous class" do
+ klass = Class.new
+ instance = klass.new
+
+ begin
+ instance.bar
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']bar' for an instance of #<Class:0x\h+>\Z/
end
end
- it "fallbacks to a simpler representation of the receiver when receiver.inspect raises an exception" do
+ it "uses class name when receiver has a singleton class" do
+ instance = NoMethodErrorSpecs::NoMethodErrorA.new
+ def instance.foo; end
+
+ begin
+ instance.bar
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']bar' for #<NoMethodErrorSpecs::NoMethodErrorA:0x\h+>\Z/
+ end
+ end
+
+ it "does not call #inspect when calling Exception#message" do
+ ScratchPad.record []
test_class = Class.new do
def inspect
- raise NoMethodErrorSpecs::InstanceException
+ ScratchPad << :inspect_called
+ "<inspect>"
end
end
instance = test_class.new
+
begin
instance.bar
- rescue Exception => e
- e.name.should == :bar
- message = e.message
- message.should =~ /undefined method.+\bbar\b/
- message.should include test_class.inspect
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']bar' for an instance of #<Class:0x\h+>\Z/
+ ScratchPad.recorded.should == []
end
end
- ruby_version_is "3.0" do
- it "uses #name to display the receiver if it is a class or a module" do
- klass = Class.new { def self.name; "MyClass"; end }
- begin
- klass.foo
- rescue NoMethodError => error
- error.message.lines.first.chomp.should == "undefined method `foo' for MyClass:Class"
- end
+ it "does not truncate long class names" do
+ class_name = 'ExceptionSpecs::A' + 'a'*100
- mod = Module.new { def self.name; "MyModule"; end }
- begin
- mod.foo
- rescue NoMethodError => error
- error.message.lines.first.chomp.should == "undefined method `foo' for MyModule:Module"
- end
+ begin
+ eval <<~RUBY
+ class #{class_name}
+ end
+
+ obj = #{class_name}.new
+ obj.foo
+ RUBY
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for an instance of #{class_name}\Z/
end
end
end
diff --git a/spec/ruby/core/exception/reason_spec.rb b/spec/ruby/core/exception/reason_spec.rb
index 210bbc9725..d7022768b6 100644
--- a/spec/ruby/core/exception/reason_spec.rb
+++ b/spec/ruby/core/exception/reason_spec.rb
@@ -6,7 +6,7 @@ describe "LocalJumpError#reason" do
end
it "returns 'return' for a return" do
- -> { get_me_a_return.call }.should raise_error(LocalJumpError) { |e|
+ -> { get_me_a_return.call }.should.raise(LocalJumpError) { |e|
e.reason.should == :return
}
end
diff --git a/spec/ruby/core/exception/receiver_spec.rb b/spec/ruby/core/exception/receiver_spec.rb
index d1c23b67be..6ecf640ad8 100644
--- a/spec/ruby/core/exception/receiver_spec.rb
+++ b/spec/ruby/core/exception/receiver_spec.rb
@@ -11,31 +11,31 @@ describe "NameError#receiver" do
-> {
receiver.doesnt_exist
- }.should raise_error(NameError) {|e| e.receiver.should equal(receiver) }
+ }.should.raise(NameError) {|e| e.receiver.should.equal?(receiver) }
end
it "returns the Object class when an undefined constant is called without namespace" do
-> {
DoesntExist
- }.should raise_error(NameError) {|e| e.receiver.should equal(Object) }
+ }.should.raise(NameError) {|e| e.receiver.should.equal?(Object) }
end
it "returns a class when an undefined constant is called" do
-> {
NameErrorSpecs::ReceiverClass::DoesntExist
- }.should raise_error(NameError) {|e| e.receiver.should equal(NameErrorSpecs::ReceiverClass) }
+ }.should.raise(NameError) {|e| e.receiver.should.equal?(NameErrorSpecs::ReceiverClass) }
end
it "returns the Object class when an undefined class variable is called" do
-> {
eval("class singleton_class::A; @@doesnt_exist end", binding, __FILE__, __LINE__)
- }.should raise_error(NameError) {|e| e.receiver.should equal(singleton_class::A) }
+ }.should.raise(NameError) {|e| e.receiver.should.equal?(singleton_class::A) }
end
it "returns a class when an undefined class variable is called in a subclass' namespace" do
-> {
NameErrorSpecs::ReceiverClass.new.call_undefined_class_variable
- }.should raise_error(NameError) {|e| e.receiver.should equal(NameErrorSpecs::ReceiverClass) }
+ }.should.raise(NameError) {|e| e.receiver.should.equal?(NameErrorSpecs::ReceiverClass) }
end
it "returns the receiver when raised from #instance_variable_get" do
@@ -43,16 +43,16 @@ describe "NameError#receiver" do
-> {
receiver.instance_variable_get("invalid_ivar_name")
- }.should raise_error(NameError) {|e| e.receiver.should equal(receiver) }
+ }.should.raise(NameError) {|e| e.receiver.should.equal?(receiver) }
end
it "returns the receiver when raised from #class_variable_get" do
-> {
Object.class_variable_get("invalid_cvar_name")
- }.should raise_error(NameError) {|e| e.receiver.should equal(Object) }
+ }.should.raise(NameError) {|e| e.receiver.should.equal?(Object) }
end
it "raises an ArgumentError when the receiver is none" do
- -> { NameError.new.receiver }.should raise_error(ArgumentError)
+ -> { NameError.new.receiver }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/exception/result_spec.rb b/spec/ruby/core/exception/result_spec.rb
index d42fcdffcb..451ff43af5 100644
--- a/spec/ruby/core/exception/result_spec.rb
+++ b/spec/ruby/core/exception/result_spec.rb
@@ -14,8 +14,8 @@ describe "StopIteration#result" do
it "returns the method-returned-object from an Enumerator" do
@enum.next
@enum.next
- -> { @enum.next }.should raise_error(StopIteration) { |error|
- error.result.should equal(:method_returned)
+ -> { @enum.next }.should.raise(StopIteration) { |error|
+ error.result.should.equal?(:method_returned)
}
end
end
diff --git a/spec/ruby/core/exception/set_backtrace_spec.rb b/spec/ruby/core/exception/set_backtrace_spec.rb
index ba2e1bf7aa..2cd93326ec 100644
--- a/spec/ruby/core/exception/set_backtrace_spec.rb
+++ b/spec/ruby/core/exception/set_backtrace_spec.rb
@@ -1,56 +1,23 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
+require_relative 'shared/set_backtrace'
describe "Exception#set_backtrace" do
- it "accepts an Array of Strings" do
- err = RuntimeError.new
- err.set_backtrace ["unhappy"]
- err.backtrace.should == ["unhappy"]
- end
-
it "allows the user to set the backtrace from a rescued exception" do
bt = ExceptionSpecs::Backtrace.backtrace
err = RuntimeError.new
+ err.backtrace.should == nil
+ err.backtrace_locations.should == nil
err.set_backtrace bt
- err.backtrace.should == bt
- end
-
- it "accepts an empty Array" do
- err = RuntimeError.new
- err.set_backtrace []
- err.backtrace.should == []
- end
-
- it "accepts a String" do
- err = RuntimeError.new
- err.set_backtrace "unhappy"
- err.backtrace.should == ["unhappy"]
- end
- it "accepts nil" do
- err = RuntimeError.new
- err.set_backtrace nil
- err.backtrace.should be_nil
- end
-
- it "raises a TypeError when passed a Symbol" do
- err = RuntimeError.new
- -> { err.set_backtrace :unhappy }.should raise_error(TypeError)
+ err.backtrace.should == bt
+ err.backtrace_locations.should == nil
end
- it "raises a TypeError when the Array contains a Symbol" do
+ it_behaves_like :exception_set_backtrace, -> backtrace {
err = RuntimeError.new
- -> { err.set_backtrace ["String", :unhappy] }.should raise_error(TypeError)
- end
-
- it "raises a TypeError when the array contains nil" do
- err = Exception.new
- -> { err.set_backtrace ["String", nil] }.should raise_error(TypeError)
- end
-
- it "raises a TypeError when the argument is a nested array" do
- err = Exception.new
- -> { err.set_backtrace ["String", ["String"]] }.should raise_error(TypeError)
- end
+ err.set_backtrace(backtrace)
+ err
+ }
end
diff --git a/spec/ruby/core/exception/shared/new.rb b/spec/ruby/core/exception/shared/new.rb
index bcde8ee4b2..048fd14dd2 100644
--- a/spec/ruby/core/exception/shared/new.rb
+++ b/spec/ruby/core/exception/shared/new.rb
@@ -1,6 +1,6 @@
describe :exception_new, shared: true do
it "creates a new instance of Exception" do
- Exception.should be_ancestor_of(Exception.send(@method).class)
+ Exception.send(@method).class.ancestors.should.include?(Exception)
end
it "sets the message of the Exception when passes a message" do
@@ -12,7 +12,7 @@ describe :exception_new, shared: true do
end
it "returns the exception when it has a custom constructor" do
- ExceptionSpecs::ConstructorException.send(@method).should be_kind_of(ExceptionSpecs::ConstructorException)
+ ExceptionSpecs::ConstructorException.send(@method).should.is_a?(ExceptionSpecs::ConstructorException)
end
end
diff --git a/spec/ruby/core/exception/shared/set_backtrace.rb b/spec/ruby/core/exception/shared/set_backtrace.rb
new file mode 100644
index 0000000000..934bf3dc5f
--- /dev/null
+++ b/spec/ruby/core/exception/shared/set_backtrace.rb
@@ -0,0 +1,64 @@
+require_relative '../fixtures/common'
+
+describe :exception_set_backtrace, shared: true do
+ it "accepts an Array of Strings" do
+ err = @method.call(["unhappy"])
+ err.backtrace.should == ["unhappy"]
+ end
+
+ it "allows the user to set the backtrace from a rescued exception" do
+ bt = ExceptionSpecs::Backtrace.backtrace
+ err = @method.call(bt)
+ err.backtrace.should == bt
+ end
+
+ ruby_version_is "3.4" do
+ it "allows the user to set backtrace locations from a rescued exception" do
+ bt_locations = ExceptionSpecs::Backtrace.backtrace_locations
+ err = @method.call(bt_locations)
+ err.backtrace_locations.size.should == bt_locations.size
+ err.backtrace_locations.each_with_index do |loc, index|
+ other_loc = bt_locations[index]
+
+ loc.path.should == other_loc.path
+ loc.label.should == other_loc.label
+ loc.base_label.should == other_loc.base_label
+ loc.lineno.should == other_loc.lineno
+ loc.absolute_path.should == other_loc.absolute_path
+ loc.to_s.should == other_loc.to_s
+ end
+ err.backtrace.size.should == err.backtrace_locations.size
+ end
+ end
+
+ it "accepts an empty Array" do
+ err = @method.call([])
+ err.backtrace.should == []
+ end
+
+ it "accepts a String" do
+ err = @method.call("unhappy")
+ err.backtrace.should == ["unhappy"]
+ end
+
+ it "accepts nil" do
+ err = @method.call(nil)
+ err.backtrace.should == nil
+ end
+
+ it "raises a TypeError when passed a Symbol" do
+ -> { @method.call(:unhappy) }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError when the Array contains a Symbol" do
+ -> { @method.call(["String", :unhappy]) }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError when the array contains nil" do
+ -> { @method.call(["String", nil]) }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError when the argument is a nested array" do
+ -> { @method.call(["String", ["String"]]) }.should.raise(TypeError)
+ end
+end
diff --git a/spec/ruby/core/exception/signal_exception_spec.rb b/spec/ruby/core/exception/signal_exception_spec.rb
index 1a0940743f..010181bc55 100644
--- a/spec/ruby/core/exception/signal_exception_spec.rb
+++ b/spec/ruby/core/exception/signal_exception_spec.rb
@@ -9,7 +9,7 @@ describe "SignalException.new" do
end
it "raises an exception with an invalid signal number" do
- -> { SignalException.new(100000) }.should raise_error(ArgumentError)
+ -> { SignalException.new(100000) }.should.raise(ArgumentError)
end
it "takes a signal name without SIG prefix as the first argument" do
@@ -27,11 +27,11 @@ describe "SignalException.new" do
end
it "raises an exception with an invalid signal name" do
- -> { SignalException.new("NONEXISTENT") }.should raise_error(ArgumentError)
+ -> { SignalException.new("NONEXISTENT") }.should.raise(ArgumentError)
end
it "raises an exception with an invalid first argument type" do
- -> { SignalException.new(Object.new) }.should raise_error(ArgumentError)
+ -> { SignalException.new(Object.new) }.should.raise(ArgumentError)
end
it "takes a signal symbol without SIG prefix as the first argument" do
@@ -49,7 +49,7 @@ describe "SignalException.new" do
end
it "raises an exception with an invalid signal name" do
- -> { SignalException.new(:NONEXISTENT) }.should raise_error(ArgumentError)
+ -> { SignalException.new(:NONEXISTENT) }.should.raise(ArgumentError)
end
it "takes an optional message argument with a signal number" do
@@ -60,7 +60,7 @@ describe "SignalException.new" do
end
it "raises an exception for an optional argument with a signal name" do
- -> { SignalException.new("INT","name") }.should raise_error(ArgumentError)
+ -> { SignalException.new("INT","name") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/exception/signm_spec.rb b/spec/ruby/core/exception/signm_spec.rb
index 4adff3b5ee..cabcc7ad58 100644
--- a/spec/ruby/core/exception/signm_spec.rb
+++ b/spec/ruby/core/exception/signm_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "SignalException#signm" do
it "returns the signal name" do
- -> { Process.kill(:TERM, Process.pid) }.should raise_error(SignalException) { |e|
+ -> { Process.kill(:TERM, Process.pid) }.should.raise(SignalException) { |e|
e.signm.should == 'SIGTERM'
}
end
diff --git a/spec/ruby/core/exception/signo_spec.rb b/spec/ruby/core/exception/signo_spec.rb
index 62fc321516..46e79a8daf 100644
--- a/spec/ruby/core/exception/signo_spec.rb
+++ b/spec/ruby/core/exception/signo_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "SignalException#signo" do
it "returns the signal number" do
- -> { Process.kill(:TERM, Process.pid) }.should raise_error(SignalException) { |e|
+ -> { Process.kill(:TERM, Process.pid) }.should.raise(SignalException) { |e|
e.signo.should == Signal.list['TERM']
}
end
diff --git a/spec/ruby/core/exception/standard_error_spec.rb b/spec/ruby/core/exception/standard_error_spec.rb
index 17e98ce7f0..b05d247f67 100644
--- a/spec/ruby/core/exception/standard_error_spec.rb
+++ b/spec/ruby/core/exception/standard_error_spec.rb
@@ -18,6 +18,6 @@ describe "StandardError" do
end
it "does not rescue superclass of StandardError" do
- -> { begin; raise Exception; rescue; end }.should raise_error(Exception)
+ -> { begin; raise Exception; rescue; end }.should.raise(Exception)
end
end
diff --git a/spec/ruby/core/exception/status_spec.rb b/spec/ruby/core/exception/status_spec.rb
index 8ace00fe10..7369b0815d 100644
--- a/spec/ruby/core/exception/status_spec.rb
+++ b/spec/ruby/core/exception/status_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "SystemExit#status" do
it "returns the exit status" do
- -> { exit 42 }.should raise_error(SystemExit) { |e|
+ -> { exit 42 }.should.raise(SystemExit) { |e|
e.status.should == 42
}
end
diff --git a/spec/ruby/core/exception/success_spec.rb b/spec/ruby/core/exception/success_spec.rb
index 6f21743340..5ab8f94454 100644
--- a/spec/ruby/core/exception/success_spec.rb
+++ b/spec/ruby/core/exception/success_spec.rb
@@ -2,13 +2,13 @@ require_relative '../../spec_helper'
describe "SystemExit#success?" do
it "returns true if the process exited successfully" do
- -> { exit 0 }.should raise_error(SystemExit) { |e|
+ -> { exit 0 }.should.raise(SystemExit) { |e|
e.should.success?
}
end
it "returns false if the process exited unsuccessfully" do
- -> { exit(-1) }.should raise_error(SystemExit) { |e|
+ -> { exit(-1) }.should.raise(SystemExit) { |e|
e.should_not.success?
}
end
diff --git a/spec/ruby/core/exception/syntax_error_spec.rb b/spec/ruby/core/exception/syntax_error_spec.rb
new file mode 100644
index 0000000000..66eb5649aa
--- /dev/null
+++ b/spec/ruby/core/exception/syntax_error_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+
+describe "SyntaxError#path" do
+ it "returns the file path provided to eval" do
+ filename = "speccing.rb"
+
+ -> {
+ eval("if true", TOPLEVEL_BINDING, filename)
+ }.should.raise(SyntaxError) { |e|
+ e.path.should == filename
+ }
+ end
+
+ it "returns the file path that raised an exception" do
+ expected_path = fixture(__FILE__, "syntax_error.rb")
+
+ -> {
+ require_relative "fixtures/syntax_error"
+ }.should.raise(SyntaxError) { |e| e.path.should == expected_path }
+ end
+
+ it "returns nil when constructed directly" do
+ SyntaxError.new.path.should == nil
+ end
+end
diff --git a/spec/ruby/core/exception/system_call_error_spec.rb b/spec/ruby/core/exception/system_call_error_spec.rb
index 73167bc288..da01c5b6b0 100644
--- a/spec/ruby/core/exception/system_call_error_spec.rb
+++ b/spec/ruby/core/exception/system_call_error_spec.rb
@@ -14,8 +14,10 @@ describe "SystemCallError" do
end
exc = ExceptionSpecs::SCESub.new
- ScratchPad.recorded.should equal(:initialize)
- exc.should be_an_instance_of(ExceptionSpecs::SCESub)
+ ScratchPad.recorded.should.equal?(:initialize)
+ exc.should.instance_of?(ExceptionSpecs::SCESub)
+ ensure
+ ExceptionSpecs.send(:remove_const, :SCESub)
end
end
@@ -25,10 +27,11 @@ describe "SystemCallError.new" do
@example_errno_class = Errno::EINVAL
@last_known_errno = Errno.constants.size - 1
@unknown_errno = Errno.constants.size
+ @some_human_readable = /[[:graph:]]+/
end
it "requires at least one argument" do
- -> { SystemCallError.new }.should raise_error(ArgumentError)
+ -> { SystemCallError.new }.should.raise(ArgumentError)
end
it "accepts single Integer argument as errno" do
@@ -41,28 +44,33 @@ describe "SystemCallError.new" do
end
it "constructs a SystemCallError for an unknown error number" do
- SystemCallError.new(-2**24).should be_an_instance_of(SystemCallError)
- SystemCallError.new(-1).should be_an_instance_of(SystemCallError)
- SystemCallError.new(@unknown_errno).should be_an_instance_of(SystemCallError)
- SystemCallError.new(2**24).should be_an_instance_of(SystemCallError)
+ SystemCallError.new(-2**24).should.instance_of?(SystemCallError)
+ SystemCallError.new(-1).should.instance_of?(SystemCallError)
+ SystemCallError.new(@unknown_errno).should.instance_of?(SystemCallError)
+ SystemCallError.new(2**24).should.instance_of?(SystemCallError)
end
it "constructs the appropriate Errno class" do
e = SystemCallError.new(@example_errno)
- e.should be_kind_of(SystemCallError)
- e.should be_an_instance_of(@example_errno_class)
+ e.should.is_a?(SystemCallError)
+ e.should.instance_of?(@example_errno_class)
+ end
+
+ it "sets an error message corresponding to an appropriate Errno class" do
+ e = SystemCallError.new(@example_errno)
+ e.message.should == 'Invalid argument'
end
it "accepts an optional custom message preceding the errno" do
exc = SystemCallError.new("custom message", @example_errno)
- exc.should be_an_instance_of(@example_errno_class)
+ exc.should.instance_of?(@example_errno_class)
exc.errno.should == @example_errno
exc.message.should == 'Invalid argument - custom message'
end
it "accepts an optional third argument specifying the location" do
exc = SystemCallError.new("custom message", @example_errno, "location")
- exc.should be_an_instance_of(@example_errno_class)
+ exc.should.instance_of?(@example_errno_class)
exc.errno.should == @example_errno
exc.message.should == 'Invalid argument @ location - custom message'
end
@@ -81,20 +89,37 @@ describe "SystemCallError.new" do
SystemCallError.new('foo', 2.9).should == SystemCallError.new('foo', 2)
end
+ it "treats nil errno as unknown error value" do
+ SystemCallError.new(nil).should.instance_of?(SystemCallError)
+ end
+
+ it "treats nil custom message as if it is not passed at all" do
+ exc = SystemCallError.new(nil, @example_errno)
+ exc.message.should == 'Invalid argument'
+ end
+
+ it "sets an 'unknown error' message when an unknown error number" do
+ SystemCallError.new(-1).message.should =~ @some_human_readable
+ end
+
+ it "adds a custom error message to an 'unknown error' message when an unknown error number and a custom message specified" do
+ SystemCallError.new("custom message", -1).message.should =~ /#{@some_human_readable}.* - custom message/
+ end
+
it "converts to Integer if errno is a Complex convertible to Integer" do
SystemCallError.new('foo', Complex(2.9, 0)).should == SystemCallError.new('foo', 2)
end
it "raises TypeError if message is not a String" do
- -> { SystemCallError.new(:foo, 1) }.should raise_error(TypeError, /no implicit conversion of Symbol into String/)
+ -> { SystemCallError.new(:foo, 1) }.should.raise(TypeError, /no implicit conversion of Symbol into String/)
end
it "raises TypeError if errno is not an Integer" do
- -> { SystemCallError.new('foo', 'bar') }.should raise_error(TypeError, /no implicit conversion of String into Integer/)
+ -> { SystemCallError.new('foo', 'bar') }.should.raise(TypeError, /no implicit conversion of String into Integer/)
end
it "raises RangeError if errno is a Complex not convertible to Integer" do
- -> { SystemCallError.new('foo', Complex(2.9, 1)) }.should raise_error(RangeError, /can't convert/)
+ -> { SystemCallError.new('foo', Complex(2.9, 1)) }.should.raise(RangeError, /can't convert/)
end
end
@@ -115,12 +140,7 @@ end
describe "SystemCallError#message" do
it "returns the default message when no message is given" do
- platform_is :aix do
- SystemCallError.new(2**28).message.should =~ /Error .*occurred/i
- end
- platform_is_not :aix do
- SystemCallError.new(2**28).message.should =~ /Unknown error/i
- end
+ SystemCallError.new(2**28).message.should =~ @some_human_readable
end
it "returns the message given as an argument to new" do
diff --git a/spec/ruby/core/exception/to_s_spec.rb b/spec/ruby/core/exception/to_s_spec.rb
index 4c4c7ab432..65c0d73a98 100644
--- a/spec/ruby/core/exception/to_s_spec.rb
+++ b/spec/ruby/core/exception/to_s_spec.rb
@@ -23,7 +23,7 @@ describe "NameError#to_s" do
begin
puts not_defined
rescue => exception
- exception.message.should =~ /undefined local variable or method `not_defined'/
+ exception.message.should =~ /undefined local variable or method [`']not_defined'/
end
end
diff --git a/spec/ruby/core/exception/top_level_spec.rb b/spec/ruby/core/exception/top_level_spec.rb
index b47648425e..cc961d06d5 100644
--- a/spec/ruby/core/exception/top_level_spec.rb
+++ b/spec/ruby/core/exception/top_level_spec.rb
@@ -2,30 +2,38 @@ require_relative '../../spec_helper'
describe "An Exception reaching the top level" do
it "is printed on STDERR" do
- ruby_exe('raise "foo"', args: "2>&1", exit_status: 1).should.include?("in `<main>': foo (RuntimeError)")
+ ruby_exe('raise "foo"', args: "2>&1", exit_status: 1).should =~ /in [`']<main>': foo \(RuntimeError\)/
end
it "the Exception#cause is printed to STDERR with backtraces" do
code = <<-RUBY
def raise_cause
- raise "the cause"
+ raise "the cause" # 2
end
def raise_wrapped
- raise "wrapped"
+ raise "wrapped" # 5
end
begin
- raise_cause
+ raise_cause # 8
rescue
- raise_wrapped
+ raise_wrapped # 10
end
RUBY
lines = ruby_exe(code, args: "2>&1", exit_status: 1).lines
- lines.reject! { |l| l.include?('rescue in') }
- lines.map! { |l| l.chomp[/:(in.+)/, 1] }
- lines.should == ["in `raise_wrapped': wrapped (RuntimeError)",
- "in `<main>'",
- "in `raise_cause': the cause (RuntimeError)",
- "in `<main>'"]
+
+ lines.map! { |l| l.chomp[/:(\d+:in.+)/, 1] }
+ lines[0].should =~ /\A5:in [`'](?:Object#)?raise_wrapped': wrapped \(RuntimeError\)\z/
+ if lines[1].include? 'rescue in'
+ # CRuby < 3.4 has an extra 'rescue in' backtrace entry
+ lines[1].should =~ /\A10:in [`']rescue in <main>'\z/
+ lines.delete_at 1
+ lines[1].should =~ /\A7:in [`']<main>'\z/
+ else
+ lines[1].should =~ /\A10:in [`']<main>'\z/
+ end
+ lines[2].should =~ /\A2:in [`'](?:Object#)?raise_cause': the cause \(RuntimeError\)\z/
+ lines[3].should =~ /\A8:in [`']<main>'\z/
+ lines.size.should == 4
end
describe "with a custom backtrace" do
@@ -42,4 +50,16 @@ describe "An Exception reaching the top level" do
EOS
end
end
+
+ describe "kills all threads and fibers, ensure clauses are only run for threads current fibers, not for suspended fibers" do
+ it "with ensure on the root fiber" do
+ file = fixture(__FILE__, "thread_fiber_ensure.rb")
+ ruby_exe(file, args: "2>&1", exit_status: 0).should == "current fiber ensure\n"
+ end
+
+ it "with ensure on non-root fiber" do
+ file = fixture(__FILE__, "thread_fiber_ensure_non_root_fiber.rb")
+ ruby_exe(file, args: "2>&1", exit_status: 0).should == "current fiber ensure\n"
+ end
+ end
end
diff --git a/spec/ruby/core/false/case_compare_spec.rb b/spec/ruby/core/false/case_compare_spec.rb
new file mode 100644
index 0000000000..0bd0ab44ae
--- /dev/null
+++ b/spec/ruby/core/false/case_compare_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "FalseClass#===" do
+ it "returns true for false" do
+ (false === false).should == true
+ end
+
+ it "returns false for non-false object" do
+ (false === 0).should == false
+ (false === "").should == false
+ (false === Object).should == false
+ (false === nil).should == false
+ end
+end
diff --git a/spec/ruby/core/false/dup_spec.rb b/spec/ruby/core/false/dup_spec.rb
index 1a569a2f4f..b0eb85529e 100644
--- a/spec/ruby/core/false/dup_spec.rb
+++ b/spec/ruby/core/false/dup_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../spec_helper'
describe "FalseClass#dup" do
it "returns self" do
- false.dup.should equal(false)
+ false.dup.should.equal?(false)
end
end
diff --git a/spec/ruby/core/false/falseclass_spec.rb b/spec/ruby/core/false/falseclass_spec.rb
index c018ef2421..8dfe5ae891 100644
--- a/spec/ruby/core/false/falseclass_spec.rb
+++ b/spec/ruby/core/false/falseclass_spec.rb
@@ -4,12 +4,12 @@ describe "FalseClass" do
it ".allocate raises a TypeError" do
-> do
FalseClass.allocate
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it ".new is undefined" do
-> do
FalseClass.new
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
end
diff --git a/spec/ruby/core/false/singleton_method_spec.rb b/spec/ruby/core/false/singleton_method_spec.rb
new file mode 100644
index 0000000000..72aee8609a
--- /dev/null
+++ b/spec/ruby/core/false/singleton_method_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+
+describe "FalseClass#singleton_method" do
+ it "raises regardless of whether FalseClass defines the method" do
+ -> { false.singleton_method(:foo) }.should.raise(NameError)
+ begin
+ def (false).foo; end
+ -> { false.singleton_method(:foo) }.should.raise(NameError)
+ ensure
+ FalseClass.send(:remove_method, :foo)
+ end
+ end
+end
diff --git a/spec/ruby/core/false/to_s_spec.rb b/spec/ruby/core/false/to_s_spec.rb
index 62f67f6f55..9e24be26a2 100644
--- a/spec/ruby/core/false/to_s_spec.rb
+++ b/spec/ruby/core/false/to_s_spec.rb
@@ -10,6 +10,6 @@ describe "FalseClass#to_s" do
end
it "always returns the same string" do
- false.to_s.should equal(false.to_s)
+ false.to_s.should.equal?(false.to_s)
end
end
diff --git a/spec/ruby/core/fiber/alive_spec.rb b/spec/ruby/core/fiber/alive_spec.rb
new file mode 100644
index 0000000000..6fb1229d95
--- /dev/null
+++ b/spec/ruby/core/fiber/alive_spec.rb
@@ -0,0 +1,44 @@
+require_relative '../../spec_helper'
+
+describe "Fiber#alive?" do
+ it "returns true for a Fiber that hasn't had #resume called" do
+ fiber = Fiber.new { true }
+ fiber.alive?.should == true
+ end
+
+ # FIXME: Better description?
+ it "returns true for a Fiber that's yielded to the caller" do
+ fiber = Fiber.new { Fiber.yield }
+ fiber.resume
+ fiber.alive?.should == true
+ end
+
+ it "returns true when called from its Fiber" do
+ fiber = Fiber.new { fiber.alive?.should == true }
+ fiber.resume
+ end
+
+ it "doesn't invoke the block associated with the Fiber" do
+ offthehook = mock('do not call')
+ offthehook.should_not_receive(:ring)
+ fiber = Fiber.new { offthehook.ring }
+ fiber.alive?
+ end
+
+ it "returns false for a Fiber that's dead" do
+ fiber = Fiber.new { true }
+ fiber.resume
+ -> { fiber.resume }.should.raise(FiberError)
+ fiber.alive?.should == false
+ end
+
+ it "always returns false for a dead Fiber" do
+ fiber = Fiber.new { true }
+ fiber.resume
+ -> { fiber.resume }.should.raise(FiberError)
+ fiber.alive?.should == false
+ -> { fiber.resume }.should.raise(FiberError)
+ fiber.alive?.should == false
+ fiber.alive?.should == false
+ end
+end
diff --git a/spec/ruby/core/fiber/blocking_spec.rb b/spec/ruby/core/fiber/blocking_spec.rb
index 5ae5fbd577..d5caf81fbe 100644
--- a/spec/ruby/core/fiber/blocking_spec.rb
+++ b/spec/ruby/core/fiber/blocking_spec.rb
@@ -1,62 +1,73 @@
require_relative '../../spec_helper'
require_relative 'shared/blocking'
-ruby_version_is "3.0" do
- require "fiber"
+describe "Fiber.blocking?" do
+ it_behaves_like :non_blocking_fiber, -> { Fiber.blocking? }
- describe "Fiber.blocking?" do
- it_behaves_like :non_blocking_fiber, -> { Fiber.blocking? }
+ context "when fiber is blocking" do
+ context "root Fiber of the main thread" do
+ it "returns 1 for blocking: true" do
+ fiber = Fiber.new(blocking: true) { Fiber.blocking? }
+ blocking = fiber.resume
- context "when fiber is blocking" do
- context "root Fiber of the main thread" do
- it "returns 1 for blocking: true" do
+ blocking.should == 1
+ end
+ end
+
+ context "root Fiber of a new thread" do
+ it "returns 1 for blocking: true" do
+ thread = Thread.new do
fiber = Fiber.new(blocking: true) { Fiber.blocking? }
blocking = fiber.resume
blocking.should == 1
end
+
+ thread.join
end
+ end
+ end
+end
- context "root Fiber of a new thread" do
- it "returns 1 for blocking: true" do
- thread = Thread.new do
- fiber = Fiber.new(blocking: true) { Fiber.blocking? }
- blocking = fiber.resume
+describe "Fiber#blocking?" do
+ it_behaves_like :non_blocking_fiber, -> { Fiber.current.blocking? }
- blocking.should == 1
- end
+ context "when fiber is blocking" do
+ context "root Fiber of the main thread" do
+ it "returns true for blocking: true" do
+ fiber = Fiber.new(blocking: true) { Fiber.current.blocking? }
+ blocking = fiber.resume
- thread.join
- end
+ blocking.should == true
end
end
- end
- describe "Fiber#blocking?" do
- it_behaves_like :non_blocking_fiber, -> { Fiber.current.blocking? }
-
- context "when fiber is blocking" do
- context "root Fiber of the main thread" do
- it "returns true for blocking: true" do
+ context "root Fiber of a new thread" do
+ it "returns true for blocking: true" do
+ thread = Thread.new do
fiber = Fiber.new(blocking: true) { Fiber.current.blocking? }
blocking = fiber.resume
blocking.should == true
end
- end
- context "root Fiber of a new thread" do
- it "returns true for blocking: true" do
- thread = Thread.new do
- fiber = Fiber.new(blocking: true) { Fiber.current.blocking? }
- blocking = fiber.resume
-
- blocking.should == true
- end
+ thread.join
+ end
+ end
+ end
+end
- thread.join
+describe "Fiber.blocking" do
+ context "when fiber is non-blocking" do
+ it "can become blocking" do
+ fiber = Fiber.new(blocking: false) do
+ Fiber.blocking do |f|
+ f.blocking? ? :blocking : :non_blocking
end
end
+
+ blocking = fiber.resume
+ blocking.should == :blocking
end
end
end
diff --git a/spec/ruby/core/fiber/current_spec.rb b/spec/ruby/core/fiber/current_spec.rb
new file mode 100644
index 0000000000..cc5c9117b6
--- /dev/null
+++ b/spec/ruby/core/fiber/current_spec.rb
@@ -0,0 +1,50 @@
+require_relative '../../spec_helper'
+
+describe "Fiber.current" do
+ it "returns the root Fiber when called outside of a Fiber" do
+ root = Fiber.current
+ root.should.instance_of?(Fiber)
+ # We can always transfer to the root Fiber; it will never die
+ 5.times do
+ root.transfer.should == nil
+ root.alive?.should == true
+ end
+ end
+
+ it "returns the current Fiber when called from a Fiber" do
+ fiber = Fiber.new do
+ this = Fiber.current
+ this.should.instance_of?(Fiber)
+ this.should == fiber
+ this.alive?.should == true
+ end
+ fiber.resume
+ end
+
+ it "returns the current Fiber when called from a Fiber that transferred to another" do
+ states = []
+ fiber = Fiber.new do
+ states << :fiber
+ this = Fiber.current
+ this.should.instance_of?(Fiber)
+ this.should == fiber
+ this.alive?.should == true
+ end
+
+ fiber2 = Fiber.new do
+ states << :fiber2
+ fiber.transfer
+ flunk
+ end
+
+ fiber3 = Fiber.new do
+ states << :fiber3
+ fiber2.transfer
+ states << :fiber3_terminated
+ end
+
+ fiber3.resume
+
+ states.should == [:fiber3, :fiber2, :fiber, :fiber3_terminated]
+ end
+end
diff --git a/spec/ruby/core/fiber/fixtures/classes.rb b/spec/ruby/core/fiber/fixtures/classes.rb
index c00facd6e1..6b0e0fbc42 100644
--- a/spec/ruby/core/fiber/fixtures/classes.rb
+++ b/spec/ruby/core/fiber/fixtures/classes.rb
@@ -1,10 +1,20 @@
module FiberSpecs
class NewFiberToRaise
- def self.raise(*args)
- fiber = Fiber.new { Fiber.yield }
+ def self.raise(*args, **kwargs, &block)
+ fiber = Fiber.new do
+ if block_given?
+ block.call do
+ Fiber.yield
+ end
+ else
+ Fiber.yield
+ end
+ end
+
fiber.resume
- fiber.raise(*args)
+
+ fiber.raise(*args, **kwargs)
end
end
diff --git a/spec/ruby/core/fiber/fixtures/scheduler.rb b/spec/ruby/core/fiber/fixtures/scheduler.rb
new file mode 100644
index 0000000000..16bd2f6b44
--- /dev/null
+++ b/spec/ruby/core/fiber/fixtures/scheduler.rb
@@ -0,0 +1,35 @@
+module FiberSpecs
+
+ class LoggingScheduler
+ attr_reader :events
+ def initialize
+ @events = []
+ end
+
+ def block(*args)
+ @events << { event: :block, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+
+ def io_wait(*args)
+ @events << { event: :io_wait, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+
+ def kernel_sleep(*args)
+ @events << { event: :kernel_sleep, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+
+ def unblock(*args)
+ @events << { event: :unblock, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+
+ def fiber_interrupt(*args)
+ @events << { event: :fiber_interrupt, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+ end
+
+end
diff --git a/spec/ruby/core/fiber/inspect_spec.rb b/spec/ruby/core/fiber/inspect_spec.rb
new file mode 100644
index 0000000000..fcfef20716
--- /dev/null
+++ b/spec/ruby/core/fiber/inspect_spec.rb
@@ -0,0 +1,35 @@
+require_relative '../../spec_helper'
+
+describe "Fiber#inspect" do
+ describe "status" do
+ it "is resumed for the root Fiber of a Thread" do
+ inspected = Thread.new { Fiber.current.inspect }.value
+ inspected.should =~ /\A#<Fiber:0x\h+ .*\(resumed\)>\z/
+ end
+
+ it "is created for a Fiber which did not run yet" do
+ inspected = Fiber.new {}.inspect
+ inspected.should =~ /\A#<Fiber:0x\h+ .+ \(created\)>\z/
+ end
+
+ it "is resumed for a Fiber which was resumed" do
+ inspected = Fiber.new { Fiber.current.inspect }.resume
+ inspected.should =~ /\A#<Fiber:0x\h+ .+ \(resumed\)>\z/
+ end
+
+ it "is resumed for a Fiber which was transferred" do
+ inspected = Fiber.new { Fiber.current.inspect }.transfer
+ inspected.should =~ /\A#<Fiber:0x\h+ .+ \(resumed\)>\z/
+ end
+
+ it "is suspended for a Fiber which was resumed and yielded" do
+ inspected = Fiber.new { Fiber.yield }.tap(&:resume).inspect
+ inspected.should =~ /\A#<Fiber:0x\h+ .+ \(suspended\)>\z/
+ end
+
+ it "is terminated for a Fiber which has terminated" do
+ inspected = Fiber.new {}.tap(&:resume).inspect
+ inspected.should =~ /\A#<Fiber:0x\h+ .+ \(terminated\)>\z/
+ end
+ end
+end
diff --git a/spec/ruby/core/fiber/kill_spec.rb b/spec/ruby/core/fiber/kill_spec.rb
new file mode 100644
index 0000000000..abf23ff176
--- /dev/null
+++ b/spec/ruby/core/fiber/kill_spec.rb
@@ -0,0 +1,88 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative '../../shared/kernel/raise'
+
+describe "Fiber#kill" do
+ it "kills a non-resumed fiber" do
+ fiber = Fiber.new{}
+
+ fiber.alive?.should == true
+
+ fiber.kill
+ fiber.alive?.should == false
+ end
+
+ it "kills a resumed fiber" do
+ fiber = Fiber.new{while true; Fiber.yield; end}
+ fiber.resume
+
+ fiber.alive?.should == true
+
+ fiber.kill
+ fiber.alive?.should == false
+ end
+
+ it "can kill itself" do
+ fiber = Fiber.new do
+ Fiber.current.kill
+ end
+
+ fiber.alive?.should == true
+
+ fiber.resume
+ fiber.alive?.should == false
+ end
+
+ it "kills a resumed fiber from a child" do
+ parent = Fiber.new do
+ child = Fiber.new do
+ parent.kill
+ parent.alive?.should == true
+ end
+
+ child.resume
+ end
+
+ parent.resume
+ parent.alive?.should == false
+ end
+
+ it "executes the ensure block" do
+ ensure_executed = false
+
+ fiber = Fiber.new do
+ while true; Fiber.yield; end
+ ensure
+ ensure_executed = true
+ end
+
+ fiber.resume
+ fiber.kill
+ ensure_executed.should == true
+ end
+
+ it "does not execute rescue block" do
+ rescue_executed = false
+
+ fiber = Fiber.new do
+ while true; Fiber.yield; end
+ rescue Exception
+ rescue_executed = true
+ end
+
+ fiber.resume
+ fiber.kill
+ rescue_executed.should == false
+ end
+
+ it "repeatedly kills a fiber" do
+ fiber = Fiber.new do
+ while true; Fiber.yield; end
+ ensure
+ while true; Fiber.yield; end
+ end
+
+ fiber.kill
+ fiber.alive?.should == false
+ end
+end
diff --git a/spec/ruby/core/fiber/new_spec.rb b/spec/ruby/core/fiber/new_spec.rb
index b43c1386be..d31167496d 100644
--- a/spec/ruby/core/fiber/new_spec.rb
+++ b/spec/ruby/core/fiber/new_spec.rb
@@ -4,7 +4,7 @@ describe "Fiber.new" do
it "creates a fiber from the given block" do
fiber = Fiber.new {}
fiber.resume
- fiber.should be_an_instance_of(Fiber)
+ fiber.should.instance_of?(Fiber)
end
it "creates a fiber from a subclass" do
@@ -12,17 +12,17 @@ describe "Fiber.new" do
end
fiber = MyFiber.new {}
fiber.resume
- fiber.should be_an_instance_of(MyFiber)
+ fiber.should.instance_of?(MyFiber)
end
it "raises an ArgumentError if called without a block" do
- -> { Fiber.new }.should raise_error(ArgumentError)
+ -> { Fiber.new }.should.raise(ArgumentError)
end
it "does not invoke the block" do
invoked = false
fiber = Fiber.new { invoked = true }
- invoked.should be_false
+ invoked.should == false
fiber.resume
end
diff --git a/spec/ruby/core/fiber/raise_spec.rb b/spec/ruby/core/fiber/raise_spec.rb
index 09c4c1b524..107e5bd4ce 100644
--- a/spec/ruby/core/fiber/raise_spec.rb
+++ b/spec/ruby/core/fiber/raise_spec.rb
@@ -3,56 +3,62 @@ require_relative 'fixtures/classes'
require_relative '../../shared/kernel/raise'
describe "Fiber#raise" do
+ it "is a public method" do
+ Fiber.public_instance_methods.should.include?(:raise)
+ end
+
it_behaves_like :kernel_raise, :raise, FiberSpecs::NewFiberToRaise
-end
+ it_behaves_like :kernel_raise_across_contexts, :raise, FiberSpecs::NewFiberToRaise
+ ruby_version_is "4.0" do
+ it_behaves_like :kernel_raise_with_cause, :raise, FiberSpecs::NewFiberToRaise
+ end
-describe "Fiber#raise" do
it 'raises RuntimeError by default' do
- -> { FiberSpecs::NewFiberToRaise.raise }.should raise_error(RuntimeError)
+ -> { FiberSpecs::NewFiberToRaise.raise }.should.raise(RuntimeError)
end
it "raises FiberError if Fiber is not born" do
fiber = Fiber.new { true }
- -> { fiber.raise }.should raise_error(FiberError, "cannot raise exception on unborn fiber")
+ -> { fiber.raise }.should.raise(FiberError, "cannot raise exception on unborn fiber")
end
it "raises FiberError if Fiber is dead" do
fiber = Fiber.new { true }
fiber.resume
- -> { fiber.raise }.should raise_error(FiberError, /dead fiber called|attempt to resume a terminated fiber/)
+ -> { fiber.raise }.should.raise(FiberError, /dead fiber called|attempt to resume a terminated fiber/)
end
it 'accepts error class' do
- -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError }.should raise_error(FiberSpecs::CustomError)
+ -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError }.should.raise(FiberSpecs::CustomError)
end
it 'accepts error message' do
- -> { FiberSpecs::NewFiberToRaise.raise "error message" }.should raise_error(RuntimeError, "error message")
+ -> { FiberSpecs::NewFiberToRaise.raise "error message" }.should.raise(RuntimeError, "error message")
end
it 'does not accept array of backtrace information only' do
- -> { FiberSpecs::NewFiberToRaise.raise ['foo'] }.should raise_error(TypeError)
+ -> { FiberSpecs::NewFiberToRaise.raise ['foo'] }.should.raise(TypeError)
end
it 'does not accept integer' do
- -> { FiberSpecs::NewFiberToRaise.raise 100 }.should raise_error(TypeError)
+ -> { FiberSpecs::NewFiberToRaise.raise 100 }.should.raise(TypeError)
end
it 'accepts error class with error message' do
- -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error' }.should raise_error(FiberSpecs::CustomError, 'test error')
+ -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error' }.should.raise(FiberSpecs::CustomError, 'test error')
end
- it 'accepts error class with with error message and backtrace information' do
+ it 'accepts error class with error message and backtrace information' do
-> {
FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error', ['foo', 'boo']
- }.should raise_error(FiberSpecs::CustomError) { |e|
+ }.should.raise(FiberSpecs::CustomError) { |e|
e.message.should == 'test error'
e.backtrace.should == ['foo', 'boo']
}
end
it 'does not accept only error message and backtrace information' do
- -> { FiberSpecs::NewFiberToRaise.raise 'test error', ['foo', 'boo'] }.should raise_error(TypeError)
+ -> { FiberSpecs::NewFiberToRaise.raise 'test error', ['foo', 'boo'] }.should.raise(TypeError)
end
it "raises a FiberError if invoked from a different Thread" do
@@ -61,15 +67,15 @@ describe "Fiber#raise" do
Thread.new do
-> {
fiber.raise
- }.should raise_error(FiberError, "fiber called across threads")
+ }.should.raise(FiberError, "fiber called across threads")
end.join
end
it "kills Fiber" do
fiber = Fiber.new { Fiber.yield :first; :second }
fiber.resume
- -> { fiber.raise }.should raise_error
- -> { fiber.resume }.should raise_error(FiberError, /dead fiber called|attempt to resume a terminated fiber/)
+ -> { fiber.raise }.should.raise
+ -> { fiber.resume }.should.raise(FiberError, /dead fiber called|attempt to resume a terminated fiber/)
end
it "returns to calling fiber after raise" do
@@ -91,29 +97,45 @@ describe "Fiber#raise" do
fiber_two.resume.should == [:yield_one, :rescued]
end
-end
+ ruby_version_is "3.4" do
+ it "raises on the resumed fiber" do
+ root_fiber = Fiber.current
+ f1 = Fiber.new { root_fiber.transfer }
+ f2 = Fiber.new { f1.resume }
+ f2.transfer
-ruby_version_is ""..."3.0" do
- describe "Fiber#raise" do
- it "raises a FiberError if invoked on a transferring Fiber" do
- require "fiber"
- root = Fiber.current
- fiber = Fiber.new { root.transfer }
- fiber.transfer
- -> { fiber.raise }.should raise_error(FiberError, "cannot resume transferred Fiber")
+ -> do
+ f2.raise(RuntimeError, "Expected error")
+ end.should.raise(RuntimeError, "Expected error")
end
- end
-end
-ruby_version_is "3.0" do
- describe "Fiber#raise" do
- it "transfers and raises on a transferring fiber" do
- require "fiber"
- root = Fiber.current
- fiber = Fiber.new { root.transfer }
- fiber.transfer
- -> { fiber.raise "msg" }.should raise_error(RuntimeError, "msg")
+ it "raises on itself" do
+ -> do
+ Fiber.current.raise(RuntimeError, "Expected error")
+ end.should.raise(RuntimeError, "Expected error")
end
+
+ it "should raise on parent fiber" do
+ f2 = nil
+ f1 = Fiber.new do
+ # This is equivalent to Kernel#raise:
+ f2.raise(RuntimeError, "Expected error")
+ end
+ f2 = Fiber.new do
+ f1.resume
+ end
+
+ -> do
+ f2.resume
+ end.should.raise(RuntimeError, "Expected error")
+ end
+ end
+
+ it "transfers and raises on a transferring fiber" do
+ root = Fiber.current
+ fiber = Fiber.new { root.transfer }
+ fiber.transfer
+ -> { fiber.raise "msg" }.should.raise(RuntimeError, "msg")
end
end
diff --git a/spec/ruby/core/fiber/resume_spec.rb b/spec/ruby/core/fiber/resume_spec.rb
index 273bc866af..e183cc10d9 100644
--- a/spec/ruby/core/fiber/resume_spec.rb
+++ b/spec/ruby/core/fiber/resume_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/fiber/resume'
+require_relative 'shared/resume'
describe "Fiber#resume" do
it_behaves_like :fiber_resume, :resume
@@ -28,18 +28,9 @@ describe "Fiber#resume" do
fiber.resume :second
end
- ruby_version_is '3.0' do
- it "raises a FiberError if the Fiber tries to resume itself" do
- fiber = Fiber.new { fiber.resume }
- -> { fiber.resume }.should raise_error(FiberError, /current fiber/)
- end
- end
-
- ruby_version_is '' ... '3.0' do
- it "raises a FiberError if the Fiber tries to resume itself" do
- fiber = Fiber.new { fiber.resume }
- -> { fiber.resume }.should raise_error(FiberError, /double resume/)
- end
+ it "raises a FiberError if the Fiber tries to resume itself" do
+ fiber = Fiber.new { fiber.resume }
+ -> { fiber.resume }.should.raise(FiberError, /current fiber/)
end
it "returns control to the calling Fiber if called from one" do
@@ -76,4 +67,17 @@ describe "Fiber#resume" do
ruby_exe(code).should == "ensure executed\n"
end
+
+ it "can work with Fiber#transfer" do
+ fiber1 = Fiber.new { true }
+ fiber2 = Fiber.new { fiber1.transfer; Fiber.yield 10 ; Fiber.yield 20; raise }
+ fiber2.resume.should == 10
+ fiber2.resume.should == 20
+ end
+
+ it "raises a FiberError if the Fiber attempts to resume a resuming fiber" do
+ root_fiber = Fiber.current
+ fiber1 = Fiber.new { root_fiber.resume }
+ -> { fiber1.resume }.should.raise(FiberError, /attempt to resume a resuming fiber/)
+ end
end
diff --git a/spec/ruby/core/fiber/scheduler_spec.rb b/spec/ruby/core/fiber/scheduler_spec.rb
new file mode 100644
index 0000000000..15a03c1479
--- /dev/null
+++ b/spec/ruby/core/fiber/scheduler_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+require_relative 'shared/scheduler'
+
+require "fiber"
+
+describe "Fiber.scheduler" do
+ it_behaves_like :scheduler, :scheduler
+end
diff --git a/spec/ruby/core/fiber/set_scheduler_spec.rb b/spec/ruby/core/fiber/set_scheduler_spec.rb
new file mode 100644
index 0000000000..82f6acbe86
--- /dev/null
+++ b/spec/ruby/core/fiber/set_scheduler_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+require_relative 'shared/scheduler'
+
+require "fiber"
+
+describe "Fiber.scheduler" do
+ it_behaves_like :scheduler, :set_scheduler
+end
diff --git a/spec/ruby/core/fiber/shared/resume.rb b/spec/ruby/core/fiber/shared/resume.rb
new file mode 100644
index 0000000000..ff4bb72c73
--- /dev/null
+++ b/spec/ruby/core/fiber/shared/resume.rb
@@ -0,0 +1,58 @@
+describe :fiber_resume, shared: true do
+ it "can be invoked from the root Fiber" do
+ fiber = Fiber.new { :fiber }
+ fiber.send(@method).should == :fiber
+ end
+
+ it "raises a FiberError if invoked from a different Thread" do
+ fiber = Fiber.new { 42 }
+ Thread.new do
+ -> {
+ fiber.send(@method)
+ }.should.raise(FiberError)
+ end.join
+
+ # Check the Fiber can still be used
+ fiber.send(@method).should == 42
+ end
+
+ it "passes control to the beginning of the block on first invocation" do
+ invoked = false
+ fiber = Fiber.new { invoked = true }
+ fiber.send(@method)
+ invoked.should == true
+ end
+
+ it "returns the last value encountered on first invocation" do
+ fiber = Fiber.new { 1+1; true }
+ fiber.send(@method).should == true
+ end
+
+ it "runs until the end of the block" do
+ obj = mock('obj')
+ obj.should_receive(:do).once
+ fiber = Fiber.new { 1 + 2; a = "glark"; obj.do }
+ fiber.send(@method)
+ end
+
+ it "accepts any number of arguments" do
+ fiber = Fiber.new { |a| }
+ -> { fiber.send(@method, *(1..10).to_a) }.should_not.raise
+ end
+
+ it "raises a FiberError if the Fiber is dead" do
+ fiber = Fiber.new { true }
+ fiber.send(@method)
+ -> { fiber.send(@method) }.should.raise(FiberError)
+ end
+
+ it "raises a LocalJumpError if the block includes a return statement" do
+ fiber = Fiber.new { return; }
+ -> { fiber.send(@method) }.should.raise(LocalJumpError)
+ end
+
+ it "raises a LocalJumpError if the block includes a break statement" do
+ fiber = Fiber.new { break; }
+ -> { fiber.send(@method) }.should.raise(LocalJumpError)
+ end
+end
diff --git a/spec/ruby/core/fiber/shared/scheduler.rb b/spec/ruby/core/fiber/shared/scheduler.rb
new file mode 100644
index 0000000000..04bdded53a
--- /dev/null
+++ b/spec/ruby/core/fiber/shared/scheduler.rb
@@ -0,0 +1,51 @@
+describe :scheduler, shared: true do
+ it "validates the scheduler for required methods" do
+ required_methods = [:block, :unblock, :kernel_sleep, :io_wait]
+ required_methods.each do |missing_method|
+ scheduler = Object.new
+ required_methods.difference([missing_method]).each do |method|
+ scheduler.define_singleton_method(method) {}
+ end
+ -> {
+ suppress_warning { Fiber.set_scheduler(scheduler) }
+ }.should.raise(ArgumentError, /Scheduler must implement ##{missing_method}/)
+ end
+ end
+
+ it "can set and get the scheduler" do
+ required_methods = [:block, :unblock, :kernel_sleep, :io_wait]
+ scheduler = Object.new
+ required_methods.each do |method|
+ scheduler.define_singleton_method(method) {}
+ end
+ suppress_warning { Fiber.set_scheduler(scheduler) }
+ Fiber.scheduler.should == scheduler
+ end
+
+ it "returns the scheduler after setting it" do
+ required_methods = [:block, :unblock, :kernel_sleep, :io_wait]
+ scheduler = Object.new
+ required_methods.each do |method|
+ scheduler.define_singleton_method(method) {}
+ end
+ result = suppress_warning { Fiber.set_scheduler(scheduler) }
+ result.should == scheduler
+ end
+
+ it "can remove the scheduler" do
+ required_methods = [:block, :unblock, :kernel_sleep, :io_wait]
+ scheduler = Object.new
+ required_methods.each do |method|
+ scheduler.define_singleton_method(method) {}
+ end
+ suppress_warning { Fiber.set_scheduler(scheduler) }
+ Fiber.set_scheduler(nil)
+ Fiber.scheduler.should == nil
+ end
+
+ it "can assign a nil scheduler multiple times" do
+ Fiber.set_scheduler(nil)
+ Fiber.set_scheduler(nil)
+ Fiber.scheduler.should == nil
+ end
+end
diff --git a/spec/ruby/core/fiber/storage_spec.rb b/spec/ruby/core/fiber/storage_spec.rb
new file mode 100644
index 0000000000..a3f6bf9cad
--- /dev/null
+++ b/spec/ruby/core/fiber/storage_spec.rb
@@ -0,0 +1,177 @@
+require_relative '../../spec_helper'
+
+describe "Fiber.new(storage:)" do
+ it "creates a Fiber with the given storage" do
+ storage = {life: 42}
+ fiber = Fiber.new(storage: storage) { Fiber.current.storage }
+ fiber.resume.should == storage
+ end
+
+ it "creates a fiber with lazily initialized storage" do
+ Fiber.new(storage: nil) { Fiber[:x] = 10; Fiber.current.storage }.resume.should == {x: 10}
+ end
+
+ it "creates a fiber by inheriting the storage of the parent fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Fiber.new { Fiber.current.storage }.resume
+ end
+ fiber.resume.should == {life: 42}
+ end
+
+ it "cannot create a fiber with non-hash storage" do
+ -> { Fiber.new(storage: 42) {} }.should.raise(TypeError)
+ end
+
+ it "cannot create a fiber with a frozen hash as storage" do
+ -> { Fiber.new(storage: {life: 43}.freeze) {} }.should.raise(FrozenError)
+ end
+
+ it "cannot create a fiber with a storage hash with non-symbol keys" do
+ -> { Fiber.new(storage: {life: 43, Object.new => 44}) {} }.should.raise(TypeError)
+ end
+end
+
+describe "Fiber#storage" do
+ it "cannot be accessed from a different fiber" do
+ f = Fiber.new(storage: {life: 42}) { nil }
+ -> {
+ f.storage
+ }.should.raise(ArgumentError, /Fiber storage can only be accessed from the Fiber it belongs to/)
+ end
+end
+
+describe "Fiber#storage=" do
+ it "can clear the storage of the fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Fiber.current.storage = nil
+ Fiber[:x] = 10
+ Fiber.current.storage
+ end
+ fiber.resume.should == {x: 10}
+ end
+
+ it "can set the storage of the fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Fiber.current.storage = {life: 43}
+ Fiber.current.storage
+ end
+ fiber.resume.should == {life: 43}
+ end
+
+ it "can't set the storage of the fiber to non-hash" do
+ -> { Fiber.current.storage = 42 }.should.raise(TypeError)
+ end
+
+ it "can't set the storage of the fiber to a frozen hash" do
+ -> { Fiber.current.storage = {life: 43}.freeze }.should.raise(FrozenError)
+ end
+
+ it "can't set the storage of the fiber to a hash with non-symbol keys" do
+ -> { Fiber.current.storage = {life: 43, Object.new => 44} }.should.raise(TypeError)
+ end
+end
+
+describe "Fiber.[]" do
+ it "returns the value of the given key in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:life] }.resume.should == 42
+ end
+
+ it "returns nil if the key is not present in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:death] }.resume.should == nil
+ end
+
+ it "returns nil if the current fiber has no storage" do
+ Fiber.new { Fiber[:life] }.resume.should == nil
+ end
+
+ it "can use dynamically defined keys" do
+ key = :"#{self.class.name}#.#{self.object_id}"
+ Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42
+ end
+
+ it "can't use invalid keys" do
+ invalid_keys = [Object.new, 12]
+ invalid_keys.each do |key|
+ -> { Fiber[key] }.should.raise(TypeError)
+ end
+ end
+
+ ruby_bug "#20978", ""..."3.4" do
+ it "can use keys as strings" do
+ key = Object.new
+ def key.to_str; "Foo"; end
+ Fiber.new { Fiber[key] = 42; Fiber["Foo"] }.resume.should == 42
+ end
+
+ it "converts a String key into a Symbol" do
+ Fiber.new { Fiber["key"] = 42; Fiber[:key] }.resume.should == 42
+ Fiber.new { Fiber[:key] = 42; Fiber["key"] }.resume.should == 42
+ end
+
+ it "can use any object that responds to #to_str as a key" do
+ key = mock("key")
+ key.should_receive(:to_str).twice.and_return("key")
+ Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42
+ end
+ end
+
+ it "does not call #to_sym on the key" do
+ key = mock("key")
+ key.should_not_receive(:to_sym)
+ -> { Fiber[key] }.should.raise(TypeError)
+ end
+
+ it "can access the storage of the parent fiber" do
+ f = Fiber.new(storage: {life: 42}) do
+ Fiber.new { Fiber[:life] }.resume
+ end
+ f.resume.should == 42
+ end
+
+ it "can't access the storage of the fiber with non-symbol keys" do
+ -> { Fiber[Object.new] }.should.raise(TypeError)
+ end
+end
+
+describe "Fiber.[]=" do
+ it "sets the value of the given key in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
+ end
+
+ it "sets the value of the given key in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:death] = 43; Fiber[:death] }.resume.should == 43
+ end
+
+ it "sets the value of the given key in the storage of the current fiber" do
+ Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
+ end
+
+ it "does not overwrite the storage of the parent fiber" do
+ f = Fiber.new(storage: {life: 42}) do
+ Fiber.yield Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume
+ Fiber[:life]
+ end
+ f.resume.should == 43 # Value of the inner fiber
+ f.resume.should == 42 # Value of the outer fiber
+ end
+
+ it "can't access the storage of the fiber with non-symbol keys" do
+ -> { Fiber[Object.new] = 44 }.should.raise(TypeError)
+ end
+
+ it "deletes the fiber storage key when assigning nil" do
+ Fiber.new(storage: {life: 42}) {
+ Fiber[:life] = nil
+ Fiber.current.storage
+ }.resume.should == {}
+ end
+end
+
+describe "Thread.new" do
+ it "creates a thread with the storage of the current fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Thread.new { Fiber.current.storage }.value
+ end
+ fiber.resume.should == {life: 42}
+ end
+end
diff --git a/spec/ruby/core/fiber/transfer_spec.rb b/spec/ruby/core/fiber/transfer_spec.rb
new file mode 100644
index 0000000000..d8737aeeb3
--- /dev/null
+++ b/spec/ruby/core/fiber/transfer_spec.rb
@@ -0,0 +1,84 @@
+require_relative '../../spec_helper'
+require_relative 'shared/resume'
+
+describe "Fiber#transfer" do
+ it_behaves_like :fiber_resume, :transfer
+end
+
+describe "Fiber#transfer" do
+ it "transfers control from one Fiber to another when called from a Fiber" do
+ fiber1 = Fiber.new { :fiber1 }
+ fiber2 = Fiber.new { fiber1.transfer; :fiber2 }
+ fiber2.resume.should == :fiber2
+ end
+
+ it "returns to the root Fiber when finished" do
+ f1 = Fiber.new { :fiber_1 }
+ f2 = Fiber.new { f1.transfer; :fiber_2 }
+
+ f2.transfer.should == :fiber_1
+ f2.transfer.should == :fiber_2
+ end
+
+ it "can be invoked from the same Fiber it transfers control to" do
+ states = []
+ fiber = Fiber.new { states << :start; fiber.transfer; states << :end }
+ fiber.transfer
+ states.should == [:start, :end]
+
+ states = []
+ fiber = Fiber.new { states << :start; fiber.transfer; states << :end }
+ fiber.resume
+ states.should == [:start, :end]
+ end
+
+ it "can not transfer control to a Fiber that has suspended by Fiber.yield" do
+ states = []
+ fiber1 = Fiber.new { states << :fiber1 }
+ fiber2 = Fiber.new { states << :fiber2_start; Fiber.yield fiber1.transfer; states << :fiber2_end}
+ fiber2.resume.should == [:fiber2_start, :fiber1]
+ -> { fiber2.transfer }.should.raise(FiberError)
+ end
+
+ it "raises a FiberError when transferring to a Fiber which resumes itself" do
+ fiber = Fiber.new { fiber.resume }
+ -> { fiber.transfer }.should.raise(FiberError)
+ end
+
+ it "works if Fibers in different Threads each transfer to a Fiber in the same Thread" do
+ # This catches a bug where Fibers are running on a thread-pool
+ # and Fibers from a different Ruby Thread reuse the same native thread.
+ # Caching the Ruby Thread based on the native thread is not correct in that case,
+ # and the check for "fiber called across threads" in Fiber#transfer
+ # might be incorrect based on that.
+ 2.times do
+ Thread.new do
+ io_fiber = Fiber.new do |calling_fiber|
+ calling_fiber.transfer
+ end
+ io_fiber.transfer(Fiber.current)
+ value = Object.new
+ io_fiber.transfer(value).should.equal? value
+ end.join
+ end
+ end
+
+ it "transfers control between a non-main thread's root fiber to a child fiber and back again" do
+ states = []
+ thread = Thread.new do
+ f1 = Fiber.new do |f0|
+ states << 0
+ value2 = f0.transfer(1)
+ states << value2
+ 3
+ end
+
+ value1 = f1.transfer(Fiber.current)
+ states << value1
+ value3 = f1.transfer(2)
+ states << value3
+ end
+ thread.join
+ states.should == [0, 1, 2, 3]
+ end
+end
diff --git a/spec/ruby/core/fiber/yield_spec.rb b/spec/ruby/core/fiber/yield_spec.rb
index b010912c87..12ec6ebcef 100644
--- a/spec/ruby/core/fiber/yield_spec.rb
+++ b/spec/ruby/core/fiber/yield_spec.rb
@@ -18,7 +18,7 @@ describe "Fiber.yield" do
it "returns nil to the caller if given no arguments" do
fiber = Fiber.new { true; Fiber.yield; true }
- fiber.resume.should be_nil
+ fiber.resume.should == nil
fiber.resume
end
@@ -44,6 +44,6 @@ describe "Fiber.yield" do
end
it "raises a FiberError if called from the root Fiber" do
- ->{ Fiber.yield }.should raise_error(FiberError)
+ ->{ Fiber.yield }.should.raise(FiberError)
end
end
diff --git a/spec/ruby/core/file/absolute_path_spec.rb b/spec/ruby/core/file/absolute_path_spec.rb
index e35c80ec3c..fc12985a75 100644
--- a/spec/ruby/core/file/absolute_path_spec.rb
+++ b/spec/ruby/core/file/absolute_path_spec.rb
@@ -6,47 +6,47 @@ describe "File.absolute_path?" do
end
it "returns true if it's an absolute pathname" do
- File.absolute_path?(@abs).should be_true
+ File.absolute_path?(@abs).should == true
end
it "returns false if it's a relative path" do
- File.absolute_path?(File.basename(__FILE__)).should be_false
+ File.absolute_path?(File.basename(__FILE__)).should == false
end
it "returns false if it's a tricky relative path" do
- File.absolute_path?("C:foo\\bar").should be_false
+ File.absolute_path?("C:foo\\bar").should == false
end
it "does not expand '~' to a home directory." do
- File.absolute_path?('~').should be_false
+ File.absolute_path?('~').should == false
end
it "does not expand '~user' to a home directory." do
path = File.dirname(@abs)
Dir.chdir(path) do
- File.absolute_path?('~user').should be_false
+ File.absolute_path?('~user').should == false
end
end
it "calls #to_path on its argument" do
mock = mock_to_path(File.expand_path(__FILE__))
- File.absolute_path?(mock).should be_true
+ File.absolute_path?(mock).should == true
end
platform_is_not :windows do
it "takes into consideration the platform's root" do
- File.absolute_path?("C:\\foo\\bar").should be_false
- File.absolute_path?("C:/foo/bar").should be_false
- File.absolute_path?("/foo/bar\\baz").should be_true
+ File.absolute_path?("C:\\foo\\bar").should == false
+ File.absolute_path?("C:/foo/bar").should == false
+ File.absolute_path?("/foo/bar\\baz").should == true
end
end
platform_is :windows do
it "takes into consideration the platform path separator(s)" do
- File.absolute_path?("C:\\foo\\bar").should be_true
- File.absolute_path?("C:/foo/bar").should be_true
- File.absolute_path?("/foo/bar\\baz").should be_false
+ File.absolute_path?("C:\\foo\\bar").should == true
+ File.absolute_path?("C:/foo/bar").should == true
+ File.absolute_path?("/foo/bar\\baz").should == false
end
end
end
@@ -85,7 +85,7 @@ describe "File.absolute_path" do
end
it "accepts a second argument of a directory from which to resolve the path" do
- File.absolute_path(__FILE__, File.dirname(__FILE__)).should == @abs
+ File.absolute_path(__FILE__, __dir__).should == @abs
end
it "calls #to_path on its argument" do
diff --git a/spec/ruby/core/file/atime_spec.rb b/spec/ruby/core/file/atime_spec.rb
index cef07ba010..5c6c110eec 100644
--- a/spec/ruby/core/file/atime_spec.rb
+++ b/spec/ruby/core/file/atime_spec.rb
@@ -12,14 +12,14 @@ describe "File.atime" do
it "returns the last access time for the named file as a Time object" do
File.atime(@file)
- File.atime(@file).should be_kind_of(Time)
+ File.atime(@file).should.is_a?(Time)
end
platform_is :linux, :windows do
- platform_is_not :"powerpc64le-linux" do # https://bugs.ruby-lang.org/issues/17926
+ unless ENV.key?('TRAVIS') # https://bugs.ruby-lang.org/issues/17926
## NOTE also that some Linux systems disable atime (e.g. via mount params) for better filesystem speed.
it "returns the last access time for the named file with microseconds" do
- supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d+)/, 1], 10)
+ supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10)
if supports_subseconds != 0
expected_time = Time.at(Time.now.to_i + 0.123456)
File.utime expected_time, 0, @file
@@ -27,12 +27,15 @@ describe "File.atime" do
else
File.atime(__FILE__).usec.should == 0
end
+ rescue Errno::ENOENT => e
+ # Native Windows don't have stat command.
+ skip e.message
end
end
end
it "raises an Errno::ENOENT exception if the file is not found" do
- -> { File.atime('a_fake_file') }.should raise_error(Errno::ENOENT)
+ -> { File.atime('a_fake_file') }.should.raise(Errno::ENOENT)
end
it "accepts an object that has a #to_path method" do
@@ -52,6 +55,6 @@ describe "File#atime" do
it "returns the last access time to self" do
@file.atime
- @file.atime.should be_kind_of(Time)
+ @file.atime.should.is_a?(Time)
end
end
diff --git a/spec/ruby/core/file/basename_spec.rb b/spec/ruby/core/file/basename_spec.rb
index 989409d76b..77afe5c22f 100644
--- a/spec/ruby/core/file/basename_spec.rb
+++ b/spec/ruby/core/file/basename_spec.rb
@@ -42,7 +42,7 @@ describe "File.basename" do
end
it "returns an string" do
- File.basename("foo").should be_kind_of(String)
+ File.basename("foo").should.is_a?(String)
end
it "returns the basename for unix format" do
@@ -105,10 +105,10 @@ describe "File.basename" do
end
it "raises a TypeError if the arguments are not String types" do
- -> { File.basename(nil) }.should raise_error(TypeError)
- -> { File.basename(1) }.should raise_error(TypeError)
- -> { File.basename("bar.txt", 1) }.should raise_error(TypeError)
- -> { File.basename(true) }.should raise_error(TypeError)
+ -> { File.basename(nil) }.should.raise(TypeError)
+ -> { File.basename(1) }.should.raise(TypeError)
+ -> { File.basename("bar.txt", 1) }.should.raise(TypeError)
+ -> { File.basename(true) }.should.raise(TypeError)
end
it "accepts an object that has a #to_path method" do
@@ -116,7 +116,7 @@ describe "File.basename" do
end
it "raises an ArgumentError if passed more than two arguments" do
- -> { File.basename('bar.txt', '.txt', '.txt') }.should raise_error(ArgumentError)
+ -> { File.basename('bar.txt', '.txt', '.txt') }.should.raise(ArgumentError)
end
# specific to MS Windows
@@ -151,8 +151,30 @@ describe "File.basename" do
File.basename("c:\\bar.txt", ".*").should == "bar"
File.basename("c:\\bar.txt.exe", ".*").should == "bar.txt"
end
+
+ it "handles Shift JIS 0x5C (\\) as second byte of a multi-byte sequence" do
+ # dir\fileソname.txt
+ path = "dir\\file\x83\x5cname.txt".b.force_encoding(Encoding::SHIFT_JIS)
+ path.valid_encoding?.should == true
+ File.basename(path).should == "file\x83\x5cname.txt".b.force_encoding(Encoding::SHIFT_JIS)
+ end
+ end
+
+ it "rejects strings encoded with non ASCII-compatible encodings" do
+ Encoding.list.reject(&:ascii_compatible?).reject(&:dummy?).each do |enc|
+ path = "/foo/bar".encode(enc)
+
+ -> {
+ File.basename(path)
+ }.should.raise(Encoding::CompatibilityError)
+ end
end
+ it "works with all ASCII-compatible encodings" do
+ Encoding.list.select(&:ascii_compatible?).each do |enc|
+ File.basename("/foo/bar".encode(enc)).should == "bar".encode(enc)
+ end
+ end
it "returns the extension for a multibyte filename" do
File.basename('/path/Офис.m4a').should == "Офис.m4a"
@@ -174,7 +196,7 @@ describe "File.basename" do
else
File.basename(original)
end
- result.should_not equal(original)
+ result.should_not.equal?(original)
result.frozen?.should == false
end
end
diff --git a/spec/ruby/core/file/birthtime_spec.rb b/spec/ruby/core/file/birthtime_spec.rb
index 755601df64..039fd7572c 100644
--- a/spec/ruby/core/file/birthtime_spec.rb
+++ b/spec/ruby/core/file/birthtime_spec.rb
@@ -1,60 +1,56 @@
require_relative '../../spec_helper'
-describe "File.birthtime" do
- before :each do
- @file = __FILE__
- end
+platform_is :windows, :darwin, :freebsd, :netbsd, :linux do
+ not_implemented_messages = [
+ "birthtime() function is unimplemented", # unsupported OS/version
+ "birthtime is unimplemented", # unsupported filesystem
+ ]
+
+ describe "File.birthtime" do
+ before :each do
+ @file = __FILE__
+ end
- after :each do
- @file = nil
- end
+ after :each do
+ @file = nil
+ end
- platform_is :windows, :darwin, :freebsd, :netbsd do
it "returns the birth time for the named file as a Time object" do
File.birthtime(@file)
- File.birthtime(@file).should be_kind_of(Time)
+ File.birthtime(@file).should.is_a?(Time)
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
it "accepts an object that has a #to_path method" do
+ File.birthtime(@file) # Avoid to failure of mock object with old Kernel and glibc
File.birthtime(mock_to_path(@file))
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
it "raises an Errno::ENOENT exception if the file is not found" do
- -> { File.birthtime('bogus') }.should raise_error(Errno::ENOENT)
+ -> { File.birthtime('bogus') }.should.raise(Errno::ENOENT)
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
end
- platform_is :openbsd do
- it "raises an NotImplementedError" do
- -> { File.birthtime(@file) }.should raise_error(NotImplementedError)
+ describe "File#birthtime" do
+ before :each do
+ @file = File.open(__FILE__)
end
- end
-
- # TODO: depends on Linux kernel version
-end
-describe "File#birthtime" do
- before :each do
- @file = File.open(__FILE__)
- end
-
- after :each do
- @file.close
- @file = nil
- end
+ after :each do
+ @file.close
+ @file = nil
+ end
- platform_is :windows, :darwin, :freebsd, :netbsd do
it "returns the birth time for self" do
@file.birthtime
- @file.birthtime.should be_kind_of(Time)
+ @file.birthtime.should.is_a?(Time)
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
end
-
- platform_is :openbsd do
- it "raises an NotImplementedError" do
- -> { @file.birthtime }.should raise_error(NotImplementedError)
- end
- end
-
- # TODO: depends on Linux kernel version
end
diff --git a/spec/ruby/core/file/chmod_spec.rb b/spec/ruby/core/file/chmod_spec.rb
index 5ca15c9748..e0fd10ceb1 100644
--- a/spec/ruby/core/file/chmod_spec.rb
+++ b/spec/ruby/core/file/chmod_spec.rb
@@ -16,8 +16,8 @@ describe "File#chmod" do
end
it "raises RangeError with too large values" do
- -> { @file.chmod(2**64) }.should raise_error(RangeError)
- -> { @file.chmod(-2**63 - 1) }.should raise_error(RangeError)
+ -> { @file.chmod(2**64) }.should.raise(RangeError)
+ -> { @file.chmod(-2**63 - 1) }.should.raise(RangeError)
end
it "invokes to_int on non-integer argument" do
@@ -97,8 +97,8 @@ describe "File.chmod" do
end
it "raises RangeError with too large values" do
- -> { File.chmod(2**64, @file) }.should raise_error(RangeError)
- -> { File.chmod(-2**63 - 1, @file) }.should raise_error(RangeError)
+ -> { File.chmod(2**64, @file) }.should.raise(RangeError)
+ -> { File.chmod(-2**63 - 1, @file) }.should.raise(RangeError)
end
it "accepts an object that has a #to_path method" do
@@ -106,13 +106,13 @@ describe "File.chmod" do
end
it "throws a TypeError if the given path is not coercible into a string" do
- -> { File.chmod(0, []) }.should raise_error(TypeError)
+ -> { File.chmod(0, []) }.should.raise(TypeError)
end
it "raises an error for a non existent path" do
-> {
File.chmod(0644, "#{@file}.not.existing")
- }.should raise_error(Errno::ENOENT)
+ }.should.raise(Errno::ENOENT)
end
it "invokes to_int on non-integer argument" do
diff --git a/spec/ruby/core/file/chown_spec.rb b/spec/ruby/core/file/chown_spec.rb
index 8cc8f0d04b..3353aafc70 100644
--- a/spec/ruby/core/file/chown_spec.rb
+++ b/spec/ruby/core/file/chown_spec.rb
@@ -68,7 +68,7 @@ describe "File.chown" do
it "raises an error for a non existent path" do
-> {
File.chown(nil, nil, "#{@fname}_not_existing")
- }.should raise_error(Errno::ENOENT)
+ }.should.raise(Errno::ENOENT)
end
end
@@ -78,15 +78,15 @@ describe "File.chown" do
end
describe "File#chown" do
- before :each do
- @fname = tmp('file_chown_test')
- @file = File.open(@fname, 'w')
- end
+ before :each do
+ @fname = tmp('file_chown_test')
+ @file = File.open(@fname, 'w')
+ end
- after :each do
- @file.close unless @file.closed?
- rm_r @fname
- end
+ after :each do
+ @file.close unless @file.closed?
+ rm_r @fname
+ end
as_superuser do
platform_is :windows do
diff --git a/spec/ruby/core/file/constants/constants_spec.rb b/spec/ruby/core/file/constants/constants_spec.rb
index 86946822c5..9d9c1c3b25 100644
--- a/spec/ruby/core/file/constants/constants_spec.rb
+++ b/spec/ruby/core/file/constants/constants_spec.rb
@@ -4,10 +4,10 @@ require_relative '../../../spec_helper'
"FNM_DOTMATCH", "FNM_EXTGLOB", "FNM_NOESCAPE", "FNM_PATHNAME",
"FNM_SYSCASE", "LOCK_EX", "LOCK_NB", "LOCK_SH",
"LOCK_UN", "NONBLOCK", "RDONLY",
- "RDWR", "TRUNC", "WRONLY"].each do |const|
+ "RDWR", "TRUNC", "WRONLY", "SHARE_DELETE"].each do |const|
describe "File::Constants::#{const}" do
it "is defined" do
- File::Constants.const_defined?(const).should be_true
+ File::Constants.const_defined?(const).should == true
end
end
end
@@ -15,7 +15,7 @@ end
platform_is :windows do
describe "File::Constants::BINARY" do
it "is defined" do
- File::Constants.const_defined?(:BINARY).should be_true
+ File::Constants.const_defined?(:BINARY).should == true
end
end
end
@@ -24,7 +24,7 @@ platform_is_not :windows do
["NOCTTY", "SYNC"].each do |const|
describe "File::Constants::#{const}" do
it "is defined" do
- File::Constants.const_defined?(const).should be_true
+ File::Constants.const_defined?(const).should == true
end
end
end
diff --git a/spec/ruby/core/file/ctime_spec.rb b/spec/ruby/core/file/ctime_spec.rb
index b16eb13c1e..cf37d1f4ee 100644
--- a/spec/ruby/core/file/ctime_spec.rb
+++ b/spec/ruby/core/file/ctime_spec.rb
@@ -11,17 +11,20 @@ describe "File.ctime" do
it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself)." do
File.ctime(@file)
- File.ctime(@file).should be_kind_of(Time)
+ File.ctime(@file).should.is_a?(Time)
end
platform_is :linux, :windows do
it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself) with microseconds." do
- supports_subseconds = Integer(`stat -c%z '#{__FILE__}'`[/\.(\d+)/, 1], 10)
+ supports_subseconds = Integer(`stat -c%z '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10)
if supports_subseconds != 0
File.ctime(__FILE__).usec.should > 0
else
File.ctime(__FILE__).usec.should == 0
end
+ rescue Errno::ENOENT => e
+ # Windows don't have stat command.
+ skip e.message
end
end
@@ -30,7 +33,7 @@ describe "File.ctime" do
end
it "raises an Errno::ENOENT exception if the file is not found" do
- -> { File.ctime('bogus') }.should raise_error(Errno::ENOENT)
+ -> { File.ctime('bogus') }.should.raise(Errno::ENOENT)
end
end
@@ -46,6 +49,6 @@ describe "File#ctime" do
it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself)." do
@file.ctime
- @file.ctime.should be_kind_of(Time)
+ @file.ctime.should.is_a?(Time)
end
end
diff --git a/spec/ruby/core/file/dirname_spec.rb b/spec/ruby/core/file/dirname_spec.rb
index cf0f909f59..855148a684 100644
--- a/spec/ruby/core/file/dirname_spec.rb
+++ b/spec/ruby/core/file/dirname_spec.rb
@@ -11,24 +11,37 @@ describe "File.dirname" do
File.dirname('/foo/foo').should == '/foo'
end
- ruby_version_is '3.1' do
+ context "when level is passed" do
it "returns all the components of filename except the last parts by the level" do
File.dirname('/home/jason', 2).should == '/'
File.dirname('/home/jason/poot.txt', 2).should == '/home'
end
- it "returns the same string if the level is 0" do
+ it "returns the same String if the level is 0" do
File.dirname('poot.txt', 0).should == 'poot.txt'
File.dirname('/', 0).should == '/'
end
it "raises ArgumentError if the level is negative" do
- -> {File.dirname('/home/jason', -1)}.should raise_error(ArgumentError)
+ -> {
+ File.dirname('/home/jason', -1)
+ }.should.raise(ArgumentError, "negative level: -1")
+ end
+
+ it "returns '/' when level exceeds the number of segments in the path" do
+ File.dirname("/home/jason", 100).should == '/'
+ end
+
+ it "calls #to_int if passed not numeric value" do
+ object = Object.new
+ def object.to_int; 2; end
+
+ File.dirname("/a/b/c/d", object).should == '/a/b'
end
end
it "returns a String" do
- File.dirname("foo").should be_kind_of(String)
+ File.dirname("foo").should.is_a?(String)
end
it "does not modify its argument" do
@@ -50,22 +63,48 @@ describe "File.dirname" do
end
it "returns all the components of filename except the last one (edge cases on all platforms)" do
- File.dirname("").should == "."
- File.dirname(".").should == "."
- File.dirname("./").should == "."
- File.dirname("./b/./").should == "./b"
- File.dirname("..").should == "."
- File.dirname("../").should == "."
- File.dirname("/").should == "/"
- File.dirname("/.").should == "/"
- File.dirname("/foo/").should == "/"
- File.dirname("/foo/.").should == "/foo"
- File.dirname("/foo/./").should == "/foo"
- File.dirname("/foo/../.").should == "/foo/.."
- File.dirname("foo/../").should == "foo"
+ File.dirname("").should == "."
+ File.dirname(".").should == "."
+ File.dirname("./").should == "."
+ File.dirname("./b/./").should == "./b"
+ File.dirname("..").should == "."
+ File.dirname("../").should == "."
+ File.dirname("/").should == "/"
+ File.dirname("/.").should == "/"
+ File.dirname("/foo/").should == "/"
+ File.dirname("/foo/.").should == "/foo"
+ File.dirname("/foo/./").should == "/foo"
+ File.dirname("/foo/../.").should == "/foo/.."
+ File.dirname("foo/../").should == "foo"
+ end
+
+ it "rejects strings encoded with non ASCII-compatible encodings" do
+ Encoding.list.reject(&:ascii_compatible?).reject(&:dummy?).each do |enc|
+ path = "/foo/bar".encode(enc)
+ -> {
+ File.dirname(path)
+ }.should.raise(Encoding::CompatibilityError)
+ end
+ end
+
+ it "works with all ASCII-compatible encodings" do
+ Encoding.list.select(&:ascii_compatible?).each do |enc|
+ File.dirname("/foo/bar".encode(enc)).should == "/foo".encode(enc)
+ end
+ end
+
+ it "handles Shift JIS 0x5C (\\) as second byte of a multi-byte sequence" do
+ # dir/fileソname.txt
+ path = "dir/file\x83\x5cname.txt".b.force_encoding(Encoding::SHIFT_JIS)
+ path.valid_encoding?.should == true
+ File.dirname(path).should == "dir"
end
platform_is_not :windows do
+ it "ignores repeated leading / (edge cases on non-windows)" do
+ File.dirname("/////foo/bar/").should == "/foo"
+ end
+
it "returns all the components of filename except the last one (edge cases on non-windows)" do
File.dirname('/////').should == '/'
File.dirname("//foo//").should == "/"
@@ -81,6 +120,13 @@ describe "File.dirname" do
File.dirname("//foo//").should == "//foo"
File.dirname('/////').should == '//'
end
+
+ it "handles Shift JIS 0x5C (\\) as second byte of a multi-byte sequence (windows)" do
+ # dir\fileソname.txt
+ path = "dir\\file\x83\x5cname.txt".b.force_encoding(Encoding::SHIFT_JIS)
+ path.valid_encoding?.should == true
+ File.dirname(path).should == "dir"
+ end
end
it "accepts an object that has a #to_path method" do
@@ -88,10 +134,10 @@ describe "File.dirname" do
end
it "raises a TypeError if not passed a String type" do
- -> { File.dirname(nil) }.should raise_error(TypeError)
- -> { File.dirname(0) }.should raise_error(TypeError)
- -> { File.dirname(true) }.should raise_error(TypeError)
- -> { File.dirname(false) }.should raise_error(TypeError)
+ -> { File.dirname(nil) }.should.raise(TypeError)
+ -> { File.dirname(0) }.should.raise(TypeError)
+ -> { File.dirname(true) }.should.raise(TypeError)
+ -> { File.dirname(false) }.should.raise(TypeError)
end
# Windows specific tests
diff --git a/spec/ruby/core/file/empty_spec.rb b/spec/ruby/core/file/empty_spec.rb
index 77f132303e..e8c9941676 100644
--- a/spec/ruby/core/file/empty_spec.rb
+++ b/spec/ruby/core/file/empty_spec.rb
@@ -4,10 +4,4 @@ require_relative '../../shared/file/zero'
describe "File.empty?" 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
diff --git a/spec/ruby/core/file/exist_spec.rb b/spec/ruby/core/file/exist_spec.rb
index ddb5febcba..b5600e5b07 100644
--- a/spec/ruby/core/file/exist_spec.rb
+++ b/spec/ruby/core/file/exist_spec.rb
@@ -4,3 +4,9 @@ require_relative '../../shared/file/exist'
describe "File.exist?" do
it_behaves_like :file_exist, :exist?, File
end
+
+describe "File.exists?" do
+ it "has been removed" do
+ File.should_not.respond_to?(:exists?)
+ end
+end
diff --git a/spec/ruby/core/file/expand_path_spec.rb b/spec/ruby/core/file/expand_path_spec.rb
index c31f885b92..160494f145 100644
--- a/spec/ruby/core/file/expand_path_spec.rb
+++ b/spec/ruby/core/file/expand_path_spec.rb
@@ -92,7 +92,7 @@ describe "File.expand_path" do
end
it "raises an ArgumentError if the path is not valid" do
- -> { File.expand_path("~a_not_existing_user") }.should raise_error(ArgumentError)
+ -> { File.expand_path("~a_not_existing_user") }.should.raise(ArgumentError)
end
it "expands ~ENV['USER'] to the user's home directory" do
@@ -117,9 +117,9 @@ describe "File.expand_path" do
end
it "raises a TypeError if not passed a String type" do
- -> { File.expand_path(1) }.should raise_error(TypeError)
- -> { File.expand_path(nil) }.should raise_error(TypeError)
- -> { File.expand_path(true) }.should raise_error(TypeError)
+ -> { File.expand_path(1) }.should.raise(TypeError)
+ -> { File.expand_path(nil) }.should.raise(TypeError)
+ -> { File.expand_path(true) }.should.raise(TypeError)
end
platform_is_not :windows do
@@ -137,11 +137,11 @@ describe "File.expand_path" do
it "returns a String in the same encoding as the argument" do
Encoding.default_external = Encoding::SHIFT_JIS
- path = "./a".force_encoding Encoding::CP1251
- File.expand_path(path).encoding.should equal(Encoding::CP1251)
+ path = "./a".dup.force_encoding Encoding::CP1251
+ File.expand_path(path).encoding.should.equal?(Encoding::CP1251)
weird_path = [222, 173, 190, 175].pack('C*')
- File.expand_path(weird_path).encoding.should equal(Encoding::BINARY)
+ File.expand_path(weird_path).encoding.should.equal?(Encoding::BINARY)
end
platform_is_not :windows do
@@ -159,7 +159,7 @@ describe "File.expand_path" do
platform_is_not :windows do
it "raises an Encoding::CompatibilityError if the external encoding is not compatible" do
Encoding.default_external = Encoding::UTF_16BE
- -> { File.expand_path("./a") }.should raise_error(Encoding::CompatibilityError)
+ -> { File.expand_path("./a") }.should.raise(Encoding::CompatibilityError)
end
end
@@ -179,7 +179,7 @@ describe "File.expand_path" do
str = FileSpecs::SubString.new "./a/b/../c"
path = File.expand_path(str, @base)
path.should == "#{@base}/a/c"
- path.should be_an_instance_of(String)
+ path.should.instance_of?(String)
end
end
@@ -244,7 +244,7 @@ platform_is_not :windows do
it "raises an ArgumentError when passed '~' if HOME == ''" do
ENV["HOME"] = ""
- -> { File.expand_path("~") }.should raise_error(ArgumentError)
+ -> { File.expand_path("~") }.should.raise(ArgumentError)
end
end
@@ -259,7 +259,7 @@ platform_is_not :windows do
it "raises an ArgumentError" do
ENV["HOME"] = "non-absolute"
- -> { File.expand_path("~") }.should raise_error(ArgumentError, 'non-absolute home')
+ -> { File.expand_path("~") }.should.raise(ArgumentError, 'non-absolute home')
end
end
end
diff --git a/spec/ruby/core/file/extname_spec.rb b/spec/ruby/core/file/extname_spec.rb
index d20cf813d9..995d0ea31a 100644
--- a/spec/ruby/core/file/extname_spec.rb
+++ b/spec/ruby/core/file/extname_spec.rb
@@ -57,15 +57,15 @@ describe "File.extname" do
end
it "raises a TypeError if not passed a String type" do
- -> { File.extname(nil) }.should raise_error(TypeError)
- -> { File.extname(0) }.should raise_error(TypeError)
- -> { File.extname(true) }.should raise_error(TypeError)
- -> { File.extname(false) }.should raise_error(TypeError)
+ -> { File.extname(nil) }.should.raise(TypeError)
+ -> { File.extname(0) }.should.raise(TypeError)
+ -> { File.extname(true) }.should.raise(TypeError)
+ -> { File.extname(false) }.should.raise(TypeError)
end
it "raises an ArgumentError if not passed one argument" do
- -> { File.extname }.should raise_error(ArgumentError)
- -> { File.extname("foo.bar", "foo.baz") }.should raise_error(ArgumentError)
+ -> { File.extname }.should.raise(ArgumentError)
+ -> { File.extname("foo.bar", "foo.baz") }.should.raise(ArgumentError)
end
diff --git a/spec/ruby/core/file/flock_spec.rb b/spec/ruby/core/file/flock_spec.rb
index 751e99d994..23ddf89ed8 100644
--- a/spec/ruby/core/file/flock_spec.rb
+++ b/spec/ruby/core/file/flock_spec.rb
@@ -30,7 +30,7 @@ describe "File#flock" do
it "returns false if trying to lock an exclusively locked file" do
@file.flock File::LOCK_EX
- ruby_exe(<<-END_OF_CODE, escape: true).should == "false"
+ ruby_exe(<<-END_OF_CODE).should == "false"
File.open('#{@name}', "w") do |f2|
print f2.flock(File::LOCK_EX | File::LOCK_NB).to_s
end
@@ -40,7 +40,7 @@ describe "File#flock" do
it "blocks if trying to lock an exclusively locked file" do
@file.flock File::LOCK_EX
- out = ruby_exe(<<-END_OF_CODE, escape: true)
+ out = ruby_exe(<<-END_OF_CODE)
running = false
t = Thread.new do
@@ -72,35 +72,3 @@ describe "File#flock" do
end
end
end
-
-platform_is :solaris do
- describe "File#flock on Solaris" do
- before :each do
- @name = tmp("flock_test")
- touch(@name)
-
- @read_file = File.open @name, "r"
- @write_file = File.open @name, "w"
- end
-
- after :each do
- @read_file.flock File::LOCK_UN
- @read_file.close
- @write_file.flock File::LOCK_UN
- @write_file.close
- rm_r @name
- end
-
- it "fails with EBADF acquiring exclusive lock on read-only File" do
- -> do
- @read_file.flock File::LOCK_EX
- end.should raise_error(Errno::EBADF)
- end
-
- it "fails with EBADF acquiring shared lock on read-only File" do
- -> do
- @write_file.flock File::LOCK_SH
- end.should raise_error(Errno::EBADF)
- end
- end
-end
diff --git a/spec/ruby/core/file/ftype_spec.rb b/spec/ruby/core/file/ftype_spec.rb
index cdddc404dc..ab9f76b79b 100644
--- a/spec/ruby/core/file/ftype_spec.rb
+++ b/spec/ruby/core/file/ftype_spec.rb
@@ -7,19 +7,19 @@ describe "File.ftype" do
end
it "raises ArgumentError if not given exactly one filename" do
- -> { File.ftype }.should raise_error(ArgumentError)
- -> { File.ftype('blah', 'bleh') }.should raise_error(ArgumentError)
+ -> { File.ftype }.should.raise(ArgumentError)
+ -> { File.ftype('blah', 'bleh') }.should.raise(ArgumentError)
end
it "raises Errno::ENOENT if the file is not valid" do
-> {
File.ftype("/#{$$}#{Time.now.to_f}")
- }.should raise_error(Errno::ENOENT)
+ }.should.raise(Errno::ENOENT)
end
it "returns a String" do
FileSpecs.normal_file do |file|
- File.ftype(file).should be_kind_of(String)
+ File.ftype(file).should.is_a?(String)
end
end
diff --git a/spec/ruby/core/file/inspect_spec.rb b/spec/ruby/core/file/inspect_spec.rb
index 148e789c62..fe87429e8d 100644
--- a/spec/ruby/core/file/inspect_spec.rb
+++ b/spec/ruby/core/file/inspect_spec.rb
@@ -12,6 +12,6 @@ describe "File#inspect" do
end
it "returns a String" do
- @file.inspect.should be_an_instance_of(String)
+ @file.inspect.should.instance_of?(String)
end
end
diff --git a/spec/ruby/core/file/join_spec.rb b/spec/ruby/core/file/join_spec.rb
index 0feedbae93..0f0911ea31 100644
--- a/spec/ruby/core/file/join_spec.rb
+++ b/spec/ruby/core/file/join_spec.rb
@@ -52,7 +52,7 @@ describe "File.join" do
it "returns a duplicate string when given a single argument" do
str = "usr"
File.join(str).should == str
- File.join(str).should_not equal(str)
+ File.join(str).should_not.equal?(str)
end
it "supports any number of arguments" do
@@ -104,15 +104,15 @@ describe "File.join" do
it "raises an ArgumentError if passed a recursive array" do
a = ["a"]
a << a
- -> { File.join a }.should raise_error(ArgumentError)
+ -> { File.join a }.should.raise(ArgumentError)
end
it "raises a TypeError exception when args are nil" do
- -> { File.join nil }.should raise_error(TypeError)
+ -> { File.join nil }.should.raise(TypeError)
end
it "calls #to_str" do
- -> { File.join(mock('x')) }.should raise_error(TypeError)
+ -> { File.join(mock('x')) }.should.raise(TypeError)
bin = mock("bin")
bin.should_receive(:to_str).exactly(:twice).and_return("bin")
@@ -129,7 +129,7 @@ describe "File.join" do
end
it "calls #to_path" do
- -> { File.join(mock('x')) }.should raise_error(TypeError)
+ -> { File.join(mock('x')) }.should.raise(TypeError)
bin = mock("bin")
bin.should_receive(:to_path).exactly(:twice).and_return("bin")
@@ -138,10 +138,10 @@ describe "File.join" do
end
it "raises errors for null bytes" do
- -> { File.join("\x00x", "metadata.gz") }.should raise_error(ArgumentError) { |e|
+ -> { File.join("\x00x", "metadata.gz") }.should.raise(ArgumentError) { |e|
e.message.should == 'string contains null byte'
}
- -> { File.join("metadata.gz", "\x00x") }.should raise_error(ArgumentError) { |e|
+ -> { File.join("metadata.gz", "\x00x") }.should.raise(ArgumentError) { |e|
e.message.should == 'string contains null byte'
}
end
diff --git a/spec/ruby/core/file/lchmod_spec.rb b/spec/ruby/core/file/lchmod_spec.rb
index 7420b95e4a..3c44374983 100644
--- a/spec/ruby/core/file/lchmod_spec.rb
+++ b/spec/ruby/core/file/lchmod_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "File.lchmod" do
- platform_is_not :linux, :windows, :openbsd, :solaris, :aix do
+ platform_is_not :linux, :windows, :openbsd, :aix do
before :each do
@fname = tmp('file_chmod_test')
@lname = @fname + '.lnk'
diff --git a/spec/ruby/core/file/link_spec.rb b/spec/ruby/core/file/link_spec.rb
index a5d5b4815f..768ee4b0fa 100644
--- a/spec/ruby/core/file/link_spec.rb
+++ b/spec/ruby/core/file/link_spec.rb
@@ -22,18 +22,18 @@ describe "File.link" do
it "raises an Errno::EEXIST if the target already exists" do
File.link(@file, @link)
- -> { File.link(@file, @link) }.should raise_error(Errno::EEXIST)
+ -> { File.link(@file, @link) }.should.raise(Errno::EEXIST)
end
it "raises an ArgumentError if not passed two arguments" do
- -> { File.link }.should raise_error(ArgumentError)
- -> { File.link(@file) }.should raise_error(ArgumentError)
- -> { File.link(@file, @link, @file) }.should raise_error(ArgumentError)
+ -> { File.link }.should.raise(ArgumentError)
+ -> { File.link(@file) }.should.raise(ArgumentError)
+ -> { File.link(@file, @link, @file) }.should.raise(ArgumentError)
end
it "raises a TypeError if not passed String types" do
- -> { File.link(@file, nil) }.should raise_error(TypeError)
- -> { File.link(@file, 1) }.should raise_error(TypeError)
+ -> { File.link(@file, nil) }.should.raise(TypeError)
+ -> { File.link(@file, 1) }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/file/lutime_spec.rb b/spec/ruby/core/file/lutime_spec.rb
index 1f0625f61e..0f6df42ea3 100644
--- a/spec/ruby/core/file/lutime_spec.rb
+++ b/spec/ruby/core/file/lutime_spec.rb
@@ -1,7 +1,12 @@
require_relative '../../spec_helper'
+require_relative 'shared/update_time'
-describe "File.lutime" do
- platform_is_not :windows do
+platform_is_not :windows do
+ describe "File.lutime" do
+ it_behaves_like :update_time, :lutime
+ end
+
+ describe "File.lutime" do
before :each do
@atime = Time.utc(2000)
@mtime = Time.utc(2001)
diff --git a/spec/ruby/core/file/mkfifo_spec.rb b/spec/ruby/core/file/mkfifo_spec.rb
index 19298c967c..ce4a67fe31 100644
--- a/spec/ruby/core/file/mkfifo_spec.rb
+++ b/spec/ruby/core/file/mkfifo_spec.rb
@@ -19,13 +19,13 @@ describe "File.mkfifo" do
context "when path passed is not a String value" do
it "raises a TypeError" do
- -> { File.mkfifo(:"/tmp/fifo") }.should raise_error(TypeError)
+ -> { File.mkfifo(:"/tmp/fifo") }.should.raise(TypeError)
end
end
context "when path does not exist" do
it "raises an Errno::ENOENT exception" do
- -> { File.mkfifo("/bogus/path") }.should raise_error(Errno::ENOENT)
+ -> { File.mkfifo("/bogus/path") }.should.raise(Errno::ENOENT)
end
end
diff --git a/spec/ruby/core/file/mtime_spec.rb b/spec/ruby/core/file/mtime_spec.rb
index 8d47d3021a..d83725e25d 100644
--- a/spec/ruby/core/file/mtime_spec.rb
+++ b/spec/ruby/core/file/mtime_spec.rb
@@ -11,25 +11,30 @@ describe "File.mtime" do
end
it "returns the modification Time of the file" do
- File.mtime(@filename).should be_kind_of(Time)
+ File.mtime(@filename).should.is_a?(Time)
File.mtime(@filename).should be_close(@mtime, TIME_TOLERANCE)
end
platform_is :linux, :windows do
- it "returns the modification Time of the file with microseconds" do
- supports_subseconds = Integer(`stat -c%y '#{__FILE__}'`[/\.(\d+)/, 1], 10)
- if supports_subseconds != 0
- expected_time = Time.at(Time.now.to_i + 0.123456)
- File.utime 0, expected_time, @filename
- File.mtime(@filename).usec.should == expected_time.usec
- else
- File.mtime(__FILE__).usec.should == 0
+ unless ENV.key?('TRAVIS') # https://bugs.ruby-lang.org/issues/17926
+ it "returns the modification Time of the file with microseconds" do
+ supports_subseconds = Integer(`stat -c%y '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10)
+ if supports_subseconds != 0
+ expected_time = Time.at(Time.now.to_i + 0.123456)
+ File.utime 0, expected_time, @filename
+ File.mtime(@filename).usec.should == expected_time.usec
+ else
+ File.mtime(__FILE__).usec.should == 0
+ end
+ rescue Errno::ENOENT => e
+ # Windows don't have stat command.
+ skip e.message
end
end
end
it "raises an Errno::ENOENT exception if the file is not found" do
- -> { File.mtime('bogus') }.should raise_error(Errno::ENOENT)
+ -> { File.mtime('bogus') }.should.raise(Errno::ENOENT)
end
end
@@ -45,7 +50,7 @@ describe "File#mtime" do
end
it "returns the modification Time of the file" do
- @f.mtime.should be_kind_of(Time)
+ @f.mtime.should.is_a?(Time)
end
end
diff --git a/spec/ruby/core/file/new_spec.rb b/spec/ruby/core/file/new_spec.rb
index 004f78503a..4cd2cb5dcb 100644
--- a/spec/ruby/core/file/new_spec.rb
+++ b/spec/ruby/core/file/new_spec.rb
@@ -16,13 +16,13 @@ describe "File.new" do
it "returns a new File with mode string" do
@fh = File.new(@file, 'w')
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
it "returns a new File with mode num" do
@fh = File.new(@file, @flags)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
@@ -30,7 +30,7 @@ describe "File.new" do
rm_r @file
File.umask(0011)
@fh = File.new(@file, @flags, 0755)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
platform_is_not :windows do
File.stat(@file).mode.to_s(8).should == "100744"
end
@@ -44,7 +44,7 @@ describe "File.new" do
rm_r @file
begin
f = File.new(@file, "w", 0444)
- -> { f.puts("test") }.should_not raise_error(IOError)
+ -> { f.puts("test") }.should_not.raise(IOError)
ensure
f.close
end
@@ -74,49 +74,84 @@ describe "File.new" do
@fh = File.new(@file)
fh_copy = File.new(@fh.fileno)
fh_copy.autoclose = false
- fh_copy.should be_kind_of(File)
+ fh_copy.should.is_a?(File)
+ File.should.exist?(@file)
+ end
+
+ it "returns a new read-only File when mode is not specified" do
+ @fh = File.new(@file)
+
+ -> { @fh.puts("test") }.should.raise(IOError)
+ @fh.read.should == ""
+ File.should.exist?(@file)
+ end
+
+ it "returns a new read-only File when mode is not specified but flags option is present" do
+ @fh = File.new(@file, flags: File::CREAT)
+
+ -> { @fh.puts("test") }.should.raise(IOError)
+ @fh.read.should == ""
File.should.exist?(@file)
end
it "creates a new file when use File::EXCL mode" do
@fh = File.new(@file, File::EXCL)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
- it "raises an Errorno::EEXIST if the file exists when create a new file with File::CREAT|File::EXCL" do
- -> { @fh = File.new(@file, File::CREAT|File::EXCL) }.should raise_error(Errno::EEXIST)
+ it "raises an Errno::EEXIST if the file exists when create a new file with File::CREAT|File::EXCL" do
+ -> { @fh = File.new(@file, File::CREAT|File::EXCL) }.should.raise(Errno::EEXIST)
end
it "creates a new file when use File::WRONLY|File::APPEND mode" do
@fh = File.new(@file, File::WRONLY|File::APPEND)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
it "returns a new File when use File::APPEND mode" do
@fh = File.new(@file, File::APPEND)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
it "returns a new File when use File::RDONLY|File::APPEND mode" do
@fh = File.new(@file, File::RDONLY|File::APPEND)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
it "returns a new File when use File::RDONLY|File::WRONLY mode" do
@fh = File.new(@file, File::RDONLY|File::WRONLY)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
-
it "creates a new file when use File::WRONLY|File::TRUNC mode" do
@fh = File.new(@file, File::WRONLY|File::TRUNC)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
+ File.should.exist?(@file)
+ end
+
+ it "returns a new read-only File when use File::RDONLY|File::CREAT mode" do
+ @fh = File.new(@file, File::RDONLY|File::CREAT)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
+
+ # it's read-only
+ -> { @fh.puts("test") }.should.raise(IOError)
+ @fh.read.should == ""
+ end
+
+ it "returns a new read-only File when use File::CREAT mode" do
+ @fh = File.new(@file, File::CREAT)
+ @fh.should.is_a?(File)
+ File.should.exist?(@file)
+
+ # it's read-only
+ -> { @fh.puts("test") }.should.raise(IOError)
+ @fh.read.should == ""
end
it "coerces filename using to_str" do
@@ -133,17 +168,43 @@ describe "File.new" do
File.should.exist?(@file)
end
+ it "accepts options as a keyword argument" do
+ @fh = File.new(@file, 'w', 0755, flags: @flags)
+ @fh.should.is_a?(File)
+ @fh.close
+
+ -> {
+ @fh = File.new(@file, 'w', 0755, {flags: @flags})
+ }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
+ end
+
+ it "bitwise-ORs mode and flags option" do
+ -> {
+ @fh = File.new(@file, 'w', flags: File::EXCL)
+ }.should.raise(Errno::EEXIST, /File exists/)
+
+ -> {
+ @fh = File.new(@file, mode: 'w', flags: File::EXCL)
+ }.should.raise(Errno::EEXIST, /File exists/)
+ end
+
+ it "does not use the given block and warns to use File::open" do
+ -> {
+ @fh = File.new(@file) { raise }
+ }.should complain(/warning: File::new\(\) does not take block; use File::open\(\) instead/)
+ end
+
it "raises a TypeError if the first parameter can't be coerced to a string" do
- -> { File.new(true) }.should raise_error(TypeError)
- -> { File.new(false) }.should raise_error(TypeError)
+ -> { File.new(true) }.should.raise(TypeError)
+ -> { File.new(false) }.should.raise(TypeError)
end
it "raises a TypeError if the first parameter is nil" do
- -> { File.new(nil) }.should raise_error(TypeError)
+ -> { File.new(nil) }.should.raise(TypeError)
end
it "raises an Errno::EBADF if the first parameter is an invalid file descriptor" do
- -> { File.new(-1) }.should raise_error(Errno::EBADF)
+ -> { File.new(-1) }.should.raise(Errno::EBADF)
end
platform_is_not :windows do
@@ -152,7 +213,7 @@ describe "File.new" do
-> {
f = File.new(@fh.fileno, @flags)
f.autoclose = false
- }.should raise_error(Errno::EINVAL)
+ }.should.raise(Errno::EINVAL)
end
end
diff --git a/spec/ruby/core/file/open_spec.rb b/spec/ruby/core/file/open_spec.rb
index 1729780570..7318c31636 100644
--- a/spec/ruby/core/file/open_spec.rb
+++ b/spec/ruby/core/file/open_spec.rb
@@ -40,7 +40,7 @@ describe "File.open" do
it "propagates non-StandardErrors produced by close" do
-> {
File.open(@file, 'r') { |f| FileSpecs.make_closer f, Exception }
- }.should raise_error(Exception)
+ }.should.raise(Exception)
ScratchPad.recorded.should == [:file_opened, :file_closed]
end
@@ -48,7 +48,7 @@ describe "File.open" do
it "propagates StandardErrors produced by close" do
-> {
File.open(@file, 'r') { |f| FileSpecs.make_closer f, StandardError }
- }.should raise_error(StandardError)
+ }.should.raise(StandardError)
ScratchPad.recorded.should == [:file_opened, :file_closed]
end
@@ -62,13 +62,13 @@ describe "File.open" do
it "opens the file (basic case)" do
@fh = File.open(@file)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
it "opens the file with unicode characters" do
@fh = File.open(@unicode_path, "w")
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@unicode_path)
end
@@ -79,7 +79,7 @@ describe "File.open" do
it "opens with mode string" do
@fh = File.open(@file, 'w')
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
@@ -90,7 +90,7 @@ describe "File.open" do
it "opens a file with mode num" do
@fh = File.open(@file, @flags)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
@@ -101,7 +101,7 @@ describe "File.open" do
it "opens a file with mode and permission as nil" do
@fh = File.open(@file, nil, nil)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
end
# For this test we delete the file first to reset the perms
@@ -109,7 +109,7 @@ describe "File.open" do
rm_r @file
File.umask(0011)
@fh = File.open(@file, @flags, 0755)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
platform_is_not :windows do
@fh.lstat.mode.to_s(8).should == "100744"
end
@@ -161,69 +161,69 @@ describe "File.open" do
@fh = File.open(@file)
fh_copy = File.open(@fh.fileno)
fh_copy.autoclose = false
- fh_copy.should be_kind_of(File)
+ fh_copy.should.is_a?(File)
File.should.exist?(@file)
end
it "opens a file that no exists when use File::WRONLY mode" do
- -> { File.open(@nonexistent, File::WRONLY) }.should raise_error(Errno::ENOENT)
+ -> { File.open(@nonexistent, File::WRONLY) }.should.raise(Errno::ENOENT)
end
it "opens a file that no exists when use File::RDONLY mode" do
- -> { File.open(@nonexistent, File::RDONLY) }.should raise_error(Errno::ENOENT)
+ -> { File.open(@nonexistent, File::RDONLY) }.should.raise(Errno::ENOENT)
end
it "opens a file that no exists when use 'r' mode" do
- -> { File.open(@nonexistent, 'r') }.should raise_error(Errno::ENOENT)
+ -> { File.open(@nonexistent, 'r') }.should.raise(Errno::ENOENT)
end
it "opens a file that no exists when use File::EXCL mode" do
- -> { File.open(@nonexistent, File::EXCL) }.should raise_error(Errno::ENOENT)
+ -> { File.open(@nonexistent, File::EXCL) }.should.raise(Errno::ENOENT)
end
it "opens a file that no exists when use File::NONBLOCK mode" do
- -> { File.open(@nonexistent, File::NONBLOCK) }.should raise_error(Errno::ENOENT)
+ -> { File.open(@nonexistent, File::NONBLOCK) }.should.raise(Errno::ENOENT)
end
platform_is_not :openbsd, :windows do
it "opens a file that no exists when use File::TRUNC mode" do
- -> { File.open(@nonexistent, File::TRUNC) }.should raise_error(Errno::ENOENT)
+ -> { File.open(@nonexistent, File::TRUNC) }.should.raise(Errno::ENOENT)
end
end
platform_is :openbsd, :windows do
it "does not open a file that does no exists when using File::TRUNC mode" do
- -> { File.open(@nonexistent, File::TRUNC) }.should raise_error(Errno::EINVAL)
+ -> { File.open(@nonexistent, File::TRUNC) }.should.raise(Errno::EINVAL)
end
end
platform_is_not :windows do
it "opens a file that no exists when use File::NOCTTY mode" do
- -> { File.open(@nonexistent, File::NOCTTY) }.should raise_error(Errno::ENOENT)
+ -> { File.open(@nonexistent, File::NOCTTY) }.should.raise(Errno::ENOENT)
end
end
it "opens a file that no exists when use File::CREAT mode" do
@fh = File.open(@nonexistent, File::CREAT) { |f| f }
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
it "opens a file that no exists when use 'a' mode" do
@fh = File.open(@nonexistent, 'a') { |f| f }
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
it "opens a file that no exists when use 'w' mode" do
@fh = File.open(@nonexistent, 'w') { |f| f }
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
# Check the grants associated to the different open modes combinations.
it "raises an ArgumentError exception when call with an unknown mode" do
- -> { File.open(@file, "q") }.should raise_error(ArgumentError)
+ -> { File.open(@file, "q") }.should.raise(ArgumentError)
end
it "can read in a block when call open with RDONLY mode" do
@@ -240,13 +240,13 @@ describe "File.open" do
it "raises an IO exception when write in a block opened with RDONLY mode" do
File.open(@file, File::RDONLY) do |f|
- -> { f.puts "writing ..." }.should raise_error(IOError)
+ -> { f.puts "writing ..." }.should.raise(IOError)
end
end
it "raises an IO exception when write in a block opened with 'r' mode" do
File.open(@file, "r") do |f|
- -> { f.puts "writing ..." }.should raise_error(IOError)
+ -> { f.puts "writing ..." }.should.raise(IOError)
end
end
@@ -261,7 +261,7 @@ describe "File.open" do
File.open(@file, File::WRONLY|File::RDONLY ) do |f|
f.gets.should == nil
end
- }.should raise_error(IOError)
+ }.should.raise(IOError)
end
it "can write in a block when call open with WRONLY mode" do
@@ -278,48 +278,48 @@ describe "File.open" do
it "raises an IOError when read in a block opened with WRONLY mode" do
File.open(@file, File::WRONLY) do |f|
- -> { f.gets }.should raise_error(IOError)
+ -> { f.gets }.should.raise(IOError)
end
end
it "raises an IOError when read in a block opened with 'w' mode" do
File.open(@file, "w") do |f|
- -> { f.gets }.should raise_error(IOError)
+ -> { f.gets }.should.raise(IOError)
end
end
it "raises an IOError when read in a block opened with 'a' mode" do
File.open(@file, "a") do |f|
- -> { f.gets }.should raise_error(IOError)
+ -> { f.gets }.should.raise(IOError)
end
end
it "raises an IOError when read in a block opened with 'a' mode" do
File.open(@file, "a") do |f|
f.puts("writing").should == nil
- -> { f.gets }.should raise_error(IOError)
+ -> { f.gets }.should.raise(IOError)
end
end
it "raises an IOError when read in a block opened with 'a' mode" do
File.open(@file, File::WRONLY|File::APPEND ) do |f|
- -> { f.gets }.should raise_error(IOError)
+ -> { f.gets }.should.raise(IOError)
end
end
it "raises an IOError when read in a block opened with File::WRONLY|File::APPEND mode" do
File.open(@file, File::WRONLY|File::APPEND ) do |f|
f.puts("writing").should == nil
- -> { f.gets }.should raise_error(IOError)
+ -> { f.gets }.should.raise(IOError)
end
end
- it "raises an IOError when read in a block opened with File::RDONLY|File::APPEND mode" do
+ it "raises an IOError when write in a block opened with File::RDONLY|File::APPEND mode" do
-> {
File.open(@file, File::RDONLY|File::APPEND ) do |f|
f.puts("writing")
end
- }.should raise_error(IOError)
+ }.should.raise(IOError)
end
it "can read and write in a block when call open with RDWR mode" do
@@ -336,7 +336,7 @@ describe "File.open" do
File.open(@file, File::EXCL) do |f|
f.puts("writing").should == nil
end
- }.should raise_error(IOError)
+ }.should.raise(IOError)
end
it "can read in a block when call open with File::EXCL mode" do
@@ -354,17 +354,17 @@ describe "File.open" do
end
end
- it "raises an Errorno::EEXIST if the file exists when open with File::CREAT|File::EXCL" do
+ it "raises an Errno::EEXIST if the file exists when open with File::CREAT|File::EXCL" do
-> {
File.open(@file, File::CREAT|File::EXCL) do |f|
f.puts("writing")
end
- }.should raise_error(Errno::EEXIST)
+ }.should.raise(Errno::EEXIST)
end
it "creates a new file when use File::WRONLY|File::APPEND mode" do
@fh = File.open(@file, File::WRONLY|File::APPEND)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
@@ -386,7 +386,7 @@ describe "File.open" do
File.open(@file, File::RDONLY|File::APPEND) do |f|
f.puts("writing").should == nil
end
- }.should raise_error(IOError)
+ }.should.raise(IOError)
end
platform_is_not :openbsd, :windows do
@@ -407,7 +407,7 @@ describe "File.open" do
fh1 = File.open(@file, "w")
begin
@fh = File.open(@file, File::WRONLY|File::TRUNC)
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
ensure
fh1.close
@@ -420,15 +420,15 @@ describe "File.open" do
File.open(@file, File::TRUNC) do |f|
f.puts("writing")
end
- }.should raise_error(IOError)
+ }.should.raise(IOError)
end
- it "raises an Errorno::EEXIST if the file exists when open with File::RDONLY|File::TRUNC" do
+ it "raises an Errno::EEXIST if the file exists when open with File::RDONLY|File::TRUNC" do
-> {
File.open(@file, File::RDONLY|File::TRUNC) do |f|
f.puts("writing").should == nil
end
- }.should raise_error(IOError)
+ }.should.raise(IOError)
end
end
@@ -438,15 +438,15 @@ describe "File.open" do
File.open(@file, File::TRUNC) do |f|
f.puts("writing")
end
- }.should raise_error(Errno::EINVAL)
+ }.should.raise(Errno::EINVAL)
end
- it "raises an Errorno::EEXIST if the file exists when open with File::RDONLY|File::TRUNC" do
+ it "raises an Errno::EEXIST if the file exists when open with File::RDONLY|File::TRUNC" do
-> {
File.open(@file, File::RDONLY|File::TRUNC) do |f|
f.puts("writing").should == nil
end
- }.should raise_error(Errno::EINVAL)
+ }.should.raise(Errno::EINVAL)
end
end
@@ -455,7 +455,7 @@ describe "File.open" do
it "raises an Errno::EACCES when opening non-permitted file" do
@fh = File.open(@file, "w")
@fh.chmod(000)
- -> { fh1 = File.open(@file); fh1.close }.should raise_error(Errno::EACCES)
+ -> { fh1 = File.open(@file); fh1.close }.should.raise(Errno::EACCES)
end
end
end
@@ -464,19 +464,19 @@ describe "File.open" do
it "raises an Errno::EACCES when opening read-only file" do
@fh = File.open(@file, "w")
@fh.chmod(0444)
- -> { File.open(@file, "w") }.should raise_error(Errno::EACCES)
+ -> { File.open(@file, "w") }.should.raise(Errno::EACCES)
end
end
it "opens a file for binary read" do
@fh = File.open(@file, "rb")
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
it "opens a file for binary write" do
@fh = File.open(@file, "wb")
- @fh.should be_kind_of(File)
+ @fh.should.is_a?(File)
File.should.exist?(@file)
end
@@ -543,21 +543,21 @@ describe "File.open" do
end
it "raises a TypeError if passed a filename that is not a String or Integer type" do
- -> { File.open(true) }.should raise_error(TypeError)
- -> { File.open(false) }.should raise_error(TypeError)
- -> { File.open(nil) }.should raise_error(TypeError)
+ -> { File.open(true) }.should.raise(TypeError)
+ -> { File.open(false) }.should.raise(TypeError)
+ -> { File.open(nil) }.should.raise(TypeError)
end
it "raises a SystemCallError if passed an invalid Integer type" do
- -> { File.open(-1) }.should raise_error(SystemCallError)
+ -> { File.open(-1) }.should.raise(SystemCallError)
end
it "raises an ArgumentError if passed the wrong number of arguments" do
- -> { File.open(@file, File::CREAT, 0755, 'test') }.should raise_error(ArgumentError)
+ -> { File.open(@file, File::CREAT, 0755, 'test') }.should.raise(ArgumentError)
end
it "raises an ArgumentError if passed an invalid string for mode" do
- -> { File.open(@file, 'fake') }.should raise_error(ArgumentError)
+ -> { File.open(@file, 'fake') }.should.raise(ArgumentError)
end
it "defaults external_encoding to BINARY for binary modes" do
@@ -565,9 +565,18 @@ describe "File.open" do
File.open(@file, 'wb+') {|f| f.external_encoding.should == Encoding::BINARY}
end
+ it "accepts options as a keyword argument" do
+ @fh = File.open(@file, 'w', 0755, flags: File::CREAT)
+ @fh.should.instance_of?(File)
+
+ -> {
+ File.open(@file, 'w', 0755, {flags: File::CREAT})
+ }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
+ end
+
it "uses the second argument as an options Hash" do
@fh = File.open(@file, mode: "r")
- @fh.should be_an_instance_of(File)
+ @fh.should.instance_of?(File)
end
it "calls #to_hash to convert the second argument to a Hash" do
@@ -580,17 +589,17 @@ describe "File.open" do
it "accepts extra flags as a keyword argument and combine with a string mode" do
-> {
File.open(@file, "w", flags: File::EXCL) { }
- }.should raise_error(Errno::EEXIST)
+ }.should.raise(Errno::EEXIST)
-> {
File.open(@file, mode: "w", flags: File::EXCL) { }
- }.should raise_error(Errno::EEXIST)
+ }.should.raise(Errno::EEXIST)
end
it "accepts extra flags as a keyword argument and combine with an integer mode" do
-> {
File.open(@file, File::WRONLY | File::CREAT, flags: File::EXCL) { }
- }.should raise_error(Errno::EEXIST)
+ }.should.raise(Errno::EEXIST)
end
platform_is_not :windows do
@@ -634,7 +643,7 @@ describe "File.open" do
it "raises ArgumentError if mixing :newline and binary mode" do
-> {
File.open(@file, "rb", newline: :universal) {}
- }.should raise_error(ArgumentError, "newline decorator with binary mode")
+ }.should.raise(ArgumentError, "newline decorator with binary mode")
end
context "'x' flag" do
@@ -654,12 +663,12 @@ describe "File.open" do
it "throws a Errno::EEXIST error if the file exists" do
touch @xfile
- -> { File.open(@xfile, "wx") }.should raise_error(Errno::EEXIST)
+ -> { File.open(@xfile, "wx") }.should.raise(Errno::EEXIST)
end
it "can't be used with 'r' and 'a' flags" do
- -> { File.open(@xfile, "rx") }.should raise_error(ArgumentError, 'invalid access mode rx')
- -> { File.open(@xfile, "ax") }.should raise_error(ArgumentError, 'invalid access mode ax')
+ -> { File.open(@xfile, "rx") }.should.raise(ArgumentError, 'invalid access mode rx')
+ -> { File.open(@xfile, "ax") }.should.raise(ArgumentError, 'invalid access mode ax')
end
end
end
@@ -679,8 +688,8 @@ describe "File.open when passed a file descriptor" do
it "opens a file" do
@file = File.open(@fd, "w")
- @file.should be_an_instance_of(File)
- @file.fileno.should equal(@fd)
+ @file.should.instance_of?(File)
+ @file.fileno.should.equal?(@fd)
@file.write @content
@file.flush
File.read(@name).should == @content
@@ -688,8 +697,8 @@ describe "File.open when passed a file descriptor" do
it "opens a file when passed a block" do
@file = File.open(@fd, "w") do |f|
- f.should be_an_instance_of(File)
- f.fileno.should equal(@fd)
+ f.should.instance_of?(File)
+ f.fileno.should.equal?(@fd)
f.write @content
f
end
diff --git a/spec/ruby/core/file/path_spec.rb b/spec/ruby/core/file/path_spec.rb
index dfa0c4ec02..ce78dbeede 100644
--- a/spec/ruby/core/file/path_spec.rb
+++ b/spec/ruby/core/file/path_spec.rb
@@ -37,4 +37,45 @@ describe "File.path" do
path.should_receive(:to_path).and_return("abc")
File.path(path).should == "abc"
end
+
+ it "raises TypeError when #to_path result is not a string" do
+ path = mock("path")
+ path.should_receive(:to_path).and_return(nil)
+ -> { File.path(path) }.should.raise TypeError
+
+ path = mock("path")
+ path.should_receive(:to_path).and_return(42)
+ -> { File.path(path) }.should.raise TypeError
+ end
+
+ it "raises ArgumentError for string argument contains NUL character" do
+ -> { File.path("\0") }.should.raise ArgumentError
+ -> { File.path("a\0") }.should.raise ArgumentError
+ -> { File.path("a\0c") }.should.raise ArgumentError
+ end
+
+ it "raises ArgumentError when #to_path result contains NUL character" do
+ path = mock("path")
+ path.should_receive(:to_path).and_return("\0")
+ -> { File.path(path) }.should.raise ArgumentError
+
+ path = mock("path")
+ path.should_receive(:to_path).and_return("a\0")
+ -> { File.path(path) }.should.raise ArgumentError
+
+ path = mock("path")
+ path.should_receive(:to_path).and_return("a\0c")
+ -> { File.path(path) }.should.raise ArgumentError
+ end
+
+ it "raises Encoding::CompatibilityError for ASCII-incompatible string argument" do
+ path = "abc".encode(Encoding::UTF_32BE)
+ -> { File.path(path) }.should.raise Encoding::CompatibilityError
+ end
+
+ it "raises Encoding::CompatibilityError when #to_path result is ASCII-incompatible" do
+ path = mock("path")
+ path.should_receive(:to_path).and_return("abc".encode(Encoding::UTF_32BE))
+ -> { File.path(path) }.should.raise Encoding::CompatibilityError
+ end
end
diff --git a/spec/ruby/core/file/readlink_spec.rb b/spec/ruby/core/file/readlink_spec.rb
index 20741ba121..568692b9b6 100644
--- a/spec/ruby/core/file/readlink_spec.rb
+++ b/spec/ruby/core/file/readlink_spec.rb
@@ -26,12 +26,12 @@ describe "File.readlink" do
it "raises an Errno::ENOENT if there is no such file" do
# TODO: missing_file
- -> { File.readlink("/this/surely/does/not/exist") }.should raise_error(Errno::ENOENT)
+ -> { File.readlink("/this/surely/does/not/exist") }.should.raise(Errno::ENOENT)
end
it "raises an Errno::EINVAL if called with a normal file" do
touch @file
- -> { File.readlink(@file) }.should raise_error(Errno::EINVAL)
+ -> { File.readlink(@file) }.should.raise(Errno::EINVAL)
end
end
@@ -49,7 +49,7 @@ describe "File.readlink" do
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.encoding.should.equal? Encoding.find('filesystem')
result.should == @file.dup.force_encoding(Encoding.find('filesystem'))
end
end
diff --git a/spec/ruby/core/file/realdirpath_spec.rb b/spec/ruby/core/file/realdirpath_spec.rb
index 74053afce3..ecf1e0c6d9 100644
--- a/spec/ruby/core/file/realdirpath_spec.rb
+++ b/spec/ruby/core/file/realdirpath_spec.rb
@@ -61,7 +61,7 @@ platform_is_not :windows do
it "raises an Errno::ELOOP if the symlink points to itself" do
File.unlink @link
File.symlink(@link, @link)
- -> { File.realdirpath(@link) }.should raise_error(Errno::ELOOP)
+ -> { File.realdirpath(@link) }.should.raise(Errno::ELOOP)
end
it "returns the real (absolute) pathname if the file is absent" do
@@ -69,7 +69,7 @@ platform_is_not :windows do
end
it "raises Errno::ENOENT if the directory is absent" do
- -> { File.realdirpath(@fake_file_in_fake_dir) }.should raise_error(Errno::ENOENT)
+ -> { File.realdirpath(@fake_file_in_fake_dir) }.should.raise(Errno::ENOENT)
end
it "returns the real (absolute) pathname if the symlink points to an absent file" do
@@ -77,7 +77,7 @@ platform_is_not :windows do
end
it "raises Errno::ENOENT if the symlink points to an absent directory" do
- -> { File.realdirpath(@fake_link_to_fake_dir) }.should raise_error(Errno::ENOENT)
+ -> { File.realdirpath(@fake_link_to_fake_dir) }.should.raise(Errno::ENOENT)
end
end
end
diff --git a/spec/ruby/core/file/realpath_spec.rb b/spec/ruby/core/file/realpath_spec.rb
index bd27e09da6..ccb981eff1 100644
--- a/spec/ruby/core/file/realpath_spec.rb
+++ b/spec/ruby/core/file/realpath_spec.rb
@@ -54,18 +54,22 @@ platform_is_not :windows do
File.realpath(@relative_symlink).should == @file
end
+ it "removes the file element when going one level up" do
+ File.realpath('../', @file).should == @real_dir
+ end
+
it "raises an Errno::ELOOP if the symlink points to itself" do
File.unlink @link
File.symlink(@link, @link)
- -> { File.realpath(@link) }.should raise_error(Errno::ELOOP)
+ -> { File.realpath(@link) }.should.raise(Errno::ELOOP)
end
it "raises Errno::ENOENT if the file is absent" do
- -> { File.realpath(@fake_file) }.should raise_error(Errno::ENOENT)
+ -> { File.realpath(@fake_file) }.should.raise(Errno::ENOENT)
end
it "raises Errno::ENOENT if the symlink points to an absent file" do
- -> { File.realpath(@fake_link) }.should raise_error(Errno::ENOENT)
+ -> { File.realpath(@fake_link) }.should.raise(Errno::ENOENT)
end
it "converts the argument with #to_path" do
diff --git a/spec/ruby/core/file/rename_spec.rb b/spec/ruby/core/file/rename_spec.rb
index f2c18d4905..70ea669a68 100644
--- a/spec/ruby/core/file/rename_spec.rb
+++ b/spec/ruby/core/file/rename_spec.rb
@@ -23,15 +23,15 @@ describe "File.rename" do
it "raises an Errno::ENOENT if the source does not exist" do
rm_r @old
- -> { File.rename(@old, @new) }.should raise_error(Errno::ENOENT)
+ -> { File.rename(@old, @new) }.should.raise(Errno::ENOENT)
end
it "raises an ArgumentError if not passed two arguments" do
- -> { File.rename }.should raise_error(ArgumentError)
- -> { File.rename(@file) }.should raise_error(ArgumentError)
+ -> { File.rename }.should.raise(ArgumentError)
+ -> { File.rename(@file) }.should.raise(ArgumentError)
end
it "raises a TypeError if not passed String types" do
- -> { File.rename(1, 2) }.should raise_error(TypeError)
+ -> { File.rename(1, 2) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/file/setuid_spec.rb b/spec/ruby/core/file/setuid_spec.rb
index 281ef01ab9..9e5e86df61 100644
--- a/spec/ruby/core/file/setuid_spec.rb
+++ b/spec/ruby/core/file/setuid_spec.rb
@@ -26,10 +26,6 @@ describe "File.setuid?" do
platform_is_not :windows do
it "returns true when the gid bit is set" do
- platform_is :solaris do
- # Solaris requires execute bit before setting suid
- system "chmod u+x #{@name}"
- end
system "chmod u+s #{@name}"
File.setuid?(@name).should == true
diff --git a/spec/ruby/core/file/shared/fnmatch.rb b/spec/ruby/core/file/shared/fnmatch.rb
index 94f22144b0..b9140d027d 100644
--- a/spec/ruby/core/file/shared/fnmatch.rb
+++ b/spec/ruby/core/file/shared/fnmatch.rb
@@ -102,6 +102,7 @@ describe :file_fnmatch, shared: true 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]', 'cas').should == true
File.send(@method, 'ca[!t]', 'cat').should == false
end
@@ -125,6 +126,13 @@ describe :file_fnmatch, shared: true do
end
end
+ it "matches wildcard with characters when flags includes FNM_PATHNAME" do
+ File.send(@method, '*a', 'aa', File::FNM_PATHNAME).should == true
+ File.send(@method, 'a*', 'aa', File::FNM_PATHNAME).should == true
+ File.send(@method, 'a*', 'aaa', File::FNM_PATHNAME).should == true
+ File.send(@method, '*a', 'aaa', File::FNM_PATHNAME).should == true
+ end
+
it "does not match '/' characters with ? or * when flags includes FNM_PATHNAME" do
File.send(@method, '?', '/', File::FNM_PATHNAME).should == false
File.send(@method, '*', '/', File::FNM_PATHNAME).should == false
@@ -165,9 +173,19 @@ describe :file_fnmatch, shared: true do
File.should_not.send(@method, '*/*', 'dave/.profile', File::FNM_PATHNAME)
end
- it "matches patterns with leading periods to dotfiles by default" do
+ it "matches patterns with leading periods to dotfiles" do
File.send(@method, '.*', '.profile').should == true
+ File.send(@method, '.*', '.profile', File::FNM_PATHNAME).should == true
File.send(@method, ".*file", "nondotfile").should == false
+ File.send(@method, ".*file", "nondotfile", File::FNM_PATHNAME).should == false
+ end
+
+ it "does not match directories with leading periods by default with FNM_PATHNAME" do
+ File.send(@method, '.*', '.directory/nondotfile', File::FNM_PATHNAME).should == false
+ File.send(@method, '.*', '.directory/.profile', File::FNM_PATHNAME).should == false
+ File.send(@method, '.*', 'foo/.directory/nondotfile', File::FNM_PATHNAME).should == false
+ File.send(@method, '.*', 'foo/.directory/.profile', File::FNM_PATHNAME).should == false
+ File.send(@method, '**/.dotfile', '.dotsubdir/.dotfile', File::FNM_PATHNAME).should == false
end
it "matches leading periods in filenames when flags includes FNM_DOTMATCH" do
@@ -204,21 +222,48 @@ describe :file_fnmatch, shared: true do
it "returns false if '/' in pattern do not match '/' in path when flags includes FNM_PATHNAME" do
pattern = '*/*'
- File.send(@method, pattern, 'dave/.profile', File::FNM_PATHNAME).should be_false
+ File.send(@method, pattern, 'dave/.profile', File::FNM_PATHNAME).should == false
pattern = '**/foo'
- File.send(@method, pattern, 'a/.b/c/foo', File::FNM_PATHNAME).should be_false
+ File.send(@method, pattern, 'a/.b/c/foo', File::FNM_PATHNAME).should == false
end
it "returns true if '/' in pattern match '/' in path when flags includes FNM_PATHNAME" do
pattern = '*/*'
- File.send(@method, pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true
+ File.send(@method, pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true
pattern = '**/foo'
- File.send(@method, pattern, 'a/b/c/foo', File::FNM_PATHNAME).should be_true
- File.send(@method, pattern, '/a/b/c/foo', File::FNM_PATHNAME).should be_true
- File.send(@method, pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME).should be_true
- File.send(@method, pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true
+ File.send(@method, pattern, 'a/b/c/foo', File::FNM_PATHNAME).should == true
+ File.send(@method, pattern, '/a/b/c/foo', File::FNM_PATHNAME).should == true
+ File.send(@method, pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME).should == true
+ File.send(@method, pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true
+ end
+
+ it "has special handling for ./ when using * and FNM_PATHNAME" do
+ File.send(@method, './*', '.', File::FNM_PATHNAME).should == false
+ File.send(@method, './*', './', File::FNM_PATHNAME).should == true
+ File.send(@method, './*/', './', File::FNM_PATHNAME).should == false
+ File.send(@method, './**', './', File::FNM_PATHNAME).should == true
+ File.send(@method, './**/', './', File::FNM_PATHNAME).should == true
+ File.send(@method, './*', '.', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == false
+ File.send(@method, './*', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true
+ File.send(@method, './*/', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == false
+ File.send(@method, './**', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true
+ File.send(@method, './**/', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true
+ end
+
+ it "matches **/* with FNM_PATHNAME to recurse directories" do
+ File.send(@method, 'nested/**/*', 'nested/subdir', File::FNM_PATHNAME).should == true
+ File.send(@method, 'nested/**/*', 'nested/subdir/file', File::FNM_PATHNAME).should == true
+ File.send(@method, 'nested/**/*', 'nested/.dotsubdir', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true
+ File.send(@method, 'nested/**/*', 'nested/.dotsubir/.dotfile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true
+ end
+
+ it "matches ** with FNM_PATHNAME only in current directory" do
+ File.send(@method, 'nested/**', 'nested/subdir', File::FNM_PATHNAME).should == true
+ File.send(@method, 'nested/**', 'nested/subdir/file', File::FNM_PATHNAME).should == false
+ File.send(@method, 'nested/**', 'nested/.dotsubdir', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == true
+ File.send(@method, 'nested/**', 'nested/.dotsubir/.dotfile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should == false
end
it "accepts an object that has a #to_path method" do
@@ -226,21 +271,21 @@ describe :file_fnmatch, shared: true do
end
it "raises a TypeError if the first and second arguments are not string-like" do
- -> { File.send(@method, nil, nil, 0, 0) }.should raise_error(ArgumentError)
- -> { File.send(@method, 1, 'some/thing') }.should raise_error(TypeError)
- -> { File.send(@method, 'some/thing', 1) }.should raise_error(TypeError)
- -> { File.send(@method, 1, 1) }.should raise_error(TypeError)
+ -> { File.send(@method, nil, nil, 0, 0) }.should.raise(ArgumentError)
+ -> { File.send(@method, 1, 'some/thing') }.should.raise(TypeError)
+ -> { File.send(@method, 'some/thing', 1) }.should.raise(TypeError)
+ -> { File.send(@method, 1, 1) }.should.raise(TypeError)
end
it "raises a TypeError if the third argument is not an Integer" do
- -> { File.send(@method, "*/place", "path/to/file", "flags") }.should raise_error(TypeError)
- -> { File.send(@method, "*/place", "path/to/file", nil) }.should raise_error(TypeError)
+ -> { File.send(@method, "*/place", "path/to/file", "flags") }.should.raise(TypeError)
+ -> { File.send(@method, "*/place", "path/to/file", nil) }.should.raise(TypeError)
end
it "does not raise a TypeError if the third argument can be coerced to an Integer" do
flags = mock("flags")
flags.should_receive(:to_int).and_return(10)
- -> { File.send(@method, "*/place", "path/to/file", flags) }.should_not raise_error
+ -> { File.send(@method, "*/place", "path/to/file", flags) }.should_not.raise
end
it "matches multibyte characters" do
diff --git a/spec/ruby/core/file/shared/open.rb b/spec/ruby/core/file/shared/open.rb
index 677a82a351..67149235ca 100644
--- a/spec/ruby/core/file/shared/open.rb
+++ b/spec/ruby/core/file/shared/open.rb
@@ -4,7 +4,7 @@ describe :open_directory, shared: true do
it "opens directories" do
file = File.send(@method, tmp(""))
begin
- file.should be_kind_of(File)
+ file.should.is_a?(File)
ensure
file.close
end
diff --git a/spec/ruby/core/file/shared/path.rb b/spec/ruby/core/file/shared/path.rb
index 0a5abe33f0..6c6f7d4234 100644
--- a/spec/ruby/core/file/shared/path.rb
+++ b/spec/ruby/core/file/shared/path.rb
@@ -1,7 +1,7 @@
describe :file_path, shared: true do
before :each do
- @name = "file_to_path"
- @path = tmp(@name)
+ @path = tmp("file_to_path")
+ @name = File.basename(@path)
touch @path
end
@@ -12,7 +12,7 @@ describe :file_path, shared: true do
it "returns a String" do
@file = File.new @path
- @file.send(@method).should be_an_instance_of(String)
+ @file.send(@method).should.instance_of?(String)
end
it "returns a different String on every call" do
@@ -77,16 +77,6 @@ describe :file_path, shared: true do
after :each do
rm_r @dir
end
-
- it "raises IOError if file was opened with File::TMPFILE" do
- begin
- File.open(@dir, File::RDWR | File::TMPFILE) do |f|
- -> { f.send(@method) }.should raise_error(IOError)
- end
- rescue Errno::EOPNOTSUPP, Errno::EINVAL, Errno::EISDIR
- skip "no support from the filesystem"
- end
- end
end
end
end
diff --git a/spec/ruby/core/file/shared/read.rb b/spec/ruby/core/file/shared/read.rb
index f232235298..f60800bb2f 100644
--- a/spec/ruby/core/file/shared/read.rb
+++ b/spec/ruby/core/file/shared/read.rb
@@ -3,13 +3,13 @@ require_relative '../../dir/fixtures/common'
describe :file_read_directory, shared: true do
platform_is :darwin, :linux, :freebsd, :openbsd, :windows do
it "raises an Errno::EISDIR when passed a path that is a directory" do
- -> { @object.send(@method, ".") }.should raise_error(Errno::EISDIR)
+ -> { @object.send(@method, ".") }.should.raise(Errno::EISDIR)
end
end
platform_is :netbsd do
it "does not raises any exception when passed a path that is a directory" do
- -> { @object.send(@method, ".") }.should_not raise_error
+ -> { @object.send(@method, ".") }.should_not.raise
end
end
end
diff --git a/spec/ruby/core/file/shared/stat.rb b/spec/ruby/core/file/shared/stat.rb
index fdaf97ea61..879a7f11ff 100644
--- a/spec/ruby/core/file/shared/stat.rb
+++ b/spec/ruby/core/file/shared/stat.rb
@@ -10,13 +10,13 @@ describe :file_stat, shared: true do
it "returns a File::Stat object if the given file exists" do
st = File.send(@method, @file)
- st.should be_an_instance_of(File::Stat)
+ st.should.instance_of?(File::Stat)
end
it "returns a File::Stat object when called on an instance of File" do
File.open(@file) do |f|
st = f.send(@method)
- st.should be_an_instance_of(File::Stat)
+ st.should.instance_of?(File::Stat)
end
end
@@ -27,6 +27,6 @@ describe :file_stat, shared: true do
it "raises an Errno::ENOENT if the file does not exist" do
-> {
File.send(@method, "fake_file")
- }.should raise_error(Errno::ENOENT)
+ }.should.raise(Errno::ENOENT)
end
end
diff --git a/spec/ruby/core/file/shared/unlink.rb b/spec/ruby/core/file/shared/unlink.rb
index e339e93271..0032907ba2 100644
--- a/spec/ruby/core/file/shared/unlink.rb
+++ b/spec/ruby/core/file/shared/unlink.rb
@@ -31,11 +31,11 @@ describe :file_unlink, shared: true do
end
it "raises a TypeError if not passed a String type" do
- -> { File.send(@method, 1) }.should raise_error(TypeError)
+ -> { File.send(@method, 1) }.should.raise(TypeError)
end
it "raises an Errno::ENOENT when the given file doesn't exist" do
- -> { File.send(@method, 'bogus') }.should raise_error(Errno::ENOENT)
+ -> { File.send(@method, 'bogus') }.should.raise(Errno::ENOENT)
end
it "coerces a given parameter into a string if possible" do
diff --git a/spec/ruby/core/file/shared/update_time.rb b/spec/ruby/core/file/shared/update_time.rb
new file mode 100644
index 0000000000..3fe7266a00
--- /dev/null
+++ b/spec/ruby/core/file/shared/update_time.rb
@@ -0,0 +1,105 @@
+describe :update_time, shared: true do
+ before :all do
+ @time_is_float = platform_is :windows
+ end
+
+ before :each do
+ @atime = Time.now
+ @mtime = Time.now
+ @file1 = tmp("specs_file_utime1")
+ @file2 = tmp("specs_file_utime2")
+ touch @file1
+ touch @file2
+ end
+
+ after :each do
+ rm_r @file1, @file2
+ end
+
+ it "sets the access and modification time of each file" do
+ File.send(@method, @atime, @mtime, @file1, @file2)
+
+ if @time_is_float
+ File.atime(@file1).should be_close(@atime, 0.0001)
+ File.mtime(@file1).should be_close(@mtime, 0.0001)
+ File.atime(@file2).should be_close(@atime, 0.0001)
+ File.mtime(@file2).should be_close(@mtime, 0.0001)
+ else
+ File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
+ File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
+ File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
+ File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
+ end
+ end
+
+ it "uses the current times if two nil values are passed" do
+ tn = Time.now
+ File.send(@method, nil, nil, @file1, @file2)
+
+ if @time_is_float
+ File.atime(@file1).should be_close(tn, 0.050)
+ File.mtime(@file1).should be_close(tn, 0.050)
+ File.atime(@file2).should be_close(tn, 0.050)
+ File.mtime(@file2).should be_close(tn, 0.050)
+ else
+ File.atime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE)
+ File.mtime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE)
+ File.atime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE)
+ File.mtime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE)
+ end
+ end
+
+ it "accepts an object that has a #to_path method" do
+ File.send(@method, @atime, @mtime, mock_to_path(@file1), mock_to_path(@file2))
+ end
+
+ it "accepts numeric atime and mtime arguments" do
+ if @time_is_float
+ File.send(@method, @atime.to_f, @mtime.to_f, @file1, @file2)
+
+ File.atime(@file1).should be_close(@atime, 0.0001)
+ File.mtime(@file1).should be_close(@mtime, 0.0001)
+ File.atime(@file2).should be_close(@atime, 0.0001)
+ File.mtime(@file2).should be_close(@mtime, 0.0001)
+ else
+ File.send(@method, @atime.to_i, @mtime.to_i, @file1, @file2)
+
+ File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
+ File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
+ File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
+ File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
+ end
+ end
+
+ it "may set nanosecond precision" do
+ t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r)
+ File.send(@method, t, t, @file1)
+
+ File.atime(@file1).nsec.should.between?(0, 123500000)
+ File.mtime(@file1).nsec.should.between?(0, 123500000)
+ end
+
+ it "returns the number of filenames in the arguments" do
+ File.send(@method, @atime.to_f, @mtime.to_f, @file1, @file2).should == 2
+ end
+
+ platform_is :linux do
+ platform_is pointer_size: 64 do
+ it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19 or 2486-07-02)" do
+ # https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps
+ # "Therefore, timestamps should not overflow until May 2446."
+ # https://lwn.net/Articles/804382/
+ # "On-disk timestamps hitting the y2038 limit..."
+ # The problem seems to be being improved, but currently it actually fails on XFS on RHEL8
+ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20201112T123004Z.fail.html.gz
+ # Amazon Linux 2023 returns 2486-07-02 in this example
+ # http://rubyci.s3.amazonaws.com/amazon2023/ruby-master/log/20230322T063004Z.fail.html.gz
+ time = Time.at(1<<44)
+ File.send(@method, time, time, @file1)
+
+ [559444, 2486, 2446, 2038].should.include? File.atime(@file1).year
+ [559444, 2486, 2446, 2038].should.include? File.mtime(@file1).year
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/file/size_spec.rb b/spec/ruby/core/file/size_spec.rb
index 11d20cbacb..784c18c26e 100644
--- a/spec/ruby/core/file/size_spec.rb
+++ b/spec/ruby/core/file/size_spec.rb
@@ -56,11 +56,11 @@ describe "File#size" do
end
it "is an instance method" do
- @file.respond_to?(:size).should be_true
+ @file.respond_to?(:size).should == true
end
it "returns the file's size as an Integer" do
- @file.size.should be_an_instance_of(Integer)
+ @file.size.should.instance_of?(Integer)
end
it "returns the file's size in bytes" do
@@ -81,7 +81,7 @@ describe "File#size" do
it "raises an IOError on a closed file" do
@file.close
- -> { @file.size }.should raise_error(IOError)
+ -> { @file.size }.should.raise(IOError)
end
platform_is_not :windows do
diff --git a/spec/ruby/core/file/socket_spec.rb b/spec/ruby/core/file/socket_spec.rb
index 5d12e21f55..d3f4eb013a 100644
--- a/spec/ruby/core/file/socket_spec.rb
+++ b/spec/ruby/core/file/socket_spec.rb
@@ -1,42 +1,10 @@
require_relative '../../spec_helper'
require_relative '../../shared/file/socket'
-require 'socket'
describe "File.socket?" do
it_behaves_like :file_socket, :socket?, File
-end
-describe "File.socket?" do
it "returns false if file does not exist" do
File.socket?("I_am_a_bogus_file").should == false
end
-
- it "returns false if the file is not a socket" do
- filename = tmp("i_exist")
- touch(filename)
-
- File.socket?(filename).should == false
-
- rm_r filename
- end
-end
-
-platform_is_not :windows do
- describe "File.socket?" do
- before :each do
- # We need a really short name here.
- # On Linux the path length is limited to 107, see unix(7).
- @name = tmp("s")
- @server = UNIXServer.new @name
- end
-
- after :each do
- @server.close
- rm_r @name
- end
-
- it "returns true if the file is a socket" do
- File.socket?(@name).should == true
- end
- end
end
diff --git a/spec/ruby/core/file/split_spec.rb b/spec/ruby/core/file/split_spec.rb
index 7b958621b9..e989a6b86e 100644
--- a/spec/ruby/core/file/split_spec.rb
+++ b/spec/ruby/core/file/split_spec.rb
@@ -44,12 +44,12 @@ describe "File.split" do
end
it "raises an ArgumentError when not passed a single argument" do
- -> { File.split }.should raise_error(ArgumentError)
- -> { File.split('string', 'another string') }.should raise_error(ArgumentError)
+ -> { File.split }.should.raise(ArgumentError)
+ -> { File.split('string', 'another string') }.should.raise(ArgumentError)
end
it "raises a TypeError if the argument is not a String type" do
- -> { File.split(1) }.should raise_error(TypeError)
+ -> { File.split(1) }.should.raise(TypeError)
end
it "coerces the argument with to_str if it is not a String type" do
diff --git a/spec/ruby/core/file/stat/atime_spec.rb b/spec/ruby/core/file/stat/atime_spec.rb
index 9f1111ced1..2fecaed300 100644
--- a/spec/ruby/core/file/stat/atime_spec.rb
+++ b/spec/ruby/core/file/stat/atime_spec.rb
@@ -12,7 +12,7 @@ describe "File::Stat#atime" do
it "returns the atime of a File::Stat object" do
st = File.stat(@file)
- st.atime.should be_kind_of(Time)
+ st.atime.should.is_a?(Time)
st.atime.should <= Time.now
end
end
diff --git a/spec/ruby/core/file/stat/birthtime_spec.rb b/spec/ruby/core/file/stat/birthtime_spec.rb
index a727bbe566..728f635397 100644
--- a/spec/ruby/core/file/stat/birthtime_spec.rb
+++ b/spec/ruby/core/file/stat/birthtime_spec.rb
@@ -1,27 +1,29 @@
require_relative '../../../spec_helper'
-describe "File::Stat#birthtime" do
- before :each do
- @file = tmp('i_exist')
- touch(@file) { |f| f.write "rubinius" }
- end
+platform_is(:windows, :darwin, :freebsd, :netbsd,
+ *ruby_version_is("4.0") { :linux },
+ ) do
+ not_implemented_messages = [
+ "birthtime() function is unimplemented", # unsupported OS/version
+ "birthtime is unimplemented", # unsupported filesystem
+ ]
- after :each do
- rm_r @file
- end
+ describe "File::Stat#birthtime" do
+ before :each do
+ @file = tmp('i_exist')
+ touch(@file) { |f| f.write "rubinius" }
+ end
- platform_is :windows, :darwin, :freebsd, :netbsd do
- it "returns the birthtime of a File::Stat object" do
- st = File.stat(@file)
- st.birthtime.should be_kind_of(Time)
- st.birthtime.should <= Time.now
+ after :each do
+ rm_r @file
end
- end
- platform_is :linux, :openbsd do
- it "raises an NotImplementedError" do
+ it "returns the birthtime of a File::Stat object" do
st = File.stat(@file)
- -> { st.birthtime }.should raise_error(NotImplementedError)
+ st.birthtime.should.is_a?(Time)
+ st.birthtime.should <= Time.now
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
end
end
diff --git a/spec/ruby/core/file/stat/blocks_spec.rb b/spec/ruby/core/file/stat/blocks_spec.rb
index f3f903d0f7..5e0efc8bc2 100644
--- a/spec/ruby/core/file/stat/blocks_spec.rb
+++ b/spec/ruby/core/file/stat/blocks_spec.rb
@@ -21,7 +21,7 @@ describe "File::Stat#blocks" do
platform_is :windows do
it "returns nil" do
st = File.stat(@file)
- st.blocks.should be_nil
+ st.blocks.should == nil
end
end
end
diff --git a/spec/ruby/core/file/stat/ctime_spec.rb b/spec/ruby/core/file/stat/ctime_spec.rb
index fd50487a0a..dbf43a7453 100644
--- a/spec/ruby/core/file/stat/ctime_spec.rb
+++ b/spec/ruby/core/file/stat/ctime_spec.rb
@@ -12,7 +12,7 @@ describe "File::Stat#ctime" do
it "returns the ctime of a File::Stat object" do
st = File.stat(@file)
- st.ctime.should be_kind_of(Time)
+ st.ctime.should.is_a?(Time)
st.ctime.should <= Time.now
end
end
diff --git a/spec/ruby/core/file/stat/dev_major_spec.rb b/spec/ruby/core/file/stat/dev_major_spec.rb
index 4966d609e2..a199eaaa11 100644
--- a/spec/ruby/core/file/stat/dev_major_spec.rb
+++ b/spec/ruby/core/file/stat/dev_major_spec.rb
@@ -11,13 +11,13 @@ describe "File::Stat#dev_major" do
platform_is_not :windows do
it "returns the major part of File::Stat#dev" do
- File.stat(@name).dev_major.should be_kind_of(Integer)
+ File.stat(@name).dev_major.should.is_a?(Integer)
end
end
platform_is :windows do
it "returns nil" do
- File.stat(@name).dev_major.should be_nil
+ File.stat(@name).dev_major.should == nil
end
end
end
diff --git a/spec/ruby/core/file/stat/dev_minor_spec.rb b/spec/ruby/core/file/stat/dev_minor_spec.rb
index ea79c12b99..8ce94778ca 100644
--- a/spec/ruby/core/file/stat/dev_minor_spec.rb
+++ b/spec/ruby/core/file/stat/dev_minor_spec.rb
@@ -11,13 +11,13 @@ describe "File::Stat#dev_minor" do
platform_is_not :windows do
it "returns the minor part of File::Stat#dev" do
- File.stat(@name).dev_minor.should be_kind_of(Integer)
+ File.stat(@name).dev_minor.should.is_a?(Integer)
end
end
platform_is :windows do
it "returns nil" do
- File.stat(@name).dev_minor.should be_nil
+ File.stat(@name).dev_minor.should == nil
end
end
end
diff --git a/spec/ruby/core/file/stat/dev_spec.rb b/spec/ruby/core/file/stat/dev_spec.rb
index e953fcaa58..cd5e3d175e 100644
--- a/spec/ruby/core/file/stat/dev_spec.rb
+++ b/spec/ruby/core/file/stat/dev_spec.rb
@@ -10,6 +10,6 @@ describe "File::Stat#dev" do
end
it "returns the number of the device on which the file exists" do
- File.stat(@name).dev.should be_kind_of(Integer)
+ File.stat(@name).dev.should.is_a?(Integer)
end
end
diff --git a/spec/ruby/core/file/stat/ftype_spec.rb b/spec/ruby/core/file/stat/ftype_spec.rb
index eb892eae5f..df2e3ada1e 100644
--- a/spec/ruby/core/file/stat/ftype_spec.rb
+++ b/spec/ruby/core/file/stat/ftype_spec.rb
@@ -8,7 +8,7 @@ describe "File::Stat#ftype" do
it "returns a String" do
FileSpecs.normal_file do |file|
- File.lstat(file).ftype.should be_kind_of(String)
+ File.lstat(file).ftype.should.is_a?(String)
end
end
diff --git a/spec/ruby/core/file/stat/ino_spec.rb b/spec/ruby/core/file/stat/ino_spec.rb
index 42370aecb7..c09b6448c7 100644
--- a/spec/ruby/core/file/stat/ino_spec.rb
+++ b/spec/ruby/core/file/stat/ino_spec.rb
@@ -13,7 +13,7 @@ describe "File::Stat#ino" do
platform_is_not :windows do
it "returns the ino of a File::Stat object" do
st = File.stat(@file)
- st.ino.should be_kind_of(Integer)
+ st.ino.should.is_a?(Integer)
st.ino.should > 0
end
end
@@ -21,7 +21,7 @@ describe "File::Stat#ino" do
platform_is :windows do
it "returns BY_HANDLE_FILE_INFORMATION.nFileIndexHigh/Low of a File::Stat object" do
st = File.stat(@file)
- st.ino.should be_kind_of(Integer)
+ st.ino.should.is_a?(Integer)
st.ino.should > 0
end
end
diff --git a/spec/ruby/core/file/stat/mtime_spec.rb b/spec/ruby/core/file/stat/mtime_spec.rb
index 08a2b83463..7844491212 100644
--- a/spec/ruby/core/file/stat/mtime_spec.rb
+++ b/spec/ruby/core/file/stat/mtime_spec.rb
@@ -12,7 +12,7 @@ describe "File::Stat#mtime" do
it "returns the mtime of a File::Stat object" do
st = File.stat(@file)
- st.mtime.should be_kind_of(Time)
+ st.mtime.should.is_a?(Time)
st.mtime.should <= Time.now
end
end
diff --git a/spec/ruby/core/file/stat/new_spec.rb b/spec/ruby/core/file/stat/new_spec.rb
index c0d9432ac8..b8c3600028 100644
--- a/spec/ruby/core/file/stat/new_spec.rb
+++ b/spec/ruby/core/file/stat/new_spec.rb
@@ -15,12 +15,12 @@ describe "File::Stat#initialize" do
it "raises an exception if the file doesn't exist" do
-> {
File::Stat.new(tmp("i_am_a_dummy_file_that_doesnt_exist"))
- }.should raise_error(Errno::ENOENT)
+ }.should.raise(Errno::ENOENT)
end
it "creates a File::Stat object for the given file" do
st = File::Stat.new(@file)
- st.should be_kind_of(File::Stat)
+ st.should.is_a?(File::Stat)
st.ftype.should == 'file'
end
diff --git a/spec/ruby/core/file/stat/rdev_major_spec.rb b/spec/ruby/core/file/stat/rdev_major_spec.rb
index f8a8d1b107..e1b44fc2d0 100644
--- a/spec/ruby/core/file/stat/rdev_major_spec.rb
+++ b/spec/ruby/core/file/stat/rdev_major_spec.rb
@@ -2,30 +2,23 @@ require_relative '../../../spec_helper'
describe "File::Stat#rdev_major" do
before :each do
- platform_is :solaris do
- @name = "/dev/zfs"
- end
- platform_is_not :solaris do
- @name = tmp("file.txt")
- touch(@name)
- end
+ @name = tmp("file.txt")
+ touch(@name)
end
after :each do
- platform_is_not :solaris do
- rm_r @name
- end
+ rm_r @name
end
platform_is_not :windows do
it "returns the major part of File::Stat#rdev" do
- File.stat(@name).rdev_major.should be_kind_of(Integer)
+ File.stat(@name).rdev_major.should.is_a?(Integer)
end
end
platform_is :windows do
it "returns nil" do
- File.stat(@name).rdev_major.should be_nil
+ File.stat(@name).rdev_major.should == nil
end
end
end
diff --git a/spec/ruby/core/file/stat/rdev_minor_spec.rb b/spec/ruby/core/file/stat/rdev_minor_spec.rb
index dc30c1f56c..8af3b9f587 100644
--- a/spec/ruby/core/file/stat/rdev_minor_spec.rb
+++ b/spec/ruby/core/file/stat/rdev_minor_spec.rb
@@ -2,30 +2,23 @@ require_relative '../../../spec_helper'
describe "File::Stat#rdev_minor" do
before :each do
- platform_is :solaris do
- @name = "/dev/zfs"
- end
- platform_is_not :solaris do
- @name = tmp("file.txt")
- touch(@name)
- end
+ @name = tmp("file.txt")
+ touch(@name)
end
after :each do
- platform_is_not :solaris do
- rm_r @name
- end
+ rm_r @name
end
platform_is_not :windows do
it "returns the minor part of File::Stat#rdev" do
- File.stat(@name).rdev_minor.should be_kind_of(Integer)
+ File.stat(@name).rdev_minor.should.is_a?(Integer)
end
end
platform_is :windows do
it "returns nil" do
- File.stat(@name).rdev_minor.should be_nil
+ File.stat(@name).rdev_minor.should == nil
end
end
end
diff --git a/spec/ruby/core/file/stat/rdev_spec.rb b/spec/ruby/core/file/stat/rdev_spec.rb
index 9e1aee692d..7e4252fcc6 100644
--- a/spec/ruby/core/file/stat/rdev_spec.rb
+++ b/spec/ruby/core/file/stat/rdev_spec.rb
@@ -10,6 +10,6 @@ describe "File::Stat#rdev" do
end
it "returns the number of the device this file represents which the file exists" do
- File.stat(@name).rdev.should be_kind_of(Integer)
+ File.stat(@name).rdev.should.is_a?(Integer)
end
end
diff --git a/spec/ruby/core/file/stat_spec.rb b/spec/ruby/core/file/stat_spec.rb
index 6365500057..d5238b6331 100644
--- a/spec/ruby/core/file/stat_spec.rb
+++ b/spec/ruby/core/file/stat_spec.rb
@@ -28,9 +28,9 @@ platform_is_not :windows do
st.size.should == 8
st.size?.should == 8
st.blksize.should >= 0
- st.atime.should be_kind_of(Time)
- st.ctime.should be_kind_of(Time)
- st.mtime.should be_kind_of(Time)
+ st.atime.should.is_a?(Time)
+ st.ctime.should.is_a?(Time)
+ st.mtime.should.is_a?(Time)
end
end
@@ -46,9 +46,9 @@ platform_is_not :windows do
missing_path = "/missingfilepath\xE3E4".b
-> {
File.stat(missing_path)
- }.should raise_error(SystemCallError) { |e|
- [Errno::ENOENT, Errno::EILSEQ].should include(e.class)
- e.message.should include(missing_path)
+ }.should.raise(SystemCallError) { |e|
+ [Errno::ENOENT, Errno::EILSEQ].should.include?(e.class)
+ e.message.should.include?(missing_path)
}
end
end
diff --git a/spec/ruby/core/file/symlink_spec.rb b/spec/ruby/core/file/symlink_spec.rb
index 0e8b0a5a20..4ceeb28c84 100644
--- a/spec/ruby/core/file/symlink_spec.rb
+++ b/spec/ruby/core/file/symlink_spec.rb
@@ -32,18 +32,18 @@ describe "File.symlink" do
it "raises an Errno::EEXIST if the target already exists" do
File.symlink(@file, @link)
- -> { File.symlink(@file, @link) }.should raise_error(Errno::EEXIST)
+ -> { File.symlink(@file, @link) }.should.raise(Errno::EEXIST)
end
it "raises an ArgumentError if not called with two arguments" do
- -> { File.symlink }.should raise_error(ArgumentError)
- -> { File.symlink(@file) }.should raise_error(ArgumentError)
+ -> { File.symlink }.should.raise(ArgumentError)
+ -> { File.symlink(@file) }.should.raise(ArgumentError)
end
it "raises a TypeError if not called with String types" do
- -> { File.symlink(@file, nil) }.should raise_error(TypeError)
- -> { File.symlink(@file, 1) }.should raise_error(TypeError)
- -> { File.symlink(1, 1) }.should raise_error(TypeError)
+ -> { File.symlink(@file, nil) }.should.raise(TypeError)
+ -> { File.symlink(@file, 1) }.should.raise(TypeError)
+ -> { File.symlink(1, 1) }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/file/truncate_spec.rb b/spec/ruby/core/file/truncate_spec.rb
index b4a2e3e577..5f37f34155 100644
--- a/spec/ruby/core/file/truncate_spec.rb
+++ b/spec/ruby/core/file/truncate_spec.rb
@@ -54,29 +54,29 @@ describe "File.truncate" do
rm_r not_existing_file
begin
- -> { File.truncate(not_existing_file, 5) }.should raise_error(Errno::ENOENT)
+ -> { File.truncate(not_existing_file, 5) }.should.raise(Errno::ENOENT)
ensure
rm_r not_existing_file
end
end
it "raises an ArgumentError if not passed two arguments" do
- -> { File.truncate }.should raise_error(ArgumentError)
- -> { File.truncate(@name) }.should raise_error(ArgumentError)
+ -> { File.truncate }.should.raise(ArgumentError)
+ -> { File.truncate(@name) }.should.raise(ArgumentError)
end
platform_is_not :netbsd, :openbsd do
it "raises an Errno::EINVAL if the length argument is not valid" do
- -> { File.truncate(@name, -1) }.should raise_error(Errno::EINVAL) # May fail
+ -> { File.truncate(@name, -1) }.should.raise(Errno::EINVAL) # May fail
end
end
it "raises a TypeError if not passed a String type for the first argument" do
- -> { File.truncate(1, 1) }.should raise_error(TypeError)
+ -> { File.truncate(1, 1) }.should.raise(TypeError)
end
it "raises a TypeError if not passed an Integer type for the second argument" do
- -> { File.truncate(@name, nil) }.should raise_error(TypeError)
+ -> { File.truncate(@name, nil) }.should.raise(TypeError)
end
it "accepts an object that has a #to_path method" do
@@ -149,29 +149,29 @@ describe "File#truncate" do
end
it "raises an ArgumentError if not passed one argument" do
- -> { @file.truncate }.should raise_error(ArgumentError)
- -> { @file.truncate(1) }.should_not raise_error(ArgumentError)
+ -> { @file.truncate }.should.raise(ArgumentError)
+ -> { @file.truncate(1) }.should_not.raise(ArgumentError)
end
platform_is_not :netbsd do
it "raises an Errno::EINVAL if the length argument is not valid" do
- -> { @file.truncate(-1) }.should raise_error(Errno::EINVAL) # May fail
+ -> { @file.truncate(-1) }.should.raise(Errno::EINVAL) # May fail
end
end
it "raises an IOError if file is closed" do
@file.close
@file.should.closed?
- -> { @file.truncate(42) }.should raise_error(IOError)
+ -> { @file.truncate(42) }.should.raise(IOError)
end
it "raises an IOError if file is not opened for writing" do
File.open(@name, 'r') do |file|
- -> { file.truncate(42) }.should raise_error(IOError)
+ -> { file.truncate(42) }.should.raise(IOError)
end
end
it "raises a TypeError if not passed an Integer type for the for the argument" do
- -> { @file.truncate(nil) }.should raise_error(TypeError)
+ -> { @file.truncate(nil) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/file/umask_spec.rb b/spec/ruby/core/file/umask_spec.rb
index 7f7e40abbc..fea8cf7633 100644
--- a/spec/ruby/core/file/umask_spec.rb
+++ b/spec/ruby/core/file/umask_spec.rb
@@ -13,7 +13,7 @@ describe "File.umask" do
end
it "returns an Integer" do
- File.umask.should be_kind_of(Integer)
+ File.umask.should.is_a?(Integer)
end
platform_is_not :windows do
@@ -47,11 +47,11 @@ describe "File.umask" do
end
it "raises RangeError with too large values" do
- -> { File.umask(2**64) }.should raise_error(RangeError)
- -> { File.umask(-2**63 - 1) }.should raise_error(RangeError)
+ -> { File.umask(2**64) }.should.raise(RangeError)
+ -> { File.umask(-2**63 - 1) }.should.raise(RangeError)
end
it "raises ArgumentError when more than one argument is provided" do
- -> { File.umask(022, 022) }.should raise_error(ArgumentError)
+ -> { File.umask(022, 022) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/file/utime_spec.rb b/spec/ruby/core/file/utime_spec.rb
index a191e29240..d87626be50 100644
--- a/spec/ruby/core/file/utime_spec.rb
+++ b/spec/ruby/core/file/utime_spec.rb
@@ -1,100 +1,6 @@
require_relative '../../spec_helper'
+require_relative 'shared/update_time'
describe "File.utime" do
-
- before :all do
- @time_is_float = platform_is :windows
- end
-
- before :each do
- @atime = Time.now
- @mtime = Time.now
- @file1 = tmp("specs_file_utime1")
- @file2 = tmp("specs_file_utime2")
- touch @file1
- touch @file2
- end
-
- after :each do
- rm_r @file1, @file2
- end
-
- it "sets the access and modification time of each file" do
- File.utime(@atime, @mtime, @file1, @file2)
- if @time_is_float
- File.atime(@file1).should be_close(@atime, 0.0001)
- File.mtime(@file1).should be_close(@mtime, 0.0001)
- File.atime(@file2).should be_close(@atime, 0.0001)
- File.mtime(@file2).should be_close(@mtime, 0.0001)
- else
- File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
- File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
- File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
- File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
- end
- end
-
- it "uses the current times if two nil values are passed" do
- tn = Time.now
- File.utime(nil, nil, @file1, @file2)
- if @time_is_float
- File.atime(@file1).should be_close(tn, 0.050)
- File.mtime(@file1).should be_close(tn, 0.050)
- File.atime(@file2).should be_close(tn, 0.050)
- File.mtime(@file2).should be_close(tn, 0.050)
- else
- File.atime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE)
- File.mtime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE)
- File.atime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE)
- File.mtime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE)
- end
- end
-
- it "accepts an object that has a #to_path method" do
- File.utime(@atime, @mtime, mock_to_path(@file1), mock_to_path(@file2))
- end
-
- it "accepts numeric atime and mtime arguments" do
- if @time_is_float
- File.utime(@atime.to_f, @mtime.to_f, @file1, @file2)
- File.atime(@file1).should be_close(@atime, 0.0001)
- File.mtime(@file1).should be_close(@mtime, 0.0001)
- File.atime(@file2).should be_close(@atime, 0.0001)
- File.mtime(@file2).should be_close(@mtime, 0.0001)
- else
- File.utime(@atime.to_i, @mtime.to_i, @file1, @file2)
- File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
- File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
- File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
- File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
- end
- end
-
- it "may set nanosecond precision" do
- t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r)
- File.utime(t, t, @file1)
- File.atime(@file1).nsec.should.between?(0, 123500000)
- File.mtime(@file1).nsec.should.between?(0, 123500000)
- end
-
- it "returns the number of filenames in the arguments" do
- File.utime(@atime.to_f, @mtime.to_f, @file1, @file2).should == 2
- end
-
- platform_is :linux do
- platform_is wordsize: 64 do
- it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19)" do
- # https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps
- # "Therefore, timestamps should not overflow until May 2446."
- # https://lwn.net/Articles/804382/
- # "On-disk timestamps hitting the y2038 limit..."
- # The problem seems to be being improved, but currently it actually fails on XFS on RHEL8
- # https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20201112T123004Z.fail.html.gz
- time = Time.at(1<<44)
- File.utime(time, time, @file1)
- [559444, 2446, 2038].should.include? File.atime(@file1).year
- [559444, 2446, 2038].should.include? File.mtime(@file1).year
- end
- end
- end
+ it_behaves_like :update_time, :utime
end
diff --git a/spec/ruby/core/file/world_readable_spec.rb b/spec/ruby/core/file/world_readable_spec.rb
index 11b8e67d0b..0f5e0b13d7 100644
--- a/spec/ruby/core/file/world_readable_spec.rb
+++ b/spec/ruby/core/file/world_readable_spec.rb
@@ -7,6 +7,6 @@ describe "File.world_readable?" do
it "returns nil if the file does not exist" do
file = rand.to_s + $$.to_s
File.should_not.exist?(file)
- File.world_readable?(file).should be_nil
+ File.world_readable?(file).should == nil
end
end
diff --git a/spec/ruby/core/file/world_writable_spec.rb b/spec/ruby/core/file/world_writable_spec.rb
index d378cf2eb9..46ba6832f9 100644
--- a/spec/ruby/core/file/world_writable_spec.rb
+++ b/spec/ruby/core/file/world_writable_spec.rb
@@ -7,6 +7,6 @@ describe "File.world_writable?" do
it "returns nil if the file does not exist" do
file = rand.to_s + $$.to_s
File.should_not.exist?(file)
- File.world_writable?(file).should be_nil
+ File.world_writable?(file).should == nil
end
end
diff --git a/spec/ruby/core/file/zero_spec.rb b/spec/ruby/core/file/zero_spec.rb
index 63dd85ee46..01c7505ef2 100644
--- a/spec/ruby/core/file/zero_spec.rb
+++ b/spec/ruby/core/file/zero_spec.rb
@@ -4,10 +4,4 @@ require_relative '../../shared/file/zero'
describe "File.zero?" do
it_behaves_like :file_zero, :zero?, File
it_behaves_like :file_zero_missing, :zero?, File
-
- platform_is :solaris do
- it "returns false for /dev/null" do
- File.zero?('/dev/null').should == true
- end
- end
end
diff --git a/spec/ruby/core/filetest/exist_spec.rb b/spec/ruby/core/filetest/exist_spec.rb
index 4d14bea231..612ffa9fcb 100644
--- a/spec/ruby/core/filetest/exist_spec.rb
+++ b/spec/ruby/core/filetest/exist_spec.rb
@@ -4,3 +4,9 @@ require_relative '../../shared/file/exist'
describe "FileTest.exist?" do
it_behaves_like :file_exist, :exist?, FileTest
end
+
+describe "FileTest.exists?" do
+ it "has been removed" do
+ FileTest.should_not.respond_to?(:exists?)
+ end
+end
diff --git a/spec/ruby/core/filetest/grpowned_spec.rb b/spec/ruby/core/filetest/grpowned_spec.rb
index d073cb9770..d6bd6abd71 100644
--- a/spec/ruby/core/filetest/grpowned_spec.rb
+++ b/spec/ruby/core/filetest/grpowned_spec.rb
@@ -5,6 +5,6 @@ describe "FileTest.grpowned?" do
it_behaves_like :file_grpowned, :grpowned?, FileTest
it "returns false if the file doesn't exist" do
- FileTest.grpowned?("xxx-tmp-doesnt_exist-blah").should be_false
+ FileTest.grpowned?("xxx-tmp-doesnt_exist-blah").should == false
end
end
diff --git a/spec/ruby/core/filetest/socket_spec.rb b/spec/ruby/core/filetest/socket_spec.rb
index 63a6a31ecb..f274be6318 100644
--- a/spec/ruby/core/filetest/socket_spec.rb
+++ b/spec/ruby/core/filetest/socket_spec.rb
@@ -3,4 +3,8 @@ require_relative '../../shared/file/socket'
describe "FileTest.socket?" do
it_behaves_like :file_socket, :socket?, FileTest
+
+ it "returns false if file does not exist" do
+ FileTest.socket?("I_am_a_bogus_file").should == false
+ end
end
diff --git a/spec/ruby/core/filetest/zero_spec.rb b/spec/ruby/core/filetest/zero_spec.rb
index dd6a164ec9..92cab67f1b 100644
--- a/spec/ruby/core/filetest/zero_spec.rb
+++ b/spec/ruby/core/filetest/zero_spec.rb
@@ -4,10 +4,4 @@ require_relative '../../shared/file/zero'
describe "FileTest.zero?" do
it_behaves_like :file_zero, :zero?, FileTest
it_behaves_like :file_zero_missing, :zero?, FileTest
-
- platform_is :solaris do
- it "returns false for /dev/null" do
- File.zero?('/dev/null').should == true
- end
- end
end
diff --git a/spec/ruby/core/float/ceil_spec.rb b/spec/ruby/core/float/ceil_spec.rb
index 7fc18d304c..efd1e6feb2 100644
--- a/spec/ruby/core/float/ceil_spec.rb
+++ b/spec/ruby/core/float/ceil_spec.rb
@@ -1,21 +1,28 @@
require_relative '../../spec_helper'
+require_relative '../integer/shared/integer_ceil_precision'
describe "Float#ceil" do
+ context "with values equal to integers" do
+ it_behaves_like :integer_ceil_precision, :Float
+ end
+
it "returns the smallest Integer greater than or equal to self" do
- -1.2.ceil.should eql( -1)
- -1.0.ceil.should eql( -1)
- 0.0.ceil.should eql( 0 )
- 1.3.ceil.should eql( 2 )
- 3.0.ceil.should eql( 3 )
- -9223372036854775808.1.ceil.should eql(-9223372036854775808)
- +9223372036854775808.1.ceil.should eql(+9223372036854775808)
+ -1.2.ceil.should.eql?( -1)
+ -1.0.ceil.should.eql?( -1)
+ 0.0.ceil.should.eql?( 0 )
+ 1.3.ceil.should.eql?( 2 )
+ 3.0.ceil.should.eql?( 3 )
+ -9223372036854775808.1.ceil.should.eql?(-9223372036854775808)
+ +9223372036854775808.1.ceil.should.eql?(+9223372036854775808)
end
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)
+ 2.1679.ceil(0).should.eql?(3)
+ 214.94.ceil(-1).should.eql?(220)
+ 7.0.ceil(1).should.eql?(7.0)
+ 200.0.ceil(-2).should.eql?(200)
+ -1.234.ceil(2).should.eql?(-1.23)
+ 5.123812.ceil(4).should.eql?(5.1239)
+ 10.00001.ceil(5).should.eql?(10.00001)
end
end
diff --git a/spec/ruby/core/float/comparison_spec.rb b/spec/ruby/core/float/comparison_spec.rb
index 53e7ec332a..e9adf2fd6a 100644
--- a/spec/ruby/core/float/comparison_spec.rb
+++ b/spec/ruby/core/float/comparison_spec.rb
@@ -7,16 +7,32 @@ describe "Float#<=>" do
((bignum_value*1.1) <=> bignum_value).should == 1
end
- it "returns nil when either argument is NaN" do
- (nan_value <=> 71.2).should be_nil
- (1771.176 <=> nan_value).should be_nil
+ it "returns nil if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value <=> n).should == nil
+ (n <=> nan_value).should == nil
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value <=> n).should == 1
+ (n <=> infinity_value).should == -1
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value <=> n).should == -1
+ (n <=> -infinity_value).should == 1
+ }
end
it "returns nil when the given argument is not a Float" do
- (1.0 <=> "1").should be_nil
- (1.0 <=> "1".freeze).should be_nil
- (1.0 <=> :one).should be_nil
- (1.0 <=> true).should be_nil
+ (1.0 <=> "1").should == nil
+ (1.0 <=> "1".freeze).should == nil
+ (1.0 <=> :one).should == nil
+ (1.0 <=> true).should == nil
end
it "compares using #coerce when argument is not a Float" do
@@ -46,28 +62,17 @@ describe "Float#<=>" do
bad_coercible = klass.new
-> {
4.2 <=> bad_coercible
- }.should raise_error(TypeError, "coerce must return [x, y]")
+ }.should.raise(TypeError, "coerce must return [x, y]")
end
- # The 4 tests below are taken from matz's revision 23730 for Ruby trunk
- #
- it "returns 1 when self is Infinity and other is an Integer" do
+ it "returns the correct result when one side is infinite" do
(infinity_value <=> Float::MAX.to_i*2).should == 1
- end
-
- it "returns -1 when self is negative and other is Infinity" do
(-Float::MAX.to_i*2 <=> infinity_value).should == -1
- end
-
- it "returns -1 when self is -Infinity and other is negative" do
(-infinity_value <=> -Float::MAX.to_i*2).should == -1
- end
-
- it "returns 1 when self is negative and other is -Infinity" do
(-Float::MAX.to_i*2 <=> -infinity_value).should == 1
end
- it "returns 0 when self is Infinity and other other is infinite?=1" do
+ it "returns 0 when self is Infinity and other is infinite?=1" do
obj = Object.new
def obj.infinite?
1
@@ -86,7 +91,7 @@ describe "Float#<=>" do
it "returns 1 when self is Infinity and other is infinite?=nil (which means finite)" do
obj = Object.new
def obj.infinite?
- nil
+ nil
end
(infinity_value <=> obj).should == 1
end
diff --git a/spec/ruby/core/float/constants_spec.rb b/spec/ruby/core/float/constants_spec.rb
index 497e0ae188..1b71ee8adf 100644
--- a/spec/ruby/core/float/constants_spec.rb
+++ b/spec/ruby/core/float/constants_spec.rb
@@ -50,6 +50,6 @@ describe "Float constant" do
end
it "NAN is 'not a number'" do
- Float::NAN.nan?.should be_true
+ Float::NAN.nan?.should == true
end
end
diff --git a/spec/ruby/core/float/denominator_spec.rb b/spec/ruby/core/float/denominator_spec.rb
index 6f4fcfcf23..85beaa98cd 100644
--- a/spec/ruby/core/float/denominator_spec.rb
+++ b/spec/ruby/core/float/denominator_spec.rb
@@ -12,7 +12,7 @@ describe "Float#denominator" do
it "returns an Integer" do
@numbers.each do |number|
- number.denominator.should be_kind_of(Integer)
+ number.denominator.should.is_a?(Integer)
end
end
diff --git a/spec/ruby/core/float/divide_spec.rb b/spec/ruby/core/float/divide_spec.rb
index 72ab7527bd..68a2c550a7 100644
--- a/spec/ruby/core/float/divide_spec.rb
+++ b/spec/ruby/core/float/divide_spec.rb
@@ -16,25 +16,25 @@ describe "Float#/" do
end
it "returns +Infinity when dividing non-zero by zero of the same sign" do
- (1.0 / 0.0).should be_positive_infinity
- (-1.0 / -0.0).should be_positive_infinity
+ (1.0 / 0.0).should.infinite? == 1
+ (-1.0 / -0.0).should.infinite? == 1
end
it "returns -Infinity when dividing non-zero by zero of opposite sign" do
- (-1.0 / 0.0).should be_negative_infinity
- (1.0 / -0.0).should be_negative_infinity
+ (-1.0 / 0.0).should.infinite? == -1
+ (1.0 / -0.0).should.infinite? == -1
end
it "returns NaN when dividing zero by zero" do
- (0.0 / 0.0).should be_nan
- (-0.0 / 0.0).should be_nan
- (0.0 / -0.0).should be_nan
- (-0.0 / -0.0).should be_nan
+ (0.0 / 0.0).should.nan?
+ (-0.0 / 0.0).should.nan?
+ (0.0 / -0.0).should.nan?
+ (-0.0 / -0.0).should.nan?
end
it "raises a TypeError when given a non-Numeric" do
- -> { 13.0 / "10" }.should raise_error(TypeError)
- -> { 13.0 / :symbol }.should raise_error(TypeError)
+ -> { 13.0 / "10" }.should.raise(TypeError)
+ -> { 13.0 / :symbol }.should.raise(TypeError)
end
it "divides correctly by Rational numbers" do
diff --git a/spec/ruby/core/float/divmod_spec.rb b/spec/ruby/core/float/divmod_spec.rb
index 523217ac1f..7ed6cd3487 100644
--- a/spec/ruby/core/float/divmod_spec.rb
+++ b/spec/ruby/core/float/divmod_spec.rb
@@ -3,41 +3,41 @@ require_relative '../../spec_helper'
describe "Float#divmod" do
it "returns an [quotient, modulus] from dividing self by other" do
values = 3.14.divmod(2)
- values[0].should eql(1)
+ values[0].should.eql?(1)
values[1].should be_close(1.14, TOLERANCE)
values = 2.8284.divmod(3.1415)
- values[0].should eql(0)
+ values[0].should.eql?(0)
values[1].should be_close(2.8284, TOLERANCE)
values = -1.0.divmod(bignum_value)
- values[0].should eql(-1)
+ values[0].should.eql?(-1)
values[1].should be_close(18446744073709551616.0, TOLERANCE)
values = -1.0.divmod(1)
- values[0].should eql(-1)
- values[1].should eql(0.0)
+ values[0].should.eql?(-1)
+ values[1].should.eql?(0.0)
end
# Behaviour established as correct in r23953
it "raises a FloatDomainError if self is NaN" do
- -> { nan_value.divmod(1) }.should raise_error(FloatDomainError)
+ -> { nan_value.divmod(1) }.should.raise(FloatDomainError)
end
# Behaviour established as correct in r23953
it "raises a FloatDomainError if other is NaN" do
- -> { 1.divmod(nan_value) }.should raise_error(FloatDomainError)
+ -> { 1.0.divmod(nan_value) }.should.raise(FloatDomainError)
end
# Behaviour established as correct in r23953
it "raises a FloatDomainError if self is Infinity" do
- -> { infinity_value.divmod(1) }.should raise_error(FloatDomainError)
+ -> { infinity_value.divmod(1) }.should.raise(FloatDomainError)
end
it "raises a ZeroDivisionError if other is zero" do
- -> { 1.0.divmod(0) }.should raise_error(ZeroDivisionError)
- -> { 1.0.divmod(0.0) }.should raise_error(ZeroDivisionError)
+ -> { 1.0.divmod(0) }.should.raise(ZeroDivisionError)
+ -> { 1.0.divmod(0.0) }.should.raise(ZeroDivisionError)
end
# redmine #5276"
it "returns the correct [quotient, modulus] even for large quotient" do
- 0.59.divmod(7.761021455128987e-11).first.should eql(7602092113)
+ 0.59.divmod(7.761021455128987e-11).first.should.eql?(7602092113)
end
end
diff --git a/spec/ruby/core/float/dup_spec.rb b/spec/ruby/core/float/dup_spec.rb
index 294da8e2bc..b474e21325 100644
--- a/spec/ruby/core/float/dup_spec.rb
+++ b/spec/ruby/core/float/dup_spec.rb
@@ -3,6 +3,6 @@ require_relative '../../spec_helper'
describe "Float#dup" do
it "returns self" do
float = 2.4
- float.dup.should equal(float)
+ float.dup.should.equal?(float)
end
end
diff --git a/spec/ruby/core/float/eql_spec.rb b/spec/ruby/core/float/eql_spec.rb
index 6b5f91db33..cf1ad8416f 100644
--- a/spec/ruby/core/float/eql_spec.rb
+++ b/spec/ruby/core/float/eql_spec.rb
@@ -2,15 +2,15 @@ require_relative '../../spec_helper'
describe "Float#eql?" do
it "returns true if other is a Float equal to self" do
- 0.0.eql?(0.0).should be_true
+ 0.0.eql?(0.0).should == true
end
it "returns false if other is a Float not equal to self" do
- 1.0.eql?(1.1).should be_false
+ 1.0.eql?(1.1).should == false
end
it "returns false if other is not a Float" do
- 1.0.eql?(1).should be_false
- 1.0.eql?(:one).should be_false
+ 1.0.eql?(1).should == false
+ 1.0.eql?(:one).should == false
end
end
diff --git a/spec/ruby/core/float/float_spec.rb b/spec/ruby/core/float/float_spec.rb
index 263ae82079..46b2eff372 100644
--- a/spec/ruby/core/float/float_spec.rb
+++ b/spec/ruby/core/float/float_spec.rb
@@ -8,12 +8,12 @@ describe "Float" do
it ".allocate raises a TypeError" do
-> do
Float.allocate
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it ".new is undefined" do
-> do
Float.new
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
end
diff --git a/spec/ruby/core/float/floor_spec.rb b/spec/ruby/core/float/floor_spec.rb
index 046216d36d..f77300eb04 100644
--- a/spec/ruby/core/float/floor_spec.rb
+++ b/spec/ruby/core/float/floor_spec.rb
@@ -1,21 +1,28 @@
require_relative '../../spec_helper'
+require_relative '../integer/shared/integer_floor_precision'
describe "Float#floor" do
+ context "with values equal to integers" do
+ it_behaves_like :integer_floor_precision, :Float
+ end
+
it "returns the largest Integer less than or equal to self" do
- -1.2.floor.should eql( -2)
- -1.0.floor.should eql( -1)
- 0.0.floor.should eql( 0 )
- 1.0.floor.should eql( 1 )
- 5.9.floor.should eql( 5 )
- -9223372036854775808.1.floor.should eql(-9223372036854775808)
- +9223372036854775808.1.floor.should eql(+9223372036854775808)
+ -1.2.floor.should.eql?( -2)
+ -1.0.floor.should.eql?( -1)
+ 0.0.floor.should.eql?( 0 )
+ 1.0.floor.should.eql?( 1 )
+ 5.9.floor.should.eql?( 5 )
+ -9223372036854775808.1.floor.should.eql?(-9223372036854775808)
+ +9223372036854775808.1.floor.should.eql?(+9223372036854775808)
end
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)
+ 2.1679.floor(0).should.eql?(2)
+ 214.94.floor(-1).should.eql?(210)
+ 7.0.floor(1).should.eql?(7.0)
+ 200.0.floor(-2).should.eql?(200)
+ -1.234.floor(2).should.eql?(-1.24)
+ 5.123812.floor(4).should.eql?(5.1238)
+ 10.00001.floor(5).should.eql?(10.00001)
end
end
diff --git a/spec/ruby/core/float/gt_spec.rb b/spec/ruby/core/float/gt_spec.rb
index 0d73f1c3df..5194796b46 100644
--- a/spec/ruby/core/float/gt_spec.rb
+++ b/spec/ruby/core/float/gt_spec.rb
@@ -11,7 +11,28 @@ describe "Float#>" do
end
it "raises an ArgumentError when given a non-Numeric" do
- -> { 5.0 > "4" }.should raise_error(ArgumentError)
- -> { 5.0 > mock('x') }.should raise_error(ArgumentError)
+ -> { 5.0 > "4" }.should.raise(ArgumentError)
+ -> { 5.0 > mock('x') }.should.raise(ArgumentError)
+ end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value > n).should == false
+ (n > nan_value).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value > n).should == true
+ (n > infinity_value).should == false
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value > n).should == false
+ (n > -infinity_value).should == true
+ }
end
end
diff --git a/spec/ruby/core/float/gte_spec.rb b/spec/ruby/core/float/gte_spec.rb
index 98ec60b70b..4a62725d53 100644
--- a/spec/ruby/core/float/gte_spec.rb
+++ b/spec/ruby/core/float/gte_spec.rb
@@ -11,7 +11,28 @@ describe "Float#>=" do
end
it "raises an ArgumentError when given a non-Numeric" do
- -> { 5.0 >= "4" }.should raise_error(ArgumentError)
- -> { 5.0 >= mock('x') }.should raise_error(ArgumentError)
+ -> { 5.0 >= "4" }.should.raise(ArgumentError)
+ -> { 5.0 >= mock('x') }.should.raise(ArgumentError)
+ end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value >= n).should == false
+ (n >= nan_value).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value >= n).should == true
+ (n >= infinity_value).should == false
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value >= n).should == false
+ (n >= -infinity_value).should == true
+ }
end
end
diff --git a/spec/ruby/core/float/lt_spec.rb b/spec/ruby/core/float/lt_spec.rb
index c01b6e0e02..0f0e1752bd 100644
--- a/spec/ruby/core/float/lt_spec.rb
+++ b/spec/ruby/core/float/lt_spec.rb
@@ -11,7 +11,28 @@ describe "Float#<" do
end
it "raises an ArgumentError when given a non-Numeric" do
- -> { 5.0 < "4" }.should raise_error(ArgumentError)
- -> { 5.0 < mock('x') }.should raise_error(ArgumentError)
+ -> { 5.0 < "4" }.should.raise(ArgumentError)
+ -> { 5.0 < mock('x') }.should.raise(ArgumentError)
+ end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value < n).should == false
+ (n < nan_value).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value < n).should == false
+ (n < infinity_value).should == true
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value < n).should == true
+ (n < -infinity_value).should == false
+ }
end
end
diff --git a/spec/ruby/core/float/lte_spec.rb b/spec/ruby/core/float/lte_spec.rb
index 66f2ddc2c7..afb64ade09 100644
--- a/spec/ruby/core/float/lte_spec.rb
+++ b/spec/ruby/core/float/lte_spec.rb
@@ -12,7 +12,28 @@ describe "Float#<=" do
end
it "raises an ArgumentError when given a non-Numeric" do
- -> { 5.0 <= "4" }.should raise_error(ArgumentError)
- -> { 5.0 <= mock('x') }.should raise_error(ArgumentError)
+ -> { 5.0 <= "4" }.should.raise(ArgumentError)
+ -> { 5.0 <= mock('x') }.should.raise(ArgumentError)
+ end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value <= n).should == false
+ (n <= nan_value).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value <= n).should == false
+ (n <= infinity_value).should == true
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value <= n).should == true
+ (n <= -infinity_value).should == false
+ }
end
end
diff --git a/spec/ruby/core/float/magnitude_spec.rb b/spec/ruby/core/float/magnitude_spec.rb
index db577c15c5..7cdd8ef28a 100644
--- a/spec/ruby/core/float/magnitude_spec.rb
+++ b/spec/ruby/core/float/magnitude_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../spec_helper"
require_relative 'shared/abs'
describe "Float#magnitude" do
diff --git a/spec/ruby/core/float/multiply_spec.rb b/spec/ruby/core/float/multiply_spec.rb
index 2adb8796cd..edaaba7e61 100644
--- a/spec/ruby/core/float/multiply_spec.rb
+++ b/spec/ruby/core/float/multiply_spec.rb
@@ -11,7 +11,7 @@ describe "Float#*" do
end
it "raises a TypeError when given a non-Numeric" do
- -> { 13.0 * "10" }.should raise_error(TypeError)
- -> { 13.0 * :symbol }.should raise_error(TypeError)
+ -> { 13.0 * "10" }.should.raise(TypeError)
+ -> { 13.0 * :symbol }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/float/negative_spec.rb b/spec/ruby/core/float/negative_spec.rb
index 511d92ade6..484e636adb 100644
--- a/spec/ruby/core/float/negative_spec.rb
+++ b/spec/ruby/core/float/negative_spec.rb
@@ -3,31 +3,31 @@ require_relative '../../spec_helper'
describe "Float#negative?" do
describe "on positive numbers" do
it "returns false" do
- 0.1.negative?.should be_false
+ 0.1.negative?.should == false
end
end
describe "on zero" do
it "returns false" do
- 0.0.negative?.should be_false
+ 0.0.negative?.should == false
end
end
describe "on negative zero" do
it "returns false" do
- -0.0.negative?.should be_false
+ -0.0.negative?.should == false
end
end
describe "on negative numbers" do
it "returns true" do
- -0.1.negative?.should be_true
+ -0.1.negative?.should == true
end
end
describe "on NaN" do
it "returns false" do
- nan_value.negative?.should be_false
+ nan_value.negative?.should == false
end
end
end
diff --git a/spec/ruby/core/float/next_float_spec.rb b/spec/ruby/core/float/next_float_spec.rb
index 29e2d31146..59892be343 100644
--- a/spec/ruby/core/float/next_float_spec.rb
+++ b/spec/ruby/core/float/next_float_spec.rb
@@ -9,7 +9,7 @@ describe "Float#next_float" do
barely_positive.should < barely_positive.next_float
midpoint = barely_positive / 2
- [0.0, barely_positive].should include midpoint
+ [0.0, barely_positive].should.include? midpoint
end
it "returns Float::INFINITY for Float::INFINITY" do
diff --git a/spec/ruby/core/float/numerator_spec.rb b/spec/ruby/core/float/numerator_spec.rb
index 7832e8f056..53b32fdd3d 100644
--- a/spec/ruby/core/float/numerator_spec.rb
+++ b/spec/ruby/core/float/numerator_spec.rb
@@ -15,7 +15,7 @@ describe "Float#numerator" do
it "converts self to a Rational object then returns its numerator" do
@numbers.each do |number|
- number.infinite?.should be_nil
+ number.infinite?.should == nil
number.numerator.should == Rational(number).numerator
end
end
@@ -25,7 +25,7 @@ describe "Float#numerator" do
end
it "returns NaN for NaN" do
- nan_value.numerator.nan?.should be_true
+ nan_value.numerator.nan?.should == true
end
it "returns Infinity for Infinity" do
diff --git a/spec/ruby/core/float/positive_spec.rb b/spec/ruby/core/float/positive_spec.rb
index 575f92a720..aa87c03151 100644
--- a/spec/ruby/core/float/positive_spec.rb
+++ b/spec/ruby/core/float/positive_spec.rb
@@ -3,31 +3,31 @@ require_relative '../../spec_helper'
describe "Float#positive?" do
describe "on positive numbers" do
it "returns true" do
- 0.1.positive?.should be_true
+ 0.1.positive?.should == true
end
end
describe "on zero" do
it "returns false" do
- 0.0.positive?.should be_false
+ 0.0.positive?.should == false
end
end
describe "on negative zero" do
it "returns false" do
- -0.0.positive?.should be_false
+ -0.0.positive?.should == false
end
end
describe "on negative numbers" do
it "returns false" do
- -0.1.positive?.should be_false
+ -0.1.positive?.should == false
end
end
describe "on NaN" do
it "returns false" do
- nan_value.positive?.should be_false
+ nan_value.positive?.should == false
end
end
end
diff --git a/spec/ruby/core/float/prev_float_spec.rb b/spec/ruby/core/float/prev_float_spec.rb
index 5e50269da7..2d1f136254 100644
--- a/spec/ruby/core/float/prev_float_spec.rb
+++ b/spec/ruby/core/float/prev_float_spec.rb
@@ -9,7 +9,7 @@ describe "Float#prev_float" do
barely_negative.should > barely_negative.prev_float
midpoint = barely_negative / 2
- [0.0, barely_negative].should include midpoint
+ [0.0, barely_negative].should.include? midpoint
end
it "returns -Float::INFINITY for -Float::INFINITY" do
diff --git a/spec/ruby/core/float/rationalize_spec.rb b/spec/ruby/core/float/rationalize_spec.rb
index 0c5bef7ac4..fa8fb5c841 100644
--- a/spec/ruby/core/float/rationalize_spec.rb
+++ b/spec/ruby/core/float/rationalize_spec.rb
@@ -29,15 +29,15 @@ describe "Float#rationalize" do
end
it "raises a FloatDomainError for Infinity" do
- -> {infinity_value.rationalize}.should raise_error(FloatDomainError)
+ -> {infinity_value.rationalize}.should.raise(FloatDomainError)
end
it "raises a FloatDomainError for NaN" do
- -> { nan_value.rationalize }.should raise_error(FloatDomainError)
+ -> { nan_value.rationalize }.should.raise(FloatDomainError)
end
it "raises ArgumentError when passed more than one argument" do
- -> { 0.3.rationalize(0.1, 0.1) }.should raise_error(ArgumentError)
- -> { 0.3.rationalize(0.1, 0.1, 2) }.should raise_error(ArgumentError)
+ -> { 0.3.rationalize(0.1, 0.1) }.should.raise(ArgumentError)
+ -> { 0.3.rationalize(0.1, 0.1, 2) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/float/round_spec.rb b/spec/ruby/core/float/round_spec.rb
index e5a8f534e7..63c1d5689c 100644
--- a/spec/ruby/core/float/round_spec.rb
+++ b/spec/ruby/core/float/round_spec.rb
@@ -16,51 +16,57 @@ describe "Float#round" do
end
it "raises FloatDomainError for exceptional values" do
- -> { (+infinity_value).round }.should raise_error(FloatDomainError)
- -> { (-infinity_value).round }.should raise_error(FloatDomainError)
- -> { nan_value.round }.should raise_error(FloatDomainError)
+ -> { (+infinity_value).round }.should.raise(FloatDomainError)
+ -> { (-infinity_value).round }.should.raise(FloatDomainError)
+ -> { nan_value.round }.should.raise(FloatDomainError)
end
it "rounds self to an optionally given precision" do
- 5.5.round(0).should eql(6)
- 5.7.round(1).should eql(5.7)
+ 5.5.round(0).should.eql?(6)
+ 5.7.round(1).should.eql?(5.7)
1.2345678.round(2).should == 1.23
- 123456.78.round(-2).should eql(123500) # rounded up
- -123456.78.round(-2).should eql(-123500)
+ 123456.78.round(-2).should.eql?(123500) # rounded up
+ -123456.78.round(-2).should.eql?(-123500)
12.345678.round(3.999).should == 12.346
end
+ it "correctly rounds exact floats with a numerous digits in a fraction part" do
+ 0.8241000000000004.round(10).should == 0.8241
+ 0.8241000000000002.round(10).should == 0.8241
+ end
+
it "returns zero when passed a negative argument with magnitude greater than magnitude of the whole number portion of the Float" do
- 0.8346268.round(-1).should eql(0)
+ 0.8346268.round(-1).should.eql?(0)
end
it "raises a TypeError when its argument can not be converted to an Integer" do
- -> { 1.0.round("4") }.should raise_error(TypeError)
- -> { 1.0.round(nil) }.should raise_error(TypeError)
+ -> { 1.0.round("4") }.should.raise(TypeError)
+ -> { 1.0.round(nil) }.should.raise(TypeError)
end
it "raises FloatDomainError for exceptional values when passed a non-positive precision" do
- -> { Float::INFINITY.round( 0) }.should raise_error(FloatDomainError)
- -> { Float::INFINITY.round(-2) }.should raise_error(FloatDomainError)
- -> { (-Float::INFINITY).round( 0) }.should raise_error(FloatDomainError)
- -> { (-Float::INFINITY).round(-2) }.should raise_error(FloatDomainError)
+ -> { Float::INFINITY.round( 0) }.should.raise(FloatDomainError)
+ -> { Float::INFINITY.round(-2) }.should.raise(FloatDomainError)
+ -> { (-Float::INFINITY).round( 0) }.should.raise(FloatDomainError)
+ -> { (-Float::INFINITY).round(-2) }.should.raise(FloatDomainError)
end
it "raises RangeError for NAN when passed a non-positive precision" do
- -> { Float::NAN.round(0) }.should raise_error(RangeError)
- -> { Float::NAN.round(-2) }.should raise_error(RangeError)
+ -> { Float::NAN.round(0) }.should.raise(RangeError)
+ -> { Float::NAN.round(-2) }.should.raise(RangeError)
end
it "returns self for exceptional values when passed a non-negative precision" do
Float::INFINITY.round(2).should == Float::INFINITY
(-Float::INFINITY).round(2).should == -Float::INFINITY
- Float::NAN.round(2).should be_nan
+ Float::NAN.round(2).should.nan?
end
# redmine:5227
it "works for corner cases" do
- 42.0.round(308).should eql(42.0)
- 1.0e307.round(2).should eql(1.0e307)
+ 42.0.round(308).should.eql?(42.0)
+ 1.0e307.round(2).should.eql?(1.0e307)
+ 120.0.round(-1).should.eql?(120)
end
# redmine:5271
@@ -68,115 +74,117 @@ describe "Float#round" do
0.42.round(2.0**30).should == 0.42
end
+ it "returns rounded values for not so big argument" do
+ 0.42.round(2.0**23).should == 0.42
+ end
+
it "returns big values rounded to nearest" do
- +2.5e20.round(-20).should eql( +3 * 10 ** 20 )
- -2.5e20.round(-20).should eql( -3 * 10 ** 20 )
+ +2.5e20.round(-20).should.eql?( +3 * 10 ** 20 )
+ -2.5e20.round(-20).should.eql?( -3 * 10 ** 20 )
end
# redmine #5272
it "returns rounded values for big values" do
- +2.4e20.round(-20).should eql( +2 * 10 ** 20 )
- -2.4e20.round(-20).should eql( -2 * 10 ** 20 )
- +2.5e200.round(-200).should eql( +3 * 10 ** 200 )
- +2.4e200.round(-200).should eql( +2 * 10 ** 200 )
- -2.5e200.round(-200).should eql( -3 * 10 ** 200 )
- -2.4e200.round(-200).should eql( -2 * 10 ** 200 )
+ +2.4e20.round(-20).should.eql?( +2 * 10 ** 20 )
+ -2.4e20.round(-20).should.eql?( -2 * 10 ** 20 )
+ +2.5e200.round(-200).should.eql?( +3 * 10 ** 200 )
+ +2.4e200.round(-200).should.eql?( +2 * 10 ** 200 )
+ -2.5e200.round(-200).should.eql?( -3 * 10 ** 200 )
+ -2.4e200.round(-200).should.eql?( -2 * 10 ** 200 )
end
it "returns different rounded values depending on the half option" do
- 2.5.round(half: nil).should eql(3)
- 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: nil).should eql(4)
- 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: nil).should eql(-3)
- (-2.5).round(half: :up).should eql(-3)
- (-2.5).round(half: :down).should eql(-2)
- (-2.5).round(half: :even).should eql(-2)
+ 2.5.round(half: nil).should.eql?(3)
+ 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: nil).should.eql?(4)
+ 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: nil).should.eql?(-3)
+ (-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
it "rounds self to an optionally given precision with a half option" do
- 5.55.round(1, half: nil).should eql(5.6)
- 5.55.round(1, half: :up).should eql(5.6)
- 5.55.round(1, half: :down).should eql(5.5)
- 5.55.round(1, half: :even).should eql(5.6)
- -5.55.round(1, half: nil).should eql(-5.6)
- -5.55.round(1, half: :up).should eql(-5.6)
- -5.55.round(1, half: :down).should eql(-5.5)
- -5.55.round(1, half: :even).should eql(-5.6)
+ 5.55.round(1, half: nil).should.eql?(5.6)
+ 5.55.round(1, half: :up).should.eql?(5.6)
+ 5.55.round(1, half: :down).should.eql?(5.5)
+ 5.55.round(1, half: :even).should.eql?(5.6)
+ -5.55.round(1, half: nil).should.eql?(-5.6)
+ -5.55.round(1, half: :up).should.eql?(-5.6)
+ -5.55.round(1, half: :down).should.eql?(-5.5)
+ -5.55.round(1, half: :even).should.eql?(-5.6)
end
it "preserves cases where neighbouring floating pointer number increase the decimal places" do
- 4.8100000000000005.round(5, half: nil).should eql(4.81)
- 4.8100000000000005.round(5, half: :up).should eql(4.81)
- 4.8100000000000005.round(5, half: :down).should eql(4.81)
- 4.8100000000000005.round(5, half: :even).should eql(4.81)
- -4.8100000000000005.round(5, half: nil).should eql(-4.81)
- -4.8100000000000005.round(5, half: :up).should eql(-4.81)
- -4.8100000000000005.round(5, half: :down).should eql(-4.81)
- -4.8100000000000005.round(5, half: :even).should eql(-4.81)
- 4.81.round(5, half: nil).should eql(4.81)
- 4.81.round(5, half: :up).should eql(4.81)
- 4.81.round(5, half: :down).should eql(4.81)
- 4.81.round(5, half: :even).should eql(4.81)
- -4.81.round(5, half: nil).should eql(-4.81)
- -4.81.round(5, half: :up).should eql(-4.81)
- -4.81.round(5, half: :down).should eql(-4.81)
- -4.81.round(5, half: :even).should eql(-4.81)
- 4.809999999999999.round(5, half: nil).should eql(4.81)
- 4.809999999999999.round(5, half: :up).should eql(4.81)
- 4.809999999999999.round(5, half: :down).should eql(4.81)
- 4.809999999999999.round(5, half: :even).should eql(4.81)
- -4.809999999999999.round(5, half: nil).should eql(-4.81)
- -4.809999999999999.round(5, half: :up).should eql(-4.81)
- -4.809999999999999.round(5, half: :down).should eql(-4.81)
- -4.809999999999999.round(5, half: :even).should eql(-4.81)
- end
-
- ruby_bug "", ""..."3.3" do
- # These numbers are neighbouring floating point numbers round a
- # precise value. They test that the rounding modes work correctly
- # round that value and precision is not lost which might cause
- # incorrect results.
- it "does not lose precision during the rounding process" do
- 767573.1875850001.round(5, half: nil).should eql(767573.18759)
- 767573.1875850001.round(5, half: :up).should eql(767573.18759)
- 767573.1875850001.round(5, half: :down).should eql(767573.18759)
- 767573.1875850001.round(5, half: :even).should eql(767573.18759)
- -767573.1875850001.round(5, half: nil).should eql(-767573.18759)
- -767573.1875850001.round(5, half: :up).should eql(-767573.18759)
- -767573.1875850001.round(5, half: :down).should eql(-767573.18759)
- -767573.1875850001.round(5, half: :even).should eql(-767573.18759)
- 767573.187585.round(5, half: nil).should eql(767573.18759)
- 767573.187585.round(5, half: :up).should eql(767573.18759)
- 767573.187585.round(5, half: :down).should eql(767573.18758)
- 767573.187585.round(5, half: :even).should eql(767573.18758)
- -767573.187585.round(5, half: nil).should eql(-767573.18759)
- -767573.187585.round(5, half: :up).should eql(-767573.18759)
- -767573.187585.round(5, half: :down).should eql(-767573.18758)
- -767573.187585.round(5, half: :even).should eql(-767573.18758)
- 767573.1875849998.round(5, half: nil).should eql(767573.18758)
- 767573.1875849998.round(5, half: :up).should eql(767573.18758)
- 767573.1875849998.round(5, half: :down).should eql(767573.18758)
- 767573.1875849998.round(5, half: :even).should eql(767573.18758)
- -767573.1875849998.round(5, half: nil).should eql(-767573.18758)
- -767573.1875849998.round(5, half: :up).should eql(-767573.18758)
- -767573.1875849998.round(5, half: :down).should eql(-767573.18758)
- -767573.1875849998.round(5, half: :even).should eql(-767573.18758)
- end
+ 4.8100000000000005.round(5, half: nil).should.eql?(4.81)
+ 4.8100000000000005.round(5, half: :up).should.eql?(4.81)
+ 4.8100000000000005.round(5, half: :down).should.eql?(4.81)
+ 4.8100000000000005.round(5, half: :even).should.eql?(4.81)
+ -4.8100000000000005.round(5, half: nil).should.eql?(-4.81)
+ -4.8100000000000005.round(5, half: :up).should.eql?(-4.81)
+ -4.8100000000000005.round(5, half: :down).should.eql?(-4.81)
+ -4.8100000000000005.round(5, half: :even).should.eql?(-4.81)
+ 4.81.round(5, half: nil).should.eql?(4.81)
+ 4.81.round(5, half: :up).should.eql?(4.81)
+ 4.81.round(5, half: :down).should.eql?(4.81)
+ 4.81.round(5, half: :even).should.eql?(4.81)
+ -4.81.round(5, half: nil).should.eql?(-4.81)
+ -4.81.round(5, half: :up).should.eql?(-4.81)
+ -4.81.round(5, half: :down).should.eql?(-4.81)
+ -4.81.round(5, half: :even).should.eql?(-4.81)
+ 4.809999999999999.round(5, half: nil).should.eql?(4.81)
+ 4.809999999999999.round(5, half: :up).should.eql?(4.81)
+ 4.809999999999999.round(5, half: :down).should.eql?(4.81)
+ 4.809999999999999.round(5, half: :even).should.eql?(4.81)
+ -4.809999999999999.round(5, half: nil).should.eql?(-4.81)
+ -4.809999999999999.round(5, half: :up).should.eql?(-4.81)
+ -4.809999999999999.round(5, half: :down).should.eql?(-4.81)
+ -4.809999999999999.round(5, half: :even).should.eql?(-4.81)
+ end
+
+ # These numbers are neighbouring floating point numbers round a
+ # precise value. They test that the rounding modes work correctly
+ # round that value and precision is not lost which might cause
+ # incorrect results.
+ it "does not lose precision during the rounding process" do
+ 767573.1875850001.round(5, half: nil).should.eql?(767573.18759)
+ 767573.1875850001.round(5, half: :up).should.eql?(767573.18759)
+ 767573.1875850001.round(5, half: :down).should.eql?(767573.18759)
+ 767573.1875850001.round(5, half: :even).should.eql?(767573.18759)
+ -767573.1875850001.round(5, half: nil).should.eql?(-767573.18759)
+ -767573.1875850001.round(5, half: :up).should.eql?(-767573.18759)
+ -767573.1875850001.round(5, half: :down).should.eql?(-767573.18759)
+ -767573.1875850001.round(5, half: :even).should.eql?(-767573.18759)
+ 767573.187585.round(5, half: nil).should.eql?(767573.18759)
+ 767573.187585.round(5, half: :up).should.eql?(767573.18759)
+ 767573.187585.round(5, half: :down).should.eql?(767573.18758)
+ 767573.187585.round(5, half: :even).should.eql?(767573.18758)
+ -767573.187585.round(5, half: nil).should.eql?(-767573.18759)
+ -767573.187585.round(5, half: :up).should.eql?(-767573.18759)
+ -767573.187585.round(5, half: :down).should.eql?(-767573.18758)
+ -767573.187585.round(5, half: :even).should.eql?(-767573.18758)
+ 767573.1875849998.round(5, half: nil).should.eql?(767573.18758)
+ 767573.1875849998.round(5, half: :up).should.eql?(767573.18758)
+ 767573.1875849998.round(5, half: :down).should.eql?(767573.18758)
+ 767573.1875849998.round(5, half: :even).should.eql?(767573.18758)
+ -767573.1875849998.round(5, half: nil).should.eql?(-767573.18758)
+ -767573.1875849998.round(5, half: :up).should.eql?(-767573.18758)
+ -767573.1875849998.round(5, half: :down).should.eql?(-767573.18758)
+ -767573.1875849998.round(5, half: :even).should.eql?(-767573.18758)
end
it "raises FloatDomainError for exceptional values with a half option" do
- -> { (+infinity_value).round(half: :up) }.should raise_error(FloatDomainError)
- -> { (-infinity_value).round(half: :down) }.should raise_error(FloatDomainError)
- -> { nan_value.round(half: :even) }.should raise_error(FloatDomainError)
+ -> { (+infinity_value).round(half: :up) }.should.raise(FloatDomainError)
+ -> { (-infinity_value).round(half: :down) }.should.raise(FloatDomainError)
+ -> { nan_value.round(half: :even) }.should.raise(FloatDomainError)
end
it "raise for a non-existent round mode" do
- -> { 14.2.round(half: :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode: nonsense")
+ -> { 14.2.round(half: :nonsense) }.should.raise(ArgumentError, "invalid rounding mode: nonsense")
end
describe "when 0.0 is given" do
@@ -188,7 +196,13 @@ describe "Float#round" do
it "returns 0 for 0 or undefined ndigits" do
(0.0).round.should == 0
(-0.0).round(0).should == 0
- (0.0).round(half: :up) == 0
+ (0.0).round(half: :up).should == 0
+ end
+
+ it "returns 0 for negative ndigits" do
+ (0.0).round(-1).should == 0
+ (-0.0).round(-1).should == 0
+ (0.0).round(-1, half: :up).should == 0
end
end
end
diff --git a/spec/ruby/core/float/shared/abs.rb b/spec/ruby/core/float/shared/abs.rb
index 607983322d..ab21480e24 100644
--- a/spec/ruby/core/float/shared/abs.rb
+++ b/spec/ruby/core/float/shared/abs.rb
@@ -16,6 +16,6 @@ describe :float_abs, shared: true do
end
it "returns NaN if NaN" do
- nan_value.send(@method).nan?.should be_true
+ nan_value.send(@method).nan?.should == true
end
end
diff --git a/spec/ruby/core/float/shared/arg.rb b/spec/ruby/core/float/shared/arg.rb
index 136cf19ec8..de0024313d 100644
--- a/spec/ruby/core/float/shared/arg.rb
+++ b/spec/ruby/core/float/shared/arg.rb
@@ -1,12 +1,12 @@
describe :float_arg, shared: true do
it "returns NaN if NaN" do
f = nan_value
- f.send(@method).nan?.should be_true
+ f.send(@method).nan?.should == true
end
it "returns self if NaN" do
f = nan_value
- f.send(@method).should equal(f)
+ f.send(@method).should.equal?(f)
end
it "returns 0 if positive" do
diff --git a/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb b/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb
index eec92d858f..bd3bf9019f 100644
--- a/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb
+++ b/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb
@@ -6,6 +6,6 @@ describe :float_arithmetic_exception_in_coerce, shared: true do
b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError)
# e.g. 1.0 > b
- -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError)
+ -> { 1.0.send(@method, b) }.should.raise(FloatSpecs::CoerceError)
end
end
diff --git a/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb b/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb
index 3e2c1e28dd..eec5d8daf9 100644
--- a/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb
+++ b/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb
@@ -6,6 +6,6 @@ describe :float_comparison_exception_in_coerce, shared: true do
b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError)
# e.g. 1.0 > b
- -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError)
+ -> { 1.0.send(@method, b) }.should.raise(FloatSpecs::CoerceError)
end
end
diff --git a/spec/ruby/core/float/shared/equal.rb b/spec/ruby/core/float/shared/equal.rb
index 668aa069b5..4d524e1cf2 100644
--- a/spec/ruby/core/float/shared/equal.rb
+++ b/spec/ruby/core/float/shared/equal.rb
@@ -14,4 +14,25 @@ describe :float_equal, shared: true do
1.0.send(@method, x).should == false
2.0.send(@method, x).should == true
end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value.send(@method, n)).should == false
+ (n.send(@method, nan_value)).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value.send(@method, n)).should == false
+ (n.send(@method, infinity_value)).should == false
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ ((-infinity_value).send(@method, n)).should == false
+ (n.send(@method, -infinity_value)).should == false
+ }
+ end
end
diff --git a/spec/ruby/core/float/shared/modulo.rb b/spec/ruby/core/float/shared/modulo.rb
index 6700bd4f4e..1efee1476d 100644
--- a/spec/ruby/core/float/shared/modulo.rb
+++ b/spec/ruby/core/float/shared/modulo.rb
@@ -16,13 +16,13 @@ describe :float_modulo, shared: true do
end
it "returns NaN when called on NaN or Infinities" do
- Float::NAN.send(@method, 42).should be_nan
- Float::INFINITY.send(@method, 42).should be_nan
- (-Float::INFINITY).send(@method, 42).should be_nan
+ Float::NAN.send(@method, 42).should.nan?
+ Float::INFINITY.send(@method, 42).should.nan?
+ (-Float::INFINITY).send(@method, 42).should.nan?
end
it "returns NaN when modulus is NaN" do
- 4.2.send(@method, Float::NAN).should be_nan
+ 4.2.send(@method, Float::NAN).should.nan?
end
it "returns -0.0 when called on -0.0 with a non zero modulus" do
@@ -42,7 +42,7 @@ describe :float_modulo, shared: true do
end
it "raises a ZeroDivisionError if other is zero" do
- -> { 1.0.send(@method, 0) }.should raise_error(ZeroDivisionError)
- -> { 1.0.send(@method, 0.0) }.should raise_error(ZeroDivisionError)
+ -> { 1.0.send(@method, 0) }.should.raise(ZeroDivisionError)
+ -> { 1.0.send(@method, 0.0) }.should.raise(ZeroDivisionError)
end
end
diff --git a/spec/ruby/core/float/shared/quo.rb b/spec/ruby/core/float/shared/quo.rb
index 0c90171b87..930187aaf7 100644
--- a/spec/ruby/core/float/shared/quo.rb
+++ b/spec/ruby/core/float/shared/quo.rb
@@ -12,8 +12,8 @@ describe :float_quo, shared: true do
end
it "returns NaN when the argument is NaN" do
- -1819.999999.send(@method, nan_value).nan?.should be_true
- 11109.1981271.send(@method, nan_value).nan?.should be_true
+ -1819.999999.send(@method, nan_value).nan?.should == true
+ 11109.1981271.send(@method, nan_value).nan?.should == true
end
it "returns Infinity when the argument is 0.0" do
@@ -50,10 +50,10 @@ describe :float_quo, shared: true do
end
it "raises a TypeError when argument isn't numeric" do
- -> { 27292.2.send(@method, mock('non-numeric')) }.should raise_error(TypeError)
+ -> { 27292.2.send(@method, mock('non-numeric')) }.should.raise(TypeError)
end
it "raises an ArgumentError when passed multiple arguments" do
- -> { 272.221.send(@method, 6,0.2) }.should raise_error(ArgumentError)
+ -> { 272.221.send(@method, 6,0.2) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/float/shared/to_i.rb b/spec/ruby/core/float/shared/to_i.rb
index 960295f095..1e6f941467 100644
--- a/spec/ruby/core/float/shared/to_i.rb
+++ b/spec/ruby/core/float/shared/to_i.rb
@@ -1,10 +1,14 @@
describe :float_to_i, shared: true do
it "returns self truncated to an Integer" do
- 899.2.send(@method).should eql(899)
- -1.122256e-45.send(@method).should eql(0)
- 5_213_451.9201.send(@method).should eql(5213451)
- 1.233450999123389e+12.send(@method).should eql(1233450999123)
- -9223372036854775808.1.send(@method).should eql(-9223372036854775808)
- 9223372036854775808.1.send(@method).should eql(9223372036854775808)
+ 899.2.send(@method).should.eql?(899)
+ -1.122256e-45.send(@method).should.eql?(0)
+ 5_213_451.9201.send(@method).should.eql?(5213451)
+ 1.233450999123389e+12.send(@method).should.eql?(1233450999123)
+ -9223372036854775808.1.send(@method).should.eql?(-9223372036854775808)
+ 9223372036854775808.1.send(@method).should.eql?(9223372036854775808)
+ end
+
+ it "raises a FloatDomainError for NaN" do
+ -> { nan_value.send(@method) }.should.raise(FloatDomainError)
end
end
diff --git a/spec/ruby/core/float/shared/to_s.rb b/spec/ruby/core/float/shared/to_s.rb
index 0925efc0f7..81ffdd9e81 100644
--- a/spec/ruby/core/float/shared/to_s.rb
+++ b/spec/ruby/core/float/shared/to_s.rb
@@ -297,12 +297,12 @@ describe :float_to_s, shared: true do
it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do
Encoding.default_internal = nil
- 1.23.send(@method).encoding.should equal(Encoding::US_ASCII)
+ 1.23.send(@method).encoding.should.equal?(Encoding::US_ASCII)
end
it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do
Encoding.default_internal = Encoding::IBM437
- 5.47.send(@method).encoding.should equal(Encoding::US_ASCII)
+ 5.47.send(@method).encoding.should.equal?(Encoding::US_ASCII)
end
end
end
diff --git a/spec/ruby/core/float/truncate_spec.rb b/spec/ruby/core/float/truncate_spec.rb
index 2c80145f9f..1750e3fdbc 100644
--- a/spec/ruby/core/float/truncate_spec.rb
+++ b/spec/ruby/core/float/truncate_spec.rb
@@ -5,10 +5,10 @@ describe "Float#truncate" do
it_behaves_like :float_to_i, :truncate
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)
+ 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
diff --git a/spec/ruby/core/float/uplus_spec.rb b/spec/ruby/core/float/uplus_spec.rb
index 936123558c..b979b2717a 100644
--- a/spec/ruby/core/float/uplus_spec.rb
+++ b/spec/ruby/core/float/uplus_spec.rb
@@ -4,6 +4,6 @@ describe "Float#+@" do
it "returns the same value with same sign (twos complement)" do
34.56.send(:+@).should == 34.56
-34.56.send(:+@).should == -34.56
- 0.0.send(:+@).should eql(0.0)
+ 0.0.send(:+@).should.eql?(0.0)
end
end
diff --git a/spec/ruby/core/gc/auto_compact_spec.rb b/spec/ruby/core/gc/auto_compact_spec.rb
index 4f9d043171..33ad1cb56c 100644
--- a/spec/ruby/core/gc/auto_compact_spec.rb
+++ b/spec/ruby/core/gc/auto_compact_spec.rb
@@ -1,26 +1,24 @@
require_relative '../../spec_helper'
-ruby_version_is "3.0" do
- describe "GC.auto_compact" do
- it "can set and get a boolean value" do
- begin
- GC.auto_compact = GC.auto_compact
- rescue NotImplementedError # platform does not support autocompact
- skip
- end
+describe "GC.auto_compact" do
+ it "can set and get a boolean value" do
+ begin
+ GC.auto_compact = GC.auto_compact
+ rescue NotImplementedError # platform does not support autocompact
+ skip
+ end
- original = GC.auto_compact
- begin
- GC.auto_compact = !original
- rescue NotImplementedError # platform does not support autocompact
- skip
- end
+ original = GC.auto_compact
+ begin
+ GC.auto_compact = !original
+ rescue NotImplementedError # platform does not support autocompact
+ skip
+ end
- begin
- GC.auto_compact.should == !original
- ensure
- GC.auto_compact = original
- end
+ begin
+ GC.auto_compact.should == !original
+ ensure
+ GC.auto_compact = original
end
end
end
diff --git a/spec/ruby/core/gc/config_spec.rb b/spec/ruby/core/gc/config_spec.rb
new file mode 100644
index 0000000000..57160f122c
--- /dev/null
+++ b/spec/ruby/core/gc/config_spec.rb
@@ -0,0 +1,97 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.4" do
+ describe "GC.config" do
+ context "without arguments" do
+ it "returns a hash of current settings" do
+ GC.config.should.is_a?(Hash)
+ end
+
+ it "includes the name of currently loaded GC implementation as a global key" do
+ GC.config.should.include?(:implementation)
+ GC.config[:implementation].should.is_a?(String)
+ end
+ end
+
+ context "with a hash of options" do
+ it "allows to set GC implementation's options, returning the new config" do
+ config = GC.config({})
+ # Try to find a boolean setting to reliably test changing it.
+ key, _value = config.find { |_k, v| v == true }
+ skip unless key
+
+ GC.config(key => false).should == config.merge(key => false)
+ GC.config[key].should == false
+ GC.config(key => true).should == config
+ GC.config[key].should == true
+ ensure
+ GC.config(config.except(:implementation))
+ end
+
+ it "does not change settings that aren't present in the hash" do
+ previous = GC.config
+ GC.config({})
+ GC.config.should == previous
+ end
+
+ it "ignores unknown keys" do
+ previous = GC.config
+ GC.config(foo: "bar")
+ GC.config.should == previous
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "returns the same as GC.config but without the :implementation key" do
+ previous = GC.config
+ GC.config({}).should == previous.except(:implementation)
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "returns the same as GC.config, including the :implementation key" do
+ previous = GC.config
+ GC.config({}).should == previous
+ end
+ end
+
+ it "raises an ArgumentError if options include global keys" do
+ -> { GC.config(implementation: "default") }.should.raise(ArgumentError, 'Attempting to set read-only key "Implementation"')
+ end
+ end
+
+ context "with a non-hash argument" do
+ it "returns current settings if argument is nil" do
+ GC.config(nil).should == GC.config
+ end
+
+ it "raises ArgumentError for all other arguments" do
+ -> { GC.config([]) }.should.raise(ArgumentError)
+ -> { GC.config("default") }.should.raise(ArgumentError)
+ -> { GC.config(1) }.should.raise(ArgumentError)
+ end
+ end
+
+ guard -> { PlatformGuard.standard? && GC.config[:implementation] == "default" } do
+ context "with default GC implementation on MRI" do
+ before do
+ @default_config = GC.config({})
+ end
+
+ after do
+ GC.config(@default_config.except(:implementation))
+ end
+
+ it "includes :rgengc_allow_full_mark option, true by default" do
+ GC.config.should.include?(:rgengc_allow_full_mark)
+ GC.config[:rgengc_allow_full_mark].should == true
+ end
+
+ it "allows to set :rgengc_allow_full_mark" do
+ # This key maps truthy and falsey values to true and false.
+ GC.config(rgengc_allow_full_mark: nil).should == @default_config.merge(rgengc_allow_full_mark: false)
+ GC.config(rgengc_allow_full_mark: 1.23).should == @default_config.merge(rgengc_allow_full_mark: true)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/gc/count_spec.rb b/spec/ruby/core/gc/count_spec.rb
index af2fbbe713..fe20c4ed2b 100644
--- a/spec/ruby/core/gc/count_spec.rb
+++ b/spec/ruby/core/gc/count_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "GC.count" do
it "returns an integer" do
- GC.count.should be_kind_of(Integer)
+ GC.count.should.is_a?(Integer)
end
it "increases as collections are run" do
diff --git a/spec/ruby/core/gc/measure_total_time_spec.rb b/spec/ruby/core/gc/measure_total_time_spec.rb
index 05d4598ebc..f5377c18fd 100644
--- a/spec/ruby/core/gc/measure_total_time_spec.rb
+++ b/spec/ruby/core/gc/measure_total_time_spec.rb
@@ -1,19 +1,17 @@
require_relative '../../spec_helper'
-ruby_version_is "3.1" do
- describe "GC.measure_total_time" do
- before :each do
- @default = GC.measure_total_time
- end
+describe "GC.measure_total_time" do
+ before :each do
+ @default = GC.measure_total_time
+ end
- after :each do
- GC.measure_total_time = @default
- end
+ after :each do
+ GC.measure_total_time = @default
+ end
- it "can set and get a boolean value" do
- original = GC.measure_total_time
- GC.measure_total_time = !original
- GC.measure_total_time.should == !original
- end
+ it "can set and get a boolean value" do
+ original = GC.measure_total_time
+ GC.measure_total_time = !original
+ GC.measure_total_time.should == !original
end
end
diff --git a/spec/ruby/core/gc/profiler/enabled_spec.rb b/spec/ruby/core/gc/profiler/enabled_spec.rb
index 23677be555..cfcd0951f0 100644
--- a/spec/ruby/core/gc/profiler/enabled_spec.rb
+++ b/spec/ruby/core/gc/profiler/enabled_spec.rb
@@ -11,11 +11,11 @@ describe "GC::Profiler.enabled?" do
it "reports as enabled when enabled" do
GC::Profiler.enable
- GC::Profiler.enabled?.should be_true
+ GC::Profiler.enabled?.should == true
end
it "reports as disabled when disabled" do
GC::Profiler.disable
- GC::Profiler.enabled?.should be_false
+ GC::Profiler.enabled?.should == false
end
end
diff --git a/spec/ruby/core/gc/profiler/result_spec.rb b/spec/ruby/core/gc/profiler/result_spec.rb
index 2ab46a8371..e888f975dc 100644
--- a/spec/ruby/core/gc/profiler/result_spec.rb
+++ b/spec/ruby/core/gc/profiler/result_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../../spec_helper'
describe "GC::Profiler.result" do
it "returns a string" do
- GC::Profiler.result.should be_kind_of(String)
+ GC::Profiler.result.should.is_a?(String)
end
end
diff --git a/spec/ruby/core/gc/profiler/total_time_spec.rb b/spec/ruby/core/gc/profiler/total_time_spec.rb
index 7709f168dd..a351e922af 100644
--- a/spec/ruby/core/gc/profiler/total_time_spec.rb
+++ b/spec/ruby/core/gc/profiler/total_time_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../../spec_helper'
describe "GC::Profiler.total_time" do
it "returns an float" do
- GC::Profiler.total_time.should be_kind_of(Float)
+ GC::Profiler.total_time.should.is_a?(Float)
end
end
diff --git a/spec/ruby/core/gc/stat_spec.rb b/spec/ruby/core/gc/stat_spec.rb
index 3b43b28a92..6e4800b3e3 100644
--- a/spec/ruby/core/gc/stat_spec.rb
+++ b/spec/ruby/core/gc/stat_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "GC.stat" do
it "returns hash of values" do
stat = GC.stat
- stat.should be_kind_of(Hash)
+ stat.should.is_a?(Hash)
stat.keys.should.include?(:count)
end
@@ -11,18 +11,18 @@ describe "GC.stat" do
hash = { count: "hello", __other__: "world" }
stat = GC.stat(hash)
- stat.should be_kind_of(Hash)
- stat.should equal hash
- stat[:count].should be_kind_of(Integer)
+ stat.should.is_a?(Hash)
+ stat.should.equal? hash
+ stat[:count].should.is_a?(Integer)
stat[:__other__].should == "world"
end
it "the values are all Integer since rb_gc_stat() returns size_t" do
- GC.stat.values.each { |value| value.should be_kind_of(Integer) }
+ GC.stat.values.each { |value| value.should.is_a?(Integer) }
end
it "can return a single value" do
- GC.stat(:count).should be_kind_of(Integer)
+ GC.stat(:count).should.is_a?(Integer)
end
it "increases count after GC is run" do
@@ -38,25 +38,25 @@ describe "GC.stat" do
end
it "provides some number for count" do
- GC.stat(:count).should be_kind_of(Integer)
- GC.stat[:count].should be_kind_of(Integer)
+ GC.stat(:count).should.is_a?(Integer)
+ GC.stat[:count].should.is_a?(Integer)
end
it "provides some number for heap_free_slots" do
- GC.stat(:heap_free_slots).should be_kind_of(Integer)
- GC.stat[:heap_free_slots].should be_kind_of(Integer)
+ GC.stat(:heap_free_slots).should.is_a?(Integer)
+ GC.stat[:heap_free_slots].should.is_a?(Integer)
end
it "provides some number for total_allocated_objects" do
- GC.stat(:total_allocated_objects).should be_kind_of(Integer)
- GC.stat[:total_allocated_objects].should be_kind_of(Integer)
+ GC.stat(:total_allocated_objects).should.is_a?(Integer)
+ GC.stat[:total_allocated_objects].should.is_a?(Integer)
end
it "raises an error if argument is not nil, a symbol, or a hash" do
- -> { GC.stat(7) }.should raise_error(TypeError, "non-hash or symbol given")
+ -> { GC.stat(7) }.should.raise(TypeError, "non-hash or symbol given")
end
it "raises an error if an unknown key is given" do
- -> { GC.stat(:foo) }.should raise_error(ArgumentError, "unknown key: foo")
+ -> { GC.stat(:foo) }.should.raise(ArgumentError, "unknown key: foo")
end
end
diff --git a/spec/ruby/core/gc/stress_spec.rb b/spec/ruby/core/gc/stress_spec.rb
index ca62c0cb4e..227a795e7f 100644
--- a/spec/ruby/core/gc/stress_spec.rb
+++ b/spec/ruby/core/gc/stress_spec.rb
@@ -7,11 +7,11 @@ describe "GC.stress" do
end
it "returns current status of GC stress mode" do
- GC.stress.should be_false
+ GC.stress.should == false
GC.stress = true
- GC.stress.should be_true
+ GC.stress.should == true
GC.stress = false
- GC.stress.should be_false
+ GC.stress.should == false
end
end
@@ -22,6 +22,6 @@ describe "GC.stress=" do
it "sets the stress mode" do
GC.stress = true
- GC.stress.should be_true
+ GC.stress.should == true
end
end
diff --git a/spec/ruby/core/gc/total_time_spec.rb b/spec/ruby/core/gc/total_time_spec.rb
index fcc8f45a83..f10e0ad742 100644
--- a/spec/ruby/core/gc/total_time_spec.rb
+++ b/spec/ruby/core/gc/total_time_spec.rb
@@ -1,15 +1,13 @@
require_relative '../../spec_helper'
-ruby_version_is "3.1" do
- describe "GC.total_time" do
- it "returns an Integer" do
- GC.total_time.should be_kind_of(Integer)
- end
+describe "GC.total_time" do
+ it "returns an Integer" do
+ GC.total_time.should.is_a?(Integer)
+ end
- it "increases as collections are run" do
- time_before = GC.total_time
- GC.start
- GC.total_time.should >= time_before
- end
+ it "increases as collections are run" do
+ time_before = GC.total_time
+ GC.start
+ GC.total_time.should >= time_before
end
end
diff --git a/spec/ruby/core/hash/allocate_spec.rb b/spec/ruby/core/hash/allocate_spec.rb
index 93420de866..a92accc161 100644
--- a/spec/ruby/core/hash/allocate_spec.rb
+++ b/spec/ruby/core/hash/allocate_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Hash.allocate" do
it "returns an instance of Hash" do
hsh = Hash.allocate
- hsh.should be_an_instance_of(Hash)
+ hsh.should.instance_of?(Hash)
end
it "returns a fully-formed instance of Hash" do
diff --git a/spec/ruby/core/hash/assoc_spec.rb b/spec/ruby/core/hash/assoc_spec.rb
index 64442918d1..51af51a20f 100644
--- a/spec/ruby/core/hash/assoc_spec.rb
+++ b/spec/ruby/core/hash/assoc_spec.rb
@@ -6,7 +6,7 @@ describe "Hash#assoc" do
end
it "returns an Array if the argument is == to a key of the Hash" do
- @h.assoc(:apple).should be_an_instance_of(Array)
+ @h.assoc(:apple).should.instance_of?(Array)
end
it "returns a 2-element Array if the argument is == to a key of the Hash" do
@@ -22,11 +22,11 @@ describe "Hash#assoc" do
end
it "only returns the first matching key-value pair for identity hashes" do
- # Avoid literal String keys in Hash#[]= due to https://bugs.ruby-lang.org/issues/12855
+ # Avoid literal String keys since string literals can be frozen and interned e.g. with --enable-frozen-string-literal
h = {}.compare_by_identity
- k1 = 'pear'
+ k1 = 'pear'.dup
h[k1] = :red
- k2 = 'pear'
+ k2 = 'pear'.dup
h[k2] = :green
h.size.should == 2
h.keys.grep(/pear/).size.should == 2
@@ -40,11 +40,11 @@ describe "Hash#assoc" do
end
it "returns nil if the argument is not a key of the Hash" do
- @h.assoc(:green).should be_nil
+ @h.assoc(:green).should == nil
end
it "returns nil if the argument is not a key of the Hash even when there is a default" do
- Hash.new(42).merge!( foo: :bar ).assoc(42).should be_nil
- Hash.new{|h, k| h[k] = 42}.merge!( foo: :bar ).assoc(42).should be_nil
+ Hash.new(42).merge!( foo: :bar ).assoc(42).should == nil
+ Hash.new{|h, k| h[k] = 42}.merge!( foo: :bar ).assoc(42).should == nil
end
end
diff --git a/spec/ruby/core/hash/clear_spec.rb b/spec/ruby/core/hash/clear_spec.rb
index cf05e36ac9..beff925a63 100644
--- a/spec/ruby/core/hash/clear_spec.rb
+++ b/spec/ruby/core/hash/clear_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
describe "Hash#clear" do
it "removes all key, value pairs" do
h = { 1 => 2, 3 => 4 }
- h.clear.should equal(h)
+ h.clear.should.equal?(h)
h.should == {}
end
@@ -26,7 +26,7 @@ describe "Hash#clear" do
end
it "raises a FrozenError if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.clear }.should raise_error(FrozenError)
- -> { HashSpecs.empty_frozen_hash.clear }.should raise_error(FrozenError)
+ -> { HashSpecs.frozen_hash.clear }.should.raise(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.clear }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/clone_spec.rb b/spec/ruby/core/hash/clone_spec.rb
index 6c96fc0c67..d135a84453 100644
--- a/spec/ruby/core/hash/clone_spec.rb
+++ b/spec/ruby/core/hash/clone_spec.rb
@@ -7,6 +7,6 @@ describe "Hash#clone" do
clone = hash.clone
clone.should == hash
- clone.should_not equal hash
+ clone.should_not.equal? hash
end
end
diff --git a/spec/ruby/core/hash/compact_spec.rb b/spec/ruby/core/hash/compact_spec.rb
index 2989afc8b7..de83dabed3 100644
--- a/spec/ruby/core/hash/compact_spec.rb
+++ b/spec/ruby/core/hash/compact_spec.rb
@@ -10,7 +10,7 @@ describe "Hash#compact" do
it "returns new object that rejects pair has nil value" do
ret = @hash.compact
- ret.should_not equal(@hash)
+ ret.should_not.equal?(@hash)
ret.should == @compact
end
@@ -18,6 +18,28 @@ describe "Hash#compact" do
@hash.compact
@hash.should == @initial_pairs
end
+
+ it "retains the default value" do
+ hash = Hash.new(1)
+ hash.compact.default.should == 1
+ hash[:a] = 1
+ hash.compact.default.should == 1
+ end
+
+ it "retains the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ hash = Hash.new(&pr)
+ hash.compact.default_proc.should == pr
+ hash[:a] = 1
+ hash.compact.default_proc.should == pr
+ end
+
+ it "retains compare_by_identity flag" do
+ hash = {}.compare_by_identity
+ hash.compact.compare_by_identity?.should == true
+ hash[:a] = 1
+ hash.compact.compare_by_identity?.should == true
+ end
end
describe "Hash#compact!" do
@@ -28,7 +50,7 @@ describe "Hash#compact!" do
end
it "returns self" do
- @hash.compact!.should equal(@hash)
+ @hash.compact!.should.equal?(@hash)
end
it "rejects own pair has nil value" do
@@ -42,7 +64,7 @@ describe "Hash#compact!" do
end
it "returns nil" do
- @hash.compact!.should be_nil
+ @hash.compact!.should == nil
end
end
@@ -52,7 +74,7 @@ describe "Hash#compact!" do
end
it "keeps pairs and raises a FrozenError" do
- ->{ @hash.compact! }.should raise_error(FrozenError)
+ ->{ @hash.compact! }.should.raise(FrozenError)
@hash.should == @initial_pairs
end
end
diff --git a/spec/ruby/core/hash/compare_by_identity_spec.rb b/spec/ruby/core/hash/compare_by_identity_spec.rb
index 874cd46eb7..1abf9d5666 100644
--- a/spec/ruby/core/hash/compare_by_identity_spec.rb
+++ b/spec/ruby/core/hash/compare_by_identity_spec.rb
@@ -11,7 +11,7 @@ describe "Hash#compare_by_identity" do
@h[[1]] = :a
@h[[1]].should == :a
@h.compare_by_identity
- @h[[1].dup].should be_nil
+ @h[[1].dup].should == nil
end
it "rehashes internally so that old keys can be looked up" do
@@ -27,21 +27,21 @@ describe "Hash#compare_by_identity" do
it "returns self" do
h = {}
h[:foo] = :bar
- h.compare_by_identity.should equal h
+ h.compare_by_identity.should.equal? h
end
it "has no effect on an already compare_by_identity hash" do
@idh[:foo] = :bar
- @idh.compare_by_identity.should equal @idh
+ @idh.compare_by_identity.should.equal? @idh
@idh.should.compare_by_identity?
@idh[:foo].should == :bar
end
it "uses the semantics of BasicObject#equal? to determine key identity" do
- [1].should_not equal([1])
+ [1].should_not.equal?([1])
@idh[[1]] = :c
@idh[[1]] = :d
- :bar.should equal(:bar)
+ :bar.should.equal?(:bar)
@idh[:bar] = :e
@idh[:bar] = :f
@idh.values.should == [:c, :d, :f]
@@ -64,13 +64,13 @@ describe "Hash#compare_by_identity" do
it "regards #dup'd objects as having different identities" do
key = ['foo']
@idh[key.dup] = :str
- @idh[key].should be_nil
+ @idh[key].should == nil
end
it "regards #clone'd objects as having different identities" do
key = ['foo']
@idh[key.clone] = :str
- @idh[key].should be_nil
+ @idh[key].should == nil
end
it "regards references to the same object as having the same identity" do
@@ -82,22 +82,24 @@ describe "Hash#compare_by_identity" do
it "raises a FrozenError on frozen hashes" do
@h = @h.freeze
- -> { @h.compare_by_identity }.should raise_error(FrozenError)
+ -> { @h.compare_by_identity }.should.raise(FrozenError)
end
- # Behaviour confirmed in bug #1871
+ # Behaviour confirmed in https://bugs.ruby-lang.org/issues/1871
it "persists over #dups" do
- @idh['foo'] = :bar
- @idh['foo'] = :glark
+ @idh['foo'.dup] = :bar
+ @idh['foo'.dup] = :glark
@idh.dup.should == @idh
@idh.dup.size.should == @idh.size
+ @idh.dup.should.compare_by_identity?
end
it "persists over #clones" do
- @idh['foo'] = :bar
- @idh['foo'] = :glark
+ @idh['foo'.dup] = :bar
+ @idh['foo'.dup] = :glark
@idh.clone.should == @idh
@idh.clone.size.should == @idh.size
+ @idh.dup.should.compare_by_identity?
end
it "does not copy string keys" do
@@ -105,12 +107,19 @@ describe "Hash#compare_by_identity" do
@idh[foo] = true
@idh[foo] = true
@idh.size.should == 1
- @idh.keys.first.should equal foo
+ @idh.keys.first.should.equal? foo
end
+ # Check `#[]=` call with a String literal.
+ # Don't use `#+` because with `#+` it's no longer a String literal.
+ #
+ # See https://bugs.ruby-lang.org/issues/12855
it "gives different identity for string literals" do
+ eval <<~RUBY
+ # frozen_string_literal: false
@idh['foo'] = 1
@idh['foo'] = 2
+ RUBY
@idh.values.should == [1, 2]
@idh.size.should == 2
end
@@ -119,20 +128,20 @@ end
describe "Hash#compare_by_identity?" do
it "returns false by default" do
h = {}
- h.compare_by_identity?.should be_false
+ h.compare_by_identity?.should == false
end
it "returns true once #compare_by_identity has been invoked on self" do
h = {}
h.compare_by_identity
- h.compare_by_identity?.should be_true
+ h.compare_by_identity?.should == true
end
it "returns true when called multiple times on the same ident hash" do
h = {}
h.compare_by_identity
- h.compare_by_identity?.should be_true
- h.compare_by_identity?.should be_true
- h.compare_by_identity?.should be_true
+ h.compare_by_identity?.should == true
+ h.compare_by_identity?.should == true
+ h.compare_by_identity?.should == true
end
end
diff --git a/spec/ruby/core/hash/constructor_spec.rb b/spec/ruby/core/hash/constructor_spec.rb
index 8fba47958f..c16f373160 100644
--- a/spec/ruby/core/hash/constructor_spec.rb
+++ b/spec/ruby/core/hash/constructor_spec.rb
@@ -44,23 +44,23 @@ describe "Hash.[]" do
it "raises for elements that are not arrays" do
-> {
- Hash[[:a]].should == {}
- }.should raise_error(ArgumentError)
+ Hash[[:a]]
+ }.should.raise(ArgumentError, "wrong element type Symbol at 0 (expected array)")
-> {
- Hash[[:nil]].should == {}
- }.should raise_error(ArgumentError)
+ Hash[[nil]]
+ }.should.raise(ArgumentError, "wrong element type nil at 0 (expected array)")
end
it "raises an ArgumentError for arrays of more than 2 elements" do
- ->{ Hash[[[:a, :b, :c]]].should == {} }.should raise_error(ArgumentError)
+ ->{
+ Hash[[[:a, :b, :c]]]
+ }.should.raise(ArgumentError, "invalid number of elements (3 for 1..2)")
end
it "raises an ArgumentError when passed a list of value-invalid-pairs in an array" do
-> {
- -> {
- Hash[[[:a, 1], [:b], 42, [:d, 2], [:e, 2, 3], []]]
- }.should complain(/ignoring wrong elements/)
- }.should raise_error(ArgumentError)
+ Hash[[[:a, 1], [:b], 42, [:d, 2], [:e, 2, 3], []]]
+ }.should.raise(ArgumentError, "wrong element type Integer at 2 (expected array)")
end
describe "passed a single argument which responds to #to_hash" do
@@ -71,13 +71,13 @@ describe "Hash.[]" do
result = Hash[to_hash]
result.should == h
- result.should_not equal(h)
+ result.should_not.equal?(h)
end
end
it "raises an ArgumentError when passed an odd number of arguments" do
- -> { Hash[1, 2, 3] }.should raise_error(ArgumentError)
- -> { Hash[1, 2, { 3 => 4 }] }.should raise_error(ArgumentError)
+ -> { Hash[1, 2, 3] }.should.raise(ArgumentError)
+ -> { Hash[1, 2, { 3 => 4 }] }.should.raise(ArgumentError)
end
it "calls to_hash" do
@@ -87,24 +87,41 @@ describe "Hash.[]" do
end
it "returns an instance of a subclass when passed an Array" do
- HashSpecs::MyHash[1,2,3,4].should be_an_instance_of(HashSpecs::MyHash)
+ HashSpecs::MyHash[1,2,3,4].should.instance_of?(HashSpecs::MyHash)
end
it "returns instances of subclasses" do
- HashSpecs::MyHash[].should be_an_instance_of(HashSpecs::MyHash)
+ HashSpecs::MyHash[].should.instance_of?(HashSpecs::MyHash)
end
it "returns an instance of the class it's called on" do
Hash[HashSpecs::MyHash[1, 2]].class.should == Hash
- HashSpecs::MyHash[Hash[1, 2]].should be_an_instance_of(HashSpecs::MyHash)
+ HashSpecs::MyHash[Hash[1, 2]].should.instance_of?(HashSpecs::MyHash)
end
it "does not call #initialize on the subclass instance" do
- HashSpecs::MyInitializerHash[Hash[1, 2]].should be_an_instance_of(HashSpecs::MyInitializerHash)
+ HashSpecs::MyInitializerHash[Hash[1, 2]].should.instance_of?(HashSpecs::MyInitializerHash)
end
- it "removes the default_proc" do
+ it "does not retain the default value" do
+ hash = Hash.new(1)
+ Hash[hash].default.should == nil
+ hash[:a] = 1
+ Hash[hash].default.should == nil
+ end
+
+ it "does not retain the default_proc" do
hash = Hash.new { |h, k| h[k] = [] }
- Hash[hash].default_proc.should be_nil
+ Hash[hash].default_proc.should == nil
+ hash[:a] = 1
+ Hash[hash].default_proc.should == nil
+ end
+
+ it "does not retain compare_by_identity flag" do
+ hash = { a: 1 }.compare_by_identity
+ Hash[hash].compare_by_identity?.should == false
+
+ hash = {}.compare_by_identity
+ Hash[hash].compare_by_identity?.should == false
end
end
diff --git a/spec/ruby/core/hash/deconstruct_keys_spec.rb b/spec/ruby/core/hash/deconstruct_keys_spec.rb
index bbcd8932e5..f6ff3a2818 100644
--- a/spec/ruby/core/hash/deconstruct_keys_spec.rb
+++ b/spec/ruby/core/hash/deconstruct_keys_spec.rb
@@ -4,13 +4,13 @@ describe "Hash#deconstruct_keys" do
it "returns self" do
hash = {a: 1, b: 2}
- hash.deconstruct_keys([:a, :b]).should equal hash
+ hash.deconstruct_keys([:a, :b]).should.equal? hash
end
it "requires one argument" do
-> {
{a: 1}.deconstruct_keys
- }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
+ }.should.raise(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
end
it "ignores argument" do
diff --git a/spec/ruby/core/hash/default_proc_spec.rb b/spec/ruby/core/hash/default_proc_spec.rb
index f4e4803632..4830e02acd 100644
--- a/spec/ruby/core/hash/default_proc_spec.rb
+++ b/spec/ruby/core/hash/default_proc_spec.rb
@@ -25,24 +25,24 @@ describe "Hash#default_proc=" do
h = Hash.new { 'Paris' }
obj = mock('to_proc')
obj.should_receive(:to_proc).and_return(Proc.new { 'Montreal' })
- (h.default_proc = obj).should equal(obj)
+ (h.default_proc = obj).should.equal?(obj)
h[:cool_city].should == 'Montreal'
end
it "overrides the static default" do
h = Hash.new(42)
h.default_proc = Proc.new { 6 }
- h.default.should be_nil
+ h.default.should == nil
h.default_proc.call.should == 6
end
it "raises an error if passed stuff not convertible to procs" do
- ->{{}.default_proc = 42}.should raise_error(TypeError)
+ ->{{}.default_proc = 42}.should.raise(TypeError)
end
it "returns the passed Proc" do
new_proc = Proc.new {}
- ({}.default_proc = new_proc).should equal(new_proc)
+ ({}.default_proc = new_proc).should.equal?(new_proc)
end
it "clears the default proc if passed nil" do
@@ -53,28 +53,28 @@ describe "Hash#default_proc=" do
end
it "returns nil if passed nil" do
- ({}.default_proc = nil).should be_nil
+ ({}.default_proc = nil).should == nil
end
it "accepts a lambda with an arity of 2" do
h = {}
-> do
h.default_proc = -> a, b { }
- end.should_not raise_error(TypeError)
+ end.should_not.raise(TypeError)
end
it "raises a TypeError if passed a lambda with an arity other than 2" do
h = {}
-> do
h.default_proc = -> a { }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
-> do
h.default_proc = -> a, b, c { }
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a FrozenError if self is frozen" do
- -> { {}.freeze.default_proc = Proc.new {} }.should raise_error(FrozenError)
- -> { {}.freeze.default_proc = nil }.should raise_error(FrozenError)
+ -> { {}.freeze.default_proc = Proc.new {} }.should.raise(FrozenError)
+ -> { {}.freeze.default_proc = nil }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/default_spec.rb b/spec/ruby/core/hash/default_spec.rb
index d8b62ea196..17ee032e2b 100644
--- a/spec/ruby/core/hash/default_spec.rb
+++ b/spec/ruby/core/hash/default_spec.rb
@@ -40,7 +40,7 @@ describe "Hash#default=" do
end
it "raises a FrozenError if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.default = nil }.should raise_error(FrozenError)
- -> { HashSpecs.empty_frozen_hash.default = nil }.should raise_error(FrozenError)
+ -> { HashSpecs.frozen_hash.default = nil }.should.raise(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.default = nil }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/delete_if_spec.rb b/spec/ruby/core/hash/delete_if_spec.rb
index c9e670ffc3..3090633d88 100644
--- a/spec/ruby/core/hash/delete_if_spec.rb
+++ b/spec/ruby/core/hash/delete_if_spec.rb
@@ -12,13 +12,13 @@ describe "Hash#delete_if" do
it "removes every entry for which block is true and returns self" do
h = { a: 1, b: 2, c: 3, d: 4 }
- h.delete_if { |k,v| v % 2 == 1 }.should equal(h)
+ h.delete_if { |k,v| v % 2 == 1 }.should.equal?(h)
h.should == { b: 2, d: 4 }
end
it "removes all entries if the block is true" do
h = { a: 1, b: 2, c: 3 }
- h.delete_if { |k,v| true }.should equal(h)
+ h.delete_if { |k,v| true }.should.equal?(h)
h.should == {}
end
@@ -35,8 +35,8 @@ describe "Hash#delete_if" do
end
it "raises a FrozenError if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.delete_if { false } }.should raise_error(FrozenError)
- -> { HashSpecs.empty_frozen_hash.delete_if { true } }.should raise_error(FrozenError)
+ -> { HashSpecs.frozen_hash.delete_if { false } }.should.raise(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.delete_if { true } }.should.raise(FrozenError)
end
it_behaves_like :hash_iteration_no_block, :delete_if
diff --git a/spec/ruby/core/hash/delete_spec.rb b/spec/ruby/core/hash/delete_spec.rb
index b262e8846b..33ff01bf36 100644
--- a/spec/ruby/core/hash/delete_spec.rb
+++ b/spec/ruby/core/hash/delete_spec.rb
@@ -24,7 +24,7 @@ describe "Hash#delete" do
it "allows removing a key while iterating" do
h = { a: 1, b: 2 }
visited = []
- h.each_pair { |k,v|
+ h.each_pair { |k, v|
visited << k
h.delete(k)
}
@@ -32,13 +32,27 @@ describe "Hash#delete" do
h.should == {}
end
+ it "allows removing a key while iterating for big hashes" do
+ h = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10,
+ k: 11, l: 12, m: 13, n: 14, o: 15, p: 16, q: 17, r: 18, s: 19, t: 20,
+ u: 21, v: 22, w: 23, x: 24, y: 25, z: 26 }
+ visited = []
+ h.each_pair { |k, v|
+ visited << k
+ h.delete(k)
+ }
+ visited.should == [:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m,
+ :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z]
+ h.should == {}
+ end
+
it "accepts keys with private #hash method" do
key = HashSpecs::KeyWithPrivateHash.new
{ key => 5 }.delete(key).should == 5
end
it "raises a FrozenError if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.delete("foo") }.should raise_error(FrozenError)
- -> { HashSpecs.empty_frozen_hash.delete("foo") }.should raise_error(FrozenError)
+ -> { HashSpecs.frozen_hash.delete("foo") }.should.raise(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.delete("foo") }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/dig_spec.rb b/spec/ruby/core/hash/dig_spec.rb
index aa0ecadd2f..94ac94e850 100644
--- a/spec/ruby/core/hash/dig_spec.rb
+++ b/spec/ruby/core/hash/dig_spec.rb
@@ -5,16 +5,16 @@ describe "Hash#dig" do
it "returns #[] with one arg" do
h = { 0 => false, a: 1 }
h.dig(:a).should == 1
- h.dig(0).should be_false
- h.dig(1).should be_nil
+ h.dig(0).should == false
+ h.dig(1).should == nil
end
it "returns the nested value specified by the sequence of keys" do
h = { foo: { bar: { baz: 1 } } }
h.dig(:foo, :bar, :baz).should == 1
- h.dig(:foo, :bar, :nope).should be_nil
- h.dig(:foo, :baz).should be_nil
- h.dig(:bar, :baz, :foo).should be_nil
+ h.dig(:foo, :bar, :nope).should == nil
+ h.dig(:foo, :baz).should == nil
+ h.dig(:bar, :baz, :foo).should == nil
end
it "returns the nested value specified if the sequence includes an index" do
@@ -28,7 +28,7 @@ describe "Hash#dig" do
end
it "raises an ArgumentError if no arguments provided" do
- -> { { the: 'borg' }.dig() }.should raise_error(ArgumentError)
+ -> { { the: 'borg' }.dig() }.should.raise(ArgumentError)
end
it "handles type-mixed deep digging" do
@@ -47,8 +47,8 @@ describe "Hash#dig" do
it "raises TypeError if an intermediate element does not respond to #dig" do
h = {}
h[:foo] = [ { bar: [ 1 ] }, [ nil, 'str' ] ]
- -> { h.dig(:foo, 0, :bar, 0, 0) }.should raise_error(TypeError)
- -> { h.dig(:foo, 1, 1, 0) }.should raise_error(TypeError)
+ -> { h.dig(:foo, 0, :bar, 0, 0) }.should.raise(TypeError)
+ -> { h.dig(:foo, 1, 1, 0) }.should.raise(TypeError)
end
it "calls #dig on the result of #[] with the remaining arguments" do
@@ -60,7 +60,7 @@ describe "Hash#dig" do
it "respects Hash's default" do
default = {bar: 42}
h = Hash.new(default)
- h.dig(:foo).should equal default
+ h.dig(:foo).should.equal? default
h.dig(:foo, :bar).should == 42
end
end
diff --git a/spec/ruby/core/hash/each_key_spec.rb b/spec/ruby/core/hash/each_key_spec.rb
index c84dd696d5..5b2e9deb63 100644
--- a/spec/ruby/core/hash/each_key_spec.rb
+++ b/spec/ruby/core/hash/each_key_spec.rb
@@ -7,7 +7,7 @@ describe "Hash#each_key" do
it "calls block once for each key, passing key" do
r = {}
h = { 1 => -1, 2 => -2, 3 => -3, 4 => -4 }
- h.each_key { |k| r[k] = k }.should equal(h)
+ h.each_key { |k| r[k] = k }.should.equal?(h)
r.should == { 1 => 1, 2 => 2, 3 => 3, 4 => 4 }
end
diff --git a/spec/ruby/core/hash/each_pair_spec.rb b/spec/ruby/core/hash/each_pair_spec.rb
index eb6656681d..01810c130c 100644
--- a/spec/ruby/core/hash/each_pair_spec.rb
+++ b/spec/ruby/core/hash/each_pair_spec.rb
@@ -1,11 +1,111 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
require_relative 'shared/iteration'
-require_relative 'shared/each'
require_relative '../enumerable/shared/enumeratorized'
describe "Hash#each_pair" do
- it_behaves_like :hash_each, :each_pair
it_behaves_like :hash_iteration_no_block, :each_pair
it_behaves_like :enumeratorized_with_origin_size, :each_pair, { 1 => 2, 3 => 4, 5 => 6 }
+
+ # This is inconsistent with below, MRI checks the block arity in rb_hash_each_pair()
+ it "yields a [[key, value]] Array for each pair to a block expecting |*args|" do
+ all_args = []
+ { 1 => 2, 3 => 4 }.each_pair { |*args| all_args << args }
+ all_args.sort.should == [[[1, 2]], [[3, 4]]]
+ end
+
+ it "yields the key and value of each pair to a block expecting |key, value|" do
+ r = {}
+ h = { a: 1, b: 2, c: 3, d: 5 }
+ h.each_pair { |k,v| r[k.to_s] = v.to_s }.should.equal?(h)
+ r.should == { "a" => "1", "b" => "2", "c" => "3", "d" => "5" }
+ end
+
+ it "yields the key only to a block expecting |key,|" do
+ ary = []
+ h = { "a" => 1, "b" => 2, "c" => 3 }
+ h.each_pair { |k,| ary << k }
+ ary.sort.should == ["a", "b", "c"]
+ end
+
+ it "always yields an Array of 2 elements, even when given a callable of arity 2" do
+ obj = Object.new
+ def obj.foo(key, value)
+ end
+
+ -> {
+ { "a" => 1 }.each_pair(&obj.method(:foo))
+ }.should.raise(ArgumentError)
+
+ -> {
+ { "a" => 1 }.each_pair(&-> key, value { })
+ }.should.raise(ArgumentError)
+ end
+
+ it "yields an Array of 2 elements when given a callable of arity 1" do
+ obj = Object.new
+ def obj.foo(key_value)
+ ScratchPad << key_value
+ end
+
+ ScratchPad.record([])
+ { "a" => 1 }.each_pair(&obj.method(:foo))
+ ScratchPad.recorded.should == [["a", 1]]
+ end
+
+ it "raises an error for a Hash when an arity enforcing callable of arity >2 is passed in" do
+ obj = Object.new
+ def obj.foo(key, value, extra)
+ end
+
+ -> {
+ { "a" => 1 }.each_pair(&obj.method(:foo))
+ }.should.raise(ArgumentError)
+ end
+
+ it "uses the same order as keys() and values()" do
+ h = { a: 1, b: 2, c: 3, d: 5 }
+ keys = []
+ values = []
+
+ h.each_pair do |k, v|
+ keys << k
+ values << v
+ end
+
+ keys.should == h.keys
+ values.should == h.values
+ end
+
+ # Confirming the argument-splatting works from child class for both k, v and [k, v]
+ it "properly expands (or not) child class's 'each'-yielded args" do
+ cls1 = Class.new(Hash) do
+ attr_accessor :k_v
+ def each
+ super do |k, v|
+ @k_v = [k, v]
+ yield k, v
+ end
+ end
+ end
+
+ cls2 = Class.new(Hash) do
+ attr_accessor :k_v
+ def each
+ super do |k, v|
+ @k_v = [k, v]
+ yield([k, v])
+ end
+ end
+ end
+
+ obj1 = cls1.new
+ obj1['a'] = 'b'
+ obj1.map {|k, v| [k, v]}.should == [['a', 'b']]
+ obj1.k_v.should == ['a', 'b']
+
+ obj2 = cls2.new
+ obj2['a'] = 'b'
+ obj2.map {|k, v| [k, v]}.should == [['a', 'b']]
+ obj2.k_v.should == ['a', 'b']
+ end
end
diff --git a/spec/ruby/core/hash/each_spec.rb b/spec/ruby/core/hash/each_spec.rb
index f0de0bdee5..1644b63216 100644
--- a/spec/ruby/core/hash/each_spec.rb
+++ b/spec/ruby/core/hash/each_spec.rb
@@ -1,11 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/iteration'
-require_relative 'shared/each'
-require_relative '../enumerable/shared/enumeratorized'
describe "Hash#each" do
- it_behaves_like :hash_each, :each
- it_behaves_like :hash_iteration_no_block, :each
- it_behaves_like :enumeratorized_with_origin_size, :each, { 1 => 2, 3 => 4, 5 => 6 }
+ it "is an alias of Hash#each_pair" do
+ Hash.instance_method(:each).should == Hash.instance_method(:each_pair)
+ end
end
diff --git a/spec/ruby/core/hash/each_value_spec.rb b/spec/ruby/core/hash/each_value_spec.rb
index 19b076730d..2df95a8789 100644
--- a/spec/ruby/core/hash/each_value_spec.rb
+++ b/spec/ruby/core/hash/each_value_spec.rb
@@ -7,7 +7,7 @@ describe "Hash#each_value" do
it "calls block once for each key, passing value" do
r = []
h = { a: -5, b: -3, c: -2, d: -1, e: -1 }
- h.each_value { |v| r << v }.should equal(h)
+ h.each_value { |v| r << v }.should.equal?(h)
r.sort.should == [-5, -3, -2, -1, -1]
end
diff --git a/spec/ruby/core/hash/element_reference_spec.rb b/spec/ruby/core/hash/element_reference_spec.rb
index e271f37ea6..3d074b346d 100644
--- a/spec/ruby/core/hash/element_reference_spec.rb
+++ b/spec/ruby/core/hash/element_reference_spec.rb
@@ -12,7 +12,7 @@ describe "Hash#[]" do
h[[]].should == "baz"
end
- it "returns nil as default default value" do
+ it "returns nil as default value" do
{ 0 => 0 }[5].should == nil
end
@@ -30,13 +30,13 @@ describe "Hash#[]" do
end
it "does not create copies of the immediate default value" do
- str = "foo"
+ str = +"foo"
h = Hash.new(str)
a = h[:a]
b = h[:b]
a << "bar"
- a.should equal(b)
+ a.should.equal?(b)
a.should == "foobar"
b.should == "foobar"
end
diff --git a/spec/ruby/core/hash/element_set_spec.rb b/spec/ruby/core/hash/element_set_spec.rb
index 67c5a04d73..bb805477ca 100644
--- a/spec/ruby/core/hash/element_set_spec.rb
+++ b/spec/ruby/core/hash/element_set_spec.rb
@@ -1,7 +1,121 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/store'
describe "Hash#[]=" do
- it_behaves_like :hash_store, :[]=
+ it "associates the key with the value" do
+ h = { a: 1 }
+ h[:b] = 2
+ h.should == { b:2, a:1 }
+ end
+
+ it "returns the assigned value" do
+ h = {}
+ h.send(:[]=, 1, 2).should == 2
+ end
+
+ it "duplicates string keys using dup semantics" do
+ # dup doesn't copy singleton methods
+ key = +"foo"
+ def key.reverse() "bar" end
+ h = {}
+ h[key] = 0
+ h.keys[0].reverse.should == "oof"
+ end
+
+ it "stores unequal keys that hash to the same value" do
+ h = {}
+ k1 = ["x"]
+ k2 = ["y"]
+ # So they end up in the same bucket
+ k1.should_receive(:hash).and_return(0)
+ k2.should_receive(:hash).and_return(0)
+
+ h[k1] = 1
+ h[k2] = 2
+ h.size.should == 2
+ end
+
+ it "accepts keys with private #hash method" do
+ key = HashSpecs::KeyWithPrivateHash.new
+ h = {}
+ h[key] = "foo"
+ h[key].should == "foo"
+ end
+
+ it " accepts keys with an Integer hash" do
+ o = mock(hash: 1 << 100)
+ h = {}
+ h[o] = 1
+ h[o].should == 1
+ end
+
+ it "duplicates and freezes string keys" do
+ key = +"foo"
+ h = {}
+ h[key] = 0
+ key << "bar"
+
+ h.should == { "foo" => 0 }
+ h.keys[0].should.frozen?
+ end
+
+ it "doesn't duplicate and freeze already frozen string keys" do
+ key = "foo".freeze
+ h = {}
+ h[key] = 0
+ h.keys[0].should.equal?(key)
+ end
+
+ it "keeps the existing key in the hash if there is a matching one" do
+ h = { "a" => 1, "b" => 2, "c" => 3, "d" => 4 }
+ key1 = HashSpecs::ByValueKey.new(13)
+ key2 = HashSpecs::ByValueKey.new(13)
+ h[key1] = 41
+ key_in_hash = h.keys.last
+ key_in_hash.should.equal?(key1)
+ h[key2] = 42
+ last_key = h.keys.last
+ last_key.should.equal?(key_in_hash)
+ last_key.should_not.equal?(key2)
+ end
+
+ it "keeps the existing String key in the hash if there is a matching one" do
+ h = { "a" => 1, "b" => 2, "c" => 3, "d" => 4 }
+ key1 = "foo".dup
+ key2 = "foo".dup
+ key1.should_not.equal?(key2)
+ h[key1] = 41
+ frozen_key = h.keys.last
+ frozen_key.should_not.equal?(key1)
+ h[key2] = 42
+ h.keys.last.should.equal?(frozen_key)
+ h.keys.last.should_not.equal?(key2)
+ end
+
+ it "raises a FrozenError if called on a frozen instance" do
+ -> { HashSpecs.frozen_hash[1] = 2 }.should.raise(FrozenError)
+ end
+
+ it "does not raise an exception if changing the value of an existing key during iteration" do
+ hash = {1 => 2, 3 => 4, 5 => 6}
+ hash.each { hash[1] = :foo }
+ hash.should == {1 => :foo, 3 => 4, 5 => 6}
+ end
+
+ it "does not dispatch to hash for Boolean, Integer, Float, String, or Symbol" do
+ code = <<-EOC
+ load '#{fixture __FILE__, "name.rb"}'
+ hash = {}
+ [true, false, 1, 2.0, "hello", :ok].each do |value|
+ hash[value] = 42
+ raise "incorrect value" unless hash[value] == 42
+ hash[value] = 43
+ raise "incorrect value" unless hash[value] == 43
+ end
+ puts "OK"
+ puts hash.size
+ EOC
+ result = ruby_exe(code, args: "2>&1")
+ result.should == "OK\n6\n"
+ end
end
diff --git a/spec/ruby/core/hash/equal_value_spec.rb b/spec/ruby/core/hash/equal_value_spec.rb
index ae13a42679..ab14f81489 100644
--- a/spec/ruby/core/hash/equal_value_spec.rb
+++ b/spec/ruby/core/hash/equal_value_spec.rb
@@ -13,6 +13,6 @@ describe "Hash#==" do
l_val.should_receive(:==).with(r_val).and_return(true)
- ({ 1 => l_val } == { 1 => r_val }).should be_true
+ ({ 1 => l_val } == { 1 => r_val }).should == true
end
end
diff --git a/spec/ruby/core/hash/except_spec.rb b/spec/ruby/core/hash/except_spec.rb
index 82cfced72f..77a020e9b7 100644
--- a/spec/ruby/core/hash/except_spec.rb
+++ b/spec/ruby/core/hash/except_spec.rb
@@ -1,34 +1,42 @@
require_relative '../../spec_helper'
-ruby_version_is "3.0" do
- describe "Hash#except" do
- before :each do
- @hash = { a: 1, b: 2, c: 3 }
- end
+describe "Hash#except" do
+ before :each do
+ @hash = { a: 1, b: 2, c: 3 }
+ end
+
+ it "returns a new duplicate hash without arguments" do
+ ret = @hash.except
+ ret.should_not.equal?(@hash)
+ ret.should == @hash
+ end
+
+ it "returns a hash without the requested subset" do
+ @hash.except(:c, :a).should == { b: 2 }
+ end
- it "returns a new duplicate hash without arguments" do
- ret = @hash.except
- ret.should_not equal(@hash)
- ret.should == @hash
- end
+ it "ignores keys not present in the original hash" do
+ @hash.except(:a, :chunky_bacon).should == { b: 2, c: 3 }
+ end
- it "returns a hash without the requested subset" do
- @hash.except(:c, :a).should == { b: 2 }
- end
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.except(:a).default.should == nil
+ h[:a] = 1
+ h.except(:a).default.should == nil
+ end
- it "ignores keys not present in the original hash" do
- @hash.except(:a, :chunky_bacon).should == { b: 2, c: 3 }
- end
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.except(:a).default_proc.should == nil
+ h[:a] = 1
+ h.except(:a).default_proc.should == nil
+ end
- it "always returns a Hash without a default" do
- klass = Class.new(Hash)
- h = klass.new(:default)
- h[:bar] = 12
- h[:foo] = 42
- r = h.except(:foo)
- r.should == {bar: 12}
- r.class.should == Hash
- r.default.should == nil
- end
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.except(:a)
+ h2.compare_by_identity?.should == true
end
end
diff --git a/spec/ruby/core/hash/fetch_spec.rb b/spec/ruby/core/hash/fetch_spec.rb
index 753167f709..f9b80b6c49 100644
--- a/spec/ruby/core/hash/fetch_spec.rb
+++ b/spec/ruby/core/hash/fetch_spec.rb
@@ -4,7 +4,7 @@ require_relative '../../shared/hash/key_error'
describe "Hash#fetch" do
context "when the key is not found" do
- it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, Hash.new(a: 5)
+ it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, Hash.new({ a: 5 })
it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, {}
it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, Hash.new { 5 }
it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, Hash.new(5)
@@ -12,7 +12,7 @@ describe "Hash#fetch" do
it "formats the object with #inspect in the KeyError message" do
-> {
{}.fetch('foo')
- }.should raise_error(KeyError, 'key not found: "foo"')
+ }.should.raise(KeyError, 'key not found: "foo"')
end
end
@@ -38,7 +38,7 @@ describe "Hash#fetch" do
end
it "raises an ArgumentError when not passed one or two arguments" do
- -> { {}.fetch() }.should raise_error(ArgumentError)
- -> { {}.fetch(1, 2, 3) }.should raise_error(ArgumentError)
+ -> { {}.fetch() }.should.raise(ArgumentError)
+ -> { {}.fetch(1, 2, 3) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/hash/fetch_values_spec.rb b/spec/ruby/core/hash/fetch_values_spec.rb
index af3673f6ef..0cd48565af 100644
--- a/spec/ruby/core/hash/fetch_values_spec.rb
+++ b/spec/ruby/core/hash/fetch_values_spec.rb
@@ -19,7 +19,7 @@ describe "Hash#fetch_values" do
end
describe "with unmatched keys" do
- it_behaves_like :key_error, -> obj, key { obj.fetch_values(key) }, Hash.new(a: 5)
+ it_behaves_like :key_error, -> obj, key { obj.fetch_values(key) }, Hash.new({ a: 5 })
it "returns the default value from block" do
@hash.fetch_values(:z) { |key| "`#{key}' is not found" }.should == ["`z' is not found"]
diff --git a/spec/ruby/core/hash/filter_spec.rb b/spec/ruby/core/hash/filter_spec.rb
index 7dabe44984..625a7feb90 100644
--- a/spec/ruby/core/hash/filter_spec.rb
+++ b/spec/ruby/core/hash/filter_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'shared/select'
describe "Hash#filter" do
- it_behaves_like :hash_select, :filter
+ it "is an alias of Hash#select" do
+ Hash.instance_method(:filter).should == Hash.instance_method(:select)
+ end
end
describe "Hash#filter!" do
- it_behaves_like :hash_select!, :filter!
+ it "is an alias of Hash#select!" do
+ Hash.instance_method(:filter!).should == Hash.instance_method(:select!)
+ end
end
diff --git a/spec/ruby/core/hash/flatten_spec.rb b/spec/ruby/core/hash/flatten_spec.rb
index 825da15bfc..18e9a7b56a 100644
--- a/spec/ruby/core/hash/flatten_spec.rb
+++ b/spec/ruby/core/hash/flatten_spec.rb
@@ -9,7 +9,7 @@ describe "Hash#flatten" do
end
it "returns an Array" do
- {}.flatten.should be_an_instance_of(Array)
+ {}.flatten.should.instance_of?(Array)
end
it "returns an empty Array for an empty Hash" do
@@ -57,6 +57,6 @@ describe "Hash#flatten" do
it "raises a TypeError if given a non-Integer argument" do
-> do
@h.flatten(Object.new)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/hash/gt_spec.rb b/spec/ruby/core/hash/gt_spec.rb
index cd541d4d83..69d23b7d29 100644
--- a/spec/ruby/core/hash/gt_spec.rb
+++ b/spec/ruby/core/hash/gt_spec.rb
@@ -8,7 +8,7 @@ describe "Hash#>" do
it "returns false if both hashes are identical" do
h = { a: 1, b: 2 }
- (h > h).should be_false
+ (h > h).should == false
end
end
diff --git a/spec/ruby/core/hash/gte_spec.rb b/spec/ruby/core/hash/gte_spec.rb
index 99b89e7217..be5060ea4f 100644
--- a/spec/ruby/core/hash/gte_spec.rb
+++ b/spec/ruby/core/hash/gte_spec.rb
@@ -8,7 +8,7 @@ describe "Hash#>=" do
it "returns true if both hashes are identical" do
h = { a: 1, b: 2 }
- (h >= h).should be_true
+ (h >= h).should == true
end
end
diff --git a/spec/ruby/core/hash/has_key_spec.rb b/spec/ruby/core/hash/has_key_spec.rb
index 4af53579e5..9a6244c6f6 100644
--- a/spec/ruby/core/hash/has_key_spec.rb
+++ b/spec/ruby/core/hash/has_key_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/key'
describe "Hash#has_key?" do
- it_behaves_like :hash_key_p, :has_key?
+ it "is an alias of Hash#include?" do
+ Hash.instance_method(:has_key?).should == Hash.instance_method(:include?)
+ end
end
diff --git a/spec/ruby/core/hash/has_value_spec.rb b/spec/ruby/core/hash/has_value_spec.rb
index 39f1627fd3..d40e52ebfd 100644
--- a/spec/ruby/core/hash/has_value_spec.rb
+++ b/spec/ruby/core/hash/has_value_spec.rb
@@ -1,7 +1,16 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/value'
describe "Hash#has_value?" do
- it_behaves_like :hash_value_p, :has_value?
+ it "returns true if the value exists in the hash" do
+ { a: :b }.has_value?(:a).should == false
+ { 1 => 2 }.has_value?(2).should == true
+ h = Hash.new(5)
+ h.has_value?(5).should == false
+ h = Hash.new { 5 }
+ h.has_value?(5).should == false
+ end
+
+ it "uses == semantics for comparing values" do
+ { 5 => 2.0 }.has_value?(2).should == true
+ end
end
diff --git a/spec/ruby/core/hash/hash_spec.rb b/spec/ruby/core/hash/hash_spec.rb
index 3649d4d8de..cd67f7a652 100644
--- a/spec/ruby/core/hash/hash_spec.rb
+++ b/spec/ruby/core/hash/hash_spec.rb
@@ -41,4 +41,11 @@ describe "Hash#hash" do
h.hash.should == {x: [h]}.hash
# Like above, because h.eql?(x: [h])
end
+
+ it "allows omitting values" do
+ a = 1
+ b = 2
+
+ {a:, b:}.should == { a: 1, b: 2 }
+ end
end
diff --git a/spec/ruby/core/hash/include_spec.rb b/spec/ruby/core/hash/include_spec.rb
index f3959dc589..1c32e9fb23 100644
--- a/spec/ruby/core/hash/include_spec.rb
+++ b/spec/ruby/core/hash/include_spec.rb
@@ -1,7 +1,40 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/key'
describe "Hash#include?" do
- it_behaves_like :hash_key_p, :include?
+ it "returns true if argument is a key" do
+ h = { a: 1, b: 2, c: 3, 4 => 0 }
+ h.include?(:a).should == true
+ h.include?(:b).should == true
+ h.include?(2).should == false
+ h.include?(4).should == true
+
+ not_supported_on :opal do
+ h.include?('b').should == false
+ h.include?(4.0).should == false
+ end
+ end
+
+ it "returns true if the key's matching value was nil" do
+ { xyz: nil }.include?(:xyz).should == true
+ end
+
+ it "returns true if the key's matching value was false" do
+ { xyz: false }.include?(:xyz).should == true
+ end
+
+ it "returns true if the key is nil" do
+ { nil => 'b' }.include?(nil).should == true
+ { nil => nil }.include?(nil).should == true
+ end
+
+ it "compares keys with the same #hash value via #eql?" do
+ x = mock('x')
+ x.stub!(:hash).and_return(42)
+
+ y = mock('y')
+ y.stub!(:hash).and_return(42)
+ y.should_receive(:eql?).and_return(false)
+
+ { x => nil }.include?(y).should == false
+ end
end
diff --git a/spec/ruby/core/hash/index_spec.rb b/spec/ruby/core/hash/index_spec.rb
deleted file mode 100644
index be4e2cc6ab..0000000000
--- a/spec/ruby/core/hash/index_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/index'
-
-ruby_version_is ''...'3.0' do
- describe "Hash#index" do
- it_behaves_like :hash_index, :index
- end
-end
diff --git a/spec/ruby/core/hash/initialize_spec.rb b/spec/ruby/core/hash/initialize_spec.rb
index d13496ba3b..cdba598813 100644
--- a/spec/ruby/core/hash/initialize_spec.rb
+++ b/spec/ruby/core/hash/initialize_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Hash#initialize" do
it "is private" do
- Hash.should have_private_instance_method("initialize")
+ Hash.private_instance_methods(false).should.include?(:initialize)
end
it "can be used to reset default_proc" do
@@ -42,20 +42,20 @@ describe "Hash#initialize" do
it "returns self" do
h = Hash.new
- h.send(:initialize).should equal(h)
+ h.send(:initialize).should.equal?(h)
end
it "raises a FrozenError if called on a frozen instance" do
block = -> { HashSpecs.frozen_hash.instance_eval { initialize() }}
- block.should raise_error(FrozenError)
+ block.should.raise(FrozenError)
block = -> { HashSpecs.frozen_hash.instance_eval { initialize(nil) } }
- block.should raise_error(FrozenError)
+ block.should.raise(FrozenError)
block = -> { HashSpecs.frozen_hash.instance_eval { initialize(5) } }
- block.should raise_error(FrozenError)
+ block.should.raise(FrozenError)
block = -> { HashSpecs.frozen_hash.instance_eval { initialize { 5 } } }
- block.should raise_error(FrozenError)
+ block.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/inspect_spec.rb b/spec/ruby/core/hash/inspect_spec.rb
index f41ebb70a6..359b13360f 100644
--- a/spec/ruby/core/hash/inspect_spec.rb
+++ b/spec/ruby/core/hash/inspect_spec.rb
@@ -1,7 +1,123 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/to_s'
describe "Hash#inspect" do
- it_behaves_like :hash_to_s, :inspect
+ it "returns a string representation with same order as each()" do
+ h = { a: [1, 2], b: -2, d: -6, nil => nil }
+ expected = ruby_version_is("3.4") ? "{a: [1, 2], b: -2, d: -6, nil => nil}" : "{:a=>[1, 2], :b=>-2, :d=>-6, nil=>nil}"
+ h.inspect.should == expected
+ end
+
+ it "calls #inspect on keys and values" do
+ key = mock('key')
+ val = mock('val')
+ key.should_receive(:inspect).and_return('key')
+ val.should_receive(:inspect).and_return('val')
+ expected = ruby_version_is("3.4") ? "{key => val}" : "{key=>val}"
+ { key => val }.inspect.should == expected
+ end
+
+ it "does not call #to_s on a String returned from #inspect" do
+ str = +"abc"
+ str.should_not_receive(:to_s)
+ expected = ruby_version_is("3.4") ? '{a: "abc"}' : '{:a=>"abc"}'
+ { a: str }.inspect.should == expected
+ end
+
+ it "calls #to_s on the object returned from #inspect if the Object isn't a String" do
+ obj = mock("Hash#inspect/to_s calls #to_s")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_receive(:to_s).and_return("abc")
+ expected = ruby_version_is("3.4") ? "{a: abc}" : "{:a=>abc}"
+ { a: obj }.inspect.should == expected
+ end
+
+ it "does not call #to_str on the object returned from #inspect when it is not a String" do
+ obj = mock("Hash#inspect/to_s does not call #to_str")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_not_receive(:to_str)
+ expected_pattern = ruby_version_is("3.4") ? /^\{a: #<MockObject:0x[0-9a-f]+>\}$/ : /^\{:a=>#<MockObject:0x[0-9a-f]+>\}$/
+ { a: obj }.inspect.should =~ expected_pattern
+ end
+
+ it "does not call #to_str on the object returned from #to_s when it is not a String" do
+ obj = mock("Hash#inspect/to_s does not call #to_str on #to_s result")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_receive(:to_s).and_return(obj)
+ obj.should_not_receive(:to_str)
+ expected_pattern = ruby_version_is("3.4") ? /^\{a: #<MockObject:0x[0-9a-f]+>\}$/ : /^\{:a=>#<MockObject:0x[0-9a-f]+>\}$/
+ { a: obj }.inspect.should =~ expected_pattern
+ end
+
+ it "does not swallow exceptions raised by #to_s" do
+ obj = mock("Hash#inspect/to_s does not swallow #to_s exceptions")
+ obj.should_receive(:inspect).and_return(obj)
+ obj.should_receive(:to_s).and_raise(Exception)
+
+ -> { { a: obj }.inspect }.should.raise(Exception)
+ end
+
+ it "handles hashes with recursive values" do
+ x = {}
+ x[0] = x
+ expected = ruby_version_is("3.4") ? '{0 => {...}}' : '{0=>{...}}'
+ x.inspect.should == expected
+
+ x = {}
+ y = {}
+ x[0] = y
+ y[1] = x
+ expected_x = ruby_version_is("3.4") ? '{0 => {1 => {...}}}' : '{0=>{1=>{...}}}'
+ expected_y = ruby_version_is("3.4") ? '{1 => {0 => {...}}}' : '{1=>{0=>{...}}}'
+ x.inspect.should == expected_x
+ y.inspect.should == expected_y
+ end
+
+ it "does not raise if inspected result is not default external encoding" do
+ utf_16be = mock("utf_16be")
+ utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode(Encoding::UTF_16BE))
+ expected = ruby_version_is("3.4") ? '{a: "utf_16be \u3042"}' : '{:a=>"utf_16be \u3042"}'
+ {a: utf_16be}.inspect.should == expected
+ end
+
+ it "works for keys and values whose #inspect return a frozen String" do
+ expected = ruby_version_is("3.4") ? "{true => false}" : "{true=>false}"
+ { true => false }.inspect.should == expected
+ end
+
+ ruby_version_is "3.4" do
+ it "adds quotes to symbol keys that are not valid symbol literals" do
+ { "needs-quotes": 1 }.inspect.should == '{"needs-quotes": 1}'
+ end
+
+ it "can be evaled" do
+ no_quote = '{a: 1, a!: 1, a?: 1}'
+ eval(no_quote).inspect.should == no_quote
+ [
+ '{"": 1}',
+ '{"0": 1, "!": 1, "%": 1, "&": 1, "*": 1, "+": 1, "-": 1, "/": 1, "<": 1, ">": 1, "^": 1, "`": 1, "|": 1, "~": 1}',
+ '{"@a": 1, "$a": 1, "+@": 1, "a=": 1, "[]": 1}',
+ '{"a\"b": 1, "@@a": 1, "<=>": 1, "===": 1, "[]=": 1}',
+ ].each do |quote|
+ eval(quote).inspect.should == quote
+ end
+ end
+
+ it "can be evaled when Encoding.default_external is changed" do
+ external = Encoding.default_external
+
+ Encoding.default_external = Encoding::ASCII
+ utf8_ascii_hash = '{"\\u3042": 1}'
+ eval(utf8_ascii_hash).inspect.should == utf8_ascii_hash
+
+ Encoding.default_external = Encoding::UTF_8
+ utf8_hash = "{\u3042: 1}"
+ eval(utf8_hash).inspect.should == utf8_hash
+
+ Encoding.default_external = Encoding::Windows_31J
+ sjis_hash = "{\x87]: 1}".dup.force_encoding('sjis')
+ eval(sjis_hash).inspect.should == sjis_hash
+ ensure
+ Encoding.default_external = external
+ end
+ end
end
diff --git a/spec/ruby/core/hash/invert_spec.rb b/spec/ruby/core/hash/invert_spec.rb
index 73377a9e97..ea441751f2 100644
--- a/spec/ruby/core/hash/invert_spec.rb
+++ b/spec/ruby/core/hash/invert_spec.rb
@@ -24,4 +24,25 @@ describe "Hash#invert" do
HashSpecs::MyHash[1 => 2, 3 => 4].invert.class.should == Hash
HashSpecs::MyHash[].invert.class.should == Hash
end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.invert.default.should == nil
+ h[:a] = 1
+ h.invert.default.should == nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.invert.default_proc.should == nil
+ h[:a] = 1
+ h.invert.default_proc.should == nil
+ end
+
+ it "does not retain compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.invert
+ h2.compare_by_identity?.should == false
+ end
end
diff --git a/spec/ruby/core/hash/keep_if_spec.rb b/spec/ruby/core/hash/keep_if_spec.rb
index d50d969467..c975efc5f8 100644
--- a/spec/ruby/core/hash/keep_if_spec.rb
+++ b/spec/ruby/core/hash/keep_if_spec.rb
@@ -12,24 +12,24 @@ describe "Hash#keep_if" do
it "keeps every entry for which block is true and returns self" do
h = { a: 1, b: 2, c: 3, d: 4 }
- h.keep_if { |k,v| v % 2 == 0 }.should equal(h)
+ h.keep_if { |k,v| v % 2 == 0 }.should.equal?(h)
h.should == { b: 2, d: 4 }
end
it "removes all entries if the block is false" do
h = { a: 1, b: 2, c: 3 }
- h.keep_if { |k,v| false }.should equal(h)
+ h.keep_if { |k,v| false }.should.equal?(h)
h.should == {}
end
it "returns self even if unmodified" do
h = { 1 => 2, 3 => 4 }
- h.keep_if { true }.should equal(h)
+ h.keep_if { true }.should.equal?(h)
end
it "raises a FrozenError if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.keep_if { true } }.should raise_error(FrozenError)
- -> { HashSpecs.empty_frozen_hash.keep_if { false } }.should raise_error(FrozenError)
+ -> { HashSpecs.frozen_hash.keep_if { true } }.should.raise(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.keep_if { false } }.should.raise(FrozenError)
end
it_behaves_like :hash_iteration_no_block, :keep_if
diff --git a/spec/ruby/core/hash/key_spec.rb b/spec/ruby/core/hash/key_spec.rb
index 73eecbc98e..c2d7049aed 100644
--- a/spec/ruby/core/hash/key_spec.rb
+++ b/spec/ruby/core/hash/key_spec.rb
@@ -1,12 +1,32 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/key'
-require_relative 'shared/index'
describe "Hash#key?" do
- it_behaves_like :hash_key_p, :key?
+ it "is an alias of Hash#include?" do
+ Hash.instance_method(:key?).should == Hash.instance_method(:include?)
+ end
end
describe "Hash#key" do
- it_behaves_like :hash_index, :key
+ it "returns the corresponding key for value" do
+ { 2 => 'a', 1 => 'b' }.key('b').should == 1
+ end
+
+ it "returns nil if the value is not found" do
+ { a: -1, b: 3.14, c: 2.718 }.key(1).should == nil
+ end
+
+ it "doesn't return default value if the value is not found" do
+ Hash.new(5).key(5).should == nil
+ end
+
+ it "compares values using ==" do
+ { 1 => 0 }.key(0.0).should == 1
+ { 1 => 0.0 }.key(0).should == 1
+
+ needle = mock('needle')
+ inhash = mock('inhash')
+ inhash.should_receive(:==).with(needle).and_return(true)
+
+ { 1 => inhash }.key(needle).should == 1
+ end
end
diff --git a/spec/ruby/core/hash/keys_spec.rb b/spec/ruby/core/hash/keys_spec.rb
index 9a067085e5..789c413bee 100644
--- a/spec/ruby/core/hash/keys_spec.rb
+++ b/spec/ruby/core/hash/keys_spec.rb
@@ -5,11 +5,11 @@ describe "Hash#keys" do
it "returns an array with the keys in the order they were inserted" do
{}.keys.should == []
- {}.keys.should be_kind_of(Array)
+ {}.keys.should.is_a?(Array)
Hash.new(5).keys.should == []
Hash.new { 5 }.keys.should == []
{ 1 => 2, 4 => 8, 2 => 4 }.keys.should == [1, 4, 2]
- { 1 => 2, 2 => 4, 4 => 8 }.keys.should be_kind_of(Array)
+ { 1 => 2, 2 => 4, 4 => 8 }.keys.should.is_a?(Array)
{ nil => nil }.keys.should == [nil]
end
diff --git a/spec/ruby/core/hash/length_spec.rb b/spec/ruby/core/hash/length_spec.rb
index d0af0945df..325973306f 100644
--- a/spec/ruby/core/hash/length_spec.rb
+++ b/spec/ruby/core/hash/length_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/length'
describe "Hash#length" do
- it_behaves_like :hash_length, :length
+ it "is an alias of Hash#size" do
+ Hash.instance_method(:size).should == Hash.instance_method(:length)
+ end
end
diff --git a/spec/ruby/core/hash/lt_spec.rb b/spec/ruby/core/hash/lt_spec.rb
index 2219615880..4ca326d077 100644
--- a/spec/ruby/core/hash/lt_spec.rb
+++ b/spec/ruby/core/hash/lt_spec.rb
@@ -8,7 +8,7 @@ describe "Hash#<" do
it "returns false if both hashes are identical" do
h = { a: 1, b: 2 }
- (h < h).should be_false
+ (h < h).should == false
end
end
diff --git a/spec/ruby/core/hash/lte_spec.rb b/spec/ruby/core/hash/lte_spec.rb
index a166e5bca4..29e60273d1 100644
--- a/spec/ruby/core/hash/lte_spec.rb
+++ b/spec/ruby/core/hash/lte_spec.rb
@@ -8,7 +8,7 @@ describe "Hash#<=" do
it "returns true if both hashes are identical" do
h = { a: 1, b: 2 }
- (h <= h).should be_true
+ (h <= h).should == true
end
end
diff --git a/spec/ruby/core/hash/member_spec.rb b/spec/ruby/core/hash/member_spec.rb
index 37c0414559..e7309c3f7d 100644
--- a/spec/ruby/core/hash/member_spec.rb
+++ b/spec/ruby/core/hash/member_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/key'
describe "Hash#member?" do
- it_behaves_like :hash_key_p, :member?
+ it "is an alias of Hash#include?" do
+ Hash.instance_method(:member?).should == Hash.instance_method(:include?)
+ end
end
diff --git a/spec/ruby/core/hash/merge_spec.rb b/spec/ruby/core/hash/merge_spec.rb
index 5521864297..9e566fcee9 100644
--- a/spec/ruby/core/hash/merge_spec.rb
+++ b/spec/ruby/core/hash/merge_spec.rb
@@ -1,7 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/iteration'
-require_relative 'shared/update'
describe "Hash#merge" do
it "returns a new hash by combining self with the contents of other" do
@@ -30,7 +28,7 @@ describe "Hash#merge" do
-> {
h1.merge(h2) { |k, x, y| raise(IndexError) }
- }.should raise_error(IndexError)
+ }.should.raise(IndexError)
r = h1.merge(h1) { |k,x,y| :x }
r.should == { a: :x, b: :x, d: :x }
@@ -47,8 +45,8 @@ describe "Hash#merge" do
end
it "returns subclass instance for subclasses" do
- HashSpecs::MyHash[1 => 2, 3 => 4].merge({ 1 => 2 }).should be_an_instance_of(HashSpecs::MyHash)
- HashSpecs::MyHash[].merge({ 1 => 2 }).should be_an_instance_of(HashSpecs::MyHash)
+ HashSpecs::MyHash[1 => 2, 3 => 4].merge({ 1 => 2 }).should.instance_of?(HashSpecs::MyHash)
+ HashSpecs::MyHash[].merge({ 1 => 2 }).should.instance_of?(HashSpecs::MyHash)
{ 1 => 2, 3 => 4 }.merge(HashSpecs::MyHash[1 => 2]).class.should == Hash
{}.merge(HashSpecs::MyHash[1 => 2]).class.should == Hash
@@ -90,11 +88,36 @@ describe "Hash#merge" do
hash = { a: 1 }
merged = hash.merge
- merged.should eql(hash)
- merged.should_not equal(hash)
+ merged.should.eql?(hash)
+ merged.should_not.equal?(hash)
+ end
+
+ it "retains the default value" do
+ h = Hash.new(1)
+ h.merge(b: 1, d: 2).default.should == 1
+ end
+
+ it "retains the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.merge(b: 1, d: 2).default_proc.should == pr
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.merge(b: 1, d: 2)
+ h2.compare_by_identity?.should == true
+ end
+
+ it "ignores compare_by_identity flag of an argument" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = { b: 1, d: 2 }.merge(h)
+ h2.compare_by_identity?.should == false
end
end
describe "Hash#merge!" do
- it_behaves_like :hash_update, :merge!
+ it "is an alias of Hash#update" do
+ Hash.instance_method(:merge!).should == Hash.instance_method(:update)
+ end
end
diff --git a/spec/ruby/core/hash/new_spec.rb b/spec/ruby/core/hash/new_spec.rb
index 6054b69bdd..207fc2931f 100644
--- a/spec/ruby/core/hash/new_spec.rb
+++ b/spec/ruby/core/hash/new_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+# Actually these are specs of Hash#initialize, there is no Hash.new it's just Class.new.
describe "Hash.new" do
it "creates an empty Hash if passed no arguments" do
Hash.new.should == {}
@@ -14,7 +15,7 @@ describe "Hash.new" do
it "does not create a copy of the default argument" do
str = "foo"
- Hash.new(str).default.should equal(str)
+ Hash.new(str).default.should.equal?(str)
end
it "creates a Hash with a default_proc if passed a block" do
@@ -26,11 +27,42 @@ describe "Hash.new" do
end
it "raises an ArgumentError if more than one argument is passed" do
- -> { Hash.new(5,6) }.should raise_error(ArgumentError)
+ -> { Hash.new(5,6) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if passed both default argument and default block" do
- -> { Hash.new(5) { 0 } }.should raise_error(ArgumentError)
- -> { Hash.new(nil) { 0 } }.should raise_error(ArgumentError)
+ -> { Hash.new(5) { 0 } }.should.raise(ArgumentError)
+ -> { Hash.new(nil) { 0 } }.should.raise(ArgumentError)
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "emits a deprecation warning if keyword arguments are passed" do
+ -> { Hash.new(unknown: true) }.should complain(
+ Regexp.new(Regexp.escape("Calling Hash.new with keyword arguments is deprecated and will be removed in Ruby 3.4; use Hash.new({ key: value }) instead"))
+ )
+
+ -> { Hash.new(1, unknown: true) }.should.raise(ArgumentError)
+ -> { Hash.new(unknown: true) { 0 } }.should.raise(ArgumentError)
+
+ Hash.new({ unknown: true }).default.should == { unknown: true }
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "accepts a capacity: argument" do
+ Hash.new(5, capacity: 42).default.should == 5
+ Hash.new(capacity: 42).default.should == nil
+ (Hash.new(capacity: 42) { 1 }).default_proc.should_not == nil
+ end
+
+ it "ignores negative capacity" do
+ -> { Hash.new(capacity: -42) }.should_not.raise
+ end
+
+ it "raises an error if unknown keyword arguments are passed" do
+ -> { Hash.new(unknown: true) }.should.raise(ArgumentError)
+ -> { Hash.new(1, unknown: true) }.should.raise(ArgumentError)
+ -> { Hash.new(unknown: true) { 0 } }.should.raise(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/hash/rassoc_spec.rb b/spec/ruby/core/hash/rassoc_spec.rb
index f3b2a6de20..73379f6867 100644
--- a/spec/ruby/core/hash/rassoc_spec.rb
+++ b/spec/ruby/core/hash/rassoc_spec.rb
@@ -6,7 +6,7 @@ describe "Hash#rassoc" do
end
it "returns an Array if the argument is a value of the Hash" do
- @h.rassoc(:green).should be_an_instance_of(Array)
+ @h.rassoc(:green).should.instance_of?(Array)
end
it "returns a 2-element Array if the argument is a value of the Hash" do
@@ -28,15 +28,15 @@ describe "Hash#rassoc" do
it "uses #== to compare the argument to the values" do
@h[:key] = 1.0
1.should == 1.0
- @h.rassoc(1).should eql [:key, 1.0]
+ @h.rassoc(1).should.eql? [:key, 1.0]
end
it "returns nil if the argument is not a value of the Hash" do
- @h.rassoc(:banana).should be_nil
+ @h.rassoc(:banana).should == nil
end
it "returns nil if the argument is not a value of the Hash even when there is a default" do
- Hash.new(42).merge!( foo: :bar ).rassoc(42).should be_nil
- Hash.new{|h, k| h[k] = 42}.merge!( foo: :bar ).rassoc(42).should be_nil
+ Hash.new(42).merge!( foo: :bar ).rassoc(42).should == nil
+ Hash.new{|h, k| h[k] = 42}.merge!( foo: :bar ).rassoc(42).should == nil
end
end
diff --git a/spec/ruby/core/hash/rehash_spec.rb b/spec/ruby/core/hash/rehash_spec.rb
index 0049080456..fcd5a037bd 100644
--- a/spec/ruby/core/hash/rehash_spec.rb
+++ b/spec/ruby/core/hash/rehash_spec.rb
@@ -20,7 +20,7 @@ describe "Hash#rehash" do
h.keys.include?(k1).should == true
- h.rehash.should equal(h)
+ h.rehash.should.equal?(h)
h.key?(k1).should == true
h[k1].should == :v1
end
@@ -77,8 +77,38 @@ describe "Hash#rehash" do
h.keys.should_not.include? [1]
end
+ it "iterates keys in insertion order" do
+ key = Class.new do
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def hash
+ 123
+ end
+ end
+
+ a, b, c, d = key.new('a'), key.new('b'), key.new('c'), key.new('d')
+ h = { a => 1, b => 2, c => 3, d => 4 }
+ h.size.should == 4
+
+ key.class_exec do
+ def eql?(other)
+ true
+ end
+ end
+
+ h.rehash
+ h.size.should == 1
+ k, v = h.first
+ k.name.should == 'a'
+ v.should == 4
+ end
+
it "raises a FrozenError if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.rehash }.should raise_error(FrozenError)
- -> { HashSpecs.empty_frozen_hash.rehash }.should raise_error(FrozenError)
+ -> { HashSpecs.frozen_hash.rehash }.should.raise(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.rehash }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/reject_spec.rb b/spec/ruby/core/hash/reject_spec.rb
index dd8e817237..aa1a074897 100644
--- a/spec/ruby/core/hash/reject_spec.rb
+++ b/spec/ruby/core/hash/reject_spec.rb
@@ -28,8 +28,8 @@ describe "Hash#reject" do
context "with extra state" do
it "returns Hash instance for subclasses" do
- HashSpecs::MyHash[1 => 2, 3 => 4].reject { false }.should be_kind_of(Hash)
- HashSpecs::MyHash[1 => 2, 3 => 4].reject { true }.should be_kind_of(Hash)
+ HashSpecs::MyHash[1 => 2, 3 => 4].reject { false }.should.is_a?(Hash)
+ HashSpecs::MyHash[1 => 2, 3 => 4].reject { true }.should.is_a?(Hash)
end
end
@@ -44,6 +44,27 @@ describe "Hash#reject" do
reject_pairs.should == reject_bang_pairs
end
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.reject { false }.default.should == nil
+ h[:a] = 1
+ h.reject { false }.default.should == nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.reject { false }.default_proc.should == nil
+ h[:a] = 1
+ h.reject { false }.default_proc.should == nil
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.reject { |k, _| k == :a }
+ h2.compare_by_identity?.should == true
+ end
+
it_behaves_like :hash_iteration_no_block, :reject
it_behaves_like :enumeratorized_with_origin_size, :reject, { 1 => 2, 3 => 4, 5 => 6 }
end
@@ -58,7 +79,7 @@ describe "Hash#reject!" do
it "removes all entries if the block is true" do
h = { a: 1, b: 2, c: 3 }
- h.reject! { |k,v| true }.should equal(h)
+ h.reject! { |k,v| true }.should.equal?(h)
h.should == {}
end
@@ -83,11 +104,11 @@ describe "Hash#reject!" do
end
it "raises a FrozenError if called on a frozen instance that is modified" do
- -> { HashSpecs.empty_frozen_hash.reject! { true } }.should raise_error(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.reject! { true } }.should.raise(FrozenError)
end
it "raises a FrozenError if called on a frozen instance that would not be modified" do
- -> { HashSpecs.frozen_hash.reject! { false } }.should raise_error(FrozenError)
+ -> { HashSpecs.frozen_hash.reject! { false } }.should.raise(FrozenError)
end
it_behaves_like :hash_iteration_no_block, :reject!
diff --git a/spec/ruby/core/hash/replace_spec.rb b/spec/ruby/core/hash/replace_spec.rb
index 92b2118fd3..4dacbf9779 100644
--- a/spec/ruby/core/hash/replace_spec.rb
+++ b/spec/ruby/core/hash/replace_spec.rb
@@ -1,7 +1,79 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/replace'
describe "Hash#replace" do
- it_behaves_like :hash_replace, :replace
+ it "replaces the contents of self with other" do
+ h = { a: 1, b: 2 }
+ h.replace(c: -1, d: -2).should.equal?(h)
+ h.should == { c: -1, d: -2 }
+ end
+
+ it "tries to convert the passed argument to a hash using #to_hash" do
+ obj = mock('{1=>2,3=>4}')
+ obj.should_receive(:to_hash).and_return({ 1 => 2, 3 => 4 })
+
+ h = {}
+ h.replace(obj)
+ h.should == { 1 => 2, 3 => 4 }
+ end
+
+ it "calls to_hash on hash subclasses" do
+ h = {}
+ h.replace(HashSpecs::ToHashHash[1 => 2])
+ h.should == { 1 => 2 }
+ end
+
+ it "does not retain the default value" do
+ hash = Hash.new(1)
+ hash.replace(b: 2).default.should == nil
+ end
+
+ it "transfers the default value of an argument" do
+ hash = Hash.new(1)
+ { a: 1 }.replace(hash).default.should == 1
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ hash = Hash.new(&pr)
+ hash.replace(b: 2).default_proc.should == nil
+ end
+
+ it "transfers the default_proc of an argument" do
+ pr = proc { |h, k| h[k] = [] }
+ hash = Hash.new(&pr)
+ { a: 1 }.replace(hash).default_proc.should == pr
+ end
+
+ it "does not call the default_proc of an argument" do
+ hash_a = Hash.new { |h, k| k * 5 }
+ hash_b = Hash.new(-> { raise "Should not invoke lambda" })
+ hash_a.replace(hash_b)
+ hash_a.default.should == hash_b.default
+ end
+
+ it "transfers compare_by_identity flag of an argument" do
+ h = { a: 1, c: 3 }
+ h2 = { b: 2, d: 4 }.compare_by_identity
+ h.replace(h2)
+ h.compare_by_identity?.should == true
+ end
+
+ it "does not retain compare_by_identity flag" do
+ h = { a: 1, c: 3 }.compare_by_identity
+ h.replace(b: 2, d: 4)
+ h.compare_by_identity?.should == false
+ end
+
+ it "raises a FrozenError if called on a frozen instance that would not be modified" do
+ -> do
+ HashSpecs.frozen_hash.replace(HashSpecs.frozen_hash)
+ end.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError if called on a frozen instance that is modified" do
+ -> do
+ HashSpecs.frozen_hash.replace(HashSpecs.empty_frozen_hash)
+ end.should.raise(FrozenError)
+ end
end
diff --git a/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb b/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb
index e9337b9d1c..609a53f81f 100644
--- a/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb
+++ b/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb
@@ -16,7 +16,7 @@ describe "Hash.ruby2_keywords_hash?" do
end
it "raises TypeError for non-Hash" do
- -> { Hash.ruby2_keywords_hash?(nil) }.should raise_error(TypeError)
+ -> { Hash.ruby2_keywords_hash?(nil) }.should.raise(TypeError)
end
end
@@ -54,6 +54,28 @@ describe "Hash.ruby2_keywords_hash" do
end
it "raises TypeError for non-Hash" do
- -> { Hash.ruby2_keywords_hash(nil) }.should raise_error(TypeError)
+ -> { Hash.ruby2_keywords_hash(nil) }.should.raise(TypeError)
+ end
+
+ it "retains the default value" do
+ hash = Hash.new(1)
+ Hash.ruby2_keywords_hash(hash).default.should == 1
+ hash[:a] = 1
+ Hash.ruby2_keywords_hash(hash).default.should == 1
+ end
+
+ it "retains the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ hash = Hash.new(&pr)
+ Hash.ruby2_keywords_hash(hash).default_proc.should == pr
+ hash[:a] = 1
+ Hash.ruby2_keywords_hash(hash).default_proc.should == pr
+ end
+
+ it "retains compare_by_identity_flag" do
+ hash = {}.compare_by_identity
+ Hash.ruby2_keywords_hash(hash).compare_by_identity?.should == true
+ hash[:a] = 1
+ Hash.ruby2_keywords_hash(hash).compare_by_identity?.should == true
end
end
diff --git a/spec/ruby/core/hash/select_spec.rb b/spec/ruby/core/hash/select_spec.rb
index 38b0180b0e..60b2ce67c1 100644
--- a/spec/ruby/core/hash/select_spec.rb
+++ b/spec/ruby/core/hash/select_spec.rb
@@ -1,10 +1,112 @@
require_relative '../../spec_helper'
-require_relative 'shared/select'
+require_relative '../enumerable/shared/enumeratorized'
+require_relative 'fixtures/classes'
+require_relative 'shared/iteration'
describe "Hash#select" do
- it_behaves_like :hash_select, :select
+ before :each do
+ @hsh = { 1 => 2, 3 => 4, 5 => 6 }
+ @empty = {}
+ end
+
+ it "yields two arguments: key and value" do
+ all_args = []
+ { 1 => 2, 3 => 4 }.select { |*args| all_args << args }
+ all_args.sort.should == [[1, 2], [3, 4]]
+ end
+
+ it "returns a Hash of entries for which block is true" do
+ a_pairs = { 'a' => 9, 'c' => 4, 'b' => 5, 'd' => 2 }.select { |k,v| v % 2 == 0 }
+ a_pairs.should.instance_of?(Hash)
+ a_pairs.sort.should == [['c', 4], ['d', 2]]
+ end
+
+ it "processes entries with the same order as reject" do
+ h = { a: 9, c: 4, b: 5, d: 2 }
+
+ select_pairs = []
+ reject_pairs = []
+ h.dup.select{ |*pair| select_pairs << pair }
+ h.reject { |*pair| reject_pairs << pair }
+
+ select_pairs.should == reject_pairs
+ end
+
+ it "returns an Enumerator when called on a non-empty hash without a block" do
+ @hsh.select.should.instance_of?(Enumerator)
+ end
+
+ it "returns an Enumerator when called on an empty hash without a block" do
+ @empty.select.should.instance_of?(Enumerator)
+ end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.select { true }.default.should == nil
+ h[:a] = 1
+ h.select { true }.default.should == nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.select { true }.default_proc.should == nil
+ h[:a] = 1
+ h.select { true }.default_proc.should == nil
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.select { |k, _| k == :a }
+ h2.compare_by_identity?.should == true
+ end
+
+ it_behaves_like :hash_iteration_no_block, :select
+
+ before :each do
+ @object = { 1 => 2, 3 => 4, 5 => 6 }
+ end
+ it_behaves_like :enumeratorized_with_origin_size, :select
end
describe "Hash#select!" do
- it_behaves_like :hash_select!, :select!
+ before :each do
+ @hsh = { 1 => 2, 3 => 4, 5 => 6 }
+ @empty = {}
+ end
+
+ it "is equivalent to keep_if if changes are made" do
+ h = { a: 2 }
+ h.select! { |k,v| v <= 1 }.should.equal? h
+
+ h = { 1 => 2, 3 => 4 }
+ all_args_select = []
+ h.dup.select! { |*args| all_args_select << args }
+ all_args_select.should == [[1, 2], [3, 4]]
+ end
+
+ it "removes all entries if the block is false" do
+ h = { a: 1, b: 2, c: 3 }
+ h.select! { |k,v| false }.should.equal?(h)
+ h.should == {}
+ end
+
+ it "returns nil if no changes were made" do
+ { a: 1 }.select! { |k,v| v <= 1 }.should == nil
+ end
+
+ it "raises a FrozenError if called on an empty frozen instance" do
+ -> { HashSpecs.empty_frozen_hash.select! { false } }.should.raise(FrozenError)
+ end
+
+ it "raises a FrozenError if called on a frozen instance that would not be modified" do
+ -> { HashSpecs.frozen_hash.select! { true } }.should.raise(FrozenError)
+ end
+
+ it_behaves_like :hash_iteration_no_block, :select!
+
+ before :each do
+ @object = { 1 => 2, 3 => 4, 5 => 6 }
+ end
+ it_behaves_like :enumeratorized_with_origin_size, :select!
end
diff --git a/spec/ruby/core/hash/shared/comparison.rb b/spec/ruby/core/hash/shared/comparison.rb
index 07564e4cec..2b62837232 100644
--- a/spec/ruby/core/hash/shared/comparison.rb
+++ b/spec/ruby/core/hash/shared/comparison.rb
@@ -1,15 +1,15 @@
describe :hash_comparison, shared: true do
it "raises a TypeError if the right operand is not a hash" do
- -> { { a: 1 }.send(@method, 1) }.should raise_error(TypeError)
- -> { { a: 1 }.send(@method, nil) }.should raise_error(TypeError)
- -> { { a: 1 }.send(@method, []) }.should raise_error(TypeError)
+ -> { { a: 1 }.send(@method, 1) }.should.raise(TypeError)
+ -> { { a: 1 }.send(@method, nil) }.should.raise(TypeError)
+ -> { { a: 1 }.send(@method, []) }.should.raise(TypeError)
end
it "returns false if both hashes have the same keys but different values" do
h1 = { a: 1 }
h2 = { a: 2 }
- h1.send(@method, h2).should be_false
- h2.send(@method, h1).should be_false
+ h1.send(@method, h2).should == false
+ h2.send(@method, h1).should == false
end
end
diff --git a/spec/ruby/core/hash/shared/each.rb b/spec/ruby/core/hash/shared/each.rb
deleted file mode 100644
index b2483c8116..0000000000
--- a/spec/ruby/core/hash/shared/each.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-describe :hash_each, shared: true do
-
- # This is inconsistent with below, MRI checks the block arity in rb_hash_each_pair()
- it "yields a [[key, value]] Array for each pair to a block expecting |*args|" do
- all_args = []
- { 1 => 2, 3 => 4 }.send(@method) { |*args| all_args << args }
- all_args.sort.should == [[[1, 2]], [[3, 4]]]
- end
-
- it "yields the key and value of each pair to a block expecting |key, value|" do
- r = {}
- h = { a: 1, b: 2, c: 3, d: 5 }
- h.send(@method) { |k,v| r[k.to_s] = v.to_s }.should equal(h)
- r.should == { "a" => "1", "b" => "2", "c" => "3", "d" => "5" }
- end
-
- it "yields the key only to a block expecting |key,|" do
- ary = []
- h = { "a" => 1, "b" => 2, "c" => 3 }
- h.send(@method) { |k,| ary << k }
- ary.sort.should == ["a", "b", "c"]
- end
-
- ruby_version_is ""..."3.0" do
- it "yields 2 values and not an Array of 2 elements when given a callable of arity 2" do
- obj = Object.new
- def obj.foo(key, value)
- ScratchPad << key << value
- end
-
- ScratchPad.record([])
- { "a" => 1 }.send(@method, &obj.method(:foo))
- ScratchPad.recorded.should == ["a", 1]
-
- ScratchPad.record([])
- { "a" => 1 }.send(@method, &-> key, value { ScratchPad << key << value })
- ScratchPad.recorded.should == ["a", 1]
- end
- end
-
- ruby_version_is "3.0" do
- it "always yields an Array of 2 elements, even when given a callable of arity 2" do
- obj = Object.new
- def obj.foo(key, value)
- end
-
- -> {
- { "a" => 1 }.send(@method, &obj.method(:foo))
- }.should raise_error(ArgumentError)
-
- -> {
- { "a" => 1 }.send(@method, &-> key, value { })
- }.should raise_error(ArgumentError)
- end
- end
-
- it "yields an Array of 2 elements when given a callable of arity 1" do
- obj = Object.new
- def obj.foo(key_value)
- ScratchPad << key_value
- end
-
- ScratchPad.record([])
- { "a" => 1 }.send(@method, &obj.method(:foo))
- ScratchPad.recorded.should == [["a", 1]]
- end
-
- it "raises an error for a Hash when an arity enforcing callable of arity >2 is passed in" do
- obj = Object.new
- def obj.foo(key, value, extra)
- end
-
- -> {
- { "a" => 1 }.send(@method, &obj.method(:foo))
- }.should raise_error(ArgumentError)
- end
-
- it "uses the same order as keys() and values()" do
- h = { a: 1, b: 2, c: 3, d: 5 }
- keys = []
- values = []
-
- h.send(@method) do |k, v|
- keys << k
- values << v
- end
-
- keys.should == h.keys
- values.should == h.values
- end
-
- # Confirming the argument-splatting works from child class for both k, v and [k, v]
- it "properly expands (or not) child class's 'each'-yielded args" do
- cls1 = Class.new(Hash) do
- attr_accessor :k_v
- def each
- super do |k, v|
- @k_v = [k, v]
- yield k, v
- end
- end
- end
-
- cls2 = Class.new(Hash) do
- attr_accessor :k_v
- def each
- super do |k, v|
- @k_v = [k, v]
- yield([k, v])
- end
- end
- end
-
- obj1 = cls1.new
- obj1['a'] = 'b'
- obj1.map {|k, v| [k, v]}.should == [['a', 'b']]
- obj1.k_v.should == ['a', 'b']
-
- obj2 = cls2.new
- obj2['a'] = 'b'
- obj2.map {|k, v| [k, v]}.should == [['a', 'b']]
- obj2.k_v.should == ['a', 'b']
- end
-end
diff --git a/spec/ruby/core/hash/shared/eql.rb b/spec/ruby/core/hash/shared/eql.rb
index 68db49f76d..512e1ad016 100644
--- a/spec/ruby/core/hash/shared/eql.rb
+++ b/spec/ruby/core/hash/shared/eql.rb
@@ -3,7 +3,7 @@ describe :hash_eql, shared: true do
value = mock('x')
value.should_not_receive(:==)
value.should_not_receive(:eql?)
- { 1 => value }.send(@method, { 2 => value }).should be_false
+ { 1 => value }.send(@method, { 2 => value }).should == false
end
it "returns false when the numbers of keys differ without comparing any elements" do
@@ -13,8 +13,8 @@ describe :hash_eql, shared: true do
obj.should_not_receive(:==)
obj.should_not_receive(:eql?)
- {}.send(@method, h).should be_false
- h.send(@method, {}).should be_false
+ {}.send(@method, h).should == false
+ h.send(@method, {}).should == false
end
it "first compares keys via hash" do
@@ -23,7 +23,7 @@ describe :hash_eql, shared: true do
y = mock('y')
y.should_receive(:hash).any_number_of_times.and_return(0)
- { x => 1 }.send(@method, { y => 1 }).should be_false
+ { x => 1 }.send(@method, { y => 1 }).should == false
end
it "does not compare keys with different hash codes via eql?" do
@@ -35,39 +35,39 @@ describe :hash_eql, shared: true do
x.should_receive(:hash).any_number_of_times.and_return(0)
y.should_receive(:hash).any_number_of_times.and_return(1)
- { x => 1 }.send(@method, { y => 1 }).should be_false
+ { x => 1 }.send(@method, { y => 1 }).should == false
end
it "computes equality for recursive hashes" do
h = {}
h[:a] = h
- h.send(@method, h[:a]).should be_true
- (h == h[:a]).should be_true
+ h.send(@method, h[:a]).should == true
+ (h == h[:a]).should == true
end
it "doesn't call to_hash on objects" do
mock_hash = mock("fake hash")
def mock_hash.to_hash() {} end
- {}.send(@method, mock_hash).should be_false
+ {}.send(@method, mock_hash).should == false
end
it "computes equality for complex recursive hashes" do
a, b = {}, {}
a.merge! self: a, other: b
b.merge! self: b, other: a
- a.send(@method, b).should be_true # they both have the same structure!
+ a.send(@method, b).should == true # they both have the same structure!
c = {}
c.merge! other: c, self: c
- c.send(@method, a).should be_true # subtle, but they both have the same structure!
+ c.send(@method, a).should == true # subtle, but they both have the same structure!
a[:delta] = c[:delta] = a
- c.send(@method, a).should be_false # not quite the same structure, as a[:other][:delta] = nil
+ c.send(@method, a).should == false # not quite the same structure, as a[:other][:delta] = nil
c[:delta] = 42
- c.send(@method, a).should be_false
+ c.send(@method, a).should == false
a[:delta] = 42
- c.send(@method, a).should be_false
+ c.send(@method, a).should == false
b[:delta] = 42
- c.send(@method, a).should be_true
+ c.send(@method, a).should == true
end
it "computes equality for recursive hashes & arrays" do
@@ -76,19 +76,19 @@ describe :hash_eql, shared: true do
x << a
y << c
z << b
- b.send(@method, c).should be_true # they clearly have the same structure!
- y.send(@method, z).should be_true
- a.send(@method, b).should be_true # subtle, but they both have the same structure!
- x.send(@method, y).should be_true
+ b.send(@method, c).should == true # they clearly have the same structure!
+ y.send(@method, z).should == true
+ a.send(@method, b).should == true # subtle, but they both have the same structure!
+ x.send(@method, y).should == true
y << x
- y.send(@method, z).should be_false
+ y.send(@method, z).should == false
z << x
- y.send(@method, z).should be_true
+ y.send(@method, z).should == true
a[:foo], a[:bar] = a[:bar], a[:foo]
- a.send(@method, b).should be_false
+ a.send(@method, b).should == false
b[:bar] = b[:foo]
- b.send(@method, c).should be_false
+ b.send(@method, c).should == false
end
end
@@ -100,7 +100,7 @@ describe :hash_eql_additional, shared: true do
def y.==(o) false end
def x.eql?(o) false end
def y.eql?(o) false end
- { 1 => x }.send(@method, { 1 => y }).should be_false
+ { 1 => x }.send(@method, { 1 => y }).should == false
x = mock('x')
y = mock('y')
@@ -108,45 +108,45 @@ describe :hash_eql_additional, shared: true do
def y.==(o) true end
def x.eql?(o) true end
def y.eql?(o) true end
- { 1 => x }.send(@method, { 1 => y }).should be_true
+ { 1 => x }.send(@method, { 1 => y }).should == true
end
it "compares keys with eql? semantics" do
- { 1.0 => "x" }.send(@method, { 1.0 => "x" }).should be_true
- { 1.0 => "x" }.send(@method, { 1.0 => "x" }).should be_true
- { 1 => "x" }.send(@method, { 1.0 => "x" }).should be_false
- { 1.0 => "x" }.send(@method, { 1 => "x" }).should be_false
+ { 1.0 => "x" }.send(@method, { 1.0 => "x" }).should == true
+ { 1.0 => "x" }.send(@method, { 1.0 => "x" }).should == true
+ { 1 => "x" }.send(@method, { 1.0 => "x" }).should == false
+ { 1.0 => "x" }.send(@method, { 1 => "x" }).should == false
end
it "returns true if and only if other Hash has the same number of keys and each key-value pair matches" do
a = { a: 5 }
b = {}
- a.send(@method, b).should be_false
+ a.send(@method, b).should == false
b[:a] = 5
- a.send(@method, b).should be_true
+ a.send(@method, b).should == true
not_supported_on :opal do
c = { "a" => 5 }
- a.send(@method, c).should be_false
+ a.send(@method, c).should == false
end
c = { "A" => 5 }
- a.send(@method, c).should be_false
+ a.send(@method, c).should == false
c = { a: 6 }
- a.send(@method, c).should be_false
+ a.send(@method, c).should == false
end
it "does not call to_hash on hash subclasses" do
- { 5 => 6 }.send(@method, HashSpecs::ToHashHash[5 => 6]).should be_true
+ { 5 => 6 }.send(@method, HashSpecs::ToHashHash[5 => 6]).should == true
end
it "ignores hash class differences" do
h = { 1 => 2, 3 => 4 }
- HashSpecs::MyHash[h].send(@method, h).should be_true
- HashSpecs::MyHash[h].send(@method, HashSpecs::MyHash[h]).should be_true
- h.send(@method, HashSpecs::MyHash[h]).should be_true
+ HashSpecs::MyHash[h].send(@method, h).should == true
+ HashSpecs::MyHash[h].send(@method, HashSpecs::MyHash[h]).should == true
+ h.send(@method, HashSpecs::MyHash[h]).should == true
end
# Why isn't this true of eql? too ?
@@ -163,7 +163,7 @@ describe :hash_eql_additional, shared: true do
obj
end
- { a[0] => 1 }.send(@method, { a[1] => 1 }).should be_false
+ { a[0] => 1 }.send(@method, { a[1] => 1 }).should == false
a = Array.new(2) do
obj = mock('0')
@@ -176,7 +176,7 @@ describe :hash_eql_additional, shared: true do
obj
end
- { a[0] => 1 }.send(@method, { a[1] => 1 }).should be_true
+ { a[0] => 1 }.send(@method, { a[1] => 1 }).should == true
end
it "compares the values in self to values in other hash" do
@@ -185,20 +185,20 @@ describe :hash_eql_additional, shared: true do
l_val.should_receive(:eql?).with(r_val).and_return(true)
- { 1 => l_val }.eql?({ 1 => r_val }).should be_true
+ { 1 => l_val }.eql?({ 1 => r_val }).should == true
end
end
describe :hash_eql_additional_more, shared: true do
it "returns true if other Hash has the same number of keys and each key-value pair matches, even though the default-value are not same" do
- Hash.new(5).send(@method, Hash.new(1)).should be_true
- Hash.new {|h, k| 1}.send(@method, Hash.new {}).should be_true
- Hash.new {|h, k| 1}.send(@method, Hash.new(2)).should be_true
+ Hash.new(5).send(@method, Hash.new(1)).should == true
+ Hash.new {|h, k| 1}.send(@method, Hash.new {}).should == true
+ Hash.new {|h, k| 1}.send(@method, Hash.new(2)).should == true
d = Hash.new {|h, k| 1}
e = Hash.new {}
d[1] = 2
e[1] = 2
- d.send(@method, e).should be_true
+ d.send(@method, e).should == true
end
end
diff --git a/spec/ruby/core/hash/shared/equal.rb b/spec/ruby/core/hash/shared/equal.rb
deleted file mode 100644
index 43606437fe..0000000000
--- a/spec/ruby/core/hash/shared/equal.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-describe :hash_equal, shared: true do
- it "does not compare values when keys don't match" do
- value = mock('x')
- value.should_not_receive(:==)
- value.should_not_receive(:eql?)
- { 1 => value }.send(@method, { 2 => value }).should be_false
- end
-
- it "returns false when the numbers of keys differ without comparing any elements" do
- obj = mock('x')
- h = { obj => obj }
-
- obj.should_not_receive(:==)
- obj.should_not_receive(:eql?)
-
- {}.send(@method, h).should be_false
- h.send(@method, {}).should be_false
- end
-
- it "first compares keys via hash" do
- x = mock('x')
- x.should_receive(:hash).and_return(0)
- y = mock('y')
- y.should_receive(:hash).and_return(0)
-
- { x => 1 }.send(@method, { y => 1 }).should be_false
- end
-
- it "does not compare keys with different hash codes via eql?" do
- x = mock('x')
- y = mock('y')
- x.should_not_receive(:eql?)
- y.should_not_receive(:eql?)
-
- x.should_receive(:hash).and_return(0)
- y.should_receive(:hash).and_return(1)
-
- def x.hash() 0 end
- def y.hash() 1 end
-
- { x => 1 }.send(@method, { y => 1 }).should be_false
- end
-
- it "computes equality for recursive hashes" do
- h = {}
- h[:a] = h
- h.send(@method, h[:a]).should be_true
- (h == h[:a]).should be_true
- end
-
- it "computes equality for complex recursive hashes" do
- a, b = {}, {}
- a.merge! self: a, other: b
- b.merge! self: b, other: a
- a.send(@method, b).should be_true # they both have the same structure!
-
- c = {}
- c.merge! other: c, self: c
- c.send(@method, a).should be_true # subtle, but they both have the same structure!
- a[:delta] = c[:delta] = a
- c.send(@method, a).should be_false # not quite the same structure, as a[:other][:delta] = nil
- c[:delta] = 42
- c.send(@method, a).should be_false
- a[:delta] = 42
- c.send(@method, a).should be_false
- b[:delta] = 42
- c.send(@method, a).should be_true
- end
-
- it "computes equality for recursive hashes & arrays" do
- x, y, z = [], [], []
- a, b, c = {foo: x, bar: 42}, {foo: y, bar: 42}, {foo: z, bar: 42}
- x << a
- y << c
- z << b
- b.send(@method, c).should be_true # they clearly have the same structure!
- y.send(@method, z).should be_true
- a.send(@method, b).should be_true # subtle, but they both have the same structure!
- x.send(@method, y).should be_true
- y << x
- y.send(@method, z).should be_false
- z << x
- y.send(@method, z).should be_true
-
- a[:foo], a[:bar] = a[:bar], a[:foo]
- a.send(@method, b).should be_false
- b[:bar] = b[:foo]
- b.send(@method, c).should be_false
- end
-end
diff --git a/spec/ruby/core/hash/shared/greater_than.rb b/spec/ruby/core/hash/shared/greater_than.rb
index 1f8b9fcfb7..dfe0b80250 100644
--- a/spec/ruby/core/hash/shared/greater_than.rb
+++ b/spec/ruby/core/hash/shared/greater_than.rb
@@ -5,11 +5,11 @@ describe :hash_greater_than, shared: true do
end
it "returns true if the other hash is a subset of self" do
- @h1.send(@method, @h2).should be_true
+ @h1.send(@method, @h2).should == true
end
it "returns false if the other hash is not a subset of self" do
- @h2.send(@method, @h1).should be_false
+ @h2.send(@method, @h1).should == false
end
it "converts the right operand to a hash before comparing" do
@@ -18,6 +18,6 @@ describe :hash_greater_than, shared: true do
{ a: 1, b: 2 }
end
- @h1.send(@method, o).should be_true
+ @h1.send(@method, o).should == true
end
end
diff --git a/spec/ruby/core/hash/shared/index.rb b/spec/ruby/core/hash/shared/index.rb
deleted file mode 100644
index 7f6a186464..0000000000
--- a/spec/ruby/core/hash/shared/index.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require_relative '../../../spec_helper'
-require_relative '../fixtures/classes'
-
-describe :hash_index, shared: true do
- it "returns the corresponding key for value" do
- suppress_warning do # for Hash#index
- { 2 => 'a', 1 => 'b' }.send(@method, 'b').should == 1
- end
- end
-
- it "returns nil if the value is not found" do
- suppress_warning do # for Hash#index
- { a: -1, b: 3.14, c: 2.718 }.send(@method, 1).should be_nil
- end
- end
-
- it "doesn't return default value if the value is not found" do
- suppress_warning do # for Hash#index
- Hash.new(5).send(@method, 5).should be_nil
- end
- end
-
- it "compares values using ==" do
- suppress_warning do # for Hash#index
- { 1 => 0 }.send(@method, 0.0).should == 1
- { 1 => 0.0 }.send(@method, 0).should == 1
- end
-
- needle = mock('needle')
- inhash = mock('inhash')
- inhash.should_receive(:==).with(needle).and_return(true)
-
- suppress_warning do # for Hash#index
- { 1 => inhash }.send(@method, needle).should == 1
- end
- end
-end
diff --git a/spec/ruby/core/hash/shared/iteration.rb b/spec/ruby/core/hash/shared/iteration.rb
index d27c2443f8..322e4b9a2f 100644
--- a/spec/ruby/core/hash/shared/iteration.rb
+++ b/spec/ruby/core/hash/shared/iteration.rb
@@ -5,15 +5,15 @@ describe :hash_iteration_no_block, shared: true do
end
it "returns an Enumerator if called on a non-empty hash without a block" do
- @hsh.send(@method).should be_an_instance_of(Enumerator)
+ @hsh.send(@method).should.instance_of?(Enumerator)
end
it "returns an Enumerator if called on an empty hash without a block" do
- @empty.send(@method).should be_an_instance_of(Enumerator)
+ @empty.send(@method).should.instance_of?(Enumerator)
end
it "returns an Enumerator if called on a frozen instance" do
@hsh.freeze
- @hsh.send(@method).should be_an_instance_of(Enumerator)
+ @hsh.send(@method).should.instance_of?(Enumerator)
end
end
diff --git a/spec/ruby/core/hash/shared/key.rb b/spec/ruby/core/hash/shared/key.rb
deleted file mode 100644
index 17f9f81457..0000000000
--- a/spec/ruby/core/hash/shared/key.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-describe :hash_key_p, shared: true do
- it "returns true if argument is a key" do
- h = { a: 1, b: 2, c: 3, 4 => 0 }
- h.send(@method, :a).should == true
- h.send(@method, :b).should == true
- h.send(@method, 2).should == false
- h.send(@method, 4).should == true
-
- not_supported_on :opal do
- h.send(@method, 'b').should == false
- h.send(@method, 4.0).should == false
- end
- end
-
- it "returns true if the key's matching value was nil" do
- { xyz: nil }.send(@method, :xyz).should == true
- end
-
- it "returns true if the key's matching value was false" do
- { xyz: false }.send(@method, :xyz).should == true
- end
-
- it "returns true if the key is nil" do
- { nil => 'b' }.send(@method, nil).should == true
- { nil => nil }.send(@method, nil).should == true
- end
-
- it "compares keys with the same #hash value via #eql?" do
- x = mock('x')
- x.stub!(:hash).and_return(42)
-
- y = mock('y')
- y.stub!(:hash).and_return(42)
- y.should_receive(:eql?).and_return(false)
-
- { x => nil }.send(@method, y).should == false
- end
-end
diff --git a/spec/ruby/core/hash/shared/length.rb b/spec/ruby/core/hash/shared/length.rb
deleted file mode 100644
index 24f5563759..0000000000
--- a/spec/ruby/core/hash/shared/length.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-describe :hash_length, shared: true do
- it "returns the number of entries" do
- { a: 1, b: 'c' }.send(@method).should == 2
- h = { a: 1, b: 2 }
- h[:a] = 2
- h.send(@method).should == 2
- { a: 1, b: 1, c: 1 }.send(@method).should == 3
- {}.send(@method).should == 0
- Hash.new(5).send(@method).should == 0
- Hash.new { 5 }.send(@method).should == 0
- end
-end
diff --git a/spec/ruby/core/hash/shared/less_than.rb b/spec/ruby/core/hash/shared/less_than.rb
index cdc6f14546..071b3e97bb 100644
--- a/spec/ruby/core/hash/shared/less_than.rb
+++ b/spec/ruby/core/hash/shared/less_than.rb
@@ -5,11 +5,11 @@ describe :hash_less_than, shared: true do
end
it "returns true if self is a subset of the other hash" do
- @h1.send(@method, @h2).should be_true
+ @h1.send(@method, @h2).should == true
end
it "returns false if self is not a subset of the other hash" do
- @h2.send(@method, @h1).should be_false
+ @h2.send(@method, @h1).should == false
end
it "converts the right operand to a hash before comparing" do
@@ -18,6 +18,6 @@ describe :hash_less_than, shared: true do
{ a: 1, b: 2, c: 3 }
end
- @h1.send(@method, o).should be_true
+ @h1.send(@method, o).should == true
end
end
diff --git a/spec/ruby/core/hash/shared/replace.rb b/spec/ruby/core/hash/shared/replace.rb
deleted file mode 100644
index bea64384bb..0000000000
--- a/spec/ruby/core/hash/shared/replace.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-describe :hash_replace, shared: true do
- it "replaces the contents of self with other" do
- h = { a: 1, b: 2 }
- h.send(@method, c: -1, d: -2).should equal(h)
- h.should == { c: -1, d: -2 }
- end
-
- it "tries to convert the passed argument to a hash using #to_hash" do
- obj = mock('{1=>2,3=>4}')
- obj.should_receive(:to_hash).and_return({ 1 => 2, 3 => 4 })
-
- h = {}
- h.send(@method, obj)
- h.should == { 1 => 2, 3 => 4 }
- end
-
- it "calls to_hash on hash subclasses" do
- h = {}
- h.send(@method, HashSpecs::ToHashHash[1 => 2])
- h.should == { 1 => 2 }
- end
-
- it "does not transfer default values" do
- hash_a = {}
- hash_b = Hash.new(5)
- hash_a.send(@method, hash_b)
- hash_a.default.should == 5
-
- hash_a = {}
- hash_b = Hash.new { |h, k| k * 2 }
- hash_a.send(@method, hash_b)
- hash_a.default(5).should == 10
-
- hash_a = Hash.new { |h, k| k * 5 }
- hash_b = Hash.new(-> { raise "Should not invoke lambda" })
- hash_a.send(@method, hash_b)
- hash_a.default.should == hash_b.default
- end
-
- it "raises a FrozenError if called on a frozen instance that would not be modified" do
- -> do
- HashSpecs.frozen_hash.send(@method, HashSpecs.frozen_hash)
- end.should raise_error(FrozenError)
- end
-
- it "raises a FrozenError if called on a frozen instance that is modified" do
- -> do
- HashSpecs.frozen_hash.send(@method, HashSpecs.empty_frozen_hash)
- end.should raise_error(FrozenError)
- end
-end
diff --git a/spec/ruby/core/hash/shared/select.rb b/spec/ruby/core/hash/shared/select.rb
deleted file mode 100644
index 5170af50d6..0000000000
--- a/spec/ruby/core/hash/shared/select.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-require_relative '../../../spec_helper'
-require_relative '../fixtures/classes'
-require_relative '../shared/iteration'
-require_relative '../../enumerable/shared/enumeratorized'
-
-describe :hash_select, shared: true do
- before :each do
- @hsh = { 1 => 2, 3 => 4, 5 => 6 }
- @empty = {}
- end
-
- it "yields two arguments: key and value" do
- all_args = []
- { 1 => 2, 3 => 4 }.send(@method) { |*args| all_args << args }
- all_args.sort.should == [[1, 2], [3, 4]]
- end
-
- it "returns a Hash of entries for which block is true" do
- a_pairs = { 'a' => 9, 'c' => 4, 'b' => 5, 'd' => 2 }.send(@method) { |k,v| v % 2 == 0 }
- a_pairs.should be_an_instance_of(Hash)
- a_pairs.sort.should == [['c', 4], ['d', 2]]
- end
-
- it "processes entries with the same order as reject" do
- h = { a: 9, c: 4, b: 5, d: 2 }
-
- select_pairs = []
- reject_pairs = []
- h.dup.send(@method) { |*pair| select_pairs << pair }
- h.reject { |*pair| reject_pairs << pair }
-
- select_pairs.should == reject_pairs
- end
-
- it "returns an Enumerator when called on a non-empty hash without a block" do
- @hsh.send(@method).should be_an_instance_of(Enumerator)
- end
-
- it "returns an Enumerator when called on an empty hash without a block" do
- @empty.send(@method).should be_an_instance_of(Enumerator)
- end
-
- it_should_behave_like :hash_iteration_no_block
-
- before :each do
- @object = { 1 => 2, 3 => 4, 5 => 6 }
- end
- it_should_behave_like :enumeratorized_with_origin_size
-end
-
-describe :hash_select!, shared: true do
- before :each do
- @hsh = { 1 => 2, 3 => 4, 5 => 6 }
- @empty = {}
- end
-
- it "is equivalent to keep_if if changes are made" do
- h = { a: 2 }
- h.send(@method) { |k,v| v <= 1 }.should equal h
-
- h = { 1 => 2, 3 => 4 }
- all_args_select = []
- h.dup.send(@method) { |*args| all_args_select << args }
- all_args_select.should == [[1, 2], [3, 4]]
- end
-
- it "removes all entries if the block is false" do
- h = { a: 1, b: 2, c: 3 }
- h.send(@method) { |k,v| false }.should equal(h)
- h.should == {}
- end
-
- it "returns nil if no changes were made" do
- { a: 1 }.send(@method) { |k,v| v <= 1 }.should == nil
- end
-
- it "raises a FrozenError if called on an empty frozen instance" do
- -> { HashSpecs.empty_frozen_hash.send(@method) { false } }.should raise_error(FrozenError)
- end
-
- it "raises a FrozenError if called on a frozen instance that would not be modified" do
- -> { HashSpecs.frozen_hash.send(@method) { true } }.should raise_error(FrozenError)
- end
-
- it_should_behave_like :hash_iteration_no_block
-
- before :each do
- @object = { 1 => 2, 3 => 4, 5 => 6 }
- end
- it_should_behave_like :enumeratorized_with_origin_size
-end
diff --git a/spec/ruby/core/hash/shared/store.rb b/spec/ruby/core/hash/shared/store.rb
deleted file mode 100644
index b823ea45ca..0000000000
--- a/spec/ruby/core/hash/shared/store.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :hash_store, shared: true do
- it "associates the key with the value and return the value" do
- h = { a: 1 }
- h.send(@method, :b, 2).should == 2
- h.should == { b:2, a:1 }
- end
-
- it "duplicates string keys using dup semantics" do
- # dup doesn't copy singleton methods
- key = "foo"
- def key.reverse() "bar" end
- h = {}
- h.send(@method, key, 0)
- h.keys[0].reverse.should == "oof"
- end
-
- it "stores unequal keys that hash to the same value" do
- h = {}
- k1 = ["x"]
- k2 = ["y"]
- # So they end up in the same bucket
- k1.should_receive(:hash).and_return(0)
- k2.should_receive(:hash).and_return(0)
-
- h.send(@method, k1, 1)
- h.send(@method, k2, 2)
- h.size.should == 2
- end
-
- it "accepts keys with private #hash method" do
- key = HashSpecs::KeyWithPrivateHash.new
- h = {}
- h.send(@method, key, "foo")
- h[key].should == "foo"
- end
-
- it " accepts keys with an Integer hash" do
- o = mock(hash: 1 << 100)
- h = {}
- h[o] = 1
- h[o].should == 1
- end
-
- it "duplicates and freezes string keys" do
- key = "foo"
- h = {}
- h.send(@method, key, 0)
- key << "bar"
-
- h.should == { "foo" => 0 }
- h.keys[0].should.frozen?
- end
-
- it "doesn't duplicate and freeze already frozen string keys" do
- key = "foo".freeze
- h = {}
- h.send(@method, key, 0)
- h.keys[0].should equal(key)
- end
-
- it "keeps the existing key in the hash if there is a matching one" do
- h = { "a" => 1, "b" => 2, "c" => 3, "d" => 4 }
- key1 = HashSpecs::ByValueKey.new(13)
- key2 = HashSpecs::ByValueKey.new(13)
- h[key1] = 41
- key_in_hash = h.keys.last
- key_in_hash.should equal(key1)
- h[key2] = 42
- last_key = h.keys.last
- last_key.should equal(key_in_hash)
- last_key.should_not equal(key2)
- end
-
- it "keeps the existing String key in the hash if there is a matching one" do
- h = { "a" => 1, "b" => 2, "c" => 3, "d" => 4 }
- key1 = "foo"
- key2 = "foo"
- key1.should_not equal(key2)
- h[key1] = 41
- frozen_key = h.keys.last
- frozen_key.should_not equal(key1)
- h[key2] = 42
- h.keys.last.should equal(frozen_key)
- h.keys.last.should_not equal(key2)
- end
-
- it "raises a FrozenError if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.send(@method, 1, 2) }.should raise_error(FrozenError)
- end
-
- it "does not raise an exception if changing the value of an existing key during iteration" do
- hash = {1 => 2, 3 => 4, 5 => 6}
- hash.each { hash.send(@method, 1, :foo) }
- hash.should == {1 => :foo, 3 => 4, 5 => 6}
- end
-
- it "does not dispatch to hash for Boolean, Integer, Float, String, or Symbol" do
- code = <<-EOC
- load '#{fixture __FILE__, "name.rb"}'
- hash = {}
- [true, false, 1, 2.0, "hello", :ok].each do |value|
- hash[value] = 42
- raise "incorrect value" unless hash[value] == 42
- hash[value] = 43
- raise "incorrect value" unless hash[value] == 43
- end
- puts "OK"
- puts hash.size
- EOC
- result = ruby_exe(code, args: "2>&1")
- result.should == "OK\n6\n"
- end
-end
diff --git a/spec/ruby/core/hash/shared/to_s.rb b/spec/ruby/core/hash/shared/to_s.rb
deleted file mode 100644
index 2db3a96583..0000000000
--- a/spec/ruby/core/hash/shared/to_s.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-require_relative '../../../spec_helper'
-require_relative '../fixtures/classes'
-
-describe :hash_to_s, shared: true do
- it "returns a string representation with same order as each()" do
- h = { a: [1, 2], b: -2, d: -6, nil => nil }
-
- pairs = []
- h.each do |key, value|
- pairs << key.inspect + '=>' + value.inspect
- end
-
- str = '{' + pairs.join(', ') + '}'
- h.send(@method).should == str
- end
-
- it "calls #inspect on keys and values" do
- key = mock('key')
- val = mock('val')
- key.should_receive(:inspect).and_return('key')
- val.should_receive(:inspect).and_return('val')
-
- { key => val }.send(@method).should == '{key=>val}'
- end
-
- it "does not call #to_s on a String returned from #inspect" do
- str = "abc"
- str.should_not_receive(:to_s)
-
- { a: str }.send(@method).should == '{:a=>"abc"}'
- end
-
- it "calls #to_s on the object returned from #inspect if the Object isn't a String" do
- obj = mock("Hash#inspect/to_s calls #to_s")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_receive(:to_s).and_return("abc")
-
- { a: obj }.send(@method).should == "{:a=>abc}"
- end
-
- it "does not call #to_str on the object returned from #inspect when it is not a String" do
- obj = mock("Hash#inspect/to_s does not call #to_str")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_not_receive(:to_str)
-
- { a: obj }.send(@method).should =~ /^\{:a=>#<MockObject:0x[0-9a-f]+>\}$/
- end
-
- it "does not call #to_str on the object returned from #to_s when it is not a String" do
- obj = mock("Hash#inspect/to_s does not call #to_str on #to_s result")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_receive(:to_s).and_return(obj)
- obj.should_not_receive(:to_str)
-
- { a: obj }.send(@method).should =~ /^\{:a=>#<MockObject:0x[0-9a-f]+>\}$/
- end
-
- it "does not swallow exceptions raised by #to_s" do
- obj = mock("Hash#inspect/to_s does not swallow #to_s exceptions")
- obj.should_receive(:inspect).and_return(obj)
- obj.should_receive(:to_s).and_raise(Exception)
-
- -> { { a: obj }.send(@method) }.should raise_error(Exception)
- end
-
- it "handles hashes with recursive values" do
- x = {}
- x[0] = x
- x.send(@method).should == '{0=>{...}}'
-
- x = {}
- y = {}
- x[0] = y
- y[1] = x
- x.send(@method).should == "{0=>{1=>{...}}}"
- y.send(@method).should == "{1=>{0=>{...}}}"
- end
-
- it "does not raise if inspected result is not default external encoding" do
- utf_16be = mock("utf_16be")
- utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
-
- {a: utf_16be}.send(@method).should == '{:a=>"utf_16be \u3042"}'
- end
-
- it "works for keys and values whose #inspect return a frozen String" do
- { true => false }.to_s.should == "{true=>false}"
- end
-end
diff --git a/spec/ruby/core/hash/shared/update.rb b/spec/ruby/core/hash/shared/update.rb
deleted file mode 100644
index 1b0eb809bf..0000000000
--- a/spec/ruby/core/hash/shared/update.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-describe :hash_update, shared: true do
- it "adds the entries from other, overwriting duplicate keys. Returns self" do
- h = { _1: 'a', _2: '3' }
- h.send(@method, _1: '9', _9: 2).should equal(h)
- h.should == { _1: "9", _2: "3", _9: 2 }
- end
-
- it "sets any duplicate key to the value of block if passed a block" do
- h1 = { a: 2, b: -1 }
- h2 = { a: -2, c: 1 }
- h1.send(@method, h2) { |k,x,y| 3.14 }.should equal(h1)
- h1.should == { c: 1, b: -1, a: 3.14 }
-
- h1.send(@method, h1) { nil }
- h1.should == { a: nil, b: nil, c: nil }
- end
-
- it "tries to convert the passed argument to a hash using #to_hash" do
- obj = mock('{1=>2}')
- obj.should_receive(:to_hash).and_return({ 1 => 2 })
- { 3 => 4 }.send(@method, obj).should == { 1 => 2, 3 => 4 }
- end
-
- it "does not call to_hash on hash subclasses" do
- { 3 => 4 }.send(@method, HashSpecs::ToHashHash[1 => 2]).should == { 1 => 2, 3 => 4 }
- end
-
- it "processes entries with same order as merge()" do
- h = { 1 => 2, 3 => 4, 5 => 6, "x" => nil, nil => 5, [] => [] }
- merge_bang_pairs = []
- merge_pairs = []
- h.merge(h) { |*arg| merge_pairs << arg }
- h.send(@method, h) { |*arg| merge_bang_pairs << arg }
- merge_bang_pairs.should == merge_pairs
- end
-
- it "raises a FrozenError on a frozen instance that is modified" do
- -> do
- HashSpecs.frozen_hash.send(@method, 1 => 2)
- end.should raise_error(FrozenError)
- end
-
- it "checks frozen status before coercing an object with #to_hash" do
- obj = mock("to_hash frozen")
- # This is necessary because mock cleanup code cannot run on the frozen
- # object.
- def obj.to_hash() raise Exception, "should not receive #to_hash" end
- obj.freeze
-
- -> { HashSpecs.frozen_hash.send(@method, obj) }.should raise_error(FrozenError)
- end
-
- # see redmine #1571
- it "raises a FrozenError on a frozen instance that would not be modified" do
- -> do
- HashSpecs.frozen_hash.send(@method, HashSpecs.empty_frozen_hash)
- end.should raise_error(FrozenError)
- end
-
- it "does not raise an exception if changing the value of an existing key during iteration" do
- hash = {1 => 2, 3 => 4, 5 => 6}
- hash2 = {1 => :foo, 3 => :bar}
- hash.each { hash.send(@method, hash2) }
- hash.should == {1 => :foo, 3 => :bar, 5 => 6}
- end
-
- it "accepts multiple hashes" do
- result = { a: 1 }.send(@method, { b: 2 }, { c: 3 }, { d: 4 })
- result.should == { a: 1, b: 2, c: 3, d: 4 }
- end
-
- it "accepts zero arguments" do
- hash = { a: 1 }
- hash.send(@method).should eql(hash)
- end
-end
diff --git a/spec/ruby/core/hash/shared/value.rb b/spec/ruby/core/hash/shared/value.rb
deleted file mode 100644
index aac76c253e..0000000000
--- a/spec/ruby/core/hash/shared/value.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-describe :hash_value_p, shared: true do
- it "returns true if the value exists in the hash" do
- { a: :b }.send(@method, :a).should == false
- { 1 => 2 }.send(@method, 2).should == true
- h = Hash.new(5)
- h.send(@method, 5).should == false
- h = Hash.new { 5 }
- h.send(@method, 5).should == false
- end
-
- it "uses == semantics for comparing values" do
- { 5 => 2.0 }.send(@method, 2).should == true
- end
-end
diff --git a/spec/ruby/core/hash/shared/values_at.rb b/spec/ruby/core/hash/shared/values_at.rb
deleted file mode 100644
index ef3b0e8ba0..0000000000
--- a/spec/ruby/core/hash/shared/values_at.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-describe :hash_values_at, shared: true do
- it "returns an array of values for the given keys" do
- h = { a: 9, b: 'a', c: -10, d: nil }
- h.send(@method).should be_kind_of(Array)
- h.send(@method).should == []
- h.send(@method, :a, :d, :b).should be_kind_of(Array)
- h.send(@method, :a, :d, :b).should == [9, nil, 'a']
- end
-end
diff --git a/spec/ruby/core/hash/shift_spec.rb b/spec/ruby/core/hash/shift_spec.rb
index ea36488a04..6095d2e55f 100644
--- a/spec/ruby/core/hash/shift_spec.rb
+++ b/spec/ruby/core/hash/shift_spec.rb
@@ -8,7 +8,7 @@ describe "Hash#shift" do
h.size.times do |i|
r = h.shift
- r.should be_kind_of(Array)
+ r.should.is_a?(Array)
h2[r.first].should == r.last
h.size.should == h2.size - i - 1
end
@@ -30,45 +30,22 @@ describe "Hash#shift" do
h.should == {}
end
- ruby_version_is '3.2' do
- it "returns nil if the Hash is empty" do
- h = {}
- def h.default(key)
- raise
- end
- h.shift.should == nil
- end
- end
-
- ruby_version_is ''...'3.2' do
- it "calls #default with nil if the Hash is empty" do
- h = {}
- def h.default(key)
- key.should == nil
- :foo
- end
- h.shift.should == :foo
+ it "returns nil if the Hash is empty" do
+ h = {}
+ def h.default(key)
+ raise
end
+ h.shift.should == nil
end
it "returns nil from an empty hash" do
{}.shift.should == nil
end
- ruby_version_is '3.2' do
- it "returns nil for empty hashes with defaults and default procs" do
- Hash.new(5).shift.should == nil
- h = Hash.new { |*args| args }
- h.shift.should == nil
- end
- end
-
- ruby_version_is ''...'3.2' do
- it "returns (computed) default for empty hashes" do
- Hash.new(5).shift.should == 5
- h = Hash.new { |*args| args }
- h.shift.should == [h, nil]
- end
+ it "returns nil for empty hashes with defaults and default procs" do
+ Hash.new(5).shift.should == nil
+ h = Hash.new { |*args| args }
+ h.shift.should == nil
end
it "preserves Hash invariants when removing the last item" do
@@ -80,8 +57,8 @@ describe "Hash#shift" do
end
it "raises a FrozenError if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.shift }.should raise_error(FrozenError)
- -> { HashSpecs.empty_frozen_hash.shift }.should raise_error(FrozenError)
+ -> { HashSpecs.frozen_hash.shift }.should.raise(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.shift }.should.raise(FrozenError)
end
it "works when the hash is at capacity" do
diff --git a/spec/ruby/core/hash/size_spec.rb b/spec/ruby/core/hash/size_spec.rb
index 1e8abd8d97..5e5008a5dc 100644
--- a/spec/ruby/core/hash/size_spec.rb
+++ b/spec/ruby/core/hash/size_spec.rb
@@ -1,7 +1,14 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/length'
describe "Hash#size" do
- it_behaves_like :hash_length, :size
+ it "returns the number of entries" do
+ { a: 1, b: 'c' }.size.should == 2
+ h = { a: 1, b: 2 }
+ h[:a] = 2
+ h.size.should == 2
+ { a: 1, b: 1, c: 1 }.size.should == 3
+ {}.size.should == 0
+ Hash.new(5).size.should == 0
+ Hash.new { 5 }.size.should == 0
+ end
end
diff --git a/spec/ruby/core/hash/slice_spec.rb b/spec/ruby/core/hash/slice_spec.rb
index e3046d83d7..fd93254517 100644
--- a/spec/ruby/core/hash/slice_spec.rb
+++ b/spec/ruby/core/hash/slice_spec.rb
@@ -7,8 +7,8 @@ describe "Hash#slice" do
it "returns a new empty hash without arguments" do
ret = @hash.slice
- ret.should_not equal(@hash)
- ret.should be_an_instance_of(Hash)
+ ret.should_not.equal?(@hash)
+ ret.should.instance_of?(Hash)
ret.should == {}
end
@@ -50,4 +50,25 @@ describe "Hash#slice" do
ScratchPad.recorded.should == []
end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.slice(:a).default.should == nil
+ h[:a] = 1
+ h.slice(:a).default.should == nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.slice(:a).default_proc.should == nil
+ h[:a] = 1
+ h.slice(:a).default_proc.should == nil
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.slice(:a)
+ h2.compare_by_identity?.should == true
+ end
end
diff --git a/spec/ruby/core/hash/store_spec.rb b/spec/ruby/core/hash/store_spec.rb
index 7e975380ec..7017d8ba2b 100644
--- a/spec/ruby/core/hash/store_spec.rb
+++ b/spec/ruby/core/hash/store_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/store'
describe "Hash#store" do
- it_behaves_like :hash_store, :store
+ it "is an alias of Hash#[]=" do
+ Hash.instance_method(:store).should == Hash.instance_method(:[]=)
+ end
end
diff --git a/spec/ruby/core/hash/to_a_spec.rb b/spec/ruby/core/hash/to_a_spec.rb
index 8b7894a2ba..8c638db6c3 100644
--- a/spec/ruby/core/hash/to_a_spec.rb
+++ b/spec/ruby/core/hash/to_a_spec.rb
@@ -10,7 +10,7 @@ describe "Hash#to_a" do
pairs << [key, value]
end
- h.to_a.should be_kind_of(Array)
+ h.to_a.should.is_a?(Array)
h.to_a.should == pairs
end
@@ -23,17 +23,7 @@ describe "Hash#to_a" do
end
ent = h.entries
- ent.should be_kind_of(Array)
+ ent.should.is_a?(Array)
ent.should == pairs
end
-
- ruby_version_is ''...'3.0' do
- it "returns a not tainted array if self is tainted" do
- {}.taint.to_a.tainted?.should be_false
- end
-
- it "returns a trusted array if self is untrusted" do
- {}.untrust.to_a.untrusted?.should be_false
- end
- end
end
diff --git a/spec/ruby/core/hash/to_h_spec.rb b/spec/ruby/core/hash/to_h_spec.rb
index 75ebce68b1..5d5a280dac 100644
--- a/spec/ruby/core/hash/to_h_spec.rb
+++ b/spec/ruby/core/hash/to_h_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
describe "Hash#to_h" do
it "returns self for Hash instances" do
h = {}
- h.to_h.should equal(h)
+ h.to_h.should.equal?(h)
end
describe "when called on a subclass of Hash" do
@@ -14,22 +14,27 @@ describe "Hash#to_h" do
end
it "returns a new Hash instance" do
- @h.to_h.should be_an_instance_of(Hash)
+ @h.to_h.should.instance_of?(Hash)
@h.to_h.should == @h
@h[:foo].should == :bar
end
- it "copies the default" do
+ it "retains the default" do
@h.default = 42
@h.to_h.default.should == 42
@h[:hello].should == 42
end
- it "copies the default_proc" do
+ it "retains the default_proc" do
@h.default_proc = prc = Proc.new{ |h, k| h[k] = 2 * k }
@h.to_h.default_proc.should == prc
@h[42].should == 84
end
+
+ it "retains compare_by_identity flag" do
+ @h.compare_by_identity
+ @h.to_h.compare_by_identity?.should == true
+ end
end
context "with block" do
@@ -37,20 +42,30 @@ describe "Hash#to_h" do
{ a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v]}.should == { "a" => 1, "b" => 4 }
end
+ it "passes to a block each pair's key and value as separate arguments" do
+ ScratchPad.record []
+ { a: 1, b: 2 }.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
+ ScratchPad.recorded.sort.should == [[:a, 1], [:b, 2]]
+
+ ScratchPad.record []
+ { a: 1, b: 2 }.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[:a, 1], [:b, 2]]
+ end
+
it "raises ArgumentError if block returns longer or shorter array" do
-> do
{ a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v, 1] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
+ end.should.raise(ArgumentError, /element has wrong array length/)
-> do
{ a: 1, b: 2 }.to_h { |k, v| [k] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
+ end.should.raise(ArgumentError, /element has wrong array length/)
end
it "raises TypeError if block returns something other than Array" do
-> do
{ a: 1, b: 2 }.to_h { |k, v| "not-array" }
- end.should raise_error(TypeError, /wrong element type String/)
+ end.should.raise(TypeError, /wrong element type String/)
end
it "coerces returned pair to Array with #to_ary" do
@@ -66,7 +81,26 @@ describe "Hash#to_h" do
-> do
{ a: 1 }.to_h { |k| x }
- end.should raise_error(TypeError, /wrong element type MockObject/)
+ end.should.raise(TypeError, /wrong element type MockObject/)
+ end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h2 = h.to_h { |k, v| [k.to_s, v*v]}
+ h2.default.should == nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h2 = h.to_h { |k, v| [k.to_s, v*v]}
+ h2.default_proc.should == nil
+ end
+
+ it "does not retain compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.to_h { |k, v| [k.to_s, v*v]}
+ h2.compare_by_identity?.should == false
end
end
end
diff --git a/spec/ruby/core/hash/to_hash_spec.rb b/spec/ruby/core/hash/to_hash_spec.rb
index f479fa1fb2..f5622b3d9c 100644
--- a/spec/ruby/core/hash/to_hash_spec.rb
+++ b/spec/ruby/core/hash/to_hash_spec.rb
@@ -4,11 +4,11 @@ require_relative 'fixtures/classes'
describe "Hash#to_hash" do
it "returns self for Hash instances" do
h = {}
- h.to_hash.should equal(h)
+ h.to_hash.should.equal?(h)
end
it "returns self for instances of subclasses of Hash" do
h = HashSpecs::MyHash.new
- h.to_hash.should equal(h)
+ h.to_hash.should.equal?(h)
end
end
diff --git a/spec/ruby/core/hash/to_proc_spec.rb b/spec/ruby/core/hash/to_proc_spec.rb
index 8f5d21beb5..bc4756600d 100644
--- a/spec/ruby/core/hash/to_proc_spec.rb
+++ b/spec/ruby/core/hash/to_proc_spec.rb
@@ -11,7 +11,7 @@ describe "Hash#to_proc" do
end
it "returns an instance of Proc" do
- @hash.to_proc.should be_an_instance_of Proc
+ @hash.to_proc.should.instance_of? Proc
end
describe "the returned proc" do
@@ -19,41 +19,33 @@ describe "Hash#to_proc" do
@proc = @hash.to_proc
end
- ruby_version_is ""..."3.0" do
- it "is not a lambda" do
- @proc.should_not.lambda?
- end
+ it "is a lambda" do
+ @proc.should.lambda?
end
- ruby_version_is "3.0" do
- it "is a lambda" do
- @proc.should.lambda?
- end
-
- it "has an arity of 1" do
- @proc.arity.should == 1
- end
+ it "has an arity of 1" do
+ @proc.arity.should == 1
end
it "raises ArgumentError if not passed exactly one argument" do
-> {
@proc.call
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@proc.call 1, 2
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
context "with a stored key" do
it "returns the paired value" do
- @proc.call(@key).should equal(@value)
+ @proc.call(@key).should.equal?(@value)
end
end
context "passed as a block" do
it "retrieves the hash's values" do
- [@key].map(&@proc)[0].should equal(@value)
+ [@key].map(&@proc)[0].should.equal?(@value)
end
context "to instance_exec" do
@@ -71,7 +63,7 @@ describe "Hash#to_proc" do
context "with no stored key" do
it "returns nil" do
- @proc.call(@unstored).should be_nil
+ @proc.call(@unstored).should == nil
end
context "when the hash has a default value" do
@@ -80,7 +72,7 @@ describe "Hash#to_proc" do
end
it "returns the default value" do
- @proc.call(@unstored).should equal(@default)
+ @proc.call(@unstored).should.equal?(@default)
end
end
@@ -93,7 +85,7 @@ describe "Hash#to_proc" do
end
it "raises an ArgumentError when calling #call on the Proc with no arguments" do
- -> { @hash.to_proc.call }.should raise_error(ArgumentError)
+ -> { @hash.to_proc.call }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/hash/to_s_spec.rb b/spec/ruby/core/hash/to_s_spec.rb
index e52b09962e..2915db6ef8 100644
--- a/spec/ruby/core/hash/to_s_spec.rb
+++ b/spec/ruby/core/hash/to_s_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/to_s'
describe "Hash#to_s" do
- it_behaves_like :hash_to_s, :to_s
+ it "is an alias of Hash#inspect" do
+ Hash.instance_method(:to_s).should == Hash.instance_method(:inspect)
+ end
end
diff --git a/spec/ruby/core/hash/transform_keys_spec.rb b/spec/ruby/core/hash/transform_keys_spec.rb
index 361089ca97..d37a2b8616 100644
--- a/spec/ruby/core/hash/transform_keys_spec.rb
+++ b/spec/ruby/core/hash/transform_keys_spec.rb
@@ -7,8 +7,8 @@ describe "Hash#transform_keys" do
it "returns new hash" do
ret = @hash.transform_keys(&:succ)
- ret.should_not equal(@hash)
- ret.should be_an_instance_of(Hash)
+ ret.should_not.equal?(@hash)
+ ret.should.instance_of?(Hash)
end
it "sets the result as transformed keys with the given block" do
@@ -22,13 +22,13 @@ describe "Hash#transform_keys" do
it "makes both hashes to share values" do
value = [1, 2, 3]
new_hash = { a: value }.transform_keys(&:upcase)
- new_hash[:A].should equal(value)
+ new_hash[:A].should.equal?(value)
end
context "when no block is given" do
it "returns a sized Enumerator" do
enumerator = @hash.transform_keys
- enumerator.should be_an_instance_of(Enumerator)
+ enumerator.should.instance_of?(Enumerator)
enumerator.size.should == @hash.size
enumerator.each(&:succ).should == { b: 1, c: 2, d: 3 }
end
@@ -43,18 +43,37 @@ describe "Hash#transform_keys" do
r.class.should == Hash
end
- ruby_version_is "3.0" do
- it "allows a hash argument" do
- @hash.transform_keys({ a: :A, b: :B, c: :C }).should == { A: 1, B: 2, C: 3 }
- end
+ it "allows a hash argument" do
+ @hash.transform_keys({ a: :A, b: :B, c: :C }).should == { A: 1, B: 2, C: 3 }
+ end
- it "allows a partial transformation of keys when using a hash argument" do
- @hash.transform_keys({ a: :A, c: :C }).should == { A: 1, b: 2, C: 3 }
- end
+ it "allows a partial transformation of keys when using a hash argument" do
+ @hash.transform_keys({ a: :A, c: :C }).should == { A: 1, b: 2, C: 3 }
+ end
- it "allows a combination of hash and block argument" do
- @hash.transform_keys({ a: :A }, &:to_s).should == { A: 1, 'b' => 2, 'c' => 3 }
- end
+ it "allows a combination of hash and block argument" do
+ @hash.transform_keys({ a: :A }, &:to_s).should == { A: 1, 'b' => 2, 'c' => 3 }
+ end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.transform_keys(&:succ).default.should == nil
+ h[:a] = 1
+ h.transform_keys(&:succ).default.should == nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.transform_values(&:succ).default_proc.should == nil
+ h[:a] = 1
+ h.transform_values(&:succ).default_proc.should == nil
+ end
+
+ it "does not retain compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.transform_keys(&:succ)
+ h2.compare_by_identity?.should == false
end
end
@@ -65,7 +84,7 @@ describe "Hash#transform_keys!" do
end
it "returns self" do
- @hash.transform_keys!(&:succ).should equal(@hash)
+ @hash.transform_keys!(&:succ).should.equal?(@hash)
end
it "updates self as transformed values with the given block" do
@@ -78,24 +97,12 @@ describe "Hash#transform_keys!" do
@hash.should == { b: 1, c: 2, d: 3, e: 4 }
end
- ruby_version_is ""..."3.0.2" do # https://bugs.ruby-lang.org/issues/17735
- it "returns the processed keys if we break from the block" do
- @hash.transform_keys! do |v|
- break if v == :c
- v.succ
- end
- @hash.should == { b: 1, c: 2 }
- end
- end
-
- ruby_version_is "3.0.2" do
- it "returns the processed keys and non evaluated keys if we break from the block" do
- @hash.transform_keys! do |v|
- break if v == :c
- v.succ
- end
- @hash.should == { b: 1, c: 2, d: 4 }
+ it "returns the processed keys and non evaluated keys if we break from the block" do
+ @hash.transform_keys! do |v|
+ break if v == :c
+ v.succ
end
+ @hash.should == { b: 1, c: 2, d: 4 }
end
it "keeps later pair if new keys conflict" do
@@ -105,17 +112,15 @@ describe "Hash#transform_keys!" do
context "when no block is given" do
it "returns a sized Enumerator" do
enumerator = @hash.transform_keys!
- enumerator.should be_an_instance_of(Enumerator)
+ enumerator.should.instance_of?(Enumerator)
enumerator.size.should == @hash.size
enumerator.each(&:upcase).should == { A: 1, B: 2, C: 3, D: 4 }
end
end
- ruby_version_is "3.0" do
- it "allows a hash argument" do
- @hash.transform_keys!({ a: :A, b: :B, c: :C, d: :D })
- @hash.should == { A: 1, B: 2, C: 3, D: 4 }
- end
+ it "allows a hash argument" do
+ @hash.transform_keys!({ a: :A, b: :B, c: :C, d: :D })
+ @hash.should == { A: 1, B: 2, C: 3, D: 4 }
end
describe "on frozen instance" do
@@ -124,23 +129,21 @@ describe "Hash#transform_keys!" do
end
it "raises a FrozenError on an empty hash" do
- ->{ {}.freeze.transform_keys!(&:upcase) }.should raise_error(FrozenError)
+ ->{ {}.freeze.transform_keys!(&:upcase) }.should.raise(FrozenError)
end
it "keeps pairs and raises a FrozenError" do
- ->{ @hash.transform_keys!(&:upcase) }.should raise_error(FrozenError)
+ ->{ @hash.transform_keys!(&:upcase) }.should.raise(FrozenError)
@hash.should == @initial_pairs
end
- ruby_version_is "3.0" do
- it "raises a FrozenError on hash argument" do
- ->{ @hash.transform_keys!({ a: :A, b: :B, c: :C }) }.should raise_error(FrozenError)
- end
+ it "raises a FrozenError on hash argument" do
+ ->{ @hash.transform_keys!({ a: :A, b: :B, c: :C }) }.should.raise(FrozenError)
end
context "when no block is given" do
it "does not raise an exception" do
- @hash.transform_keys!.should be_an_instance_of(Enumerator)
+ @hash.transform_keys!.should.instance_of?(Enumerator)
end
end
end
diff --git a/spec/ruby/core/hash/transform_values_spec.rb b/spec/ruby/core/hash/transform_values_spec.rb
index acb469416a..b19543a9f4 100644
--- a/spec/ruby/core/hash/transform_values_spec.rb
+++ b/spec/ruby/core/hash/transform_values_spec.rb
@@ -7,8 +7,8 @@ describe "Hash#transform_values" do
it "returns new hash" do
ret = @hash.transform_values(&:succ)
- ret.should_not equal(@hash)
- ret.should be_an_instance_of(Hash)
+ ret.should_not.equal?(@hash)
+ ret.should.instance_of?(Hash)
end
it "sets the result as transformed values with the given block" do
@@ -19,13 +19,13 @@ describe "Hash#transform_values" do
key = [1, 2, 3]
new_hash = { key => 1 }.transform_values(&:succ)
new_hash[key].should == 2
- new_hash.keys[0].should equal(key)
+ new_hash.keys[0].should.equal?(key)
end
context "when no block is given" do
it "returns a sized Enumerator" do
enumerator = @hash.transform_values
- enumerator.should be_an_instance_of(Enumerator)
+ enumerator.should.instance_of?(Enumerator)
enumerator.size.should == @hash.size
enumerator.each(&:succ).should == { a: 2, b: 3, c: 4 }
end
@@ -39,6 +39,27 @@ describe "Hash#transform_values" do
r[:foo].should == 84
r.class.should == Hash
end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.transform_values(&:succ).default.should == nil
+ h[:a] = 1
+ h.transform_values(&:succ).default.should == nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.transform_values(&:succ).default_proc.should == nil
+ h[:a] = 1
+ h.transform_values(&:succ).default_proc.should == nil
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.transform_values(&:succ)
+ h2.compare_by_identity?.should == true
+ end
end
describe "Hash#transform_values!" do
@@ -48,7 +69,7 @@ describe "Hash#transform_values!" do
end
it "returns self" do
- @hash.transform_values!(&:succ).should equal(@hash)
+ @hash.transform_values!(&:succ).should.equal?(@hash)
end
it "updates self as transformed values with the given block" do
@@ -67,7 +88,7 @@ describe "Hash#transform_values!" do
context "when no block is given" do
it "returns a sized Enumerator" do
enumerator = @hash.transform_values!
- enumerator.should be_an_instance_of(Enumerator)
+ enumerator.should.instance_of?(Enumerator)
enumerator.size.should == @hash.size
enumerator.each(&:succ)
@hash.should == { a: 2, b: 3, c: 4 }
@@ -80,17 +101,17 @@ describe "Hash#transform_values!" do
end
it "raises a FrozenError on an empty hash" do
- ->{ {}.freeze.transform_values!(&:succ) }.should raise_error(FrozenError)
+ ->{ {}.freeze.transform_values!(&:succ) }.should.raise(FrozenError)
end
it "keeps pairs and raises a FrozenError" do
- ->{ @hash.transform_values!(&:succ) }.should raise_error(FrozenError)
+ ->{ @hash.transform_values!(&:succ) }.should.raise(FrozenError)
@hash.should == @initial_pairs
end
context "when no block is given" do
it "does not raise an exception" do
- @hash.transform_values!.should be_an_instance_of(Enumerator)
+ @hash.transform_values!.should.instance_of?(Enumerator)
end
end
end
diff --git a/spec/ruby/core/hash/try_convert_spec.rb b/spec/ruby/core/hash/try_convert_spec.rb
index 44195c5010..c321183356 100644
--- a/spec/ruby/core/hash/try_convert_spec.rb
+++ b/spec/ruby/core/hash/try_convert_spec.rb
@@ -4,47 +4,47 @@ require_relative 'fixtures/classes'
describe "Hash.try_convert" do
it "returns the argument if it's a Hash" do
x = Hash.new
- Hash.try_convert(x).should equal(x)
+ Hash.try_convert(x).should.equal?(x)
end
it "returns the argument if it's a kind of Hash" do
x = HashSpecs::MyHash.new
- Hash.try_convert(x).should equal(x)
+ Hash.try_convert(x).should.equal?(x)
end
it "returns nil when the argument does not respond to #to_hash" do
- Hash.try_convert(Object.new).should be_nil
+ Hash.try_convert(Object.new).should == nil
end
it "sends #to_hash to the argument and returns the result if it's nil" do
obj = mock("to_hash")
obj.should_receive(:to_hash).and_return(nil)
- Hash.try_convert(obj).should be_nil
+ Hash.try_convert(obj).should == nil
end
it "sends #to_hash to the argument and returns the result if it's a Hash" do
x = Hash.new
obj = mock("to_hash")
obj.should_receive(:to_hash).and_return(x)
- Hash.try_convert(obj).should equal(x)
+ Hash.try_convert(obj).should.equal?(x)
end
it "sends #to_hash to the argument and returns the result if it's a kind of Hash" do
x = HashSpecs::MyHash.new
obj = mock("to_hash")
obj.should_receive(:to_hash).and_return(x)
- Hash.try_convert(obj).should equal(x)
+ Hash.try_convert(obj).should.equal?(x)
end
it "sends #to_hash to the argument and raises TypeError if it's not a kind of Hash" do
obj = mock("to_hash")
obj.should_receive(:to_hash).and_return(Object.new)
- -> { Hash.try_convert obj }.should raise_error(TypeError)
+ -> { Hash.try_convert obj }.should raise_consistent_error(TypeError, "can't convert MockObject into Hash (MockObject#to_hash gives Object)")
end
it "does not rescue exceptions raised by #to_hash" do
obj = mock("to_hash")
obj.should_receive(:to_hash).and_raise(RuntimeError)
- -> { Hash.try_convert obj }.should raise_error(RuntimeError)
+ -> { Hash.try_convert obj }.should.raise(RuntimeError)
end
end
diff --git a/spec/ruby/core/hash/update_spec.rb b/spec/ruby/core/hash/update_spec.rb
index 0975045ad1..f3a3e6b4db 100644
--- a/spec/ruby/core/hash/update_spec.rb
+++ b/spec/ruby/core/hash/update_spec.rb
@@ -1,7 +1,79 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/update'
describe "Hash#update" do
- it_behaves_like :hash_update, :update
+ it "adds the entries from other, overwriting duplicate keys. Returns self" do
+ h = { _1: 'a', _2: '3' }
+ h.update(_1: '9', _9: 2).should.equal?(h)
+ h.should == { _1: "9", _2: "3", _9: 2 }
+ end
+
+ it "sets any duplicate key to the value of block if passed a block" do
+ h1 = { a: 2, b: -1 }
+ h2 = { a: -2, c: 1 }
+ h1.update(h2) { |k,x,y| 3.14 }.should.equal?(h1)
+ h1.should == { c: 1, b: -1, a: 3.14 }
+
+ h1.update(h1) { nil }
+ h1.should == { a: nil, b: nil, c: nil }
+ end
+
+ it "tries to convert the passed argument to a hash using #to_hash" do
+ obj = mock('{1=>2}')
+ obj.should_receive(:to_hash).and_return({ 1 => 2 })
+ { 3 => 4 }.update(obj).should == { 1 => 2, 3 => 4 }
+ end
+
+ it "does not call to_hash on hash subclasses" do
+ { 3 => 4 }.update(HashSpecs::ToHashHash[1 => 2]).should == { 1 => 2, 3 => 4 }
+ end
+
+ it "processes entries with same order as merge()" do
+ h = { 1 => 2, 3 => 4, 5 => 6, "x" => nil, nil => 5, [] => [] }
+ merge_bang_pairs = []
+ merge_pairs = []
+ h.merge(h) { |*arg| merge_pairs << arg }
+ h.update(h) { |*arg| merge_bang_pairs << arg }
+ merge_bang_pairs.should == merge_pairs
+ end
+
+ it "raises a FrozenError on a frozen instance that is modified" do
+ -> do
+ HashSpecs.frozen_hash.update(1 => 2)
+ end.should.raise(FrozenError)
+ end
+
+ it "checks frozen status before coercing an object with #to_hash" do
+ obj = mock("to_hash frozen")
+ # This is necessary because mock cleanup code cannot run on the frozen
+ # object.
+ def obj.to_hash() raise Exception, "should not receive #to_hash" end
+ obj.freeze
+
+ -> { HashSpecs.frozen_hash.update(obj) }.should.raise(FrozenError)
+ end
+
+ # see redmine #1571
+ it "raises a FrozenError on a frozen instance that would not be modified" do
+ -> do
+ HashSpecs.frozen_hash.update(HashSpecs.empty_frozen_hash)
+ end.should.raise(FrozenError)
+ end
+
+ it "does not raise an exception if changing the value of an existing key during iteration" do
+ hash = {1 => 2, 3 => 4, 5 => 6}
+ hash2 = {1 => :foo, 3 => :bar}
+ hash.each { hash.update(hash2) }
+ hash.should == {1 => :foo, 3 => :bar, 5 => 6}
+ end
+
+ it "accepts multiple hashes" do
+ result = { a: 1 }.update({ b: 2 }, { c: 3 }, { d: 4 })
+ result.should == { a: 1, b: 2, c: 3, d: 4 }
+ end
+
+ it "accepts zero arguments" do
+ hash = { a: 1 }
+ hash.update.should.eql?(hash)
+ end
end
diff --git a/spec/ruby/core/hash/value_spec.rb b/spec/ruby/core/hash/value_spec.rb
index 0ab16a5d1b..9cfbe576d2 100644
--- a/spec/ruby/core/hash/value_spec.rb
+++ b/spec/ruby/core/hash/value_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/value'
describe "Hash#value?" do
- it_behaves_like :hash_value_p, :value?
+ it "is an alias of Hash#has_value?" do
+ Hash.instance_method(:value?).should == Hash.instance_method(:has_value?)
+ end
end
diff --git a/spec/ruby/core/hash/values_at_spec.rb b/spec/ruby/core/hash/values_at_spec.rb
index b620a279ba..78dcd8df6a 100644
--- a/spec/ruby/core/hash/values_at_spec.rb
+++ b/spec/ruby/core/hash/values_at_spec.rb
@@ -1,7 +1,11 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/values_at'
describe "Hash#values_at" do
- it_behaves_like :hash_values_at, :values_at
+ it "returns an array of values for the given keys" do
+ h = { a: 9, b: 'a', c: -10, d: nil }
+ h.values_at.should.is_a?(Array)
+ h.values_at.should == []
+ h.values_at(:a, :d, :b).should.is_a?(Array)
+ h.values_at(:a, :d, :b).should == [9, nil, 'a']
+ end
end
diff --git a/spec/ruby/core/hash/values_spec.rb b/spec/ruby/core/hash/values_spec.rb
index 9f2a481a48..1fe5f48ad6 100644
--- a/spec/ruby/core/hash/values_spec.rb
+++ b/spec/ruby/core/hash/values_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
describe "Hash#values" do
it "returns an array of values" do
h = { 1 => :a, 'a' => :a, 'the' => 'lang' }
- h.values.should be_kind_of(Array)
+ h.values.should.is_a?(Array)
h.values.sort {|a, b| a.to_s <=> b.to_s}.should == [:a, :a, 'lang']
end
end
diff --git a/spec/ruby/core/integer/allbits_spec.rb b/spec/ruby/core/integer/allbits_spec.rb
index edce4b15e7..6023cc32bf 100644
--- a/spec/ruby/core/integer/allbits_spec.rb
+++ b/spec/ruby/core/integer/allbits_spec.rb
@@ -30,8 +30,8 @@ describe "Integer#allbits?" do
-> {
(obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10])
13.allbits?(obj)
- }.should raise_error(TypeError)
- -> { 13.allbits?("10") }.should raise_error(TypeError)
- -> { 13.allbits?(:symbol) }.should raise_error(TypeError)
+ }.should.raise(TypeError)
+ -> { 13.allbits?("10") }.should.raise(TypeError)
+ -> { 13.allbits?(:symbol) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/integer/anybits_spec.rb b/spec/ruby/core/integer/anybits_spec.rb
index e0449074a2..1ea47b76dc 100644
--- a/spec/ruby/core/integer/anybits_spec.rb
+++ b/spec/ruby/core/integer/anybits_spec.rb
@@ -29,8 +29,8 @@ describe "Integer#anybits?" do
-> {
(obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10])
13.anybits?(obj)
- }.should raise_error(TypeError)
- -> { 13.anybits?("10") }.should raise_error(TypeError)
- -> { 13.anybits?(:symbol) }.should raise_error(TypeError)
+ }.should.raise(TypeError)
+ -> { 13.anybits?("10") }.should.raise(TypeError)
+ -> { 13.anybits?(:symbol) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/integer/bit_and_spec.rb b/spec/ruby/core/integer/bit_and_spec.rb
index 8de5a14aaa..4098ad7c7b 100644
--- a/spec/ruby/core/integer/bit_and_spec.rb
+++ b/spec/ruby/core/integer/bit_and_spec.rb
@@ -30,19 +30,19 @@ describe "Integer#&" do
it "coerces the rhs and calls #coerce" do
obj = mock("fixnum bit and")
- obj.should_receive(:coerce).with(6).and_return([3, 6])
+ obj.should_receive(:coerce).with(6).and_return([6, 3])
(6 & obj).should == 2
end
it "raises a TypeError when passed a Float" do
- -> { (3 & 3.4) }.should raise_error(TypeError)
+ -> { (3 & 3.4) }.should.raise(TypeError)
end
it "raises a TypeError and does not call #to_int when defined on an object" do
obj = mock("fixnum bit and")
obj.should_not_receive(:to_int)
- -> { 3 & obj }.should raise_error(TypeError)
+ -> { 3 & obj }.should.raise(TypeError)
end
end
@@ -84,14 +84,14 @@ describe "Integer#&" do
end
it "raises a TypeError when passed a Float" do
- -> { (@bignum & 3.4) }.should raise_error(TypeError)
+ -> { (@bignum & 3.4) }.should.raise(TypeError)
end
it "raises a TypeError and does not call #to_int when defined on an object" do
obj = mock("bignum bit and")
obj.should_not_receive(:to_int)
- -> { @bignum & obj }.should raise_error(TypeError)
+ -> { @bignum & obj }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/integer/bit_or_spec.rb b/spec/ruby/core/integer/bit_or_spec.rb
index 6f4279c170..c380cd729e 100644
--- a/spec/ruby/core/integer/bit_or_spec.rb
+++ b/spec/ruby/core/integer/bit_or_spec.rb
@@ -30,20 +30,20 @@ describe "Integer#|" do
end
it "coerces the rhs and calls #coerce" do
- obj = mock("fixnum bit and")
- obj.should_receive(:coerce).with(6).and_return([3, 6])
- (6 & obj).should == 2
+ obj = mock("fixnum bit or")
+ obj.should_receive(:coerce).with(6).and_return([6, 3])
+ (6 | obj).should == 7
end
it "raises a TypeError when passed a Float" do
- -> { (3 | 3.4) }.should raise_error(TypeError)
+ -> { (3 | 3.4) }.should.raise(TypeError)
end
it "raises a TypeError and does not call #to_int when defined on an object" do
obj = mock("integer bit or")
obj.should_not_receive(:to_int)
- -> { 3 | obj }.should raise_error(TypeError)
+ -> { 3 | obj }.should.raise(TypeError)
end
end
@@ -74,16 +74,16 @@ describe "Integer#|" do
not_supported_on :opal do
-> {
bignum_value | bignum_value(0xffff).to_f
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
- -> { @bignum | 9.9 }.should raise_error(TypeError)
+ -> { @bignum | 9.9 }.should.raise(TypeError)
end
it "raises a TypeError and does not call #to_int when defined on an object" do
obj = mock("bignum bit or")
obj.should_not_receive(:to_int)
- -> { @bignum | obj }.should raise_error(TypeError)
+ -> { @bignum | obj }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/integer/bit_xor_spec.rb b/spec/ruby/core/integer/bit_xor_spec.rb
index f1150a20d5..c0cf8405f7 100644
--- a/spec/ruby/core/integer/bit_xor_spec.rb
+++ b/spec/ruby/core/integer/bit_xor_spec.rb
@@ -28,20 +28,20 @@ describe "Integer#^" do
end
it "coerces the rhs and calls #coerce" do
- obj = mock("fixnum bit and")
- obj.should_receive(:coerce).with(6).and_return([3, 6])
+ obj = mock("fixnum bit xor")
+ obj.should_receive(:coerce).with(6).and_return([6, 3])
(6 ^ obj).should == 5
end
it "raises a TypeError when passed a Float" do
- -> { (3 ^ 3.4) }.should raise_error(TypeError)
+ -> { (3 ^ 3.4) }.should.raise(TypeError)
end
it "raises a TypeError and does not call #to_int when defined on an object" do
obj = mock("integer bit xor")
obj.should_not_receive(:to_int)
- -> { 3 ^ obj }.should raise_error(TypeError)
+ -> { 3 ^ obj }.should.raise(TypeError)
end
end
@@ -78,16 +78,16 @@ describe "Integer#^" do
not_supported_on :opal do
-> {
bignum_value ^ bignum_value(0xffff).to_f
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
- -> { @bignum ^ 14.5 }.should raise_error(TypeError)
+ -> { @bignum ^ 14.5 }.should.raise(TypeError)
end
it "raises a TypeError and does not call #to_int when defined on an object" do
obj = mock("bignum bit xor")
obj.should_not_receive(:to_int)
- -> { @bignum ^ obj }.should raise_error(TypeError)
+ -> { @bignum ^ obj }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/integer/ceil_spec.rb b/spec/ruby/core/integer/ceil_spec.rb
index 13bdaf838d..395be58fbd 100644
--- a/spec/ruby/core/integer/ceil_spec.rb
+++ b/spec/ruby/core/integer/ceil_spec.rb
@@ -1,19 +1,13 @@
require_relative '../../spec_helper'
require_relative 'shared/to_i'
require_relative 'shared/integer_rounding'
+require_relative 'shared/integer_ceil_precision'
describe "Integer#ceil" do
it_behaves_like :integer_to_i, :ceil
it_behaves_like :integer_rounding_positive_precision, :ceil
- 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
+ context "with precision" do
+ it_behaves_like :integer_ceil_precision, :Integer
end
end
diff --git a/spec/ruby/core/integer/ceildiv_spec.rb b/spec/ruby/core/integer/ceildiv_spec.rb
new file mode 100644
index 0000000000..91f63832f8
--- /dev/null
+++ b/spec/ruby/core/integer/ceildiv_spec.rb
@@ -0,0 +1,20 @@
+require_relative '../../spec_helper'
+
+describe "Integer#ceildiv" do
+ it "returns a quotient of division which is rounded up to the nearest integer" do
+ 0.ceildiv(3).should.eql?(0)
+ 1.ceildiv(3).should.eql?(1)
+ 3.ceildiv(3).should.eql?(1)
+ 4.ceildiv(3).should.eql?(2)
+
+ 4.ceildiv(-3).should.eql?(-1)
+ -4.ceildiv(3).should.eql?(-1)
+ -4.ceildiv(-3).should.eql?(2)
+
+ 3.ceildiv(1.2).should.eql?(3)
+ 3.ceildiv(6/5r).should.eql?(3)
+
+ (10**100-11).ceildiv(10**99-1).should.eql?(10)
+ (10**100-9).ceildiv(10**99-1).should.eql?(11)
+ end
+end
diff --git a/spec/ruby/core/integer/chr_spec.rb b/spec/ruby/core/integer/chr_spec.rb
index 8fe20ff812..72784e1833 100644
--- a/spec/ruby/core/integer/chr_spec.rb
+++ b/spec/ruby/core/integer/chr_spec.rb
@@ -2,20 +2,20 @@ require_relative '../../spec_helper'
describe "Integer#chr without argument" do
it "returns a String" do
- 17.chr.should be_an_instance_of(String)
+ 17.chr.should.instance_of?(String)
end
it "returns a new String for each call" do
- 82.chr.should_not equal(82.chr)
+ 82.chr.should_not.equal?(82.chr)
end
it "raises a RangeError is self is less than 0" do
- -> { -1.chr }.should raise_error(RangeError)
- -> { (-bignum_value).chr }.should raise_error(RangeError)
+ -> { -1.chr }.should.raise(RangeError, /-1 out of char range/)
+ -> { (-bignum_value).chr }.should.raise(RangeError, /bignum out of char range/)
end
it "raises a RangeError if self is too large" do
- -> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError)
+ -> { 2206368128.chr(Encoding::UTF_8) }.should.raise(RangeError, /2206368128 out of char range/)
end
describe "when Encoding.default_internal is nil" do
@@ -48,8 +48,8 @@ describe "Integer#chr without argument" do
end
it "raises a RangeError is self is greater than 255" do
- -> { 256.chr }.should raise_error(RangeError)
- -> { bignum_value.chr }.should raise_error(RangeError)
+ -> { 256.chr }.should.raise(RangeError, /256 out of char range/)
+ -> { bignum_value.chr }.should.raise(RangeError, /bignum out of char range/)
end
end
@@ -137,7 +137,7 @@ describe "Integer#chr without argument" do
[620, "TIS-620"]
].each do |integer, encoding_name|
Encoding.default_internal = Encoding.find(encoding_name)
- -> { integer.chr }.should raise_error(RangeError)
+ -> { integer.chr }.should.raise(RangeError, /(invalid codepoint|out of char range)/)
end
end
end
@@ -146,15 +146,15 @@ end
describe "Integer#chr with an encoding argument" do
it "returns a String" do
- 900.chr(Encoding::UTF_8).should be_an_instance_of(String)
+ 900.chr(Encoding::UTF_8).should.instance_of?(String)
end
it "returns a new String for each call" do
- 8287.chr(Encoding::UTF_8).should_not equal(8287.chr(Encoding::UTF_8))
+ 8287.chr(Encoding::UTF_8).should_not.equal?(8287.chr(Encoding::UTF_8))
end
it "accepts a String as an argument" do
- -> { 0xA4A2.chr('euc-jp') }.should_not raise_error
+ -> { 0xA4A2.chr('euc-jp') }.should_not.raise
end
it "converts a String to an Encoding as Encoding.find does" do
@@ -165,12 +165,12 @@ describe "Integer#chr with an encoding argument" do
# http://redmine.ruby-lang.org/issues/4869
it "raises a RangeError is self is less than 0" do
- -> { -1.chr(Encoding::UTF_8) }.should raise_error(RangeError)
- -> { (-bignum_value).chr(Encoding::EUC_JP) }.should raise_error(RangeError)
+ -> { -1.chr(Encoding::UTF_8) }.should.raise(RangeError, /-1 out of char range/)
+ -> { (-bignum_value).chr(Encoding::EUC_JP) }.should.raise(RangeError, /bignum out of char range/)
end
it "raises a RangeError if self is too large" do
- -> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError)
+ -> { 2206368128.chr(Encoding::UTF_8) }.should.raise(RangeError, /2206368128 out of char range/)
end
it "returns a String with the specified encoding" do
@@ -223,25 +223,25 @@ describe "Integer#chr with an encoding argument" do
# #5864
it "raises RangeError if self is invalid as a codepoint in the specified encoding" do
- -> { 0x80.chr("US-ASCII") }.should raise_error(RangeError)
- -> { 0x0100.chr("BINARY") }.should raise_error(RangeError)
- -> { 0x0100.chr("EUC-JP") }.should raise_error(RangeError)
- -> { 0xA1A0.chr("EUC-JP") }.should raise_error(RangeError)
- -> { 0xA1.chr("EUC-JP") }.should raise_error(RangeError)
- -> { 0x80.chr("SHIFT_JIS") }.should raise_error(RangeError)
- -> { 0xE0.chr("SHIFT_JIS") }.should raise_error(RangeError)
- -> { 0x0100.chr("ISO-8859-9") }.should raise_error(RangeError)
- -> { 620.chr("TIS-620") }.should raise_error(RangeError)
+ -> { 0x80.chr("US-ASCII") }.should.raise(RangeError)
+ -> { 0x0100.chr("BINARY") }.should.raise(RangeError)
+ -> { 0x0100.chr("EUC-JP") }.should.raise(RangeError)
+ -> { 0xA1A0.chr("EUC-JP") }.should.raise(RangeError)
+ -> { 0xA1.chr("EUC-JP") }.should.raise(RangeError)
+ -> { 0x80.chr("SHIFT_JIS") }.should.raise(RangeError)
+ -> { 0xE0.chr("SHIFT_JIS") }.should.raise(RangeError)
+ -> { 0x0100.chr("ISO-8859-9") }.should.raise(RangeError)
+ -> { 620.chr("TIS-620") }.should.raise(RangeError)
# UTF-16 surrogate range
- -> { 0xD800.chr("UTF-8") }.should raise_error(RangeError)
- -> { 0xDBFF.chr("UTF-8") }.should raise_error(RangeError)
- -> { 0xDC00.chr("UTF-8") }.should raise_error(RangeError)
- -> { 0xDFFF.chr("UTF-8") }.should raise_error(RangeError)
+ -> { 0xD800.chr("UTF-8") }.should.raise(RangeError)
+ -> { 0xDBFF.chr("UTF-8") }.should.raise(RangeError)
+ -> { 0xDC00.chr("UTF-8") }.should.raise(RangeError)
+ -> { 0xDFFF.chr("UTF-8") }.should.raise(RangeError)
# UTF-16 surrogate range
- -> { 0xD800.chr("UTF-16") }.should raise_error(RangeError)
- -> { 0xDBFF.chr("UTF-16") }.should raise_error(RangeError)
- -> { 0xDC00.chr("UTF-16") }.should raise_error(RangeError)
- -> { 0xDFFF.chr("UTF-16") }.should raise_error(RangeError)
+ -> { 0xD800.chr("UTF-16") }.should.raise(RangeError)
+ -> { 0xDBFF.chr("UTF-16") }.should.raise(RangeError)
+ -> { 0xDC00.chr("UTF-16") }.should.raise(RangeError)
+ -> { 0xDFFF.chr("UTF-16") }.should.raise(RangeError)
end
it 'returns a String encoding self interpreted as a codepoint in the CESU-8 encoding' do
diff --git a/spec/ruby/core/integer/coerce_spec.rb b/spec/ruby/core/integer/coerce_spec.rb
index f1f3256032..c0e642da03 100644
--- a/spec/ruby/core/integer/coerce_spec.rb
+++ b/spec/ruby/core/integer/coerce_spec.rb
@@ -1,7 +1,5 @@
require_relative '../../spec_helper'
-require 'bigdecimal'
-
describe "Integer#coerce" do
context "fixnum" do
describe "when given a Fixnum" do
@@ -13,7 +11,7 @@ describe "Integer#coerce" do
describe "when given a String" do
it "raises an ArgumentError when trying to coerce with a non-number String" do
- -> { 1.coerce(":)") }.should raise_error(ArgumentError)
+ -> { 1.coerce(":)") }.should.raise(ArgumentError)
end
it "returns an array containing two Floats" do
@@ -23,7 +21,7 @@ describe "Integer#coerce" do
end
it "raises a TypeError when trying to coerce with nil" do
- -> { 1.coerce(nil) }.should raise_error(TypeError)
+ -> { 1.coerce(nil) }.should.raise(TypeError)
end
it "tries to convert the given Object into a Float by using #to_f" do
@@ -31,13 +29,13 @@ describe "Integer#coerce" do
2.coerce(obj).should == [1.0, 2.0]
(obj = mock('0')).should_receive(:to_f).and_return('0')
- -> { 2.coerce(obj).should == [1.0, 2.0] }.should raise_error(TypeError)
+ -> { 2.coerce(obj).should == [1.0, 2.0] }.should.raise(TypeError)
end
it "raises a TypeError when given an Object that does not respond to #to_f" do
- -> { 1.coerce(mock('x')) }.should raise_error(TypeError)
- -> { 1.coerce(1..4) }.should raise_error(TypeError)
- -> { 1.coerce(:test) }.should raise_error(TypeError)
+ -> { 1.coerce(mock('x')) }.should.raise(TypeError)
+ -> { 1.coerce(1..4) }.should.raise(TypeError)
+ -> { 1.coerce(:test) }.should.raise(TypeError)
end
end
@@ -46,8 +44,8 @@ describe "Integer#coerce" do
a = bignum_value
ary = a.coerce(2)
- ary[0].should be_kind_of(Integer)
- ary[1].should be_kind_of(Integer)
+ ary[0].should.is_a?(Integer)
+ ary[1].should.is_a?(Integer)
ary.should == [2, a]
end
@@ -56,18 +54,18 @@ describe "Integer#coerce" do
b = bignum_value
ary = a.coerce(b)
- ary[0].should be_kind_of(Integer)
- ary[1].should be_kind_of(Integer)
+ ary[0].should.is_a?(Integer)
+ ary[1].should.is_a?(Integer)
ary.should == [b, a]
end
it "raises a TypeError when not passed a Fixnum or Bignum" do
a = bignum_value
- -> { a.coerce(nil) }.should raise_error(TypeError)
- -> { a.coerce(mock('str')) }.should raise_error(TypeError)
- -> { a.coerce(1..4) }.should raise_error(TypeError)
- -> { a.coerce(:test) }.should raise_error(TypeError)
+ -> { a.coerce(nil) }.should.raise(TypeError)
+ -> { a.coerce(mock('str')) }.should.raise(TypeError)
+ -> { a.coerce(1..4) }.should.raise(TypeError)
+ -> { a.coerce(:test) }.should.raise(TypeError)
end
it "coerces both values to Floats and returns [other, self] when passed a Float" do
@@ -90,15 +88,4 @@ describe "Integer#coerce" do
ary.should == [1.2, a.to_f]
end
end
-
- context "bigdecimal" do
- it "produces Floats" do
- x, y = 3.coerce(BigDecimal("3.4"))
- x.class.should == Float
- x.should == 3.4
- y.class.should == Float
- y.should == 3.0
- end
- end
-
end
diff --git a/spec/ruby/core/integer/comparison_spec.rb b/spec/ruby/core/integer/comparison_spec.rb
index 408c8e52ce..cc5cbe2506 100644
--- a/spec/ruby/core/integer/comparison_spec.rb
+++ b/spec/ruby/core/integer/comparison_spec.rb
@@ -128,17 +128,17 @@ describe "Integer#<=>" do
@num.should_receive(:coerce).with(@big).and_raise(RuntimeError.new("my error"))
-> {
@big <=> @num
- }.should raise_error(RuntimeError, "my error")
+ }.should.raise(RuntimeError, "my error")
end
it "raises an exception if #coerce raises a non-StandardError exception" do
@num.should_receive(:coerce).with(@big).and_raise(Exception)
- -> { @big <=> @num }.should raise_error(Exception)
+ -> { @big <=> @num }.should.raise(Exception)
end
it "returns nil if #coerce does not return an Array" do
@num.should_receive(:coerce).with(@big).and_return(nil)
- (@big <=> @num).should be_nil
+ (@big <=> @num).should == nil
end
it "returns -1 if the coerced value is larger" do
@@ -157,6 +157,14 @@ describe "Integer#<=>" do
end
end
+ describe "with a Float" do
+ it "does not lose precision for values that don't fit in a double" do
+ (bignum_value(1) <=> bignum_value.to_f).should == 1
+ (bignum_value <=> bignum_value.to_f).should == 0
+ ((bignum_value - 1) <=> bignum_value.to_f).should == -1
+ end
+ end
+
# The tests below are taken from matz's revision 23730 for Ruby trunk
it "returns 1 when self is Infinity and other is a Bignum" do
(infinity_value <=> Float::MAX.to_i*2).should == 1
diff --git a/spec/ruby/core/integer/constants_spec.rb b/spec/ruby/core/integer/constants_spec.rb
index 2077ad451e..937806c72f 100644
--- a/spec/ruby/core/integer/constants_spec.rb
+++ b/spec/ruby/core/integer/constants_spec.rb
@@ -1,41 +1,13 @@
require_relative '../../spec_helper'
describe "Fixnum" do
- ruby_version_is ""..."3.2" do
- it "is unified into Integer" do
- suppress_warning do
- Fixnum.should equal(Integer)
- end
- end
-
- it "is deprecated" do
- -> { Fixnum }.should complain(/constant ::Fixnum is deprecated/)
- end
- end
-
- ruby_version_is "3.2" do
- it "is no longer defined" do
- Object.should_not.const_defined?(:Fixnum)
- end
+ it "is no longer defined" do
+ Object.should_not.const_defined?(:Fixnum)
end
end
describe "Bignum" do
- ruby_version_is ""..."3.2" do
- it "is unified into Integer" do
- suppress_warning do
- Bignum.should equal(Integer)
- end
- end
-
- it "is deprecated" do
- -> { Bignum }.should complain(/constant ::Bignum is deprecated/)
- end
- end
-
- ruby_version_is "3.2" do
- it "is no longer defined" do
- Object.should_not.const_defined?(:Bignum)
- end
+ it "is no longer defined" do
+ Object.should_not.const_defined?(:Bignum)
end
end
diff --git a/spec/ruby/core/integer/digits_spec.rb b/spec/ruby/core/integer/digits_spec.rb
index 3d0a64c25f..c4ebf2cd88 100644
--- a/spec/ruby/core/integer/digits_spec.rb
+++ b/spec/ruby/core/integer/digits_spec.rb
@@ -19,15 +19,15 @@ describe "Integer#digits" do
end
it "raises ArgumentError when calling with a radix less than 2" do
- -> { 12345.digits(1) }.should raise_error(ArgumentError)
+ -> { 12345.digits(1) }.should.raise(ArgumentError)
end
it "raises ArgumentError when calling with a negative radix" do
- -> { 12345.digits(-2) }.should raise_error(ArgumentError)
+ -> { 12345.digits(-2) }.should.raise(ArgumentError)
end
it "raises Math::DomainError when calling digits on a negative number" do
- -> { -12345.digits(7) }.should raise_error(Math::DomainError)
+ -> { -12345.digits(7) }.should.raise(Math::DomainError)
end
it "returns integer values > 9 when base is above 10" do
diff --git a/spec/ruby/core/integer/div_spec.rb b/spec/ruby/core/integer/div_spec.rb
index 344e095179..220ca4a73e 100644
--- a/spec/ruby/core/integer/div_spec.rb
+++ b/spec/ruby/core/integer/div_spec.rb
@@ -46,21 +46,21 @@ describe "Integer#div" do
end
it "raises a ZeroDivisionError when the given argument is 0 and a Float" do
- -> { 0.div(0.0) }.should raise_error(ZeroDivisionError)
- -> { 10.div(0.0) }.should raise_error(ZeroDivisionError)
- -> { -10.div(0.0) }.should raise_error(ZeroDivisionError)
+ -> { 0.div(0.0) }.should.raise(ZeroDivisionError)
+ -> { 10.div(0.0) }.should.raise(ZeroDivisionError)
+ -> { -10.div(0.0) }.should.raise(ZeroDivisionError)
end
it "raises a ZeroDivisionError when the given argument is 0 and not a Float" do
- -> { 13.div(0) }.should raise_error(ZeroDivisionError)
- -> { 13.div(-0) }.should raise_error(ZeroDivisionError)
+ -> { 13.div(0) }.should.raise(ZeroDivisionError)
+ -> { 13.div(-0) }.should.raise(ZeroDivisionError)
end
it "raises a TypeError when given a non-numeric argument" do
- -> { 13.div(mock('10')) }.should raise_error(TypeError)
- -> { 5.div("2") }.should raise_error(TypeError)
- -> { 5.div(:"2") }.should raise_error(TypeError)
- -> { 5.div([]) }.should raise_error(TypeError)
+ -> { 13.div(mock('10')) }.should.raise(TypeError)
+ -> { 5.div("2") }.should.raise(TypeError)
+ -> { 5.div(:"2") }.should.raise(TypeError)
+ -> { 5.div([]) }.should.raise(TypeError)
end
end
@@ -118,29 +118,37 @@ describe "Integer#div" do
end
it "raises a TypeError when given a non-numeric" do
- -> { @bignum.div(mock("10")) }.should raise_error(TypeError)
- -> { @bignum.div("2") }.should raise_error(TypeError)
- -> { @bignum.div(:symbol) }.should raise_error(TypeError)
+ -> { @bignum.div(mock("10")) }.should.raise(TypeError)
+ -> { @bignum.div("2") }.should.raise(TypeError)
+ -> { @bignum.div(:symbol) }.should.raise(TypeError)
end
it "returns a result of integer division of self by a float argument" do
- @bignum.div(4294967295.5).should eql(4294967296)
+ @bignum.div(4294967295.5).should.eql?(4294967296)
not_supported_on :opal do
- @bignum.div(4294967295.0).should eql(4294967297)
- @bignum.div(bignum_value(88).to_f).should eql(1)
- @bignum.div((-bignum_value(88)).to_f).should eql(-1)
+ @bignum.div(4294967295.0).should.eql?(4294967297)
+ @bignum.div(bignum_value(88).to_f).should.eql?(1)
+ @bignum.div((-bignum_value(88)).to_f).should.eql?(-1)
end
end
# #5490
it "raises ZeroDivisionError if the argument is 0 and is a Float" do
- -> { @bignum.div(0.0) }.should raise_error(ZeroDivisionError)
- -> { @bignum.div(-0.0) }.should raise_error(ZeroDivisionError)
+ -> { @bignum.div(0.0) }.should.raise(ZeroDivisionError)
+ -> { @bignum.div(-0.0) }.should.raise(ZeroDivisionError)
end
it "raises ZeroDivisionError if the argument is 0 and is not a Float" do
- -> { @bignum.div(0) }.should raise_error(ZeroDivisionError)
- -> { @bignum.div(-0) }.should raise_error(ZeroDivisionError)
+ -> { @bignum.div(0) }.should.raise(ZeroDivisionError)
+ -> { @bignum.div(-0) }.should.raise(ZeroDivisionError)
+ end
+ end
+
+ context "rational" do
+ it "returns self divided by the given argument as an Integer" do
+ 2.div(6/5r).should == 1
+ 1.div(6/5r).should == 0
+ 5.div(6/5r).should == 4
end
end
end
diff --git a/spec/ruby/core/integer/divide_spec.rb b/spec/ruby/core/integer/divide_spec.rb
index a878c4668c..e75432fd83 100644
--- a/spec/ruby/core/integer/divide_spec.rb
+++ b/spec/ruby/core/integer/divide_spec.rb
@@ -12,6 +12,17 @@ describe "Integer#/" do
it "supports dividing negative numbers" do
(-1 / 10).should == -1
+ (-1 / 10**10).should == -1
+ (-1 / 10**20).should == -1
+ end
+
+ it "preservers sign correctly" do
+ (4 / 3).should == 1
+ (4 / -3).should == -2
+ (-4 / 3).should == -2
+ (-4 / -3).should == 1
+ (0 / -3).should == 0
+ (0 / 3).should == 0
end
it "returns result the same class as the argument" do
@@ -21,7 +32,7 @@ describe "Integer#/" do
end
it "raises a ZeroDivisionError if the given argument is zero and not a Float" do
- -> { 1 / 0 }.should raise_error(ZeroDivisionError)
+ -> { 1 / 0 }.should.raise(ZeroDivisionError)
end
it "does NOT raise ZeroDivisionError if the given argument is zero and is a Float" do
@@ -35,9 +46,9 @@ describe "Integer#/" do
end
it "raises a TypeError when given a non-Integer" do
- -> { 13 / mock('10') }.should raise_error(TypeError)
- -> { 13 / "10" }.should raise_error(TypeError)
- -> { 13 / :symbol }.should raise_error(TypeError)
+ -> { 13 / mock('10') }.should.raise(TypeError)
+ -> { 13 / "10" }.should.raise(TypeError)
+ -> { 13 / :symbol }.should.raise(TypeError)
end
end
@@ -58,6 +69,15 @@ describe "Integer#/" do
((10**50) / -(10**40 + 1)).should == -10000000000
end
+ it "preservers sign correctly" do
+ (4 / bignum_value).should == 0
+ (4 / -bignum_value).should == -1
+ (-4 / bignum_value).should == -1
+ (-4 / -bignum_value).should == 0
+ (0 / bignum_value).should == 0
+ (0 / -bignum_value).should == 0
+ end
+
it "returns self divided by Float" do
not_supported_on :opal do
(bignum_value(88) / 4294967295.0).should be_close(4294967297.0, TOLERANCE)
@@ -77,13 +97,30 @@ describe "Integer#/" do
end
it "raises a ZeroDivisionError if other is zero and not a Float" do
- -> { @bignum / 0 }.should raise_error(ZeroDivisionError)
+ -> { @bignum / 0 }.should.raise(ZeroDivisionError)
end
it "raises a TypeError when given a non-numeric" do
- -> { @bignum / mock('10') }.should raise_error(TypeError)
- -> { @bignum / "2" }.should raise_error(TypeError)
- -> { @bignum / :symbol }.should raise_error(TypeError)
+ -> { @bignum / mock('10') }.should.raise(TypeError)
+ -> { @bignum / "2" }.should.raise(TypeError)
+ -> { @bignum / :symbol }.should.raise(TypeError)
end
end
+
+ it "coerces the RHS and calls #coerce" do
+ obj = mock("integer plus")
+ obj.should_receive(:coerce).with(6).and_return([6, 3])
+ (6 / obj).should == 2
+ end
+
+ it "coerces the RHS and calls #coerce even if it's private" do
+ obj = Object.new
+ class << obj
+ private def coerce(n)
+ [n, 3]
+ end
+ end
+
+ (6 / obj).should == 2
+ end
end
diff --git a/spec/ruby/core/integer/divmod_spec.rb b/spec/ruby/core/integer/divmod_spec.rb
index 7a489e9344..db470c5731 100644
--- a/spec/ruby/core/integer/divmod_spec.rb
+++ b/spec/ruby/core/integer/divmod_spec.rb
@@ -14,24 +14,24 @@ describe "Integer#divmod" do
end
it "raises a ZeroDivisionError when the given argument is 0" do
- -> { 13.divmod(0) }.should raise_error(ZeroDivisionError)
- -> { 0.divmod(0) }.should raise_error(ZeroDivisionError)
- -> { -10.divmod(0) }.should raise_error(ZeroDivisionError)
+ -> { 13.divmod(0) }.should.raise(ZeroDivisionError)
+ -> { 0.divmod(0) }.should.raise(ZeroDivisionError)
+ -> { -10.divmod(0) }.should.raise(ZeroDivisionError)
end
it "raises a ZeroDivisionError when the given argument is 0 and a Float" do
- -> { 0.divmod(0.0) }.should raise_error(ZeroDivisionError)
- -> { 10.divmod(0.0) }.should raise_error(ZeroDivisionError)
- -> { -10.divmod(0.0) }.should raise_error(ZeroDivisionError)
+ -> { 0.divmod(0.0) }.should.raise(ZeroDivisionError)
+ -> { 10.divmod(0.0) }.should.raise(ZeroDivisionError)
+ -> { -10.divmod(0.0) }.should.raise(ZeroDivisionError)
end
it "raises a TypeError when given a non-Integer" do
-> {
(obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10)
13.divmod(obj)
- }.should raise_error(TypeError)
- -> { 13.divmod("10") }.should raise_error(TypeError)
- -> { 13.divmod(:symbol) }.should raise_error(TypeError)
+ }.should.raise(TypeError)
+ -> { 13.divmod("10") }.should.raise(TypeError)
+ -> { 13.divmod(:symbol) }.should.raise(TypeError)
end
end
@@ -94,24 +94,24 @@ describe "Integer#divmod" do
end
it "raises a ZeroDivisionError when the given argument is 0" do
- -> { @bignum.divmod(0) }.should raise_error(ZeroDivisionError)
- -> { (-@bignum).divmod(0) }.should raise_error(ZeroDivisionError)
+ -> { @bignum.divmod(0) }.should.raise(ZeroDivisionError)
+ -> { (-@bignum).divmod(0) }.should.raise(ZeroDivisionError)
end
# Behaviour established as correct in r23953
it "raises a FloatDomainError if other is NaN" do
- -> { @bignum.divmod(nan_value) }.should raise_error(FloatDomainError)
+ -> { @bignum.divmod(nan_value) }.should.raise(FloatDomainError)
end
it "raises a ZeroDivisionError when the given argument is 0 and a Float" do
- -> { @bignum.divmod(0.0) }.should raise_error(ZeroDivisionError)
- -> { (-@bignum).divmod(0.0) }.should raise_error(ZeroDivisionError)
+ -> { @bignum.divmod(0.0) }.should.raise(ZeroDivisionError)
+ -> { (-@bignum).divmod(0.0) }.should.raise(ZeroDivisionError)
end
it "raises a TypeError when the given argument is not an Integer" do
- -> { @bignum.divmod(mock('10')) }.should raise_error(TypeError)
- -> { @bignum.divmod("10") }.should raise_error(TypeError)
- -> { @bignum.divmod(:symbol) }.should raise_error(TypeError)
+ -> { @bignum.divmod(mock('10')) }.should.raise(TypeError)
+ -> { @bignum.divmod("10") }.should.raise(TypeError)
+ -> { @bignum.divmod(:symbol) }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/integer/downto_spec.rb b/spec/ruby/core/integer/downto_spec.rb
index 987704b02e..a244d3df55 100644
--- a/spec/ruby/core/integer/downto_spec.rb
+++ b/spec/ruby/core/integer/downto_spec.rb
@@ -27,8 +27,8 @@ describe "Integer#downto [stop] when self and stop are Integers" do
end
it "raises an ArgumentError for invalid endpoints" do
- -> {1.downto("A") {|x| p x } }.should raise_error(ArgumentError)
- -> {1.downto(nil) {|x| p x } }.should raise_error(ArgumentError)
+ -> {1.downto("A") {|x| p x } }.should.raise(ArgumentError)
+ -> {1.downto(nil) {|x| p x } }.should.raise(ArgumentError)
end
describe "when no block is given" do
@@ -45,9 +45,9 @@ describe "Integer#downto [stop] when self and stop are Integers" do
describe "size" do
it "raises an ArgumentError for invalid endpoints" do
enum = 1.downto("A")
- -> { enum.size }.should raise_error(ArgumentError)
+ -> { enum.size }.should.raise(ArgumentError)
enum = 1.downto(nil)
- -> { enum.size }.should raise_error(ArgumentError)
+ -> { enum.size }.should.raise(ArgumentError)
end
it "returns self - stop + 1" do
diff --git a/spec/ruby/core/integer/dup_spec.rb b/spec/ruby/core/integer/dup_spec.rb
index 7f4d512465..3e5739ad37 100644
--- a/spec/ruby/core/integer/dup_spec.rb
+++ b/spec/ruby/core/integer/dup_spec.rb
@@ -3,11 +3,11 @@ require_relative '../../spec_helper'
describe "Integer#dup" do
it "returns self for small integers" do
integer = 1_000
- integer.dup.should equal(integer)
+ integer.dup.should.equal?(integer)
end
it "returns self for large integers" do
integer = 4_611_686_018_427_387_905
- integer.dup.should equal(integer)
+ integer.dup.should.equal?(integer)
end
end
diff --git a/spec/ruby/core/integer/element_reference_spec.rb b/spec/ruby/core/integer/element_reference_spec.rb
index cb7e0dc9b0..c69ec2315d 100644
--- a/spec/ruby/core/integer/element_reference_spec.rb
+++ b/spec/ruby/core/integer/element_reference_spec.rb
@@ -59,13 +59,13 @@ describe "Integer#[]" do
end
it "raises a TypeError when passed a String" do
- -> { 3["3"] }.should raise_error(TypeError)
+ -> { 3["3"] }.should.raise(TypeError)
end
it "raises a TypeError when #to_int does not return an Integer" do
obj = mock('asdf')
obj.should_receive(:to_int).and_return("asdf")
- -> { 3[obj] }.should raise_error(TypeError)
+ -> { 3[obj] }.should.raise(TypeError)
end
it "calls #to_int to coerce a String to a Bignum and returns 0" do
@@ -137,8 +137,8 @@ describe "Integer#[]" do
end
it "raises FloatDomainError if any boundary is infinity" do
- -> { 0x0001[3..Float::INFINITY] }.should raise_error(FloatDomainError, /Infinity/)
- -> { 0x0001[-Float::INFINITY..3] }.should raise_error(FloatDomainError, /-Infinity/)
+ -> { 0x0001[3..Float::INFINITY] }.should.raise(FloatDomainError, /Infinity/)
+ -> { 0x0001[-Float::INFINITY..3] }.should.raise(FloatDomainError, /-Infinity/)
end
context "when passed (..i)" do
@@ -151,7 +151,7 @@ describe "Integer#[]" do
it "raises ArgumentError if any of i bit equals 1" do
-> {
eval("0b111110[..3]")
- }.should raise_error(ArgumentError, /The beginless range for Integer#\[\] results in infinity/)
+ }.should.raise(ArgumentError, /The beginless range for Integer#\[\] results in infinity/)
end
end
end
@@ -179,10 +179,10 @@ describe "Integer#[]" do
it "raises a TypeError when the given argument can't be converted to Integer" do
obj = mock('asdf')
- -> { @bignum[obj] }.should raise_error(TypeError)
+ -> { @bignum[obj] }.should.raise(TypeError)
obj.should_receive(:to_int).and_return("asdf")
- -> { @bignum[obj] }.should raise_error(TypeError)
+ -> { @bignum[obj] }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/integer/eql_spec.rb b/spec/ruby/core/integer/eql_spec.rb
new file mode 100644
index 0000000000..9c80173206
--- /dev/null
+++ b/spec/ruby/core/integer/eql_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+
+describe "Integer#eql?" do
+ context "bignum" do
+ it "returns true for the same value" do
+ bignum_value.eql?(bignum_value).should == true
+ end
+
+ it "returns false for a different Integer value" do
+ bignum_value.eql?(bignum_value(1)).should == false
+ end
+
+ it "returns false for a Float with the same numeric value" do
+ bignum_value.eql?(bignum_value.to_f).should == false
+ end
+
+ it "returns false for a Rational with the same numeric value" do
+ bignum_value.eql?(Rational(bignum_value)).should == false
+ end
+
+ it "returns false for a Fixnum-range Integer" do
+ bignum_value.eql?(42).should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/integer/even_spec.rb b/spec/ruby/core/integer/even_spec.rb
index a314cc6b19..578979320e 100644
--- a/spec/ruby/core/integer/even_spec.rb
+++ b/spec/ruby/core/integer/even_spec.rb
@@ -3,38 +3,38 @@ require_relative '../../spec_helper'
describe "Integer#even?" do
context "fixnum" do
it "returns true for a Fixnum when it is an even number" do
- (-2).even?.should be_true
- (-1).even?.should be_false
+ (-2).even?.should == true
+ (-1).even?.should == false
- 0.even?.should be_true
- 1.even?.should be_false
- 2.even?.should be_true
+ 0.even?.should == true
+ 1.even?.should == false
+ 2.even?.should == true
end
it "returns true for a Bignum when it is an even number" do
- bignum_value(0).even?.should be_true
- bignum_value(1).even?.should be_false
+ bignum_value(0).even?.should == true
+ bignum_value(1).even?.should == false
- (-bignum_value(0)).even?.should be_true
- (-bignum_value(1)).even?.should be_false
+ (-bignum_value(0)).even?.should == true
+ (-bignum_value(1)).even?.should == false
end
end
context "bignum" do
it "returns true if self is even and positive" do
- (10000**10).even?.should be_true
+ (10000**10).even?.should == true
end
it "returns true if self is even and negative" do
- (-10000**10).even?.should be_true
+ (-10000**10).even?.should == true
end
it "returns false if self is odd and positive" do
- (9879**976).even?.should be_false
+ (9879**976).even?.should == false
end
it "returns false if self is odd and negative" do
- (-9879**976).even?.should be_false
+ (-9879**976).even?.should == false
end
end
end
diff --git a/spec/ruby/core/integer/fdiv_spec.rb b/spec/ruby/core/integer/fdiv_spec.rb
index d9ea2fdf8d..7854d66dec 100644
--- a/spec/ruby/core/integer/fdiv_spec.rb
+++ b/spec/ruby/core/integer/fdiv_spec.rb
@@ -65,8 +65,8 @@ describe "Integer#fdiv" do
end
it "returns NaN when the argument is NaN" do
- -1.fdiv(nan_value).nan?.should be_true
- 1.fdiv(nan_value).nan?.should be_true
+ -1.fdiv(nan_value).nan?.should == true
+ 1.fdiv(nan_value).nan?.should == true
end
it "returns Infinity when the argument is 0" do
@@ -86,11 +86,11 @@ describe "Integer#fdiv" do
end
it "raises a TypeError when argument isn't numeric" do
- -> { 1.fdiv(mock('non-numeric')) }.should raise_error(TypeError)
+ -> { 1.fdiv(mock('non-numeric')) }.should.raise(TypeError)
end
it "raises an ArgumentError when passed multiple arguments" do
- -> { 1.fdiv(6,0.2) }.should raise_error(ArgumentError)
+ -> { 1.fdiv(6,0.2) }.should.raise(ArgumentError)
end
it "follows the coercion protocol" do
diff --git a/spec/ruby/core/integer/fixtures/classes.rb b/spec/ruby/core/integer/fixtures/classes.rb
index 6ebfbd1565..65948efb9f 100644
--- a/spec/ruby/core/integer/fixtures/classes.rb
+++ b/spec/ruby/core/integer/fixtures/classes.rb
@@ -1,4 +1,14 @@
module IntegerSpecs
class CoerceError < StandardError
end
+
+ class CoercibleNumeric
+ def initialize(v) @v = v end
+ def coerce(other) [self.class.new(other), self] end
+ def >(other) @v.to_i > other.to_i end
+ def >=(other) @v.to_i >= other.to_i end
+ def <(other) @v.to_i < other.to_i end
+ def <=(other) @v.to_i <= other.to_i end
+ def to_i() @v.to_i end
+ end
end
diff --git a/spec/ruby/core/integer/floor_spec.rb b/spec/ruby/core/integer/floor_spec.rb
index aaa816fdc5..8fb84d58cb 100644
--- a/spec/ruby/core/integer/floor_spec.rb
+++ b/spec/ruby/core/integer/floor_spec.rb
@@ -1,19 +1,13 @@
require_relative '../../spec_helper'
require_relative 'shared/to_i'
require_relative 'shared/integer_rounding'
+require_relative 'shared/integer_floor_precision'
describe "Integer#floor" do
it_behaves_like :integer_to_i, :floor
it_behaves_like :integer_rounding_positive_precision, :floor
- 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
+ context "with precision" do
+ it_behaves_like :integer_floor_precision, :Integer
end
end
diff --git a/spec/ruby/core/integer/gcd_spec.rb b/spec/ruby/core/integer/gcd_spec.rb
index 961f1c5c2e..1fff785927 100644
--- a/spec/ruby/core/integer/gcd_spec.rb
+++ b/spec/ruby/core/integer/gcd_spec.rb
@@ -7,8 +7,8 @@ describe "Integer#gcd" do
end
it "returns an Integer" do
- 36.gcd(6).should be_kind_of(Integer)
- 4.gcd(20981).should be_kind_of(Integer)
+ 36.gcd(6).should.is_a?(Integer)
+ 4.gcd(20981).should.is_a?(Integer)
end
it "returns the greatest common divisor of self and argument" do
@@ -33,13 +33,13 @@ describe "Integer#gcd" do
it "accepts a Bignum argument" do
bignum = 9999**99
- bignum.should be_kind_of(Integer)
+ bignum.should.is_a?(Integer)
99.gcd(bignum).should == 99
end
it "works if self is a Bignum" do
bignum = 9999**99
- bignum.should be_kind_of(Integer)
+ bignum.should.is_a?(Integer)
bignum.gcd(99).should == 99
end
@@ -55,15 +55,15 @@ describe "Integer#gcd" do
end
it "raises an ArgumentError if not given an argument" do
- -> { 12.gcd }.should raise_error(ArgumentError)
+ -> { 12.gcd }.should.raise(ArgumentError)
end
it "raises an ArgumentError if given more than one argument" do
- -> { 12.gcd(30, 20) }.should raise_error(ArgumentError)
+ -> { 12.gcd(30, 20) }.should.raise(ArgumentError)
end
it "raises a TypeError unless the argument is an Integer" do
- -> { 39.gcd(3.8) }.should raise_error(TypeError)
- -> { 45872.gcd([]) }.should raise_error(TypeError)
+ -> { 39.gcd(3.8) }.should.raise(TypeError)
+ -> { 45872.gcd([]) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/integer/gcdlcm_spec.rb b/spec/ruby/core/integer/gcdlcm_spec.rb
index ebf45e55a1..419bf9f275 100644
--- a/spec/ruby/core/integer/gcdlcm_spec.rb
+++ b/spec/ruby/core/integer/gcdlcm_spec.rb
@@ -7,8 +7,8 @@ describe "Integer#gcdlcm" do
end
it "returns an Array" do
- 36.gcdlcm(6).should be_kind_of(Array)
- 4.gcdlcm(20981).should be_kind_of(Array)
+ 36.gcdlcm(6).should.is_a?(Array)
+ 4.gcdlcm(20981).should.is_a?(Array)
end
it "returns a two-element Array" do
@@ -28,26 +28,26 @@ describe "Integer#gcdlcm" do
it "accepts a Bignum argument" do
bignum = 91999**99
- bignum.should be_kind_of(Integer)
+ bignum.should.is_a?(Integer)
99.gcdlcm(bignum).should == [99.gcd(bignum), 99.lcm(bignum)]
end
it "works if self is a Bignum" do
bignum = 9999**89
- bignum.should be_kind_of(Integer)
+ bignum.should.is_a?(Integer)
bignum.gcdlcm(99).should == [bignum.gcd(99), bignum.lcm(99)]
end
it "raises an ArgumentError if not given an argument" do
- -> { 12.gcdlcm }.should raise_error(ArgumentError)
+ -> { 12.gcdlcm }.should.raise(ArgumentError)
end
it "raises an ArgumentError if given more than one argument" do
- -> { 12.gcdlcm(30, 20) }.should raise_error(ArgumentError)
+ -> { 12.gcdlcm(30, 20) }.should.raise(ArgumentError)
end
it "raises a TypeError unless the argument is an Integer" do
- -> { 39.gcdlcm(3.8) }.should raise_error(TypeError)
- -> { 45872.gcdlcm([]) }.should raise_error(TypeError)
+ -> { 39.gcdlcm(3.8) }.should.raise(TypeError)
+ -> { 45872.gcdlcm([]) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/integer/gt_spec.rb b/spec/ruby/core/integer/gt_spec.rb
index f0179e566d..75436144cf 100644
--- a/spec/ruby/core/integer/gt_spec.rb
+++ b/spec/ruby/core/integer/gt_spec.rb
@@ -17,8 +17,8 @@ describe "Integer#>" do
end
it "raises an ArgumentError when given a non-Integer" do
- -> { 5 > "4" }.should raise_error(ArgumentError)
- -> { 5 > mock('x') }.should raise_error(ArgumentError)
+ -> { 5 > "4" }.should.raise(ArgumentError)
+ -> { 5 > mock('x') }.should.raise(ArgumentError)
end
end
@@ -36,8 +36,13 @@ describe "Integer#>" do
end
it "raises an ArgumentError when given a non-Integer" do
- -> { @bignum > "4" }.should raise_error(ArgumentError)
- -> { @bignum > mock('str') }.should raise_error(ArgumentError)
+ -> { @bignum > "4" }.should.raise(ArgumentError)
+ -> { @bignum > mock('str') }.should.raise(ArgumentError)
+ end
+
+ it "dispatches the correct operator after coercion" do
+ (bignum_value > IntegerSpecs::CoercibleNumeric.new(1)).should == true
+ (bignum_value > IntegerSpecs::CoercibleNumeric.new(bignum_value * 2)).should == false
end
end
end
diff --git a/spec/ruby/core/integer/gte_spec.rb b/spec/ruby/core/integer/gte_spec.rb
index 6237fc2c51..e5cb892efd 100644
--- a/spec/ruby/core/integer/gte_spec.rb
+++ b/spec/ruby/core/integer/gte_spec.rb
@@ -18,8 +18,8 @@ describe "Integer#>=" do
end
it "raises an ArgumentError when given a non-Integer" do
- -> { 5 >= "4" }.should raise_error(ArgumentError)
- -> { 5 >= mock('x') }.should raise_error(ArgumentError)
+ -> { 5 >= "4" }.should.raise(ArgumentError)
+ -> { 5 >= mock('x') }.should.raise(ArgumentError)
end
end
@@ -36,8 +36,13 @@ describe "Integer#>=" do
end
it "raises an ArgumentError when given a non-Integer" do
- -> { @bignum >= "4" }.should raise_error(ArgumentError)
- -> { @bignum >= mock('str') }.should raise_error(ArgumentError)
+ -> { @bignum >= "4" }.should.raise(ArgumentError)
+ -> { @bignum >= mock('str') }.should.raise(ArgumentError)
+ end
+
+ it "dispatches the correct operator after coercion" do
+ (bignum_value >= IntegerSpecs::CoercibleNumeric.new(1)).should == true
+ (bignum_value >= IntegerSpecs::CoercibleNumeric.new(bignum_value * 2)).should == false
end
end
end
diff --git a/spec/ruby/core/integer/integer_spec.rb b/spec/ruby/core/integer/integer_spec.rb
index 2d5d2e3e92..19a962d548 100644
--- a/spec/ruby/core/integer/integer_spec.rb
+++ b/spec/ruby/core/integer/integer_spec.rb
@@ -6,8 +6,8 @@ describe "Integer" do
end
it "is the class of both small and large integers" do
- 42.class.should equal(Integer)
- bignum_value.class.should equal(Integer)
+ 42.class.should.equal?(Integer)
+ bignum_value.class.should.equal?(Integer)
end
end
diff --git a/spec/ruby/core/integer/lcm_spec.rb b/spec/ruby/core/integer/lcm_spec.rb
index 296a001c8c..6659247d1e 100644
--- a/spec/ruby/core/integer/lcm_spec.rb
+++ b/spec/ruby/core/integer/lcm_spec.rb
@@ -7,8 +7,8 @@ describe "Integer#lcm" do
end
it "returns an Integer" do
- 36.lcm(6).should be_kind_of(Integer)
- 4.lcm(20981).should be_kind_of(Integer)
+ 36.lcm(6).should.is_a?(Integer)
+ 4.lcm(20981).should.is_a?(Integer)
end
it "returns the least common multiple of self and argument" do
@@ -33,26 +33,26 @@ describe "Integer#lcm" do
it "accepts a Bignum argument" do
bignum = 9999**99
- bignum.should be_kind_of(Integer)
+ bignum.should.is_a?(Integer)
99.lcm(bignum).should == bignum
end
it "works if self is a Bignum" do
bignum = 9999**99
- bignum.should be_kind_of(Integer)
+ bignum.should.is_a?(Integer)
bignum.lcm(99).should == bignum
end
it "raises an ArgumentError if not given an argument" do
- -> { 12.lcm }.should raise_error(ArgumentError)
+ -> { 12.lcm }.should.raise(ArgumentError)
end
it "raises an ArgumentError if given more than one argument" do
- -> { 12.lcm(30, 20) }.should raise_error(ArgumentError)
+ -> { 12.lcm(30, 20) }.should.raise(ArgumentError)
end
it "raises a TypeError unless the argument is an Integer" do
- -> { 39.lcm(3.8) }.should raise_error(TypeError)
- -> { 45872.lcm([]) }.should raise_error(TypeError)
+ -> { 39.lcm(3.8) }.should.raise(TypeError)
+ -> { 45872.lcm([]) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/integer/left_shift_spec.rb b/spec/ruby/core/integer/left_shift_spec.rb
index 135af90421..7eedb91228 100644
--- a/spec/ruby/core/integer/left_shift_spec.rb
+++ b/spec/ruby/core/integer/left_shift_spec.rb
@@ -58,13 +58,13 @@ describe "Integer#<< (with n << m)" do
it "returns a Bignum == fixnum_max * 2 when fixnum_max << 1 and n > 0" do
result = fixnum_max << 1
- result.should be_an_instance_of(Integer)
+ result.should.instance_of?(Integer)
result.should == fixnum_max * 2
end
it "returns a Bignum == fixnum_min * 2 when fixnum_min << 1 and n < 0" do
result = fixnum_min << 1
- result.should be_an_instance_of(Integer)
+ result.should.instance_of?(Integer)
result.should == fixnum_min * 2
end
@@ -82,15 +82,15 @@ describe "Integer#<< (with n << m)" do
obj = mock("a string")
obj.should_receive(:to_int).and_return("asdf")
- -> { 3 << obj }.should raise_error(TypeError)
+ -> { 3 << obj }.should.raise(TypeError)
end
it "raises a TypeError when passed nil" do
- -> { 3 << nil }.should raise_error(TypeError)
+ -> { 3 << nil }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- -> { 3 << "4" }.should raise_error(TypeError)
+ -> { 3 << "4" }.should.raise(TypeError)
end
end
@@ -129,13 +129,13 @@ describe "Integer#<< (with n << m)" do
it "returns a Fixnum == fixnum_max when (fixnum_max * 2) << -1 and n > 0" do
result = (fixnum_max * 2) << -1
- result.should be_an_instance_of(Integer)
+ result.should.instance_of?(Integer)
result.should == fixnum_max
end
it "returns a Fixnum == fixnum_min when (fixnum_min * 2) << -1 and n < 0" do
result = (fixnum_min * 2) << -1
- result.should be_an_instance_of(Integer)
+ result.should.instance_of?(Integer)
result.should == fixnum_min
end
@@ -150,15 +150,15 @@ describe "Integer#<< (with n << m)" do
obj = mock("a string")
obj.should_receive(:to_int).and_return("asdf")
- -> { @bignum << obj }.should raise_error(TypeError)
+ -> { @bignum << obj }.should.raise(TypeError)
end
it "raises a TypeError when passed nil" do
- -> { @bignum << nil }.should raise_error(TypeError)
+ -> { @bignum << nil }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- -> { @bignum << "4" }.should raise_error(TypeError)
+ -> { @bignum << "4" }.should.raise(TypeError)
end
end
@@ -181,31 +181,31 @@ describe "Integer#<< (with n << m)" do
(bignum_value << -(2**40)).should == 0
end
- ruby_bug "#18517", ""..."3.2" do
- it "returns 0 when m > 0 long and n == 0" do
- (0 << (2**40)).should == 0
- end
+ it "returns 0 when m > 0 long and n == 0" do
+ (0 << (2**40)).should == 0
end
it "returns 0 when m > 0 bignum and n == 0" do
(0 << bignum_value).should == 0
end
- ruby_bug "#18518", ""..."3.3" do
- it "raises NoMemoryError when m > 0 and n != 0" do
- coerce_long = mock("long")
- coerce_long.stub!(:to_int).and_return(2**40)
- coerce_bignum = mock("bignum")
- coerce_bignum.stub!(:to_int).and_return(bignum_value)
- exps = [2**40, bignum_value, coerce_long, coerce_bignum]
-
- exps.each { |exp|
- -> { (1 << exp) }.should raise_error(NoMemoryError)
- -> { (-1 << exp) }.should raise_error(NoMemoryError)
- -> { (bignum_value << exp) }.should raise_error(NoMemoryError)
- -> { (-bignum_value << exp) }.should raise_error(NoMemoryError)
- }
- end
+ it "raises RangeError when m > 0 and n != 0" do
+ # https://bugs.ruby-lang.org/issues/18518#note-9
+ limit = RUBY_ENGINE == 'ruby' ? 2**67 : 2**32
+
+ coerce_long = mock("long")
+ coerce_long.stub!(:to_int).and_return(limit)
+ coerce_bignum = mock("bignum")
+ coerce_bignum.stub!(:to_int).and_return(bignum_value)
+ exps = [limit, coerce_long]
+ exps << bignum_value << coerce_bignum if bignum_value >= limit
+
+ exps.each { |exp|
+ -> { (1 << exp) }.should.raise(RangeError, 'shift width too big')
+ -> { (-1 << exp) }.should.raise(RangeError, 'shift width too big')
+ -> { (bignum_value << exp) }.should.raise(RangeError, 'shift width too big')
+ -> { (-bignum_value << exp) }.should.raise(RangeError, 'shift width too big')
+ }
end
end
end
diff --git a/spec/ruby/core/integer/lt_spec.rb b/spec/ruby/core/integer/lt_spec.rb
index c182f82555..dd1391d093 100644
--- a/spec/ruby/core/integer/lt_spec.rb
+++ b/spec/ruby/core/integer/lt_spec.rb
@@ -17,8 +17,8 @@ describe "Integer#<" do
end
it "raises an ArgumentError when given a non-Integer" do
- -> { 5 < "4" }.should raise_error(ArgumentError)
- -> { 5 < mock('x') }.should raise_error(ArgumentError)
+ -> { 5 < "4" }.should.raise(ArgumentError)
+ -> { 5 < mock('x') }.should.raise(ArgumentError)
end
end
@@ -38,8 +38,13 @@ describe "Integer#<" do
end
it "raises an ArgumentError when given a non-Integer" do
- -> { @bignum < "4" }.should raise_error(ArgumentError)
- -> { @bignum < mock('str') }.should raise_error(ArgumentError)
+ -> { @bignum < "4" }.should.raise(ArgumentError)
+ -> { @bignum < mock('str') }.should.raise(ArgumentError)
+ end
+
+ it "dispatches the correct operator after coercion" do
+ (bignum_value < IntegerSpecs::CoercibleNumeric.new(bignum_value * 2)).should == true
+ (bignum_value < IntegerSpecs::CoercibleNumeric.new(1)).should == false
end
end
end
diff --git a/spec/ruby/core/integer/lte_spec.rb b/spec/ruby/core/integer/lte_spec.rb
index 65b71d77f2..9ef1c9f604 100644
--- a/spec/ruby/core/integer/lte_spec.rb
+++ b/spec/ruby/core/integer/lte_spec.rb
@@ -18,8 +18,8 @@ describe "Integer#<=" do
end
it "raises an ArgumentError when given a non-Integer" do
- -> { 5 <= "4" }.should raise_error(ArgumentError)
- -> { 5 <= mock('x') }.should raise_error(ArgumentError)
+ -> { 5 <= "4" }.should.raise(ArgumentError)
+ -> { 5 <= mock('x') }.should.raise(ArgumentError)
end
end
@@ -46,8 +46,13 @@ describe "Integer#<=" do
end
it "raises an ArgumentError when given a non-Integer" do
- -> { @bignum <= "4" }.should raise_error(ArgumentError)
- -> { @bignum <= mock('str') }.should raise_error(ArgumentError)
+ -> { @bignum <= "4" }.should.raise(ArgumentError)
+ -> { @bignum <= mock('str') }.should.raise(ArgumentError)
+ end
+
+ it "dispatches the correct operator after coercion" do
+ (bignum_value <= IntegerSpecs::CoercibleNumeric.new(bignum_value * 2)).should == true
+ (bignum_value <= IntegerSpecs::CoercibleNumeric.new(1)).should == false
end
end
end
diff --git a/spec/ruby/core/integer/minus_spec.rb b/spec/ruby/core/integer/minus_spec.rb
index aadf416a05..5fd3a81a72 100644
--- a/spec/ruby/core/integer/minus_spec.rb
+++ b/spec/ruby/core/integer/minus_spec.rb
@@ -17,9 +17,9 @@ describe "Integer#-" do
-> {
(obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10)
13 - obj
- }.should raise_error(TypeError)
- -> { 13 - "10" }.should raise_error(TypeError)
- -> { 13 - :symbol }.should raise_error(TypeError)
+ }.should.raise(TypeError)
+ -> { 13 - "10" }.should.raise(TypeError)
+ -> { 13 - :symbol }.should.raise(TypeError)
end
end
@@ -35,9 +35,26 @@ describe "Integer#-" do
end
it "raises a TypeError when given a non-Integer" do
- -> { @bignum - mock('10') }.should raise_error(TypeError)
- -> { @bignum - "10" }.should raise_error(TypeError)
- -> { @bignum - :symbol }.should raise_error(TypeError)
+ -> { @bignum - mock('10') }.should.raise(TypeError)
+ -> { @bignum - "10" }.should.raise(TypeError)
+ -> { @bignum - :symbol }.should.raise(TypeError)
end
end
+
+ it "coerces the RHS and calls #coerce" do
+ obj = mock("integer plus")
+ obj.should_receive(:coerce).with(5).and_return([5, 10])
+ (5 - obj).should == -5
+ end
+
+ it "coerces the RHS and calls #coerce even if it's private" do
+ obj = Object.new
+ class << obj
+ private def coerce(n)
+ [n, 10]
+ end
+ end
+
+ (5 - obj).should == -5
+ end
end
diff --git a/spec/ruby/core/integer/multiply_spec.rb b/spec/ruby/core/integer/multiply_spec.rb
index 5037d27458..7f30eebaa5 100644
--- a/spec/ruby/core/integer/multiply_spec.rb
+++ b/spec/ruby/core/integer/multiply_spec.rb
@@ -18,9 +18,9 @@ describe "Integer#*" do
-> {
(obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10)
13 * obj
- }.should raise_error(TypeError)
- -> { 13 * "10" }.should raise_error(TypeError)
- -> { 13 * :symbol }.should raise_error(TypeError)
+ }.should.raise(TypeError)
+ -> { 13 * "10" }.should.raise(TypeError)
+ -> { 13 * :symbol }.should.raise(TypeError)
end
end
@@ -37,9 +37,9 @@ describe "Integer#*" do
end
it "raises a TypeError when given a non-Integer" do
- -> { @bignum * mock('10') }.should raise_error(TypeError)
- -> { @bignum * "10" }.should raise_error(TypeError)
- -> { @bignum * :symbol }.should raise_error(TypeError)
+ -> { @bignum * mock('10') }.should.raise(TypeError)
+ -> { @bignum * "10" }.should.raise(TypeError)
+ -> { @bignum * :symbol }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/integer/nobits_spec.rb b/spec/ruby/core/integer/nobits_spec.rb
index 685759ffa3..f1a3aca9d5 100644
--- a/spec/ruby/core/integer/nobits_spec.rb
+++ b/spec/ruby/core/integer/nobits_spec.rb
@@ -29,8 +29,8 @@ describe "Integer#nobits?" do
-> {
(obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10])
13.nobits?(obj)
- }.should raise_error(TypeError)
- -> { 13.nobits?("10") }.should raise_error(TypeError)
- -> { 13.nobits?(:symbol) }.should raise_error(TypeError)
+ }.should.raise(TypeError)
+ -> { 13.nobits?("10") }.should.raise(TypeError)
+ -> { 13.nobits?(:symbol) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/integer/odd_spec.rb b/spec/ruby/core/integer/odd_spec.rb
index dd779fa44b..f9e50ec790 100644
--- a/spec/ruby/core/integer/odd_spec.rb
+++ b/spec/ruby/core/integer/odd_spec.rb
@@ -3,36 +3,36 @@ require_relative '../../spec_helper'
describe "Integer#odd?" do
context "fixnum" do
it "returns true when self is an odd number" do
- (-2).odd?.should be_false
- (-1).odd?.should be_true
+ (-2).odd?.should == false
+ (-1).odd?.should == true
- 0.odd?.should be_false
- 1.odd?.should be_true
- 2.odd?.should be_false
+ 0.odd?.should == false
+ 1.odd?.should == true
+ 2.odd?.should == false
- bignum_value(0).odd?.should be_false
- bignum_value(1).odd?.should be_true
+ bignum_value(0).odd?.should == false
+ bignum_value(1).odd?.should == true
- (-bignum_value(0)).odd?.should be_false
- (-bignum_value(1)).odd?.should be_true
+ (-bignum_value(0)).odd?.should == false
+ (-bignum_value(1)).odd?.should == true
end
end
context "bignum" do
it "returns true if self is odd and positive" do
- (987279**19).odd?.should be_true
+ (987279**19).odd?.should == true
end
it "returns true if self is odd and negative" do
- (-9873389**97).odd?.should be_true
+ (-9873389**97).odd?.should == true
end
it "returns false if self is even and positive" do
- (10000000**10).odd?.should be_false
+ (10000000**10).odd?.should == false
end
it "returns false if self is even and negative" do
- (-1000000**100).odd?.should be_false
+ (-1000000**100).odd?.should == false
end
end
end
diff --git a/spec/ruby/core/integer/ord_spec.rb b/spec/ruby/core/integer/ord_spec.rb
index bcb57bea98..8b7dfe460d 100644
--- a/spec/ruby/core/integer/ord_spec.rb
+++ b/spec/ruby/core/integer/ord_spec.rb
@@ -2,16 +2,16 @@ require_relative '../../spec_helper'
describe "Integer#ord" do
it "returns self" do
- 20.ord.should eql(20)
- 40.ord.should eql(40)
+ 20.ord.should.eql?(20)
+ 40.ord.should.eql?(40)
- 0.ord.should eql(0)
- (-10).ord.should eql(-10)
+ 0.ord.should.eql?(0)
+ (-10).ord.should.eql?(-10)
- ?a.ord.should eql(97)
- ?Z.ord.should eql(90)
+ ?a.ord.should.eql?(97)
+ ?Z.ord.should.eql?(90)
- bignum_value.ord.should eql(bignum_value)
- (-bignum_value).ord.should eql(-bignum_value)
+ bignum_value.ord.should.eql?(bignum_value)
+ (-bignum_value).ord.should.eql?(-bignum_value)
end
end
diff --git a/spec/ruby/core/integer/plus_spec.rb b/spec/ruby/core/integer/plus_spec.rb
index d01a76ab58..b684377bd5 100644
--- a/spec/ruby/core/integer/plus_spec.rb
+++ b/spec/ruby/core/integer/plus_spec.rb
@@ -17,9 +17,9 @@ describe "Integer#+" do
-> {
(obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10)
13 + obj
- }.should raise_error(TypeError)
- -> { 13 + "10" }.should raise_error(TypeError)
- -> { 13 + :symbol }.should raise_error(TypeError)
+ }.should.raise(TypeError)
+ -> { 13 + "10" }.should.raise(TypeError)
+ -> { 13 + :symbol }.should.raise(TypeError)
end
end
@@ -35,9 +35,9 @@ describe "Integer#+" do
end
it "raises a TypeError when given a non-Integer" do
- -> { @bignum + mock('10') }.should raise_error(TypeError)
- -> { @bignum + "10" }.should raise_error(TypeError)
- -> { @bignum + :symbol}.should raise_error(TypeError)
+ -> { @bignum + mock('10') }.should.raise(TypeError)
+ -> { @bignum + "10" }.should.raise(TypeError)
+ -> { @bignum + :symbol}.should.raise(TypeError)
end
end
@@ -55,4 +55,21 @@ describe "Integer#+" do
RUBY
ruby_exe(code).should == "-1"
end
+
+ it "coerces the RHS and calls #coerce" do
+ obj = mock("integer plus")
+ obj.should_receive(:coerce).with(6).and_return([6, 3])
+ (6 + obj).should == 9
+ end
+
+ it "coerces the RHS and calls #coerce even if it's private" do
+ obj = Object.new
+ class << obj
+ private def coerce(n)
+ [n, 3]
+ end
+ end
+
+ (6 + obj).should == 9
+ end
end
diff --git a/spec/ruby/core/integer/pow_spec.rb b/spec/ruby/core/integer/pow_spec.rb
index 4712911095..12a3839c40 100644
--- a/spec/ruby/core/integer/pow_spec.rb
+++ b/spec/ruby/core/integer/pow_spec.rb
@@ -16,36 +16,36 @@ describe "Integer#pow" do
end
it "works well with bignums" do
- 2.pow(61, 5843009213693951).should eql 3697379018277258
- 2.pow(62, 5843009213693952).should eql 1551748822859776
- 2.pow(63, 5843009213693953).should eql 3103497645717974
- 2.pow(64, 5843009213693954).should eql 363986077738838
+ 2.pow(61, 5843009213693951).should.eql? 3697379018277258
+ 2.pow(62, 5843009213693952).should.eql? 1551748822859776
+ 2.pow(63, 5843009213693953).should.eql? 3103497645717974
+ 2.pow(64, 5843009213693954).should.eql? 363986077738838
end
it "handles sign like #divmod does" do
- 2.pow(5, 12).should == 8
- 2.pow(5, -12).should == -4
- -2.pow(5, 12).should == 4
+ 2.pow(5, 12).should == 8
+ 2.pow(5, -12).should == -4
+ -2.pow(5, 12).should == 4
-2.pow(5, -12).should == -8
end
it "ensures all arguments are integers" do
- -> { 2.pow(5, 12.0) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/)
- -> { 2.pow(5, Rational(12, 1)) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/)
+ -> { 2.pow(5, 12.0) }.should.raise(TypeError, /2nd argument not allowed unless all arguments are integers/)
+ -> { 2.pow(5, Rational(12, 1)) }.should.raise(TypeError, /2nd argument not allowed unless all arguments are integers/)
end
it "raises TypeError for non-numeric value" do
- -> { 2.pow(5, "12") }.should raise_error(TypeError)
- -> { 2.pow(5, []) }.should raise_error(TypeError)
- -> { 2.pow(5, nil) }.should raise_error(TypeError)
+ -> { 2.pow(5, "12") }.should.raise(TypeError)
+ -> { 2.pow(5, []) }.should.raise(TypeError)
+ -> { 2.pow(5, nil) }.should.raise(TypeError)
end
it "raises a ZeroDivisionError when the given argument is 0" do
- -> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError)
+ -> { 2.pow(5, 0) }.should.raise(ZeroDivisionError)
end
it "raises a RangeError when the first argument is negative and the second argument is present" do
- -> { 2.pow(-5, 1) }.should raise_error(RangeError)
+ -> { 2.pow(-5, 1) }.should.raise(RangeError)
end
end
end
diff --git a/spec/ruby/core/integer/pred_spec.rb b/spec/ruby/core/integer/pred_spec.rb
index 86750ebfd1..fce536b5a2 100644
--- a/spec/ruby/core/integer/pred_spec.rb
+++ b/spec/ruby/core/integer/pred_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Integer#pred" do
it "returns the Integer equal to self - 1" do
- 0.pred.should eql(-1)
- -1.pred.should eql(-2)
- bignum_value.pred.should eql(bignum_value(-1))
- fixnum_min.pred.should eql(fixnum_min - 1)
- 20.pred.should eql(19)
+ 0.pred.should.eql?(-1)
+ -1.pred.should.eql?(-2)
+ bignum_value.pred.should.eql?(bignum_value(-1))
+ fixnum_min.pred.should.eql?(fixnum_min - 1)
+ 20.pred.should.eql?(19)
end
end
diff --git a/spec/ruby/core/integer/rationalize_spec.rb b/spec/ruby/core/integer/rationalize_spec.rb
index 09d741af33..272eca6911 100644
--- a/spec/ruby/core/integer/rationalize_spec.rb
+++ b/spec/ruby/core/integer/rationalize_spec.rb
@@ -12,7 +12,7 @@ describe "Integer#rationalize" do
it "returns a Rational object" do
@numbers.each do |number|
- number.rationalize.should be_an_instance_of(Rational)
+ number.rationalize.should.instance_of?(Rational)
end
end
@@ -33,7 +33,7 @@ describe "Integer#rationalize" do
end
it "raises ArgumentError when passed more than one argument" do
- -> { 1.rationalize(0.1, 0.1) }.should raise_error(ArgumentError)
- -> { 1.rationalize(0.1, 0.1, 2) }.should raise_error(ArgumentError)
+ -> { 1.rationalize(0.1, 0.1) }.should.raise(ArgumentError)
+ -> { 1.rationalize(0.1, 0.1, 2) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/integer/remainder_spec.rb b/spec/ruby/core/integer/remainder_spec.rb
index 96268b3af5..deb81fb2a5 100644
--- a/spec/ruby/core/integer/remainder_spec.rb
+++ b/spec/ruby/core/integer/remainder_spec.rb
@@ -15,17 +15,17 @@ describe "Integer#remainder" do
end
it "keeps sign of self" do
- 5.remainder( 3).should == 2
- 5.remainder(-3).should == 2
+ 5.remainder( 3).should == 2
+ 5.remainder(-3).should == 2
-5.remainder( 3).should == -2
-5.remainder(-3).should == -2
end
it "raises TypeError if passed non-numeric argument" do
- -> { 5.remainder("3") }.should raise_error(TypeError)
- -> { 5.remainder(:"3") }.should raise_error(TypeError)
- -> { 5.remainder([]) }.should raise_error(TypeError)
- -> { 5.remainder(nil) }.should raise_error(TypeError)
+ -> { 5.remainder("3") }.should.raise(TypeError)
+ -> { 5.remainder(:"3") }.should.raise(TypeError)
+ -> { 5.remainder([]) }.should.raise(TypeError)
+ -> { 5.remainder(nil) }.should.raise(TypeError)
end
end
@@ -38,14 +38,14 @@ describe "Integer#remainder" do
end
it "raises a ZeroDivisionError if other is zero and not a Float" do
- -> { bignum_value(66).remainder(0) }.should raise_error(ZeroDivisionError)
+ -> { bignum_value(66).remainder(0) }.should.raise(ZeroDivisionError)
end
it "does raises ZeroDivisionError if other is zero and a Float" do
a = bignum_value(7)
b = bignum_value(32)
- -> { a.remainder(0.0) }.should raise_error(ZeroDivisionError)
- -> { b.remainder(-0.0) }.should raise_error(ZeroDivisionError)
+ -> { a.remainder(0.0) }.should.raise(ZeroDivisionError)
+ -> { b.remainder(-0.0) }.should.raise(ZeroDivisionError)
end
end
end
diff --git a/spec/ruby/core/integer/right_shift_spec.rb b/spec/ruby/core/integer/right_shift_spec.rb
index 81405667b2..4281d3b7ab 100644
--- a/spec/ruby/core/integer/right_shift_spec.rb
+++ b/spec/ruby/core/integer/right_shift_spec.rb
@@ -54,13 +54,13 @@ describe "Integer#>> (with n >> m)" do
it "returns a Bignum == fixnum_max * 2 when fixnum_max >> -1 and n > 0" do
result = fixnum_max >> -1
- result.should be_an_instance_of(Integer)
+ result.should.instance_of?(Integer)
result.should == fixnum_max * 2
end
it "returns a Bignum == fixnum_min * 2 when fixnum_min >> -1 and n < 0" do
result = fixnum_min >> -1
- result.should be_an_instance_of(Integer)
+ result.should.instance_of?(Integer)
result.should == fixnum_min * 2
end
@@ -78,15 +78,15 @@ describe "Integer#>> (with n >> m)" do
obj = mock("a string")
obj.should_receive(:to_int).and_return("asdf")
- -> { 3 >> obj }.should raise_error(TypeError)
+ -> { 3 >> obj }.should.raise(TypeError)
end
it "raises a TypeError when passed nil" do
- -> { 3 >> nil }.should raise_error(TypeError)
+ -> { 3 >> nil }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- -> { 3 >> "4" }.should raise_error(TypeError)
+ -> { 3 >> "4" }.should.raise(TypeError)
end
end
@@ -151,13 +151,13 @@ describe "Integer#>> (with n >> m)" do
it "returns a Fixnum == fixnum_max when (fixnum_max * 2) >> 1 and n > 0" do
result = (fixnum_max * 2) >> 1
- result.should be_an_instance_of(Integer)
+ result.should.instance_of?(Integer)
result.should == fixnum_max
end
it "returns a Fixnum == fixnum_min when (fixnum_min * 2) >> 1 and n < 0" do
result = (fixnum_min * 2) >> 1
- result.should be_an_instance_of(Integer)
+ result.should.instance_of?(Integer)
result.should == fixnum_min
end
@@ -172,15 +172,15 @@ describe "Integer#>> (with n >> m)" do
obj = mock("a string")
obj.should_receive(:to_int).and_return("asdf")
- -> { @bignum >> obj }.should raise_error(TypeError)
+ -> { @bignum >> obj }.should.raise(TypeError)
end
it "raises a TypeError when passed nil" do
- -> { @bignum >> nil }.should raise_error(TypeError)
+ -> { @bignum >> nil }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- -> { @bignum >> "4" }.should raise_error(TypeError)
+ -> { @bignum >> "4" }.should.raise(TypeError)
end
end
@@ -203,31 +203,31 @@ describe "Integer#>> (with n >> m)" do
(bignum_value >> (2**40)).should == 0
end
- ruby_bug "#18517", ""..."3.2" do
- it "returns 0 when m < 0 long and n == 0" do
- (0 >> -(2**40)).should == 0
- end
+ it "returns 0 when m < 0 long and n == 0" do
+ (0 >> -(2**40)).should == 0
end
it "returns 0 when m < 0 bignum and n == 0" do
(0 >> -bignum_value).should == 0
end
- ruby_bug "#18518", ""..."3.3" do
- it "raises NoMemoryError when m < 0 and n != 0" do
- coerce_long = mock("long")
- coerce_long.stub!(:to_int).and_return(-(2**40))
- coerce_bignum = mock("bignum")
- coerce_bignum.stub!(:to_int).and_return(-bignum_value)
- exps = [-(2**40), -bignum_value, coerce_long, coerce_bignum]
-
- exps.each { |exp|
- -> { (1 >> exp) }.should raise_error(NoMemoryError)
- -> { (-1 >> exp) }.should raise_error(NoMemoryError)
- -> { (bignum_value >> exp) }.should raise_error(NoMemoryError)
- -> { (-bignum_value >> exp) }.should raise_error(NoMemoryError)
- }
- end
+ it "raises RangeError when m < 0 and n != 0" do
+ # https://bugs.ruby-lang.org/issues/18518#note-9
+ limit = RUBY_ENGINE == 'ruby' ? 2**67 : 2**32
+
+ coerce_long = mock("long")
+ coerce_long.stub!(:to_int).and_return(-limit)
+ coerce_bignum = mock("bignum")
+ coerce_bignum.stub!(:to_int).and_return(-bignum_value)
+ exps = [-limit, coerce_long]
+ exps << -bignum_value << coerce_bignum if bignum_value >= limit
+
+ exps.each { |exp|
+ -> { (1 >> exp) }.should.raise(RangeError, 'shift width too big')
+ -> { (-1 >> exp) }.should.raise(RangeError, 'shift width too big')
+ -> { (bignum_value >> exp) }.should.raise(RangeError, 'shift width too big')
+ -> { (-bignum_value >> exp) }.should.raise(RangeError, 'shift width too big')
+ }
end
end
end
diff --git a/spec/ruby/core/integer/round_spec.rb b/spec/ruby/core/integer/round_spec.rb
index 45ac126fd3..a3f11e7a76 100644
--- a/spec/ruby/core/integer/round_spec.rb
+++ b/spec/ruby/core/integer/round_spec.rb
@@ -8,39 +8,37 @@ describe "Integer#round" do
# redmine:5228
it "returns itself rounded if passed a negative value" do
- +249.round(-2).should eql(+200)
- -249.round(-2).should eql(-200)
- (+25 * 10**70 - 1).round(-71).should eql(+20 * 10**70)
- (-25 * 10**70 + 1).round(-71).should eql(-20 * 10**70)
+ +249.round(-2).should.eql?(+200)
+ -249.round(-2).should.eql?(-200)
+ (+25 * 10**70 - 1).round(-71).should.eql?(+20 * 10**70)
+ (-25 * 10**70 + 1).round(-71).should.eql?(-20 * 10**70)
end
it "returns itself rounded to nearest if passed a negative value" do
- +250.round(-2).should eql(+300)
- -250.round(-2).should eql(-300)
- (+25 * 10**70).round(-71).should eql(+30 * 10**70)
- (-25 * 10**70).round(-71).should eql(-30 * 10**70)
+ +250.round(-2).should.eql?(+300)
+ -250.round(-2).should.eql?(-300)
+ (+25 * 10**70).round(-71).should.eql?(+30 * 10**70)
+ (-25 * 10**70).round(-71).should.eql?(-30 * 10**70)
end
- platform_is_not wordsize: 32 do
- it "raises a RangeError when passed a big negative value" do
- -> { 42.round(fixnum_min) }.should raise_error(RangeError)
- end
+ it "raises a RangeError when passed a big negative value" do
+ -> { 42.round(min_long - 1) }.should.raise(RangeError)
end
it "raises a RangeError when passed Float::INFINITY" do
- -> { 42.round(Float::INFINITY) }.should raise_error(RangeError)
+ -> { 42.round(Float::INFINITY) }.should.raise(RangeError)
end
it "raises a RangeError when passed a beyond signed int" do
- -> { 42.round(1<<31) }.should raise_error(RangeError)
+ -> { 42.round(1<<31) }.should.raise(RangeError)
end
it "raises a TypeError when passed a String" do
- -> { 42.round("4") }.should raise_error(TypeError)
+ -> { 42.round("4") }.should.raise(TypeError)
end
it "raises a TypeError when its argument cannot be converted to an Integer" do
- -> { 42.round(nil) }.should raise_error(TypeError)
+ -> { 42.round(nil) }.should.raise(TypeError)
end
it "calls #to_int on the argument to convert it to an Integer" do
@@ -52,32 +50,32 @@ describe "Integer#round" do
it "raises a TypeError when #to_int does not return an Integer" do
obj = mock("Object")
obj.stub!(:to_int).and_return([])
- -> { 42.round(obj) }.should raise_error(TypeError)
+ -> { 42.round(obj) }.should.raise(TypeError)
end
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)
- 25.round(-1, half: nil).should eql(30)
- 35.round(-1, half: :up).should eql(40)
- 35.round(-1, half: :down).should eql(30)
- 35.round(-1, half: :even).should eql(40)
- 35.round(-1, half: nil).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)
- (-25).round(-1, half: nil).should eql(-30)
+ 25.round(-1, half: :up).should.eql?(30)
+ 25.round(-1, half: :down).should.eql?(20)
+ 25.round(-1, half: :even).should.eql?(20)
+ 25.round(-1, half: nil).should.eql?(30)
+ 35.round(-1, half: :up).should.eql?(40)
+ 35.round(-1, half: :down).should.eql?(30)
+ 35.round(-1, half: :even).should.eql?(40)
+ 35.round(-1, half: nil).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)
+ (-25).round(-1, half: nil).should.eql?(-30)
end
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)
+ 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
it "raises ArgumentError for an unknown rounding mode" do
- -> { 42.round(-1, half: :foo) }.should raise_error(ArgumentError, /invalid rounding mode: foo/)
- -> { 42.round(1, half: :foo) }.should raise_error(ArgumentError, /invalid rounding mode: foo/)
+ -> { 42.round(-1, half: :foo) }.should.raise(ArgumentError, /invalid rounding mode: foo/)
+ -> { 42.round(1, half: :foo) }.should.raise(ArgumentError, /invalid rounding mode: foo/)
end
end
diff --git a/spec/ruby/core/integer/shared/arithmetic_coerce.rb b/spec/ruby/core/integer/shared/arithmetic_coerce.rb
index 4c0cbcb999..561b18fe52 100644
--- a/spec/ruby/core/integer/shared/arithmetic_coerce.rb
+++ b/spec/ruby/core/integer/shared/arithmetic_coerce.rb
@@ -1,31 +1,11 @@
require_relative '../fixtures/classes'
-describe :integer_arithmetic_coerce_rescue, shared: true do
- it "rescues exception (StandardError and subclasses) raised in other#coerce and raises TypeError" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError)
-
- # e.g. 1 + b
- -> { 1.send(@method, b) }.should raise_error(TypeError, /MockObject can't be coerced into Integer/)
- end
-
- it "does not rescue Exception and StandardError siblings raised in other#coerce" do
- [Exception, NoMemoryError].each do |exception|
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(exception)
-
- # e.g. 1 + b
- -> { 1.send(@method, b) }.should raise_error(exception)
- end
- end
-end
-
describe :integer_arithmetic_coerce_not_rescue, shared: true do
it "does not rescue exception raised in other#coerce" do
b = mock("numeric with failed #coerce")
b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError)
# e.g. 1 + b
- -> { 1.send(@method, b) }.should raise_error(IntegerSpecs::CoerceError)
+ -> { 1.send(@method, b) }.should.raise(IntegerSpecs::CoerceError)
end
end
diff --git a/spec/ruby/core/integer/shared/comparison_coerce.rb b/spec/ruby/core/integer/shared/comparison_coerce.rb
index af52f5e99b..4bb7404183 100644
--- a/spec/ruby/core/integer/shared/comparison_coerce.rb
+++ b/spec/ruby/core/integer/shared/comparison_coerce.rb
@@ -6,6 +6,6 @@ describe :integer_comparison_coerce_not_rescue, shared: true do
b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError)
# e.g. 1 > b
- -> { 1.send(@method, b) }.should raise_error(IntegerSpecs::CoerceError)
+ -> { 1.send(@method, b) }.should.raise(IntegerSpecs::CoerceError)
end
end
diff --git a/spec/ruby/core/integer/shared/equal.rb b/spec/ruby/core/integer/shared/equal.rb
index ecee17831c..c621ba3f81 100644
--- a/spec/ruby/core/integer/shared/equal.rb
+++ b/spec/ruby/core/integer/shared/equal.rb
@@ -54,5 +54,10 @@ describe :integer_equal, shared: true do
@bignum.send(@method, obj).should == true
@bignum.send(@method, obj).should == false
end
+
+ it "does not lose precision when comparing with a Float" do
+ (bignum_value(1).send(@method, bignum_value.to_f)).should == false
+ (bignum_value.send(@method, bignum_value.to_f)).should == true
+ end
end
end
diff --git a/spec/ruby/core/integer/shared/exponent.rb b/spec/ruby/core/integer/shared/exponent.rb
index 15df518b7e..0be13859f9 100644
--- a/spec/ruby/core/integer/shared/exponent.rb
+++ b/spec/ruby/core/integer/shared/exponent.rb
@@ -1,62 +1,78 @@
describe :integer_exponent, shared: true do
context "fixnum" do
it "returns self raised to the given power" do
- 2.send(@method, 0).should eql 1
- 2.send(@method, 1).should eql 2
- 2.send(@method, 2).should eql 4
+ 2.send(@method, 0).should.eql? 1
+ 2.send(@method, 1).should.eql? 2
+ 2.send(@method, 2).should.eql? 4
- 9.send(@method, 0.5).should eql 3.0
- 9.send(@method, Rational(1, 2)).should eql 3.0
+ 9.send(@method, 0.5).should.eql? 3.0
+ 9.send(@method, Rational(1, 2)).should.eql? 3.0
5.send(@method, -1).to_f.to_s.should == '0.2'
- 2.send(@method, 40).should eql 1099511627776
+ 2.send(@method, 40).should.eql? 1099511627776
end
it "overflows the answer to a bignum transparently" do
- 2.send(@method, 29).should eql 536870912
- 2.send(@method, 30).should eql 1073741824
- 2.send(@method, 31).should eql 2147483648
- 2.send(@method, 32).should eql 4294967296
+ 2.send(@method, 29).should.eql? 536870912
+ 2.send(@method, 30).should.eql? 1073741824
+ 2.send(@method, 31).should.eql? 2147483648
+ 2.send(@method, 32).should.eql? 4294967296
- 2.send(@method, 61).should eql 2305843009213693952
- 2.send(@method, 62).should eql 4611686018427387904
- 2.send(@method, 63).should eql 9223372036854775808
- 2.send(@method, 64).should eql 18446744073709551616
- 8.send(@method, 23).should eql 590295810358705651712
+ 2.send(@method, 61).should.eql? 2305843009213693952
+ 2.send(@method, 62).should.eql? 4611686018427387904
+ 2.send(@method, 63).should.eql? 9223372036854775808
+ 2.send(@method, 64).should.eql? 18446744073709551616
+ 8.send(@method, 23).should.eql? 590295810358705651712
end
it "raises negative numbers to the given power" do
- (-2).send(@method, 29).should eql(-536870912)
- (-2).send(@method, 30).should eql(1073741824)
- (-2).send(@method, 31).should eql(-2147483648)
- (-2).send(@method, 32).should eql(4294967296)
- (-2).send(@method, 33).should eql(-8589934592)
+ (-2).send(@method, 29).should.eql?(-536870912)
+ (-2).send(@method, 30).should.eql?(1073741824)
+ (-2).send(@method, 31).should.eql?(-2147483648)
+ (-2).send(@method, 32).should.eql?(4294967296)
+ (-2).send(@method, 33).should.eql?(-8589934592)
- (-2).send(@method, 61).should eql(-2305843009213693952)
- (-2).send(@method, 62).should eql(4611686018427387904)
- (-2).send(@method, 63).should eql(-9223372036854775808)
- (-2).send(@method, 64).should eql(18446744073709551616)
- (-2).send(@method, 65).should eql(-36893488147419103232)
+ (-2).send(@method, 61).should.eql?(-2305843009213693952)
+ (-2).send(@method, 62).should.eql?(4611686018427387904)
+ (-2).send(@method, 63).should.eql?(-9223372036854775808)
+ (-2).send(@method, 64).should.eql?(18446744073709551616)
+ (-2).send(@method, 65).should.eql?(-36893488147419103232)
end
it "can raise 1 to a bignum safely" do
- 1.send(@method, 4611686018427387904).should eql 1
+ 1.send(@method, 4611686018427387904).should.eql? 1
end
it "can raise -1 to a bignum safely" do
- (-1).send(@method, 4611686018427387904).should eql(1)
- (-1).send(@method, 4611686018427387905).should eql(-1)
+ (-1).send(@method, 4611686018427387904).should.eql?(1)
+ (-1).send(@method, 4611686018427387905).should.eql?(-1)
end
- it "returns Float::INFINITY when the number is too big" do
- -> {
- 2.send(@method, 427387904).should == Float::INFINITY
- }.should complain(/warning: in a\*\*b, b may be too big/)
+ ruby_version_is ""..."3.4" do
+ it "returns Float::INFINITY when the number is too big" do
+ -> {
+ 2.send(@method, 427387904).should == Float::INFINITY
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "returns an Integer for results larger than the old 32MB limit" do
+ # 2 ** 40000000 requires 40000001 bits
+ # This exceeds the old 32MB limit but is within the new 16GB limit
+ result = 2.send(@method, 40000000)
+ result.should.is_a?(Integer)
+ result.bit_length.should == 40000001
+ end
+
+ it "raises an ArgumentError when the result size exceeds the limit" do
+ -> { 100000000.send(@method, 1000000000) }.should.raise(ArgumentError)
+ end
end
it "raises a ZeroDivisionError for 0 ** -1" do
- -> { 0.send(@method, -1) }.should raise_error(ZeroDivisionError)
- -> { 0.send(@method, Rational(-1, 1)) }.should raise_error(ZeroDivisionError)
+ -> { 0.send(@method, -1) }.should.raise(ZeroDivisionError)
+ -> { 0.send(@method, Rational(-1, 1)) }.should.raise(ZeroDivisionError)
end
it "returns Float::INFINITY for 0 ** -1.0" do
@@ -64,9 +80,9 @@ describe :integer_exponent, shared: true do
end
it "raises a TypeError when given a non-numeric power" do
- -> { 13.send(@method, "10") }.should raise_error(TypeError)
- -> { 13.send(@method, :symbol) }.should raise_error(TypeError)
- -> { 13.send(@method, nil) }.should raise_error(TypeError)
+ -> { 13.send(@method, "10") }.should.raise(TypeError)
+ -> { 13.send(@method, :symbol) }.should.raise(TypeError)
+ -> { 13.send(@method, nil) }.should.raise(TypeError)
end
it "coerces power and calls #**" do
@@ -103,18 +119,38 @@ describe :integer_exponent, shared: true do
end
it "raises a TypeError when given a non-Integer" do
- -> { @bignum.send(@method, mock('10')) }.should raise_error(TypeError)
- -> { @bignum.send(@method, "10") }.should raise_error(TypeError)
- -> { @bignum.send(@method, :symbol) }.should raise_error(TypeError)
- end
-
- it "switch to a Float when the values is too big" do
- flt = nil
- -> {
- flt = @bignum.send(@method, @bignum)
- }.should complain(/warning: in a\*\*b, b may be too big/)
- flt.should be_kind_of(Float)
- flt.infinite?.should == 1
+ -> { @bignum.send(@method, mock('10')) }.should.raise(TypeError)
+ -> { @bignum.send(@method, "10") }.should.raise(TypeError)
+ -> { @bignum.send(@method, :symbol) }.should.raise(TypeError)
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "switch to a Float when the values is too big" do
+ flt = nil
+ -> {
+ flt = @bignum.send(@method, @bignum)
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ flt.should.is_a?(Float)
+ flt.infinite?.should == 1
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "returns an Integer for large Bignum results exceeding the old limit" do
+ # (2 ** 70) ** 500000 requires 35000001 bits
+ # This exceeds the old 32MB limit but is within the new 16GB limit
+ bignum_base = 2 ** 70
+ result = bignum_base.send(@method, 500000)
+ result.should.is_a?(Integer)
+ result.bit_length.should == 35000001
+ end
+
+ it "raises an ArgumentError when Bignum result exceeds the limit" do
+ # @bignum ** @bignum would require enormous memory
+ -> {
+ @bignum.send(@method, @bignum)
+ }.should.raise(ArgumentError)
+ end
end
it "returns a complex number when negative and raised to a fractional power" do
diff --git a/spec/ruby/core/integer/shared/integer_ceil_precision.rb b/spec/ruby/core/integer/shared/integer_ceil_precision.rb
new file mode 100644
index 0000000000..b23c17937f
--- /dev/null
+++ b/spec/ruby/core/integer/shared/integer_ceil_precision.rb
@@ -0,0 +1,54 @@
+describe :integer_ceil_precision, shared: true do
+ context "precision is zero" do
+ it "returns Integer equal to self" do
+ send(@method, 0).ceil(0).should.eql?(0)
+ send(@method, 123).ceil(0).should.eql?(123)
+ send(@method, -123).ceil(0).should.eql?(-123)
+ end
+ end
+
+ context "precision is positive" do
+ it "returns self" do
+ send(@method, 0).ceil(1).should.eql?(send(@method, 0))
+ send(@method, 0).ceil(10).should.eql?(send(@method, 0))
+
+ send(@method, 123).ceil(10).should.eql?(send(@method, 123))
+ send(@method, -123).ceil(10).should.eql?(send(@method, -123))
+ end
+ end
+
+ context "precision is negative" do
+ it "always returns 0 when self is 0" do
+ send(@method, 0).ceil(-1).should.eql?(0)
+ send(@method, 0).ceil(-10).should.eql?(0)
+ end
+
+ it "returns Integer equal to self if there are already at least precision.abs trailing zeros" do
+ send(@method, 10).ceil(-1).should.eql?(10)
+ send(@method, 100).ceil(-1).should.eql?(100)
+ send(@method, 100).ceil(-2).should.eql?(100)
+ send(@method, -10).ceil(-1).should.eql?(-10)
+ send(@method, -100).ceil(-1).should.eql?(-100)
+ send(@method, -100).ceil(-2).should.eql?(-100)
+ end
+
+ it "returns smallest Integer greater than self with at least precision.abs trailing zeros" do
+ send(@method, 123).ceil(-1).should.eql?(130)
+ send(@method, 123).ceil(-2).should.eql?(200)
+ send(@method, 123).ceil(-3).should.eql?(1000)
+
+ send(@method, -123).ceil(-1).should.eql?(-120)
+ send(@method, -123).ceil(-2).should.eql?(-100)
+ send(@method, -123).ceil(-3).should.eql?(0)
+
+ send(@method, 100).ceil(-3).should.eql?(1000)
+ send(@method, -100).ceil(-3).should.eql?(0)
+ end
+
+ # Bug #20654
+ it "returns 10**precision.abs when precision.abs has more digits than self" do
+ send(@method, 123).ceil(-20).should.eql?(100000000000000000000)
+ send(@method, 123).ceil(-50).should.eql?(100000000000000000000000000000000000000000000000000)
+ end
+ end
+end
diff --git a/spec/ruby/core/integer/shared/integer_floor_precision.rb b/spec/ruby/core/integer/shared/integer_floor_precision.rb
new file mode 100644
index 0000000000..6247907d4c
--- /dev/null
+++ b/spec/ruby/core/integer/shared/integer_floor_precision.rb
@@ -0,0 +1,42 @@
+describe :integer_floor_precision, shared: true do
+ context "precision is zero" do
+ it "returns integer self" do
+ send(@method, 0).floor(0).should.eql?(0)
+ send(@method, 123).floor(0).should.eql?(123)
+ send(@method, -123).floor(0).should.eql?(-123)
+ end
+ end
+
+ context "precision is positive" do
+ it "returns self" do
+ send(@method, 0).floor(1).should.eql?(send(@method, 0))
+ send(@method, 0).floor(10).should.eql?(send(@method, 0))
+
+ send(@method, 123).floor(10).should.eql?(send(@method, 123))
+ send(@method, -123).floor(10).should.eql?(send(@method, -123))
+ end
+ end
+
+ context "precision is negative" do
+ it "always returns 0 when self is 0" do
+ send(@method, 0).floor(-1).should.eql?(0)
+ send(@method, 0).floor(-10).should.eql?(0)
+ end
+
+ it "returns largest integer less than self with at least precision.abs trailing zeros" do
+ send(@method, 123).floor(-1).should.eql?(120)
+ send(@method, 123).floor(-2).should.eql?(100)
+ send(@method, 123).floor(-3).should.eql?(0)
+
+ send(@method, -123).floor(-1).should.eql?(-130)
+ send(@method, -123).floor(-2).should.eql?(-200)
+ send(@method, -123).floor(-3).should.eql?(-1000)
+ end
+
+ # Bug #20654
+ it "returns -(10**precision.abs) when self is negative and precision.abs is larger than the number digits of self" do
+ send(@method, -123).floor(-20).should.eql?(-100000000000000000000)
+ send(@method, -123).floor(-50).should.eql?(-100000000000000000000000000000000000000000000000000)
+ end
+ end
+end
diff --git a/spec/ruby/core/integer/shared/integer_rounding.rb b/spec/ruby/core/integer/shared/integer_rounding.rb
index 56d1819f84..92f2a2327c 100644
--- a/spec/ruby/core/integer/shared/integer_rounding.rb
+++ b/spec/ruby/core/integer/shared/integer_rounding.rb
@@ -1,19 +1,19 @@
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)
+ v.send(@method).should.eql?(v)
end
end
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)
+ v.send(@method, 0).should.eql?(v)
end
end
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)
+ v.send(@method, 42).should.eql?(v)
end
end
end
diff --git a/spec/ruby/core/integer/shared/modulo.rb b/spec/ruby/core/integer/shared/modulo.rb
index f678a10806..d0b5e26ed5 100644
--- a/spec/ruby/core/integer/shared/modulo.rb
+++ b/spec/ruby/core/integer/shared/modulo.rb
@@ -1,6 +1,12 @@
describe :integer_modulo, shared: true do
context "fixnum" do
it "returns the modulus obtained from dividing self by the given argument" do
+ # test all possible combinations:
+ # - integer/double/bignum argument
+ # - positive/negative argument
+ # - positive/negative self
+ # - self greater/smaller than argument
+
13.send(@method, 4).should == 1
4.send(@method, 13).should == 4
@@ -16,59 +22,93 @@ describe :integer_modulo, shared: true do
(200).send(@method, -256).should == -56
(1000).send(@method, -512).should == -24
+ 13.send(@method, -4.0).should == -3.0
+ 4.send(@method, -13.0).should == -9.0
+
+ -13.send(@method, -4.0).should == -1.0
+ -4.send(@method, -13.0).should == -4.0
+
+ -13.send(@method, 4.0).should == 3.0
+ -4.send(@method, 13.0).should == 9.0
+
1.send(@method, 2.0).should == 1.0
200.send(@method, bignum_value).should == 200
+
+ 4.send(@method, bignum_value(10)).should == 4
+ 4.send(@method, -bignum_value(10)).should == -18446744073709551622
+ -4.send(@method, bignum_value(10)).should == 18446744073709551622
+ -4.send(@method, -bignum_value(10)).should == -4
end
it "raises a ZeroDivisionError when the given argument is 0" do
- -> { 13.send(@method, 0) }.should raise_error(ZeroDivisionError)
- -> { 0.send(@method, 0) }.should raise_error(ZeroDivisionError)
- -> { -10.send(@method, 0) }.should raise_error(ZeroDivisionError)
+ -> { 13.send(@method, 0) }.should.raise(ZeroDivisionError)
+ -> { 0.send(@method, 0) }.should.raise(ZeroDivisionError)
+ -> { -10.send(@method, 0) }.should.raise(ZeroDivisionError)
end
it "raises a ZeroDivisionError when the given argument is 0 and a Float" do
- -> { 0.send(@method, 0.0) }.should raise_error(ZeroDivisionError)
- -> { 10.send(@method, 0.0) }.should raise_error(ZeroDivisionError)
- -> { -10.send(@method, 0.0) }.should raise_error(ZeroDivisionError)
+ -> { 0.send(@method, 0.0) }.should.raise(ZeroDivisionError)
+ -> { 10.send(@method, 0.0) }.should.raise(ZeroDivisionError)
+ -> { -10.send(@method, 0.0) }.should.raise(ZeroDivisionError)
end
it "raises a TypeError when given a non-Integer" do
-> {
(obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10)
13.send(@method, obj)
- }.should raise_error(TypeError)
- -> { 13.send(@method, "10") }.should raise_error(TypeError)
- -> { 13.send(@method, :symbol) }.should raise_error(TypeError)
+ }.should.raise(TypeError)
+ -> { 13.send(@method, "10") }.should.raise(TypeError)
+ -> { 13.send(@method, :symbol) }.should.raise(TypeError)
end
end
context "bignum" do
before :each do
- @bignum = bignum_value
+ @bignum = bignum_value(10)
end
it "returns the modulus obtained from dividing self by the given argument" do
+ # test all possible combinations:
+ # - integer/double/bignum argument
+ # - positive/negative argument
+ # - positive/negative self
+ # - self greater/smaller than argument
+
@bignum.send(@method, 5).should == 1
@bignum.send(@method, -5).should == -4
- @bignum.send(@method, -100).should == -84
+ (-@bignum).send(@method, 5).should == 4
+ (-@bignum).send(@method, -5).should == -1
+
@bignum.send(@method, 2.22).should be_close(1.5603603603605034, TOLERANCE)
- @bignum.send(@method, bignum_value(10)).should == 18446744073709551616
+ @bignum.send(@method, -2.22).should be_close(-0.6596396396394968, TOLERANCE)
+ (-@bignum).send(@method, 2.22).should be_close(0.6596396396394968, TOLERANCE)
+ (-@bignum).send(@method, -2.22).should be_close(-1.5603603603605034, TOLERANCE)
+
+ @bignum.send(@method, @bignum + 10).should == 18446744073709551626
+ @bignum.send(@method, -(@bignum + 10)).should == -10
+ (-@bignum).send(@method, @bignum + 10).should == 10
+ (-@bignum).send(@method, -(@bignum + 10)).should == -18446744073709551626
+
+ (@bignum + 10).send(@method, @bignum).should == 10
+ (@bignum + 10).send(@method, -@bignum).should == -18446744073709551616
+ (-(@bignum + 10)).send(@method, @bignum).should == 18446744073709551616
+ (-(@bignum + 10)).send(@method, -@bignum).should == -10
end
it "raises a ZeroDivisionError when the given argument is 0" do
- -> { @bignum.send(@method, 0) }.should raise_error(ZeroDivisionError)
- -> { (-@bignum).send(@method, 0) }.should raise_error(ZeroDivisionError)
+ -> { @bignum.send(@method, 0) }.should.raise(ZeroDivisionError)
+ -> { (-@bignum).send(@method, 0) }.should.raise(ZeroDivisionError)
end
it "raises a ZeroDivisionError when the given argument is 0 and a Float" do
- -> { @bignum.send(@method, 0.0) }.should raise_error(ZeroDivisionError)
- -> { -@bignum.send(@method, 0.0) }.should raise_error(ZeroDivisionError)
+ -> { @bignum.send(@method, 0.0) }.should.raise(ZeroDivisionError)
+ -> { -@bignum.send(@method, 0.0) }.should.raise(ZeroDivisionError)
end
it "raises a TypeError when given a non-Integer" do
- -> { @bignum.send(@method, mock('10')) }.should raise_error(TypeError)
- -> { @bignum.send(@method, "10") }.should raise_error(TypeError)
- -> { @bignum.send(@method, :symbol) }.should raise_error(TypeError)
+ -> { @bignum.send(@method, mock('10')) }.should.raise(TypeError)
+ -> { @bignum.send(@method, "10") }.should.raise(TypeError)
+ -> { @bignum.send(@method, :symbol) }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/integer/shared/to_i.rb b/spec/ruby/core/integer/shared/to_i.rb
index 7b974cd3a7..2b6a50484a 100644
--- a/spec/ruby/core/integer/shared/to_i.rb
+++ b/spec/ruby/core/integer/shared/to_i.rb
@@ -1,8 +1,8 @@
describe :integer_to_i, shared: true do
it "returns self" do
- 10.send(@method).should eql(10)
- (-15).send(@method).should eql(-15)
- bignum_value.send(@method).should eql(bignum_value)
- (-bignum_value).send(@method).should eql(-bignum_value)
+ 10.send(@method).should.eql?(10)
+ (-15).send(@method).should.eql?(-15)
+ bignum_value.send(@method).should.eql?(bignum_value)
+ (-bignum_value).send(@method).should.eql?(-bignum_value)
end
end
diff --git a/spec/ruby/core/integer/size_spec.rb b/spec/ruby/core/integer/size_spec.rb
index a134e82384..725e9eb062 100644
--- a/spec/ruby/core/integer/size_spec.rb
+++ b/spec/ruby/core/integer/size_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Integer#size" do
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
it "returns the number of bytes in the machine representation of self" do
-1.size.should == 4
0.size.should == 4
@@ -9,7 +9,7 @@ describe "Integer#size" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "returns the number of bytes in the machine representation of self" do
-1.size.should == 8
0.size.should == 8
diff --git a/spec/ruby/core/integer/sqrt_spec.rb b/spec/ruby/core/integer/sqrt_spec.rb
index 4149ca2cc9..bf90ea747e 100644
--- a/spec/ruby/core/integer/sqrt_spec.rb
+++ b/spec/ruby/core/integer/sqrt_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Integer.sqrt" do
it "returns an integer" do
- Integer.sqrt(10).should be_kind_of(Integer)
+ Integer.sqrt(10).should.is_a?(Integer)
end
it "returns the integer square root of the argument" do
@@ -14,7 +14,7 @@ describe "Integer.sqrt" do
end
it "raises a Math::DomainError if the argument is negative" do
- -> { Integer.sqrt(-4) }.should raise_error(Math::DomainError)
+ -> { Integer.sqrt(-4) }.should.raise(Math::DomainError)
end
it "accepts any argument that can be coerced to Integer" do
@@ -26,6 +26,6 @@ describe "Integer.sqrt" do
end
it "raises a TypeError if the argument cannot be coerced to Integer" do
- -> { Integer.sqrt("test") }.should raise_error(TypeError)
+ -> { Integer.sqrt("test") }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/integer/to_f_spec.rb b/spec/ruby/core/integer/to_f_spec.rb
index 9f1df9ada9..0681236095 100644
--- a/spec/ruby/core/integer/to_f_spec.rb
+++ b/spec/ruby/core/integer/to_f_spec.rb
@@ -11,9 +11,9 @@ describe "Integer#to_f" do
context "bignum" do
it "returns self converted to a Float" do
- bignum_value(0x4000_0aa0_0bb0_0000).to_f.should eql(23_058_441_774_644_068_352.0)
- bignum_value(0x8000_0000_0000_0ccc).to_f.should eql(27_670_116_110_564_330_700.0)
- (-bignum_value(99)).to_f.should eql(-18_446_744_073_709_551_715.0)
+ bignum_value(0x4000_0aa0_0bb0_0000).to_f.should.eql?(23_058_441_774_644_068_352.0)
+ bignum_value(0x8000_0000_0000_0ccc).to_f.should.eql?(27_670_116_110_564_330_700.0)
+ (-bignum_value(99)).to_f.should.eql?(-18_446_744_073_709_551_715.0)
end
it "converts number close to Float::MAX without exceeding MAX or producing NaN" do
diff --git a/spec/ruby/core/integer/to_r_spec.rb b/spec/ruby/core/integer/to_r_spec.rb
index 7732bedca1..2649c7c78d 100644
--- a/spec/ruby/core/integer/to_r_spec.rb
+++ b/spec/ruby/core/integer/to_r_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Integer#to_r" do
it "returns a Rational object" do
- 309.to_r.should be_an_instance_of(Rational)
+ 309.to_r.should.instance_of?(Rational)
end
it "constructs a rational number with self as the numerator" do
@@ -15,12 +15,12 @@ describe "Integer#to_r" do
it "works even if self is a Bignum" do
bignum = 99999**999
- bignum.should be_an_instance_of(Integer)
+ bignum.should.instance_of?(Integer)
bignum.to_r.should == Rational(bignum, 1)
end
it "raises an ArgumentError if given any arguments" do
- -> { 287.to_r(2) }.should raise_error(ArgumentError)
- -> { 9102826.to_r(309, [], 71) }.should raise_error(ArgumentError)
+ -> { 287.to_r(2) }.should.raise(ArgumentError)
+ -> { 9102826.to_r(309, [], 71) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/integer/to_s_spec.rb b/spec/ruby/core/integer/to_s_spec.rb
index ca08dad95c..4970a2a12f 100644
--- a/spec/ruby/core/integer/to_s_spec.rb
+++ b/spec/ruby/core/integer/to_s_spec.rb
@@ -13,10 +13,10 @@ describe "Integer#to_s" do
end
it "raises an ArgumentError if the base is less than 2 or higher than 36" do
- -> { 123.to_s(-1) }.should raise_error(ArgumentError)
- -> { 123.to_s(0) }.should raise_error(ArgumentError)
- -> { 123.to_s(1) }.should raise_error(ArgumentError)
- -> { 123.to_s(37) }.should raise_error(ArgumentError)
+ -> { 123.to_s(-1) }.should.raise(ArgumentError)
+ -> { 123.to_s(0) }.should.raise(ArgumentError)
+ -> { 123.to_s(1) }.should.raise(ArgumentError)
+ -> { 123.to_s(37) }.should.raise(ArgumentError)
end
end
@@ -39,12 +39,12 @@ describe "Integer#to_s" do
it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do
Encoding.default_internal = nil
- 1.to_s.encoding.should equal(Encoding::US_ASCII)
+ 1.to_s.encoding.should.equal?(Encoding::US_ASCII)
end
it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do
Encoding.default_internal = Encoding::IBM437
- 1.to_s.encoding.should equal(Encoding::US_ASCII)
+ 1.to_s.encoding.should.equal?(Encoding::US_ASCII)
end
end
@@ -59,10 +59,10 @@ describe "Integer#to_s" do
end
it "raises an ArgumentError if the base is less than 2 or higher than 36" do
- -> { 123.to_s(-1) }.should raise_error(ArgumentError)
- -> { 123.to_s(0) }.should raise_error(ArgumentError)
- -> { 123.to_s(1) }.should raise_error(ArgumentError)
- -> { 123.to_s(37) }.should raise_error(ArgumentError)
+ -> { 123.to_s(-1) }.should.raise(ArgumentError)
+ -> { 123.to_s(0) }.should.raise(ArgumentError)
+ -> { 123.to_s(1) }.should.raise(ArgumentError)
+ -> { 123.to_s(37) }.should.raise(ArgumentError)
end
end
@@ -84,12 +84,12 @@ describe "Integer#to_s" do
it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do
Encoding.default_internal = nil
- bignum_value.to_s.encoding.should equal(Encoding::US_ASCII)
+ bignum_value.to_s.encoding.should.equal?(Encoding::US_ASCII)
end
it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do
Encoding.default_internal = Encoding::IBM437
- bignum_value.to_s.encoding.should equal(Encoding::US_ASCII)
+ bignum_value.to_s.encoding.should.equal?(Encoding::US_ASCII)
end
end
end
diff --git a/spec/ruby/core/integer/truncate_spec.rb b/spec/ruby/core/integer/truncate_spec.rb
index db16e74be4..b95c183cf3 100644
--- a/spec/ruby/core/integer/truncate_spec.rb
+++ b/spec/ruby/core/integer/truncate_spec.rb
@@ -8,12 +8,12 @@ describe "Integer#truncate" 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)
+ 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
diff --git a/spec/ruby/core/integer/try_convert_spec.rb b/spec/ruby/core/integer/try_convert_spec.rb
index 45c66eec79..8c9b4276b9 100644
--- a/spec/ruby/core/integer/try_convert_spec.rb
+++ b/spec/ruby/core/integer/try_convert_spec.rb
@@ -1,40 +1,48 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.1" do
- describe "Integer.try_convert" do
- it "returns the argument if it's an Integer" do
- x = 42
- Integer.try_convert(x).should equal(x)
- end
+describe "Integer.try_convert" do
+ it "returns the argument if it's an Integer" do
+ x = 42
+ Integer.try_convert(x).should.equal?(x)
+ end
- it "returns nil when the argument does not respond to #to_int" do
- Integer.try_convert(Object.new).should be_nil
- end
+ it "returns nil when the argument does not respond to #to_int" do
+ Integer.try_convert(Object.new).should == nil
+ end
- it "sends #to_int to the argument and returns the result if it's nil" do
- obj = mock("to_int")
- obj.should_receive(:to_int).and_return(nil)
- Integer.try_convert(obj).should be_nil
- end
+ it "sends #to_int to the argument and returns the result if it's nil" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(nil)
+ Integer.try_convert(obj).should == nil
+ end
- it "sends #to_int to the argument and returns the result if it's an Integer" do
- x = 234
- obj = mock("to_int")
- obj.should_receive(:to_int).and_return(x)
- Integer.try_convert(obj).should equal(x)
- end
+ it "sends #to_int to the argument and returns the result if it's an Integer" do
+ x = 234
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(x)
+ Integer.try_convert(obj).should.equal?(x)
+ end
- it "sends #to_int to the argument and raises TypeError if it's not a kind of Integer" do
- obj = mock("to_int")
- obj.should_receive(:to_int).and_return(Object.new)
- -> { Integer.try_convert obj }.should raise_error(TypeError)
- end
+ it "sends #to_int to the argument and raises TypeError if it's not a kind of Integer" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(Object.new)
+ -> {
+ Integer.try_convert obj
+ }.should raise_consistent_error(TypeError, "can't convert MockObject into Integer (MockObject#to_int gives Object)")
+ end
+
+ it "responds with a different error message when it raises a TypeError, depending on the type of the non-Integer object :to_int returns" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return("A String")
+ -> {
+ Integer.try_convert obj
+ }.should raise_consistent_error(TypeError, "can't convert MockObject into Integer (MockObject#to_int gives String)")
+ end
- it "does not rescue exceptions raised by #to_int" do
- obj = mock("to_int")
- obj.should_receive(:to_int).and_raise(RuntimeError)
- -> { Integer.try_convert obj }.should raise_error(RuntimeError)
- end
+ it "does not rescue exceptions raised by #to_int" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_raise(RuntimeError)
+ -> { Integer.try_convert obj }.should.raise(RuntimeError)
end
end
diff --git a/spec/ruby/core/integer/upto_spec.rb b/spec/ruby/core/integer/upto_spec.rb
index dd6995e94b..ba63dcc9ea 100644
--- a/spec/ruby/core/integer/upto_spec.rb
+++ b/spec/ruby/core/integer/upto_spec.rb
@@ -27,8 +27,8 @@ describe "Integer#upto [stop] when self and stop are Integers" do
end
it "raises an ArgumentError for non-numeric endpoints" do
- -> { 1.upto("A") {|x| p x} }.should raise_error(ArgumentError)
- -> { 1.upto(nil) {|x| p x} }.should raise_error(ArgumentError)
+ -> { 1.upto("A") {|x| p x} }.should.raise(ArgumentError)
+ -> { 1.upto(nil) {|x| p x} }.should.raise(ArgumentError)
end
describe "when no block is given" do
@@ -45,9 +45,9 @@ describe "Integer#upto [stop] when self and stop are Integers" do
describe "size" do
it "raises an ArgumentError for non-numeric endpoints" do
enum = 1.upto("A")
- -> { enum.size }.should raise_error(ArgumentError)
+ -> { enum.size }.should.raise(ArgumentError)
enum = 1.upto(nil)
- -> { enum.size }.should raise_error(ArgumentError)
+ -> { enum.size }.should.raise(ArgumentError)
end
it "returns stop - self + 1" do
diff --git a/spec/ruby/core/integer/zero_spec.rb b/spec/ruby/core/integer/zero_spec.rb
index 2dac50c406..bd362c4181 100644
--- a/spec/ruby/core/integer/zero_spec.rb
+++ b/spec/ruby/core/integer/zero_spec.rb
@@ -7,15 +7,7 @@ describe "Integer#zero?" do
-1.should_not.zero?
end
- ruby_version_is "3.0" do
- it "Integer#zero? overrides Numeric#zero?" do
- 42.method(:zero?).owner.should == Integer
- end
- end
-
- ruby_version_is ""..."3.0" do
- it "Integer#zero? uses Numeric#zero?" do
- 42.method(:zero?).owner.should == Numeric
- end
+ it "Integer#zero? overrides Numeric#zero?" do
+ 42.method(:zero?).owner.should == Integer
end
end
diff --git a/spec/ruby/core/io/advise_spec.rb b/spec/ruby/core/io/advise_spec.rb
index 651fc52378..b77ed53ad4 100644
--- a/spec/ruby/core/io/advise_spec.rb
+++ b/spec/ruby/core/io/advise_spec.rb
@@ -14,73 +14,73 @@ describe "IO#advise" do
it "raises a TypeError if advise is not a Symbol" do
-> {
@io.advise("normal")
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises a TypeError if offset cannot be coerced to an Integer" do
-> {
@io.advise(:normal, "wat")
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises a TypeError if len cannot be coerced to an Integer" do
-> {
@io.advise(:normal, 0, "wat")
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises a RangeError if offset is too big" do
-> {
@io.advise(:normal, 10 ** 32)
- }.should raise_error(RangeError)
+ }.should.raise(RangeError)
end
it "raises a RangeError if len is too big" do
-> {
@io.advise(:normal, 0, 10 ** 32)
- }.should raise_error(RangeError)
+ }.should.raise(RangeError)
end
it "raises a NotImplementedError if advise is not recognized" do
->{
@io.advise(:foo)
- }.should raise_error(NotImplementedError)
+ }.should.raise(NotImplementedError)
end
it "supports the normal advice type" do
- @io.advise(:normal).should be_nil
+ @io.advise(:normal).should == nil
end
it "supports the sequential advice type" do
- @io.advise(:sequential).should be_nil
+ @io.advise(:sequential).should == nil
end
it "supports the random advice type" do
- @io.advise(:random).should be_nil
+ @io.advise(:random).should == nil
end
it "supports the dontneed advice type" do
- @io.advise(:dontneed).should be_nil
+ @io.advise(:dontneed).should == nil
end
it "supports the noreuse advice type" do
- @io.advise(:noreuse).should be_nil
+ @io.advise(:noreuse).should == nil
end
platform_is_not :linux do
it "supports the willneed advice type" do
- @io.advise(:willneed).should be_nil
+ @io.advise(:willneed).should == nil
end
end
guard -> { platform_is :linux and kernel_version_is '3.6' } do # [ruby-core:65355] tmpfs is not supported
it "supports the willneed advice type" do
- @io.advise(:willneed).should be_nil
+ @io.advise(:willneed).should == nil
end
end
it "raises an IOError if the stream is closed" do
@io.close
- -> { @io.advise(:normal) }.should raise_error(IOError)
+ -> { @io.advise(:normal) }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/autoclose_spec.rb b/spec/ruby/core/io/autoclose_spec.rb
new file mode 100644
index 0000000000..596f3d6934
--- /dev/null
+++ b/spec/ruby/core/io/autoclose_spec.rb
@@ -0,0 +1,77 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "IO#autoclose?" do
+ before :each do
+ @io = IOSpecs.io_fixture "lines.txt"
+ end
+
+ after :each do
+ @io.autoclose = true unless @io.closed?
+ @io.close unless @io.closed?
+ end
+
+ it "is set to true by default" do
+ @io.should.autoclose?
+ end
+
+ it "cannot be queried on a closed IO object" do
+ @io.close
+ -> { @io.autoclose? }.should.raise(IOError, /closed stream/)
+ end
+end
+
+describe "IO#autoclose=" do
+ before :each do
+ @io = IOSpecs.io_fixture "lines.txt"
+ end
+
+ after :each do
+ @io.autoclose = true unless @io.closed?
+ @io.close unless @io.closed?
+ end
+
+ it "can be set to true" do
+ @io.autoclose = false
+ @io.autoclose = true
+ @io.should.autoclose?
+ end
+
+ it "can be set to false" do
+ @io.autoclose = true
+ @io.autoclose = false
+ @io.should_not.autoclose?
+ end
+
+ it "can be set to any truthy value" do
+ @io.autoclose = false
+ @io.autoclose = 42
+ @io.should.autoclose?
+
+ @io.autoclose = false
+ @io.autoclose = Object.new
+ @io.should.autoclose?
+ end
+
+ it "can be set to any falsy value" do
+ @io.autoclose = true
+ @io.autoclose = nil
+ @io.should_not.autoclose?
+ end
+
+ it "can be set multiple times" do
+ @io.autoclose = true
+ @io.should.autoclose?
+
+ @io.autoclose = false
+ @io.should_not.autoclose?
+
+ @io.autoclose = true
+ @io.should.autoclose?
+ end
+
+ it "cannot be set on a closed IO object" do
+ @io.close
+ -> { @io.autoclose = false }.should.raise(IOError, /closed stream/)
+ end
+end
diff --git a/spec/ruby/core/io/binmode_spec.rb b/spec/ruby/core/io/binmode_spec.rb
index 342cac2a9b..8117229c91 100644
--- a/spec/ruby/core/io/binmode_spec.rb
+++ b/spec/ruby/core/io/binmode_spec.rb
@@ -13,11 +13,11 @@ describe "IO#binmode" do
it "returns self" do
@io = new_io(@name)
- @io.binmode.should equal(@io)
+ @io.binmode.should.equal?(@io)
end
it "raises an IOError on closed stream" do
- -> { IOSpecs.closed_io.binmode }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.binmode }.should.raise(IOError)
end
it "sets external encoding to binary" do
@@ -47,9 +47,9 @@ describe "IO#binmode?" do
end
it "is true after a call to IO#binmode" do
- @file.binmode?.should be_false
+ @file.binmode?.should == false
@file.binmode
- @file.binmode?.should be_true
+ @file.binmode?.should == true
end
it "propagates to dup'ed IO objects" do
@@ -59,6 +59,6 @@ describe "IO#binmode?" do
end
it "raises an IOError on closed stream" do
- -> { IOSpecs.closed_io.binmode? }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.binmode? }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/binread_spec.rb b/spec/ruby/core/io/binread_spec.rb
index a3f752d8f9..3023c7f177 100644
--- a/spec/ruby/core/io/binread_spec.rb
+++ b/spec/ruby/core/io/binread_spec.rb
@@ -38,10 +38,20 @@ describe "IO.binread" do
end
it "raises an ArgumentError when not passed a valid length" do
- -> { IO.binread @fname, -1 }.should raise_error(ArgumentError)
+ -> { IO.binread @fname, -1 }.should.raise(ArgumentError)
end
it "raises an Errno::EINVAL when not passed a valid offset" do
- -> { IO.binread @fname, 0, -1 }.should raise_error(Errno::EINVAL)
+ -> { IO.binread @fname, 0, -1 }.should.raise(Errno::EINVAL)
+ end
+
+ ruby_version_is ""..."4.0" do
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation given a path with a pipe" do
+ cmd = "|echo ok"
+ -> {
+ IO.binread(cmd)
+ }.should complain(/IO process creation with a leading '\|'/)
+ end
end
end
diff --git a/spec/ruby/core/io/buffer/and_spec.rb b/spec/ruby/core/io/buffer/and_spec.rb
new file mode 100644
index 0000000000..3cea163b0e
--- /dev/null
+++ b/spec/ruby/core/io/buffer/and_spec.rb
@@ -0,0 +1,62 @@
+require_relative '../../../spec_helper'
+
+describe :io_buffer_and, shared: true do
+ it "applies the argument buffer as an AND bit mask across the whole buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F") do |mask|
+ result = buffer.send(@method, mask)
+ result.get_string.should == "\x30\x02\x30\x04\x30".b
+ result.free
+ end
+ end
+ end
+
+ it "ignores extra parts of mask if it is longer than source buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F\x00\x00\x00\xFF\xFF") do |mask|
+ result = buffer.send(@method, mask)
+ result.get_string.should == "\x30\x02\x00\x00\x00".b
+ result.free
+ end
+ end
+ end
+
+ it "raises TypeError if mask is not an IO::Buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ -> { buffer.send(@method, "\xF8\x8F") }.should.raise(TypeError, "wrong argument type String (expected IO::Buffer)")
+ -> { buffer.send(@method, 0xF8) }.should.raise(TypeError, "wrong argument type Integer (expected IO::Buffer)")
+ -> { buffer.send(@method, nil) }.should.raise(TypeError, "wrong argument type nil (expected IO::Buffer)")
+ end
+ end
+end
+
+describe "IO::Buffer#&" do
+ it_behaves_like :io_buffer_and, :&
+
+ it "creates a new internal buffer of the same size" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F") do |mask|
+ result = buffer & mask
+ result.should_not.equal? buffer
+ result.should.internal?
+ result.size.should == buffer.size
+ result.free
+ buffer.get_string.should == "12345".b
+ end
+ end
+ end
+end
+
+describe "IO::Buffer#and!" do
+ it_behaves_like :io_buffer_and, :and!
+
+ it "modifies the buffer in place" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F") do |mask|
+ result = buffer.and!(mask)
+ result.should.equal? buffer
+ result.should.external?
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/bit_count_spec.rb b/spec/ruby/core/io/buffer/bit_count_spec.rb
new file mode 100644
index 0000000000..62f56f5b98
--- /dev/null
+++ b/spec/ruby/core/io/buffer/bit_count_spec.rb
@@ -0,0 +1,64 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "4.1" do
+ describe "IO::Buffer#bit_count" do
+ it "counts all set bits in the whole buffer" do
+ IO::Buffer.for(+"\xFF\x00\x0F") do |buffer|
+ buffer.bit_count.should == 12
+ end
+ end
+
+ it "returns 0 for a buffer of all zero bytes" do
+ IO::Buffer.for(+"\x00\x00\x00") do |buffer|
+ buffer.bit_count.should == 0
+ end
+ end
+
+ it "returns 8 * size for a buffer of all 0xFF bytes" do
+ IO::Buffer.for(+"\xFF" * 9) do |buffer|
+ buffer.bit_count.should == 72
+ end
+ end
+
+ it "returns 0 for an empty buffer" do
+ IO::Buffer.new(0).bit_count.should == 0
+ end
+
+ it "accepts an offset to start counting from (length defaults to remaining bytes)" do
+ IO::Buffer.for(+"\xFF\x00\x0F") do |buffer|
+ buffer.bit_count(0).should == 12 # offset=0 => entire buffer
+ buffer.bit_count(1).should == 4 # offset=1 => 0x00 + 0x0F
+ buffer.bit_count(2).should == 4 # offset=2 => 0x0F only
+ end
+ end
+
+ it "accepts an offset and length to restrict the counted region" do
+ IO::Buffer.for(+"\xFF\x00\x0F") do |buffer|
+ buffer.bit_count(0, 1).should == 8 # just 0xFF
+ buffer.bit_count(1, 1).should == 0 # just 0x00
+ buffer.bit_count(2, 1).should == 4 # just 0x0F
+ buffer.bit_count(1, 2).should == 4 # 0x00 + 0x0F
+ end
+ end
+
+ it "handles 8-byte aligned buffers efficiently" do
+ IO::Buffer.for(+"\xAA" * 8) do |buffer|
+ # 0xAA = 10101010 => 4 bits per byte => 32 total
+ buffer.bit_count.should == 32
+ end
+ end
+
+ it "raises ArgumentError when offset + length exceeds buffer size" do
+ IO::Buffer.for(+"\xFF") do |buffer|
+ -> { buffer.bit_count(0, 2) }.should.raise(ArgumentError)
+ -> { buffer.bit_count(1, 1) }.should.raise(ArgumentError)
+ end
+ end
+
+ it "returns an Integer" do
+ IO::Buffer.for(+"\xFF") do |buffer|
+ buffer.bit_count.should.is_a?(Integer)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/empty_spec.rb b/spec/ruby/core/io/buffer/empty_spec.rb
new file mode 100644
index 0000000000..4cceb4dc0d
--- /dev/null
+++ b/spec/ruby/core/io/buffer/empty_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/null_and_empty'
+
+describe "IO::Buffer#empty?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it_behaves_like :io_buffer_null_and_empty, :empty?
+
+ it "is true for a 0-length String-backed buffer created with .for" do
+ @buffer = IO::Buffer.for("")
+ @buffer.empty?.should == true
+ end
+
+ it "is true for a 0-length String-backed buffer created with .string" do
+ IO::Buffer.string(0) do |buffer|
+ buffer.empty?.should == true
+ end
+ end
+
+ it "is true for a 0-length slice of a buffer with size > 0" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice(3, 0).empty?.should == true
+ end
+end
diff --git a/spec/ruby/core/io/buffer/external_spec.rb b/spec/ruby/core/io/buffer/external_spec.rb
new file mode 100644
index 0000000000..18b2ee0d06
--- /dev/null
+++ b/spec/ruby/core/io/buffer/external_spec.rb
@@ -0,0 +1,23 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#external?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "is true for a buffer with externally-managed memory" do
+ @buffer = IO::Buffer.for("string")
+ @buffer.external?.should == true
+ end
+
+ it "is false for a buffer with self-managed memory" do
+ @buffer = IO::Buffer.new(12, IO::Buffer::MAPPED)
+ @buffer.external?.should == false
+ end
+
+ it "is false for a null buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.external?.should == false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/for_spec.rb b/spec/ruby/core/io/buffer/for_spec.rb
new file mode 100644
index 0000000000..4c614f74b0
--- /dev/null
+++ b/spec/ruby/core/io/buffer/for_spec.rb
@@ -0,0 +1,95 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer.for" do
+ before :each do
+ @string = +"för striñg"
+ end
+
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "without a block" do
+ it "copies string's contents, creating a separate read-only buffer" do
+ @buffer = IO::Buffer.for(@string)
+
+ @buffer.size.should == @string.bytesize
+ @buffer.get_string.should == @string.b
+
+ @string[0] = "d"
+ @buffer.get_string(0, 1).should == "f".b
+
+ -> { @buffer.set_string("d") }.should.raise(IO::Buffer::AccessError, "Buffer is not writable!")
+ end
+
+ it "creates an external, read-only buffer" do
+ @buffer = IO::Buffer.for(@string)
+
+ @buffer.should_not.internal?
+ @buffer.should_not.mapped?
+ @buffer.should.external?
+
+ @buffer.should_not.empty?
+ @buffer.should_not.null?
+
+ @buffer.should_not.shared?
+ @buffer.should_not.private?
+ @buffer.should.readonly?
+
+ @buffer.should_not.locked?
+ @buffer.should.valid?
+ end
+ end
+
+ context "with a block" do
+ it "returns the last value in the block" do
+ value =
+ IO::Buffer.for(@string) do |buffer|
+ buffer.size * 3
+ end
+ value.should == @string.bytesize * 3
+ end
+
+ it "frees the buffer at the end of the block" do
+ IO::Buffer.for(@string) do |buffer|
+ @buffer = buffer
+ @buffer.should_not.null?
+ end
+ @buffer.should.null?
+ end
+
+ context "if string is not frozen" do
+ it "creates a modifiable string-backed buffer" do
+ IO::Buffer.for(@string) do |buffer|
+ buffer.size.should == @string.bytesize
+ buffer.get_string.should == @string.b
+
+ buffer.should_not.readonly?
+ buffer.should_not.locked?
+
+ buffer.set_string("ghost shell")
+ @string.should == "ghost shellg"
+ end
+ end
+
+ it "locks the original string to prevent modification" do
+ IO::Buffer.for(@string) do |_buffer|
+ -> { @string[0] = "t" }.should.raise(RuntimeError, "can't modify string; temporarily locked")
+ end
+ @string[1] = "u"
+ @string.should == "fur striñg"
+ end
+ end
+
+ context "if string is frozen" do
+ it "creates a read-only string-backed buffer" do
+ IO::Buffer.for(@string.freeze) do |buffer|
+ buffer.should.readonly?
+
+ -> { buffer.set_string("ghost shell") }.should.raise(IO::Buffer::AccessError, "Buffer is not writable!")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/free_spec.rb b/spec/ruby/core/io/buffer/free_spec.rb
new file mode 100644
index 0000000000..20fb7b901f
--- /dev/null
+++ b/spec/ruby/core/io/buffer/free_spec.rb
@@ -0,0 +1,102 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#free" do
+ context "with a buffer created with .new" do
+ it "frees internal memory and nullifies the buffer" do
+ buffer = IO::Buffer.new(4)
+ buffer.free
+ buffer.null?.should == true
+ end
+
+ it "frees mapped memory and nullifies the buffer" do
+ buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ buffer.free
+ buffer.null?.should == true
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "frees mapped memory and nullifies the buffer" do
+ File.open(__FILE__, "r") do |file|
+ buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ buffer.free
+ buffer.null?.should == true
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ context "without a block" do
+ it "disassociates the buffer from the string and nullifies the buffer" do
+ string = +"test"
+ buffer = IO::Buffer.for(string)
+ # Read-only buffer, can't modify the string.
+ buffer.free
+ buffer.null?.should == true
+ end
+ end
+
+ context "with a block" do
+ it "disassociates the buffer from the string and nullifies the buffer" do
+ string = +"test"
+ IO::Buffer.for(string) do |buffer|
+ buffer.set_string("meat")
+ buffer.free
+ buffer.null?.should == true
+ end
+ string.should == "meat"
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .string" do
+ it "disassociates the buffer from the string and nullifies the buffer" do
+ string =
+ IO::Buffer.string(4) do |buffer|
+ buffer.set_string("meat")
+ buffer.free
+ buffer.null?.should == true
+ end
+ string.should == "meat"
+ end
+ end
+
+ it "can be called repeatedly without an error" do
+ buffer = IO::Buffer.new(4)
+ buffer.free
+ buffer.null?.should == true
+ buffer.free
+ buffer.null?.should == true
+ end
+
+ it "is disallowed while locked, raising IO::Buffer::LockedError" do
+ buffer = IO::Buffer.new(4)
+ buffer.locked do
+ -> { buffer.free }.should.raise(IO::Buffer::LockedError, "Buffer is locked!")
+ end
+ buffer.free
+ buffer.null?.should == true
+ end
+
+ context "with a slice of a buffer" do
+ it "nullifies the slice, not touching the buffer" do
+ buffer = IO::Buffer.new(4)
+ slice = buffer.slice(0, 2)
+
+ slice.free
+ slice.null?.should == true
+ buffer.null?.should == false
+
+ buffer.free
+ end
+
+ it "nullifies buffer, invalidating the slice" do
+ buffer = IO::Buffer.new(4)
+ slice = buffer.slice(0, 2)
+
+ buffer.free
+ slice.null?.should == false
+ slice.valid?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/initialize_spec.rb b/spec/ruby/core/io/buffer/initialize_spec.rb
new file mode 100644
index 0000000000..dba6fddc79
--- /dev/null
+++ b/spec/ruby/core/io/buffer/initialize_spec.rb
@@ -0,0 +1,119 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#initialize" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "creates a new zero-filled buffer with default size" do
+ @buffer = IO::Buffer.new
+ @buffer.size.should == IO::Buffer::DEFAULT_SIZE
+ @buffer.each(:U8).should.all? { |_offset, value| value.eql?(0) }
+ end
+
+ it "creates a buffer with default state" do
+ @buffer = IO::Buffer.new
+
+ @buffer.should_not.external?
+
+ @buffer.should_not.shared?
+ @buffer.should_not.private?
+ @buffer.should_not.readonly?
+
+ @buffer.should_not.empty?
+ @buffer.should_not.null?
+
+ @buffer.should_not.locked?
+ @buffer.should.valid?
+ end
+
+ context "with size argument" do
+ it "creates a new internal buffer if size is less than IO::Buffer::PAGE_SIZE" do
+ size = IO::Buffer::PAGE_SIZE - 1
+ @buffer = IO::Buffer.new(size)
+ @buffer.size.should == size
+ @buffer.should_not.empty?
+
+ @buffer.should.internal?
+ @buffer.should_not.mapped?
+ end
+
+ it "creates a new mapped buffer if size is greater than or equal to IO::Buffer::PAGE_SIZE" do
+ size = IO::Buffer::PAGE_SIZE
+ @buffer = IO::Buffer.new(size)
+ @buffer.size.should == size
+ @buffer.should_not.empty?
+
+ @buffer.should_not.internal?
+ @buffer.should.mapped?
+ end
+
+ it "creates a null buffer if size is 0" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.should.null?
+ @buffer.should.empty?
+ end
+
+ it "raises TypeError if size is not an Integer" do
+ -> { IO::Buffer.new(nil) }.should.raise(TypeError, "not an Integer")
+ -> { IO::Buffer.new(10.0) }.should.raise(TypeError, "not an Integer")
+ end
+
+ it "raises ArgumentError if size is negative" do
+ -> { IO::Buffer.new(-1) }.should.raise(ArgumentError, "Size can't be negative!")
+ end
+ end
+
+ context "with size and flags arguments" do
+ it "forces mapped buffer with IO::Buffer::MAPPED flag" do
+ @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE - 1, IO::Buffer::MAPPED)
+ @buffer.should.mapped?
+ @buffer.should_not.internal?
+ @buffer.should_not.empty?
+ end
+
+ it "forces internal buffer with IO::Buffer::INTERNAL flag" do
+ @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::INTERNAL)
+ @buffer.should.internal?
+ @buffer.should_not.mapped?
+ @buffer.should_not.empty?
+ end
+
+ it "allows extra flags" do
+ @buffer = IO::Buffer.new(10, IO::Buffer::INTERNAL | IO::Buffer::SHARED | IO::Buffer::READONLY)
+ @buffer.should.internal?
+ @buffer.should.shared?
+ @buffer.should.readonly?
+ end
+
+ it "ignores flags if size is 0" do
+ @buffer = IO::Buffer.new(0, 0xffff)
+ @buffer.should.null?
+ @buffer.should.empty?
+
+ @buffer.should_not.internal?
+ @buffer.should_not.mapped?
+ @buffer.should_not.external?
+
+ @buffer.should_not.shared?
+ @buffer.should_not.readonly?
+
+ @buffer.should_not.locked?
+ @buffer.should.valid?
+ end
+
+ it "raises IO::Buffer::AllocationError if neither IO::Buffer::MAPPED nor IO::Buffer::INTERNAL is given" do
+ -> { IO::Buffer.new(10, IO::Buffer::READONLY) }.should.raise(IO::Buffer::AllocationError, "Could not allocate buffer!")
+ -> { IO::Buffer.new(10, 0) }.should.raise(IO::Buffer::AllocationError, "Could not allocate buffer!")
+ end
+
+ it "raises ArgumentError if flags is negative" do
+ -> { IO::Buffer.new(10, -1) }.should.raise(ArgumentError, "Flags can't be negative!")
+ end
+
+ it "raises TypeError with non-Integer flags" do
+ -> { IO::Buffer.new(10, 0.0) }.should.raise(TypeError, "not an Integer")
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/internal_spec.rb b/spec/ruby/core/io/buffer/internal_spec.rb
new file mode 100644
index 0000000000..73e19eb85e
--- /dev/null
+++ b/spec/ruby/core/io/buffer/internal_spec.rb
@@ -0,0 +1,23 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#internal?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "is true for an internally-allocated buffer" do
+ @buffer = IO::Buffer.new(12)
+ @buffer.internal?.should == true
+ end
+
+ it "is false for an externally-allocated buffer" do
+ @buffer = IO::Buffer.new(12, IO::Buffer::MAPPED)
+ @buffer.internal?.should == false
+ end
+
+ it "is false for a null buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.internal?.should == false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/locked_spec.rb b/spec/ruby/core/io/buffer/locked_spec.rb
new file mode 100644
index 0000000000..249026aa8a
--- /dev/null
+++ b/spec/ruby/core/io/buffer/locked_spec.rb
@@ -0,0 +1,75 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#locked" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "when buffer is locked" do
+ it "allows reading and writing operations on the buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.set_string("test")
+ @buffer.locked do
+ @buffer.get_string.should == "test"
+ @buffer.set_string("meat")
+ end
+ @buffer.get_string.should == "meat"
+ end
+
+ it "disallows operations changing buffer itself, raising IO::Buffer::LockedError" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ # Just an example, each method is responsible for checking the lock state.
+ -> { @buffer.resize(8) }.should.raise(IO::Buffer::LockedError)
+ end
+ end
+ end
+
+ it "disallows reentrant locking, raising IO::Buffer::LockedError" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ -> { @buffer.locked {} }.should.raise(IO::Buffer::LockedError, "Buffer already locked!")
+ end
+ end
+
+ it "does not propagate to buffer's slices" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(0, 2)
+ @buffer.locked do
+ @buffer.locked?.should == true
+ slice.locked?.should == false
+ slice.locked { slice.locked?.should == true }
+ end
+ end
+
+ it "does not propagate backwards from buffer's slices" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(0, 2)
+ slice.locked do
+ slice.locked?.should == true
+ @buffer.locked?.should == false
+ @buffer.locked { @buffer.locked?.should == true }
+ end
+ end
+end
+
+describe "IO::Buffer#locked?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "is false by default" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked?.should == false
+ end
+
+ it "is true only inside of #locked block" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ @buffer.locked?.should == true
+ end
+ @buffer.locked?.should == false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/map_spec.rb b/spec/ruby/core/io/buffer/map_spec.rb
new file mode 100644
index 0000000000..4b28539ad8
--- /dev/null
+++ b/spec/ruby/core/io/buffer/map_spec.rb
@@ -0,0 +1,343 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer.map" do
+ before :all do
+ @tmp_files = []
+
+ @big_file_name = nil
+ @small_file_name = nil
+ end
+
+ after :all do
+ @tmp_files.each {|file| File.delete(file)}
+ end
+
+ def open_fixture
+ unless @small_file_name
+ @small_file_name = tmp("read_text.txt")
+ File.copy_stream(fixture(__dir__, "read_text.txt"), @small_file_name)
+ @tmp_files << @small_file_name
+ end
+ File.open(@small_file_name, "rb+")
+ end
+
+ def open_big_file_fixture
+ unless @big_file_name
+ @big_file_name = tmp("big_file")
+ # Usually 4 kibibytes + 16 bytes
+ File.write(@big_file_name, "12345678" * (IO::Buffer::PAGE_SIZE / 8 + 2))
+ @tmp_files << @big_file_name
+ end
+ File.open(@big_file_name, "rb+")
+ end
+
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ @file&.close
+ @file = nil
+ end
+
+ it "creates a new buffer mapped from a file" do
+ @file = open_fixture
+ @buffer = IO::Buffer.map(@file)
+
+ @buffer.size.should == 9
+ @buffer.get_string.should == "abcâdef\n".b
+ end
+
+ it "allows to close the file after creating buffer, retaining mapping" do
+ file = open_fixture
+ @buffer = IO::Buffer.map(file)
+ file.close
+
+ @buffer.get_string.should == "abcâdef\n".b
+ end
+
+ it "creates a mapped, external, shared buffer" do
+ @file = open_fixture
+ @buffer = IO::Buffer.map(@file)
+
+ @buffer.should_not.internal?
+ @buffer.should.mapped?
+ @buffer.should.external?
+
+ @buffer.should_not.empty?
+ @buffer.should_not.null?
+
+ @buffer.should.shared?
+ @buffer.should_not.private?
+ @buffer.should_not.readonly?
+
+ @buffer.should_not.locked?
+ @buffer.should.valid?
+ end
+
+ guard -> { Process.respond_to?(:fork) } do
+ it "is shareable across processes" do
+ file_name = tmp("shared_buffer")
+ @file = File.open(file_name, "w+")
+ @file << "I'm private"
+ @file.rewind
+ @buffer = IO::Buffer.map(@file)
+
+ IO.popen("-") do |child_pipe|
+ if child_pipe
+ # Synchronize on child's output.
+ child_pipe.readlines.first.chomp.should == @buffer.to_s
+ @buffer.get_string.should == "I'm shared!"
+
+ @file.read.should == "I'm shared!"
+ else
+ @buffer.set_string("I'm shared!")
+ puts @buffer
+ end
+ ensure
+ child_pipe&.close
+ end
+ ensure
+ File.unlink(file_name)
+ end
+ end
+
+ context "with an empty file" do
+ ruby_version_is "4.0" do
+ it "raises ArgumentError" do
+ file_name = tmp("empty.txt")
+ @file = File.open(file_name, "wb+")
+ @tmp_files << file_name
+ -> { IO::Buffer.map(@file) }.should.raise(ArgumentError, "Invalid negative or zero file size!")
+ end
+ end
+ end
+
+ context "with a file opened only for reading" do
+ it "raises a SystemCallError unless read-only" do
+ @file = File.open(fixture(__dir__, "read_text.txt"), "rb")
+ -> { IO::Buffer.map(@file) }.should.raise(SystemCallError)
+ end
+ end
+
+ context "with size argument" do
+ it "limits the buffer to the specified size in bytes, starting from the start of the file" do
+ @file = open_fixture
+ @buffer = IO::Buffer.map(@file, 4)
+
+ @buffer.size.should == 4
+ @buffer.get_string.should == "abc\xC3".b
+ end
+
+ it "maps the whole file if size is nil" do
+ @file = open_fixture
+ @buffer = IO::Buffer.map(@file, nil)
+
+ @buffer.size.should == 9
+ end
+
+ context "if size is 0" do
+ ruby_version_is "4.0" do
+ it "raises ArgumentError" do
+ @file = open_fixture
+ -> { IO::Buffer.map(@file, 0) }.should.raise(ArgumentError, "Size can't be zero!")
+ end
+ end
+ end
+
+ it "raises TypeError if size is not an Integer or nil" do
+ @file = open_fixture
+ -> { IO::Buffer.map(@file, "10") }.should.raise(TypeError, "not an Integer")
+ -> { IO::Buffer.map(@file, 10.0) }.should.raise(TypeError, "not an Integer")
+ end
+
+ it "raises ArgumentError if size is negative" do
+ @file = open_fixture
+ -> { IO::Buffer.map(@file, -1) }.should.raise(ArgumentError, "Size can't be negative!")
+ end
+
+ ruby_version_is ""..."4.0" do
+ # May or may not cause a crash on access.
+ it "is undefined behavior if size is larger than file size"
+ end
+
+ ruby_version_is "4.0" do
+ it "raises ArgumentError if size is larger than file size" do
+ @file = open_fixture
+ -> { IO::Buffer.map(@file, 8192) }.should.raise(ArgumentError, "Size can't be larger than file size!")
+ end
+ end
+ end
+
+ context "with size and offset arguments" do
+ # Neither Windows nor macOS have clear, stable behavior with non-zero offset.
+ # https://bugs.ruby-lang.org/issues/21700
+ platform_is :linux do
+ context "if offset is an allowed value for system call" do
+ it "maps the span specified by size starting from the offset" do
+ @file = open_big_file_fixture
+ @buffer = IO::Buffer.map(@file, 14, IO::Buffer::PAGE_SIZE)
+
+ @buffer.size.should == 14
+ @buffer.get_string(0, 14).should == "12345678123456"
+ end
+
+ context "if size is nil" do
+ ruby_version_is ""..."4.0" do
+ it "maps the rest of the file" do
+ @file = open_big_file_fixture
+ @buffer = IO::Buffer.map(@file, nil, IO::Buffer::PAGE_SIZE)
+
+ @buffer.get_string(0, 1).should == "1"
+ end
+
+ it "incorrectly sets buffer's size to file's full size" do
+ @file = open_big_file_fixture
+ @buffer = IO::Buffer.map(@file, nil, IO::Buffer::PAGE_SIZE)
+
+ @buffer.size.should == @file.size
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "maps the rest of the file" do
+ @file = open_big_file_fixture
+ @buffer = IO::Buffer.map(@file, nil, IO::Buffer::PAGE_SIZE)
+
+ @buffer.get_string(0, 1).should == "1"
+ end
+
+ it "sets buffer's size to file's remaining size" do
+ @file = open_big_file_fixture
+ @buffer = IO::Buffer.map(@file, nil, IO::Buffer::PAGE_SIZE)
+
+ @buffer.size.should == (@file.size - IO::Buffer::PAGE_SIZE)
+ end
+ end
+ end
+ end
+ end
+
+ it "maps the file from the start if offset is 0" do
+ @file = open_fixture
+ @buffer = IO::Buffer.map(@file, 4, 0)
+
+ @buffer.size.should == 4
+ @buffer.get_string.should == "abc\xC3".b
+ end
+
+ ruby_version_is ""..."4.0" do
+ # May or may not cause a crash on access.
+ it "is undefined behavior if offset+size is larger than file size"
+ end
+
+ ruby_version_is "4.0" do
+ it "raises ArgumentError if offset+size is larger than file size" do
+ @file = open_big_file_fixture
+ -> { IO::Buffer.map(@file, 17, IO::Buffer::PAGE_SIZE) }.should.raise(ArgumentError, "Offset too large!")
+ ensure
+ # Windows requires the file to be closed before deletion.
+ @file.close unless @file.closed?
+ end
+ end
+
+ it "raises TypeError if offset is not convertible to Integer" do
+ @file = open_fixture
+ -> { IO::Buffer.map(@file, 4, "4096") }.should.raise(TypeError, /no implicit conversion/)
+ -> { IO::Buffer.map(@file, 4, nil) }.should.raise(TypeError, /no implicit conversion/)
+ end
+
+ ruby_version_is "4.0" do
+ it "raises ArgumentError if offset is negative" do
+ @file = open_fixture
+ -> { IO::Buffer.map(@file, 4, -1) }.should.raise(ArgumentError, "Offset can't be negative!")
+ end
+ end
+ end
+
+ context "with flags argument" do
+ context "when READONLY flag is specified" do
+ it "sets readonly flag on the buffer, allowing only reads" do
+ @file = open_fixture
+ @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::READONLY)
+
+ @buffer.should.readonly?
+
+ @buffer.get_string.should == "abc\xC3\xA2def\n".b
+ end
+
+ it "allows mapping read-only files" do
+ @file = File.open(fixture(__dir__, "read_text.txt"), "rb")
+ @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::READONLY)
+
+ @buffer.should.readonly?
+
+ @buffer.get_string.should == "abc\xC3\xA2def\n".b
+ end
+
+ it "causes IO::Buffer::AccessError on write" do
+ @file = open_fixture
+ @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::READONLY)
+
+ -> { @buffer.set_string("test") }.should.raise(IO::Buffer::AccessError, "Buffer is not writable!")
+ end
+ end
+
+ context "when PRIVATE is specified" do
+ it "sets private flag on the buffer, making it freely modifiable" do
+ @file = open_fixture
+ @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::PRIVATE)
+
+ @buffer.should.private?
+ @buffer.should_not.shared?
+ @buffer.should_not.external?
+
+ @buffer.get_string.should == "abc\xC3\xA2def\n".b
+ @buffer.set_string("test12345")
+ @buffer.get_string.should == "test12345".b
+
+ @file.read.should == "abcâdef\n".b
+ end
+
+ it "allows mapping read-only files and modifying the buffer" do
+ @file = File.open(fixture(__dir__, "read_text.txt"), "rb")
+ @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::PRIVATE)
+
+ @buffer.should.private?
+ @buffer.should_not.shared?
+ @buffer.should_not.external?
+
+ @buffer.get_string.should == "abc\xC3\xA2def\n".b
+ @buffer.set_string("test12345")
+ @buffer.get_string.should == "test12345".b
+
+ @file.read.should == "abcâdef\n".b
+ end
+
+ guard -> { Process.respond_to?(:fork) } do
+ it "is not shared across processes" do
+ file_name = tmp("shared_buffer")
+ @file = File.open(file_name, "w+")
+ @file << "I'm private"
+ @file.rewind
+ @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::PRIVATE)
+
+ IO.popen("-") do |child_pipe|
+ if child_pipe
+ # Synchronize on child's output.
+ child_pipe.readlines.first.chomp.should == @buffer.to_s
+ @buffer.get_string.should == "I'm private"
+
+ @file.read.should == "I'm private"
+ else
+ @buffer.set_string("I'm shared!")
+ puts @buffer
+ end
+ ensure
+ child_pipe&.close
+ end
+ ensure
+ File.unlink(file_name)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/mapped_spec.rb b/spec/ruby/core/io/buffer/mapped_spec.rb
new file mode 100644
index 0000000000..0decb97704
--- /dev/null
+++ b/spec/ruby/core/io/buffer/mapped_spec.rb
@@ -0,0 +1,23 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#mapped?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "is true for a buffer with mapped memory" do
+ @buffer = IO::Buffer.new(12, IO::Buffer::MAPPED)
+ @buffer.mapped?.should == true
+ end
+
+ it "is false for a buffer with non-mapped memory" do
+ @buffer = IO::Buffer.for("string")
+ @buffer.mapped?.should == false
+ end
+
+ it "is false for a null buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.mapped?.should == false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/not_spec.rb b/spec/ruby/core/io/buffer/not_spec.rb
new file mode 100644
index 0000000000..4737a30bde
--- /dev/null
+++ b/spec/ruby/core/io/buffer/not_spec.rb
@@ -0,0 +1,37 @@
+require_relative '../../../spec_helper'
+
+describe :io_buffer_not, shared: true do
+ it "inverts every bit of the buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ result = buffer.send(@method)
+ result.get_string.should == "\xCE\xCD\xCC\xCB\xCA".b
+ result.free
+ end
+ end
+end
+
+describe "IO::Buffer#~" do
+ it_behaves_like :io_buffer_not, :~
+
+ it "creates a new internal buffer of the same size" do
+ IO::Buffer.for(+"12345") do |buffer|
+ result = ~buffer
+ result.should_not.equal? buffer
+ result.should.internal?
+ result.size.should == buffer.size
+ result.free
+ end
+ end
+end
+
+describe "IO::Buffer#not!" do
+ it_behaves_like :io_buffer_not, :not!
+
+ it "modifies the buffer in place" do
+ IO::Buffer.for(+"12345") do |buffer|
+ result = buffer.not!
+ result.should.equal? buffer
+ result.should.external?
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/null_spec.rb b/spec/ruby/core/io/buffer/null_spec.rb
new file mode 100644
index 0000000000..380a98bde1
--- /dev/null
+++ b/spec/ruby/core/io/buffer/null_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/null_and_empty'
+
+describe "IO::Buffer#null?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it_behaves_like :io_buffer_null_and_empty, :null?
+
+ it "is false for a 0-length String-backed buffer created with .for" do
+ @buffer = IO::Buffer.for("")
+ @buffer.null?.should == false
+ end
+
+ it "is false for a 0-length String-backed buffer created with .string" do
+ IO::Buffer.string(0) do |buffer|
+ buffer.null?.should == false
+ end
+ end
+
+ it "is false for a 0-length slice of a buffer with size > 0" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice(3, 0).null?.should == false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/or_spec.rb b/spec/ruby/core/io/buffer/or_spec.rb
new file mode 100644
index 0000000000..3e627c216c
--- /dev/null
+++ b/spec/ruby/core/io/buffer/or_spec.rb
@@ -0,0 +1,62 @@
+require_relative '../../../spec_helper'
+
+describe :io_buffer_or, shared: true do
+ it "applies the argument buffer as an OR bit mask across the whole buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F") do |mask|
+ result = buffer.send(@method, mask)
+ result.get_string.should == "\xF9\xBF\xFB\xBF\xFD".b
+ result.free
+ end
+ end
+ end
+
+ it "ignores extra parts of mask if it is longer than source buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F\x00\x00\x00\xFF\xFF") do |mask|
+ result = buffer.send(@method, mask)
+ result.get_string.should == "\xF9\xBF345".b
+ result.free
+ end
+ end
+ end
+
+ it "raises TypeError if mask is not an IO::Buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ -> { buffer.send(@method, "\xF8\x8F") }.should.raise(TypeError, "wrong argument type String (expected IO::Buffer)")
+ -> { buffer.send(@method, 0xF8) }.should.raise(TypeError, "wrong argument type Integer (expected IO::Buffer)")
+ -> { buffer.send(@method, nil) }.should.raise(TypeError, "wrong argument type nil (expected IO::Buffer)")
+ end
+ end
+end
+
+describe "IO::Buffer#|" do
+ it_behaves_like :io_buffer_or, :|
+
+ it "creates a new internal buffer of the same size" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F") do |mask|
+ result = buffer | mask
+ result.should_not.equal? buffer
+ result.should.internal?
+ result.size.should == buffer.size
+ result.free
+ buffer.get_string.should == "12345".b
+ end
+ end
+ end
+end
+
+describe "IO::Buffer#or!" do
+ it_behaves_like :io_buffer_or, :or!
+
+ it "modifies the buffer in place" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F") do |mask|
+ result = buffer.or!(mask)
+ result.should.equal? buffer
+ result.should.external?
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/private_spec.rb b/spec/ruby/core/io/buffer/private_spec.rb
new file mode 100644
index 0000000000..6e6afee34c
--- /dev/null
+++ b/spec/ruby/core/io/buffer/private_spec.rb
@@ -0,0 +1,23 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#private?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "is true for a buffer created with PRIVATE flag" do
+ @buffer = IO::Buffer.new(12, IO::Buffer::INTERNAL | IO::Buffer::PRIVATE)
+ @buffer.private?.should == true
+ end
+
+ it "is false for a buffer created without PRIVATE flag" do
+ @buffer = IO::Buffer.new(12, IO::Buffer::INTERNAL)
+ @buffer.private?.should == false
+ end
+
+ it "is false for a null buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.private?.should == false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/readonly_spec.rb b/spec/ruby/core/io/buffer/readonly_spec.rb
new file mode 100644
index 0000000000..4eefc9f29f
--- /dev/null
+++ b/spec/ruby/core/io/buffer/readonly_spec.rb
@@ -0,0 +1,28 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#readonly?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "is true for a buffer created with READONLY flag" do
+ @buffer = IO::Buffer.new(12, IO::Buffer::INTERNAL | IO::Buffer::READONLY)
+ @buffer.readonly?.should == true
+ end
+
+ it "is true for a buffer that is non-writable" do
+ @buffer = IO::Buffer.for("string")
+ @buffer.readonly?.should == true
+ end
+
+ it "is false for a modifiable buffer" do
+ @buffer = IO::Buffer.new(12)
+ @buffer.readonly?.should == false
+ end
+
+ it "is false for a null buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.readonly?.should == false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/resize_spec.rb b/spec/ruby/core/io/buffer/resize_spec.rb
new file mode 100644
index 0000000000..6e684475f3
--- /dev/null
+++ b/spec/ruby/core/io/buffer/resize_spec.rb
@@ -0,0 +1,151 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#resize" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "resizes internal buffer, preserving type" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.resize(IO::Buffer::PAGE_SIZE)
+ @buffer.size.should == IO::Buffer::PAGE_SIZE
+ @buffer.internal?.should == true
+ @buffer.mapped?.should == false
+ end
+
+ platform_is :linux do
+ it "resizes mapped buffer, preserving type" do
+ @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::MAPPED)
+ @buffer.resize(4)
+ @buffer.size.should == 4
+ @buffer.internal?.should == false
+ @buffer.mapped?.should == true
+ end
+ end
+
+ platform_is_not :linux do
+ it "resizes mapped buffer, changing type to internal" do
+ @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::MAPPED)
+ @buffer.resize(4)
+ @buffer.size.should == 4
+ @buffer.internal?.should == true
+ @buffer.mapped?.should == false
+ end
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "disallows resizing shared buffer, raising IO::Buffer::AccessError" do
+ File.open(__FILE__, "r+") do |file|
+ @buffer = IO::Buffer.map(file)
+ -> { @buffer.resize(10) }.should.raise(IO::Buffer::AccessError, "Cannot resize external buffer!")
+ end
+ end
+
+ it "resizes private buffer, discarding excess contents" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE)
+ @buffer.resize(10)
+ @buffer.size.should == 10
+ @buffer.get_string.should == "require_re"
+ @buffer.resize(12)
+ @buffer.size.should == 12
+ @buffer.get_string.should == "require_re\0\0"
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ context "without a block" do
+ it "disallows resizing, raising IO::Buffer::AccessError" do
+ @buffer = IO::Buffer.for(+"test")
+ -> { @buffer.resize(10) }.should.raise(IO::Buffer::AccessError, "Cannot resize external buffer!")
+ end
+ end
+
+ context "with a block" do
+ it "disallows resizing, raising IO::Buffer::AccessError" do
+ IO::Buffer.for(+'test') do |buffer|
+ -> { buffer.resize(10) }.should.raise(IO::Buffer::AccessError, "Cannot resize external buffer!")
+ end
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .string" do
+ it "disallows resizing, raising IO::Buffer::AccessError" do
+ IO::Buffer.string(4) do |buffer|
+ -> { buffer.resize(10) }.should.raise(IO::Buffer::AccessError, "Cannot resize external buffer!")
+ end
+ end
+ end
+
+ context "with a null buffer" do
+ it "allows resizing a 0-sized buffer, creating a regular buffer according to new size" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.resize(IO::Buffer::PAGE_SIZE)
+ @buffer.size.should == IO::Buffer::PAGE_SIZE
+ @buffer.internal?.should == false
+ @buffer.mapped?.should == true
+ end
+
+ it "allows resizing after a free, creating a regular buffer according to new size" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.free
+ @buffer.resize(10)
+ @buffer.size.should == 10
+ @buffer.internal?.should == true
+ @buffer.mapped?.should == false
+ end
+ end
+
+ it "allows resizing to 0, freeing memory" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.resize(0)
+ @buffer.null?.should == true
+ end
+
+ it "can be called repeatedly" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.resize(10)
+ @buffer.resize(27)
+ @buffer.resize(1)
+ @buffer.size.should == 1
+ end
+
+ it "always clears extra memory" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.set_string("test")
+ # This should not cause a re-allocation, just a technical resizing,
+ # even with very aggressive memory allocation.
+ @buffer.resize(2)
+ @buffer.resize(4)
+ @buffer.get_string.should == "te\0\0"
+ end
+
+ it "is disallowed while locked, raising IO::Buffer::LockedError" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ -> { @buffer.resize(10) }.should.raise(IO::Buffer::LockedError, "Cannot resize locked buffer!")
+ end
+ end
+
+ it "raises ArgumentError if size is negative" do
+ @buffer = IO::Buffer.new(4)
+ -> { @buffer.resize(-1) }.should.raise(ArgumentError, "Size can't be negative!")
+ end
+
+ it "raises TypeError if size is not an Integer" do
+ @buffer = IO::Buffer.new(4)
+ -> { @buffer.resize(nil) }.should.raise(TypeError, "not an Integer")
+ -> { @buffer.resize(10.0) }.should.raise(TypeError, "not an Integer")
+ end
+
+ context "with a slice of a buffer" do
+ # Current behavior of slice resizing seems unintended (it's undocumented, too).
+ # It either creates a completely new buffer, or breaks the slice on size 0.
+ it "needs to be reviewed for spec completeness"
+ end
+end
diff --git a/spec/ruby/core/io/buffer/shared/null_and_empty.rb b/spec/ruby/core/io/buffer/shared/null_and_empty.rb
new file mode 100644
index 0000000000..f8abc5f0fc
--- /dev/null
+++ b/spec/ruby/core/io/buffer/shared/null_and_empty.rb
@@ -0,0 +1,57 @@
+describe :io_buffer_null_and_empty, shared: true do
+ it "is false for a buffer with size > 0" do
+ @buffer = IO::Buffer.new(1)
+ @buffer.send(@method).should == false
+ end
+
+ it "is false for a slice with length > 0" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice(1, 2).send(@method).should == false
+ end
+
+ it "is false for a file-mapped buffer" do
+ File.open(__FILE__, "rb") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.send(@method).should == false
+ end
+ end
+
+ it "is false for a non-empty String-backed buffer created with .for" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.send(@method).should == false
+ end
+
+ it "is false for a non-empty String-backed buffer created with .string" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.send(@method).should == false
+ end
+ end
+
+ it "is true for a 0-sized buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.send(@method).should == true
+ end
+
+ it "is true for a slice of a 0-sized buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.slice(0, 0).send(@method).should == true
+ end
+
+ it "is true for a freed buffer" do
+ @buffer = IO::Buffer.new(1)
+ @buffer.free
+ @buffer.send(@method).should == true
+ end
+
+ it "is true for a buffer resized to 0" do
+ @buffer = IO::Buffer.new(1)
+ @buffer.resize(0)
+ @buffer.send(@method).should == true
+ end
+
+ it "is true for a buffer whose memory was transferred" do
+ buffer = IO::Buffer.new(1)
+ @buffer = buffer.transfer
+ buffer.send(@method).should == true
+ end
+end
diff --git a/spec/ruby/core/io/buffer/shared_spec.rb b/spec/ruby/core/io/buffer/shared_spec.rb
new file mode 100644
index 0000000000..2cc93e6d08
--- /dev/null
+++ b/spec/ruby/core/io/buffer/shared_spec.rb
@@ -0,0 +1,33 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#shared?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "is true for a buffer created with SHARED flag" do
+ @buffer = IO::Buffer.new(12, IO::Buffer::INTERNAL | IO::Buffer::SHARED)
+ @buffer.shared?.should == true
+ end
+
+ it "is true for a non-private buffer created with .map" do
+ path = fixture(__dir__, "read_text.txt")
+ file = File.open(path, "r+")
+ @buffer = IO::Buffer.map(file)
+ @buffer.shared?.should == true
+ ensure
+ @buffer.free
+ file.close
+ end
+
+ it "is false for an unshared buffer" do
+ @buffer = IO::Buffer.new(12)
+ @buffer.shared?.should == false
+ end
+
+ it "is false for a null buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.shared?.should == false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/string_spec.rb b/spec/ruby/core/io/buffer/string_spec.rb
new file mode 100644
index 0000000000..4c73ba5e1e
--- /dev/null
+++ b/spec/ruby/core/io/buffer/string_spec.rb
@@ -0,0 +1,62 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer.string" do
+ it "creates a modifiable buffer for the duration of the block" do
+ IO::Buffer.string(7) do |buffer|
+ @buffer = buffer
+
+ buffer.size.should == 7
+ buffer.get_string.should == "\0\0\0\0\0\0\0".b
+
+ buffer.set_string("test")
+ buffer.get_string.should == "test\0\0\0"
+ end
+ @buffer.should.null?
+ end
+
+ it "returns contents of the buffer as a binary string" do
+ string =
+ IO::Buffer.string(7) do |buffer|
+ buffer.set_string("ä test")
+ end
+ string.should == "\xC3\xA4 test".b
+ end
+
+ it "creates an external buffer" do
+ IO::Buffer.string(8) do |buffer|
+ buffer.should_not.internal?
+ buffer.should_not.mapped?
+ buffer.should.external?
+
+ buffer.should_not.empty?
+ buffer.should_not.null?
+
+ buffer.should_not.shared?
+ buffer.should_not.private?
+ buffer.should_not.readonly?
+
+ buffer.should_not.locked?
+ buffer.should.valid?
+ end
+ end
+
+ it "returns an empty string if size is 0" do
+ string =
+ IO::Buffer.string(0) do |buffer|
+ buffer.size.should == 0
+ end
+ string.should == ""
+ end
+
+ it "raises ArgumentError if size is negative" do
+ -> { IO::Buffer.string(-1) {} }.should.raise(ArgumentError, "negative string size (or size too big)")
+ end
+
+ it "raises RangeError if size is too large" do
+ -> { IO::Buffer.string(2 ** 232) {} }.should.raise(RangeError, /\Abignum too big to convert into [`']long'\z/)
+ end
+
+ it "raises LocalJumpError if no block is given" do
+ -> { IO::Buffer.string(7) }.should.raise(LocalJumpError, "no block given")
+ end
+end
diff --git a/spec/ruby/core/io/buffer/transfer_spec.rb b/spec/ruby/core/io/buffer/transfer_spec.rb
new file mode 100644
index 0000000000..3bc08998dd
--- /dev/null
+++ b/spec/ruby/core/io/buffer/transfer_spec.rb
@@ -0,0 +1,117 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#transfer" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "transfers internal memory to a new buffer, nullifying the original" do
+ buffer = IO::Buffer.new(4)
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should == true
+ end
+
+ it "transfers mapped memory to a new buffer, nullifying the original" do
+ buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should == true
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "transfers mapped memory to a new buffer, nullifying the original" do
+ File.open(__FILE__, "r") do |file|
+ buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should == true
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ context "without a block" do
+ it "transfers memory to a new buffer, nullifying the original" do
+ buffer = IO::Buffer.for("test")
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should == true
+ end
+ end
+
+ context "with a block" do
+ it "transfers memory to a new buffer, breaking the transaction by nullifying the original" do
+ IO::Buffer.for(+"test") do |buffer|
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should == true
+ end
+ @buffer.null?.should == false
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .string" do
+ it "transfers memory to a new buffer, breaking the transaction by nullifying the original" do
+ IO::Buffer.string(4) do |buffer|
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should == true
+ end
+ @buffer.null?.should == false
+ end
+ end
+
+ it "allows multiple transfers" do
+ buffer_1 = IO::Buffer.new(4)
+ buffer_2 = buffer_1.transfer
+ @buffer = buffer_2.transfer
+ buffer_1.null?.should == true
+ buffer_2.null?.should == true
+ @buffer.null?.should == false
+ end
+
+ it "is disallowed while locked, raising IO::Buffer::LockedError" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ -> { @buffer.transfer }.should.raise(IO::Buffer::LockedError, "Cannot transfer ownership of locked buffer!")
+ end
+ end
+
+ context "with a slice of a buffer" do
+ it "transfers source to a new slice, not touching the buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.set_string("test")
+ slice = @buffer.slice(0, 2)
+ slice.get_string.should == "te"
+
+ new_slice = slice.transfer
+ slice.null?.should == true
+ new_slice.null?.should == false
+ @buffer.null?.should == false
+
+ new_slice.set_string("ea")
+ @buffer.get_string.should == "east"
+ end
+
+ it "nullifies buffer, invalidating the slice" do
+ buffer = IO::Buffer.new(4)
+ slice = buffer.slice(0, 2)
+ @buffer = buffer.transfer
+
+ slice.null?.should == false
+ slice.valid?.should == false
+ -> { slice.get_string }.should.raise(IO::Buffer::InvalidatedError, "Buffer has been invalidated!")
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/valid_spec.rb b/spec/ruby/core/io/buffer/valid_spec.rb
new file mode 100644
index 0000000000..b84bdd0cfd
--- /dev/null
+++ b/spec/ruby/core/io/buffer/valid_spec.rb
@@ -0,0 +1,99 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#valid?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ # Non-slices are always valid
+ context "with a non-slice buffer" do
+ it "is true for a regular buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.valid?.should == true
+ end
+
+ it "is true for a 0-size buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.valid?.should == true
+ end
+
+ it "is true for a freed buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.free
+ @buffer.valid?.should == true
+ end
+
+ it "is true for a freed file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.valid?.should == true
+ @buffer.free
+ @buffer.valid?.should == true
+ end
+ end
+
+ it "is true for a freed string-backed buffer" do
+ @buffer = IO::Buffer.for("hello")
+ @buffer.valid?.should == true
+ @buffer.free
+ @buffer.valid?.should == true
+ end
+ end
+
+ # "A buffer becomes invalid if it is a slice of another buffer (or string)
+ # which has been freed or re-allocated at a different address."
+ context "with a slice" do
+ it "is true for a slice of a live buffer" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(0, 2)
+ slice.valid?.should == true
+ end
+
+ context "when buffer is resized" do
+ it "is false when slice becomes outside the buffer" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(2, 2)
+ @buffer.resize(3)
+ slice.valid?.should == false
+ end
+ end
+
+ it "is false for a slice of a transferred buffer" do
+ buffer = IO::Buffer.new(4)
+ slice = buffer.slice(0, 2)
+ @buffer = buffer.transfer
+ slice.valid?.should == false
+ end
+
+ it "is false for a slice of a freed buffer" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(0, 2)
+ @buffer.free
+ slice.valid?.should == false
+ end
+
+ it "is false for a slice of a freed file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ slice = @buffer.slice(0, 2)
+ slice.valid?.should == true
+ @buffer.free
+ slice.valid?.should == false
+ end
+ end
+
+ it "is true for a slice of a freed string-backed buffer while string is alive" do
+ @buffer = IO::Buffer.for("alive")
+ slice = @buffer.slice(0, 2)
+ slice.valid?.should == true
+ @buffer.free
+ slice.valid?.should == true
+ end
+
+ # There probably should be a test with a garbage-collected string,
+ # but it's not clear how to force that.
+
+ it "needs to be reviewed for spec completeness"
+ end
+end
diff --git a/spec/ruby/core/io/buffer/xor_spec.rb b/spec/ruby/core/io/buffer/xor_spec.rb
new file mode 100644
index 0000000000..9287611f7f
--- /dev/null
+++ b/spec/ruby/core/io/buffer/xor_spec.rb
@@ -0,0 +1,62 @@
+require_relative '../../../spec_helper'
+
+describe :io_buffer_xor, shared: true do
+ it "applies the argument buffer as an XOR bit mask across the whole buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F") do |mask|
+ result = buffer.send(@method, mask)
+ result.get_string.should == "\xC9\xBD\xCB\xBB\xCD".b
+ result.free
+ end
+ end
+ end
+
+ it "ignores extra parts of mask if it is longer than source buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F\x00\x00\x00\xFF\xFF") do |mask|
+ result = buffer.send(@method, mask)
+ result.get_string.should == "\xC9\xBD345".b
+ result.free
+ end
+ end
+ end
+
+ it "raises TypeError if mask is not an IO::Buffer" do
+ IO::Buffer.for(+"12345") do |buffer|
+ -> { buffer.send(@method, "\xF8\x8F") }.should.raise(TypeError, "wrong argument type String (expected IO::Buffer)")
+ -> { buffer.send(@method, 0xF8) }.should.raise(TypeError, "wrong argument type Integer (expected IO::Buffer)")
+ -> { buffer.send(@method, nil) }.should.raise(TypeError, "wrong argument type nil (expected IO::Buffer)")
+ end
+ end
+end
+
+describe "IO::Buffer#^" do
+ it_behaves_like :io_buffer_xor, :^
+
+ it "creates a new internal buffer of the same size" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F") do |mask|
+ result = buffer ^ mask
+ result.should_not.equal? buffer
+ result.should.internal?
+ result.size.should == buffer.size
+ result.free
+ buffer.get_string.should == "12345".b
+ end
+ end
+ end
+end
+
+describe "IO::Buffer#xor!" do
+ it_behaves_like :io_buffer_xor, :xor!
+
+ it "modifies the buffer in place" do
+ IO::Buffer.for(+"12345") do |buffer|
+ IO::Buffer.for(+"\xF8\x8F") do |mask|
+ result = buffer.xor!(mask)
+ result.should.equal? buffer
+ result.should.external?
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/bytes_spec.rb b/spec/ruby/core/io/bytes_spec.rb
deleted file mode 100644
index 6e328983f2..0000000000
--- a/spec/ruby/core/io/bytes_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- encoding: utf-8 -*-
-require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-
-ruby_version_is ''...'3.0' do
- describe "IO#bytes" do
- before :each do
- @io = IOSpecs.io_fixture "lines.txt"
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- @io.close unless @io.closed?
- end
-
- it "returns an enumerator of the next bytes from the stream" do
- enum = @io.bytes
- enum.should be_an_instance_of(Enumerator)
- @io.readline.should == "Voici la ligne une.\n"
- enum.first(5).should == [81, 117, 105, 32, 195]
- end
-
- it "yields each byte" do
- count = 0
- ScratchPad.record []
- @io.each_byte do |byte|
- ScratchPad << byte
- break if 4 < count += 1
- end
-
- ScratchPad.recorded.should == [86, 111, 105, 99, 105]
- end
-
- it "raises an IOError on closed stream" do
- enum = IOSpecs.closed_io.bytes
- -> { enum.first }.should raise_error(IOError)
- end
-
- it "raises an IOError on an enumerator for a stream that has been closed" do
- enum = @io.bytes
- enum.first.should == 86
- @io.close
- -> { enum.first }.should raise_error(IOError)
- end
- end
-end
diff --git a/spec/ruby/core/io/chars_spec.rb b/spec/ruby/core/io/chars_spec.rb
deleted file mode 100644
index 15db595aed..0000000000
--- a/spec/ruby/core/io/chars_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# -*- encoding: utf-8 -*-
-require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/chars'
-
-ruby_version_is ''...'3.0' do
- describe "IO#chars" do
- before :each do
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- end
-
- it_behaves_like :io_chars, :chars
- end
-
- describe "IO#chars" do
- before :each do
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- end
-
- it_behaves_like :io_chars_empty, :chars
- end
-end
diff --git a/spec/ruby/core/io/close_on_exec_spec.rb b/spec/ruby/core/io/close_on_exec_spec.rb
index 4e89e08d61..28cdb967b9 100644
--- a/spec/ruby/core/io/close_on_exec_spec.rb
+++ b/spec/ruby/core/io/close_on_exec_spec.rb
@@ -42,7 +42,7 @@ describe "IO#close_on_exec=" do
it "raises IOError if called on a closed IO" do
@io.close
- -> { @io.close_on_exec = true }.should raise_error(IOError)
+ -> { @io.close_on_exec = true }.should.raise(IOError)
end
end
end
@@ -70,7 +70,7 @@ describe "IO#close_on_exec?" do
it "raises IOError if called on a closed IO" do
@io.close
- -> { @io.close_on_exec? }.should raise_error(IOError)
+ -> { @io.close_on_exec? }.should.raise(IOError)
end
end
end
diff --git a/spec/ruby/core/io/close_read_spec.rb b/spec/ruby/core/io/close_read_spec.rb
index 26454bfddd..c505289d72 100644
--- a/spec/ruby/core/io/close_read_spec.rb
+++ b/spec/ruby/core/io/close_read_spec.rb
@@ -4,7 +4,8 @@ require_relative 'fixtures/classes'
describe "IO#close_read" do
before :each do
- @io = IO.popen 'cat', "r+"
+ cmd = platform_is(:windows) ? 'rem' : 'cat'
+ @io = IO.popen cmd, "r+"
@path = tmp('io.close.txt')
end
@@ -16,26 +17,26 @@ describe "IO#close_read" do
it "closes the read end of a duplex I/O stream" do
@io.close_read
- -> { @io.read }.should raise_error(IOError)
+ -> { @io.read }.should.raise(IOError)
end
it "does nothing on subsequent invocations" do
@io.close_read
- @io.close_read.should be_nil
+ @io.close_read.should == nil
end
it "allows subsequent invocation of close" do
@io.close_read
- -> { @io.close }.should_not raise_error
+ -> { @io.close }.should_not.raise
end
it "raises an IOError if the stream is writable and not duplexed" do
io = File.open @path, 'w'
begin
- -> { io.close_read }.should raise_error(IOError)
+ -> { io.close_read }.should.raise(IOError)
ensure
io.close unless io.closed?
end
@@ -55,6 +56,6 @@ describe "IO#close_read" do
it "does nothing on closed stream" do
@io.close
- @io.close_read.should be_nil
+ @io.close_read.should == nil
end
end
diff --git a/spec/ruby/core/io/close_spec.rb b/spec/ruby/core/io/close_spec.rb
index 3a44cc8b17..afd84ba101 100644
--- a/spec/ruby/core/io/close_spec.rb
+++ b/spec/ruby/core/io/close_spec.rb
@@ -23,25 +23,25 @@ describe "IO#close" do
it "raises an IOError reading from a closed IO" do
@io.close
- -> { @io.read }.should raise_error(IOError)
+ -> { @io.read }.should.raise(IOError)
end
it "raises an IOError writing to a closed IO" do
@io.close
- -> { @io.write "data" }.should raise_error(IOError)
+ -> { @io.write "data" }.should.raise(IOError)
end
it 'does not close the stream if autoclose is false' do
other_io = IO.new(@io.fileno)
other_io.autoclose = false
other_io.close
- -> { @io.write "data" }.should_not raise_error(IOError)
+ -> { @io.write "data" }.should_not.raise(IOError)
end
it "does nothing if already closed" do
@io.close
- @io.close.should be_nil
+ @io.close.should == nil
end
it "does not call the #flush method but flushes the stream internally" do
@@ -80,7 +80,7 @@ describe "IO#close" do
matching_exception&.tap {|ex| raise ex}
end
- end.should raise_error(IOError, IOSpecs::THREAD_CLOSE_ERROR_MESSAGE)
+ end.should.raise(IOError, IOSpecs::THREAD_CLOSE_ERROR_MESSAGE)
end
end
@@ -93,7 +93,7 @@ describe "IO#close on an IO.popen stream" do
io.close
- -> { io.pid }.should raise_error(IOError)
+ -> { io.pid }.should.raise(IOError)
end
it "sets $?" do
diff --git a/spec/ruby/core/io/close_write_spec.rb b/spec/ruby/core/io/close_write_spec.rb
index 14835e4e2c..60b41505c3 100644
--- a/spec/ruby/core/io/close_write_spec.rb
+++ b/spec/ruby/core/io/close_write_spec.rb
@@ -3,7 +3,8 @@ require_relative 'fixtures/classes'
describe "IO#close_write" do
before :each do
- @io = IO.popen 'cat', 'r+'
+ cmd = platform_is(:windows) ? 'rem' : 'cat'
+ @io = IO.popen cmd, 'r+'
@path = tmp('io.close.txt')
end
@@ -15,26 +16,26 @@ describe "IO#close_write" do
it "closes the write end of a duplex I/O stream" do
@io.close_write
- -> { @io.write "attempt to write" }.should raise_error(IOError)
+ -> { @io.write "attempt to write" }.should.raise(IOError)
end
it "does nothing on subsequent invocations" do
@io.close_write
- @io.close_write.should be_nil
+ @io.close_write.should == nil
end
it "allows subsequent invocation of close" do
@io.close_write
- -> { @io.close }.should_not raise_error
+ -> { @io.close }.should_not.raise
end
it "raises an IOError if the stream is readable and not duplexed" do
io = File.open @path, 'w+'
begin
- -> { io.close_write }.should raise_error(IOError)
+ -> { io.close_write }.should.raise(IOError)
ensure
io.close unless io.closed?
end
@@ -48,17 +49,20 @@ describe "IO#close_write" do
io.should.closed?
end
- it "flushes and closes the write stream" do
- @io.puts '12345'
+ # Windows didn't have command like cat
+ platform_is_not :windows do
+ it "flushes and closes the write stream" do
+ @io.puts '12345'
- @io.close_write
+ @io.close_write
- @io.read.should == "12345\n"
+ @io.read.should == "12345\n"
+ end
end
it "does nothing on closed stream" do
@io.close
- @io.close_write.should be_nil
+ @io.close_write.should == nil
end
end
diff --git a/spec/ruby/core/io/closed_spec.rb b/spec/ruby/core/io/closed_spec.rb
index 7316546a0d..1f10858e28 100644
--- a/spec/ruby/core/io/closed_spec.rb
+++ b/spec/ruby/core/io/closed_spec.rb
@@ -11,10 +11,10 @@ describe "IO#closed?" do
end
it "returns true on closed stream" do
- IOSpecs.closed_io.closed?.should be_true
+ IOSpecs.closed_io.closed?.should == true
end
it "returns false on open stream" do
- @io.closed?.should be_false
+ @io.closed?.should == false
end
end
diff --git a/spec/ruby/core/io/codepoints_spec.rb b/spec/ruby/core/io/codepoints_spec.rb
deleted file mode 100644
index 04c115dd3f..0000000000
--- a/spec/ruby/core/io/codepoints_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/codepoints'
-
-ruby_version_is ''...'3.0' do
-
- # See redmine #1667
- describe "IO#codepoints" do
- before :each do
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- end
-
- it_behaves_like :io_codepoints, :codepoints
- end
-
- describe "IO#codepoints" do
- before :each do
- @io = IOSpecs.io_fixture "lines.txt"
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- @io.close unless @io.closed?
- end
-
- it "calls the given block" do
- r = []
- @io.codepoints { |c| r << c }
- r[24].should == 232
- r.last.should == 10
- end
- end
-end
diff --git a/spec/ruby/core/io/copy_stream_spec.rb b/spec/ruby/core/io/copy_stream_spec.rb
index df9c5c7390..31383f9b0f 100644
--- a/spec/ruby/core/io/copy_stream_spec.rb
+++ b/spec/ruby/core/io/copy_stream_spec.rb
@@ -31,7 +31,7 @@ describe :io_copy_stream_to_file, shared: true do
obj = mock("io_copy_stream_to")
obj.should_receive(:to_path).and_return(1)
- -> { IO.copy_stream(@object.from, obj) }.should raise_error(TypeError)
+ -> { IO.copy_stream(@object.from, obj) }.should.raise(TypeError)
end
end
@@ -69,14 +69,17 @@ describe :io_copy_stream_to_io, shared: true do
end
it "raises an IOError if the destination IO is not open for writing" do
- @to_io.close
- @to_io = new_io @to_name, "r"
- -> { IO.copy_stream @object.from, @to_io }.should raise_error(IOError)
+ to_io = new_io __FILE__, "r"
+ begin
+ -> { IO.copy_stream @object.from, to_io }.should.raise(IOError)
+ ensure
+ to_io.close
+ end
end
it "does not close the destination IO" do
IO.copy_stream(@object.from, @to_io)
- @to_io.closed?.should be_false
+ @to_io.closed?.should == false
end
it "copies only length bytes when specified" do
@@ -109,7 +112,8 @@ describe "IO.copy_stream" do
end
after :each do
- rm_r @to_name, @from_bigfile
+ rm_r @to_name if @to_name
+ rm_r @from_bigfile
end
describe "from an IO" do
@@ -125,12 +129,12 @@ describe "IO.copy_stream" do
it "raises an IOError if the source IO is not open for reading" do
@from_io.close
@from_io = new_io @from_bigfile, "a"
- -> { IO.copy_stream @from_io, @to_name }.should raise_error(IOError)
+ -> { IO.copy_stream @from_io, @to_name }.should.raise(IOError)
end
it "does not close the source IO" do
IO.copy_stream(@from_io, @to_name)
- @from_io.closed?.should be_false
+ @from_io.closed?.should == false
end
platform_is_not :windows do
@@ -164,6 +168,25 @@ describe "IO.copy_stream" do
it_behaves_like :io_copy_stream_to_io, nil, IOSpecs::CopyStream
it_behaves_like :io_copy_stream_to_io_with_offset, nil, IOSpecs::CopyStream
end
+
+ describe "to a Tempfile" do
+ before :all do
+ require 'tempfile'
+ end
+
+ before :each do
+ @to_io = Tempfile.new("rubyspec_copy_stream", encoding: Encoding::BINARY, mode: File::RDONLY)
+ @to_name = @to_io.path
+ end
+
+ after :each do
+ @to_io.close!
+ @to_name = nil # do not rm_r it, already done by Tempfile#close!
+ end
+
+ it_behaves_like :io_copy_stream_to_io, nil, IOSpecs::CopyStream
+ it_behaves_like :io_copy_stream_to_io_with_offset, nil, IOSpecs::CopyStream
+ end
end
describe "from a file name" do
@@ -183,7 +206,7 @@ describe "IO.copy_stream" do
obj = mock("io_copy_stream_from")
obj.should_receive(:to_path).and_return(1)
- -> { IO.copy_stream(obj, @to_name) }.should raise_error(TypeError)
+ -> { IO.copy_stream(obj, @to_name) }.should.raise(TypeError)
end
describe "to a file name" do
@@ -217,12 +240,12 @@ describe "IO.copy_stream" do
it "does not close the source IO" do
IO.copy_stream(@from_io, @to_name)
- @from_io.closed?.should be_false
+ @from_io.closed?.should == false
end
platform_is_not :windows do
it "raises an error when an offset is specified" do
- -> { IO.copy_stream(@from_io, @to_name, 8, 4) }.should raise_error(Errno::ESPIPE)
+ -> { IO.copy_stream(@from_io, @to_name, 8, 4) }.should.raise(Errno::ESPIPE)
end
end
@@ -278,9 +301,15 @@ describe "IO.copy_stream" do
IO.copy_stream(@io, @to_name)
end
+ it "does not call #read on the source or #write on the destination if zero length is given" do
+ from = mock("io_copy_stream_to_object_zero_length_read")
+ to = mock("io_copy_stream_to_object_zero_length_write")
+ from.should_not_receive(:read)
+ to.should_not_receive(:write)
+ IO.copy_stream(from, to, 0)
+ end
end
-
describe "with a destination that does partial reads" do
before do
@from_out, @from_in = IO.pipe
diff --git a/spec/ruby/core/io/dup_spec.rb b/spec/ruby/core/io/dup_spec.rb
index 68d538377f..db4e9fe641 100644
--- a/spec/ruby/core/io/dup_spec.rb
+++ b/spec/ruby/core/io/dup_spec.rb
@@ -25,31 +25,31 @@ describe "IO#dup" do
@i.fileno.should_not == @f.fileno
end
-quarantine! do # This does not appear to be consistent across platforms
- it "shares the original stream between the two IOs" do
- start = @f.pos
- @i.pos.should == start
+ quarantine! do # This does not appear to be consistent across platforms
+ it "shares the original stream between the two IOs" do
+ start = @f.pos
+ @i.pos.should == start
- s = "Hello, wo.. wait, where am I?\n"
- s2 = "<evil voice> Muhahahaa!"
+ s = "Hello, wo.. wait, where am I?\n"
+ s2 = "<evil voice> Muhahahaa!"
- @f.write s
- @i.pos.should == @f.pos
+ @f.write s
+ @i.pos.should == @f.pos
- @i.rewind
- @i.gets.should == s
+ @i.rewind
+ @i.gets.should == s
- @i.rewind
- @i.write s2
+ @i.rewind
+ @i.write s2
- @f.rewind
- @f.gets.should == "#{s2}\n"
+ @f.rewind
+ @f.gets.should == "#{s2}\n"
+ end
end
-end
it "allows closing the new IO without affecting the original" do
@i.close
- -> { @f.gets }.should_not raise_error(Exception)
+ -> { @f.gets }.should_not.raise(Exception)
@i.should.closed?
@f.should_not.closed?
@@ -57,14 +57,14 @@ end
it "allows closing the original IO without affecting the new one" do
@f.close
- -> { @i.gets }.should_not raise_error(Exception)
+ -> { @i.gets }.should_not.raise(Exception)
@i.should_not.closed?
@f.should.closed?
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.dup }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.dup }.should.raise(IOError)
end
it "always sets the close-on-exec flag for the new IO object" do
diff --git a/spec/ruby/core/io/each_byte_spec.rb b/spec/ruby/core/io/each_byte_spec.rb
index ea618e8c0c..fe299f0fba 100644
--- a/spec/ruby/core/io/each_byte_spec.rb
+++ b/spec/ruby/core/io/each_byte_spec.rb
@@ -12,7 +12,7 @@ describe "IO#each_byte" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.each_byte {} }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.each_byte {} }.should.raise(IOError)
end
it "yields each byte" do
@@ -28,7 +28,7 @@ describe "IO#each_byte" do
describe "when no block is given" do
it "returns an Enumerator" do
enum = @io.each_byte
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.first(5).should == [86, 111, 105, 99, 105]
end
@@ -52,6 +52,6 @@ describe "IO#each_byte" do
end
it "returns self on an empty stream" do
- @io.each_byte { |b| }.should equal(@io)
+ @io.each_byte { |b| }.should.equal?(@io)
end
end
diff --git a/spec/ruby/core/io/each_codepoint_spec.rb b/spec/ruby/core/io/each_codepoint_spec.rb
index 07a4037c8a..26cc87fc0e 100644
--- a/spec/ruby/core/io/each_codepoint_spec.rb
+++ b/spec/ruby/core/io/each_codepoint_spec.rb
@@ -24,7 +24,7 @@ describe "IO#each_codepoint" do
end
it "returns self" do
- @io.each_codepoint { |l| l }.should equal(@io)
+ @io.each_codepoint { |l| l }.should.equal?(@io)
end
end
@@ -38,6 +38,6 @@ describe "IO#each_codepoint" do
end
it "raises an exception at incomplete character before EOF when conversion takes place" do
- -> { @io.each_codepoint {} }.should raise_error(ArgumentError)
+ -> { @io.each_codepoint {} }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/io/eof_spec.rb b/spec/ruby/core/io/eof_spec.rb
index 315345d942..c8955abde0 100644
--- a/spec/ruby/core/io/eof_spec.rb
+++ b/spec/ruby/core/io/eof_spec.rb
@@ -18,7 +18,7 @@ describe "IO#eof?" do
it "raises IOError on stream not opened for reading" do
-> do
File.open(@name, "w") { |f| f.eof? }
- end.should raise_error(IOError)
+ end.should.raise(IOError)
end
end
@@ -67,16 +67,16 @@ describe "IO#eof?" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.eof? }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.eof? }.should.raise(IOError)
end
it "raises IOError on stream closed for reading by close_read" do
@io.close_read
- -> { @io.eof? }.should raise_error(IOError)
+ -> { @io.eof? }.should.raise(IOError)
end
it "returns true on one-byte stream after single-byte read" do
- File.open(File.dirname(__FILE__) + '/fixtures/one_byte.txt') { |one_byte|
+ File.open(__dir__ + '/fixtures/one_byte.txt') { |one_byte|
one_byte.read(1)
one_byte.should.eof?
}
diff --git a/spec/ruby/core/io/external_encoding_spec.rb b/spec/ruby/core/io/external_encoding_spec.rb
index 2fcf1c7218..72d246cc2b 100644
--- a/spec/ruby/core/io/external_encoding_spec.rb
+++ b/spec/ruby/core/io/external_encoding_spec.rb
@@ -10,19 +10,19 @@ describe :io_external_encoding_write, shared: true do
it "returns nil" do
@io = new_io @name, @object
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should be_nil
+ @io.external_encoding.should == nil
end
it "returns the external encoding specified when the instance was created" do
@io = new_io @name, "#{@object}:ibm866"
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should equal(Encoding::IBM866)
+ @io.external_encoding.should.equal?(Encoding::IBM866)
end
it "returns the encoding set by #set_encoding" do
@io = new_io @name, "#{@object}:ibm866"
@io.set_encoding Encoding::EUC_JP, nil
- @io.external_encoding.should equal(Encoding::EUC_JP)
+ @io.external_encoding.should.equal?(Encoding::EUC_JP)
end
end
@@ -35,19 +35,19 @@ describe :io_external_encoding_write, shared: true do
it "returns the value of Encoding.default_external when the instance was created" do
@io = new_io @name, @object
Encoding.default_external = Encoding::UTF_8
- @io.external_encoding.should equal(Encoding::IBM437)
+ @io.external_encoding.should.equal?(Encoding::IBM437)
end
it "returns the external encoding specified when the instance was created" do
@io = new_io @name, "#{@object}:ibm866"
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should equal(Encoding::IBM866)
+ @io.external_encoding.should.equal?(Encoding::IBM866)
end
it "returns the encoding set by #set_encoding" do
@io = new_io @name, "#{@object}:ibm866"
@io.set_encoding Encoding::EUC_JP, nil
- @io.external_encoding.should equal(Encoding::EUC_JP)
+ @io.external_encoding.should.equal?(Encoding::EUC_JP)
end
end
@@ -60,19 +60,19 @@ describe :io_external_encoding_write, shared: true do
it "returns the value of Encoding.default_external when the instance was created" do
@io = new_io @name, @object
Encoding.default_external = Encoding::UTF_8
- @io.external_encoding.should equal(Encoding::IBM866)
+ @io.external_encoding.should.equal?(Encoding::IBM866)
end
it "returns the external encoding specified when the instance was created" do
@io = new_io @name, "#{@object}:ibm866"
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should equal(Encoding::IBM866)
+ @io.external_encoding.should.equal?(Encoding::IBM866)
end
it "returns the encoding set by #set_encoding" do
@io = new_io @name, "#{@object}:ibm866"
@io.set_encoding Encoding::EUC_JP, nil
- @io.external_encoding.should equal(Encoding::EUC_JP)
+ @io.external_encoding.should.equal?(Encoding::EUC_JP)
end
end
end
@@ -94,12 +94,10 @@ describe "IO#external_encoding" do
rm_r @name
end
- ruby_version_is '3.1' do
- it "can be retrieved from a closed stream" do
- io = IOSpecs.io_fixture("lines.txt", "r")
- io.close
- io.external_encoding.should equal(Encoding.default_external)
- end
+ it "can be retrieved from a closed stream" do
+ io = IOSpecs.io_fixture("lines.txt", "r")
+ io.close
+ io.external_encoding.should.equal?(Encoding.default_external)
end
describe "with 'r' mode" do
@@ -111,25 +109,25 @@ describe "IO#external_encoding" do
it "returns Encoding.default_external if the external encoding is not set" do
@io = new_io @name, "r"
- @io.external_encoding.should equal(Encoding::IBM866)
+ @io.external_encoding.should.equal?(Encoding::IBM866)
end
it "returns Encoding.default_external when that encoding is changed after the instance is created" do
@io = new_io @name, "r"
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should equal(Encoding::IBM437)
+ @io.external_encoding.should.equal?(Encoding::IBM437)
end
it "returns the external encoding specified when the instance was created" do
@io = new_io @name, "r:utf-8"
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should equal(Encoding::UTF_8)
+ @io.external_encoding.should.equal?(Encoding::UTF_8)
end
it "returns the encoding set by #set_encoding" do
@io = new_io @name, "r:utf-8"
@io.set_encoding Encoding::EUC_JP, nil
- @io.external_encoding.should equal(Encoding::EUC_JP)
+ @io.external_encoding.should.equal?(Encoding::EUC_JP)
end
end
@@ -142,19 +140,19 @@ describe "IO#external_encoding" do
it "returns the value of Encoding.default_external when the instance was created" do
@io = new_io @name, "r"
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should equal(Encoding::IBM866)
+ @io.external_encoding.should.equal?(Encoding::IBM866)
end
it "returns the external encoding specified when the instance was created" do
@io = new_io @name, "r:utf-8"
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should equal(Encoding::UTF_8)
+ @io.external_encoding.should.equal?(Encoding::UTF_8)
end
it "returns the encoding set by #set_encoding" do
@io = new_io @name, "r:utf-8"
@io.set_encoding Encoding::EUC_JP, nil
- @io.external_encoding.should equal(Encoding::EUC_JP)
+ @io.external_encoding.should.equal?(Encoding::EUC_JP)
end
end
@@ -168,13 +166,13 @@ describe "IO#external_encoding" do
it "returns the external encoding specified when the instance was created" do
@io = new_io @name, "r:utf-8"
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should equal(Encoding::UTF_8)
+ @io.external_encoding.should.equal?(Encoding::UTF_8)
end
it "returns the encoding set by #set_encoding" do
@io = new_io @name, "r:utf-8"
@io.set_encoding Encoding::EUC_JP, nil
- @io.external_encoding.should equal(Encoding::EUC_JP)
+ @io.external_encoding.should.equal?(Encoding::EUC_JP)
end
end
end
@@ -182,12 +180,12 @@ describe "IO#external_encoding" do
describe "with 'rb' mode" do
it "returns Encoding::BINARY" do
@io = new_io @name, "rb"
- @io.external_encoding.should equal(Encoding::BINARY)
+ @io.external_encoding.should.equal?(Encoding::BINARY)
end
it "returns the external encoding specified by the mode argument" do
@io = new_io @name, "rb:ibm437"
- @io.external_encoding.should equal(Encoding::IBM437)
+ @io.external_encoding.should.equal?(Encoding::IBM437)
end
end
@@ -202,12 +200,12 @@ describe "IO#external_encoding" do
describe "with 'wb' mode" do
it "returns Encoding::BINARY" do
@io = new_io @name, "wb"
- @io.external_encoding.should equal(Encoding::BINARY)
+ @io.external_encoding.should.equal?(Encoding::BINARY)
end
it "returns the external encoding specified by the mode argument" do
@io = new_io @name, "wb:ibm437"
- @io.external_encoding.should equal(Encoding::IBM437)
+ @io.external_encoding.should.equal?(Encoding::IBM437)
end
end
diff --git a/spec/ruby/core/io/fcntl_spec.rb b/spec/ruby/core/io/fcntl_spec.rb
index 30b4876fe3..be6d06c672 100644
--- a/spec/ruby/core/io/fcntl_spec.rb
+++ b/spec/ruby/core/io/fcntl_spec.rb
@@ -3,6 +3,6 @@ require_relative 'fixtures/classes'
describe "IO#fcntl" do
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.fcntl(5, 5) }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.fcntl(5, 5) }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/fileno_spec.rb b/spec/ruby/core/io/fileno_spec.rb
index 647609bf42..22fd68d166 100644
--- a/spec/ruby/core/io/fileno_spec.rb
+++ b/spec/ruby/core/io/fileno_spec.rb
@@ -7,6 +7,6 @@ describe "IO#fileno" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.fileno }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.fileno }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/fixtures/classes.rb b/spec/ruby/core/io/fixtures/classes.rb
index 067ab59d93..204a2a101b 100644
--- a/spec/ruby/core/io/fixtures/classes.rb
+++ b/spec/ruby/core/io/fixtures/classes.rb
@@ -7,6 +7,18 @@ module IOSpecs
class SubIO < IO
end
+ class SubIOWithRedefinedNew < IO
+ def self.new(...)
+ ScratchPad << :redefined_new_called
+ super
+ end
+
+ def initialize(...)
+ ScratchPad << :call_original_initialize
+ super
+ end
+ end
+
def self.collector
Proc.new { |x| ScratchPad << x }
end
diff --git a/spec/ruby/core/io/flush_spec.rb b/spec/ruby/core/io/flush_spec.rb
index 34cf42c425..4c3e8d12af 100644
--- a/spec/ruby/core/io/flush_spec.rb
+++ b/spec/ruby/core/io/flush_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "IO#flush" do
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.flush }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.flush }.should.raise(IOError)
end
describe "on a pipe" do
@@ -19,18 +19,18 @@ describe "IO#flush" do
end
end
- # [ruby-core:90895] MJIT worker may leave fd open in a forked child.
- # For instance, MJIT creates a worker before @r.close with fork(), @r.close happens,
- # and the MJIT worker keeps the pipe open until the worker execve().
- # TODO: consider acquiring GVL from MJIT worker.
- guard_not -> { defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? } do
+ # [ruby-core:90895] RJIT worker may leave fd open in a forked child.
+ # For instance, RJIT creates a worker before @r.close with fork(), @r.close happens,
+ # and the RJIT worker keeps the pipe open until the worker execve().
+ # TODO: consider acquiring GVL from RJIT worker.
+ guard_not -> { defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? } do
it "raises Errno::EPIPE if sync=false and the read end is closed" do
@w.sync = false
@w.write "foo"
@r.close
- -> { @w.flush }.should raise_error(Errno::EPIPE, /Broken pipe/)
- -> { @w.close }.should raise_error(Errno::EPIPE, /Broken pipe/)
+ -> { @w.flush }.should.raise(Errno::EPIPE, /Broken pipe/)
+ -> { @w.close }.should.raise(Errno::EPIPE, /Broken pipe/)
end
end
end
diff --git a/spec/ruby/core/io/foreach_spec.rb b/spec/ruby/core/io/foreach_spec.rb
index c2276cf544..015988f9fb 100644
--- a/spec/ruby/core/io/foreach_spec.rb
+++ b/spec/ruby/core/io/foreach_spec.rb
@@ -14,31 +14,46 @@ describe "IO.foreach" do
IO.foreach(@name) { $..should == @count += 1 }
end
- describe "when the filename starts with |" do
- it "gets data from the standard out of the subprocess" do
- cmd = "|sh -c 'echo hello;echo line2'"
- platform_is :windows do
- cmd = "|cmd.exe /C echo hello&echo line2"
+ ruby_version_is ""..."4.0" do
+ describe "when the filename starts with |" do
+ it "gets data from the standard out of the subprocess" do
+ cmd = "|sh -c 'echo hello;echo line2'"
+ platform_is :windows do
+ cmd = "|cmd.exe /C echo hello&echo line2"
+ end
+
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.foreach(cmd) { |l| ScratchPad << l }
+ end
+ ScratchPad.recorded.should == ["hello\n", "line2\n"]
end
- IO.foreach(cmd) { |l| ScratchPad << l }
- ScratchPad.recorded.should == ["hello\n", "line2\n"]
- end
- platform_is_not :windows do
- it "gets data from a fork when passed -" do
- parent_pid = $$
+ platform_is_not :windows do
+ it "gets data from a fork when passed -" do
+ parent_pid = $$
- IO.foreach("|-") { |l| ScratchPad << l }
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.foreach("|-") { |l| ScratchPad << l }
+ end
- if $$ == parent_pid
- ScratchPad.recorded.should == ["hello\n", "from a fork\n"]
- else # child
- puts "hello"
- puts "from a fork"
- exit!
+ if $$ == parent_pid
+ ScratchPad.recorded.should == ["hello\n", "from a fork\n"]
+ else # child
+ puts "hello"
+ puts "from a fork"
+ exit!
+ end
end
end
end
+
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation given a path with a pipe" do
+ cmd = "|echo ok"
+ -> {
+ IO.foreach(cmd).to_a
+ }.should complain(/IO process creation with a leading '\|'/)
+ end
end
end
@@ -58,12 +73,12 @@ describe "IO.foreach" do
it "sets $_ to nil" do
$_ = "test"
IO.foreach(@name) { }
- $_.should be_nil
+ $_.should == nil
end
describe "when no block is given" do
it "returns an Enumerator" do
- IO.foreach(@name).should be_an_instance_of(Enumerator)
+ IO.foreach(@name).should.instance_of?(Enumerator)
IO.foreach(@name).to_a.should == IOSpecs.lines
end
diff --git a/spec/ruby/core/io/fsync_spec.rb b/spec/ruby/core/io/fsync_spec.rb
index 6e6123de94..0317cbc805 100644
--- a/spec/ruby/core/io/fsync_spec.rb
+++ b/spec/ruby/core/io/fsync_spec.rb
@@ -12,7 +12,7 @@ describe "IO#fsync" do
end
it "raises an IOError on closed stream" do
- -> { IOSpecs.closed_io.fsync }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.fsync }.should.raise(IOError)
end
it "writes the buffered data to permanent storage" do
diff --git a/spec/ruby/core/io/getbyte_spec.rb b/spec/ruby/core/io/getbyte_spec.rb
index 6ba8f0a3e0..668d81519c 100644
--- a/spec/ruby/core/io/getbyte_spec.rb
+++ b/spec/ruby/core/io/getbyte_spec.rb
@@ -23,7 +23,7 @@ describe "IO#getbyte" do
end
it "raises an IOError on closed stream" do
- -> { IOSpecs.closed_io.getbyte }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.getbyte }.should.raise(IOError)
end
end
@@ -40,3 +40,19 @@ describe "IO#getbyte" do
@io.getbyte.should == nil
end
end
+
+describe "IO#getbyte" do
+ before :each do
+ @name = tmp("io_getbyte.txt")
+ @io = new_io(@name, 'w')
+ end
+
+ after :each do
+ @io.close if @io
+ rm_r @name if @name
+ end
+
+ it "raises an IOError if the stream is not readable" do
+ -> { @io.getbyte }.should.raise(IOError)
+ end
+end
diff --git a/spec/ruby/core/io/getc_spec.rb b/spec/ruby/core/io/getc_spec.rb
index 3949b5cb28..3be86203c0 100644
--- a/spec/ruby/core/io/getc_spec.rb
+++ b/spec/ruby/core/io/getc_spec.rb
@@ -19,11 +19,11 @@ describe "IO#getc" do
it "returns nil when invoked at the end of the stream" do
@io.read
- @io.getc.should be_nil
+ @io.getc.should == nil
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.getc }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.getc }.should.raise(IOError)
end
end
@@ -37,6 +37,6 @@ describe "IO#getc" do
end
it "returns nil on empty stream" do
- @io.getc.should be_nil
+ @io.getc.should == nil
end
end
diff --git a/spec/ruby/core/io/gets_spec.rb b/spec/ruby/core/io/gets_spec.rb
index b9f82f8133..ce3ee73b94 100644
--- a/spec/ruby/core/io/gets_spec.rb
+++ b/spec/ruby/core/io/gets_spec.rb
@@ -24,13 +24,19 @@ describe "IO#gets" do
end
end
+ it "sets $_ to nil after the last line has been read" do
+ while @io.gets
+ end
+ $_.should == nil
+ end
+
it "returns nil if called at the end of the stream" do
IOSpecs.lines.length.times { @io.gets }
@io.gets.should == nil
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.gets }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.gets }.should.raise(IOError)
end
describe "with no separator" do
@@ -113,6 +119,35 @@ describe "IO#gets" do
$..should == @count += 1
end
end
+
+ describe "that consists of multiple bytes" do
+ platform_is_not :windows do
+ it "should match the separator even if the buffer is filled over successive reads" do
+ IO.pipe do |read, write|
+
+ # Write part of the string with the separator split between two write calls. We want
+ # the read to intertwine such that when the read starts the full data isn't yet
+ # available in the buffer.
+ write.write("Aquí está la línea tres\r\n")
+
+ t = Thread.new do
+ # Continue reading until the separator is encountered or the pipe is closed.
+ read.gets("\r\n\r\n")
+ end
+
+ # Write the other half of the separator, which should cause the `gets` call to now
+ # match. Explicitly close the pipe for good measure so a bug in `gets` doesn't block forever.
+ Thread.pass until t.stop?
+
+ write.write("\r\nelse\r\n\r\n")
+ write.close
+
+ t.value.bytes.should == "Aquí está la línea tres\r\n\r\n".bytes
+ read.read(8).bytes.should == "else\r\n\r\n".bytes
+ end
+ end
+ end
+ end
end
describe "when passed chomp" do
@@ -120,14 +155,12 @@ describe "IO#gets" do
@io.gets(chomp: true).should == IOSpecs.lines_without_newline_characters[0]
end
- ruby_version_is "3.0" do
- it "raises exception when options passed as Hash" do
- -> { @io.gets({ chomp: true }) }.should raise_error(TypeError)
+ it "raises exception when options passed as Hash" do
+ -> { @io.gets({ chomp: true }) }.should.raise(TypeError)
- -> {
- @io.gets("\n", 1, { chomp: true })
- }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
- end
+ -> {
+ @io.gets("\n", 1, { chomp: true })
+ }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
end
end
end
@@ -142,11 +175,11 @@ describe "IO#gets" do
end
it "raises an IOError if the stream is opened for append only" do
- -> { File.open(@name, "a:utf-8") { |f| f.gets } }.should raise_error(IOError)
+ -> { File.open(@name, "a:utf-8") { |f| f.gets } }.should.raise(IOError)
end
it "raises an IOError if the stream is opened for writing only" do
- -> { File.open(@name, "w:utf-8") { |f| f.gets } }.should raise_error(IOError)
+ -> { File.open(@name, "w:utf-8") { |f| f.gets } }.should.raise(IOError)
end
end
@@ -213,6 +246,12 @@ describe "IO#gets" do
it "returns empty string when 0 passed as a limit" do
@io.gets(0).should == ""
+ @io.gets(nil, 0).should == ""
+ @io.gets("", 0).should == ""
+ end
+
+ it "does not accept limit that doesn't fit in a C off_t" do
+ -> { @io.gets(2**128) }.should.raise(RangeError)
end
end
@@ -299,11 +338,11 @@ describe "IO#gets" do
@io.gets.encoding.should == Encoding::BINARY
end
- it "transcodes to internal encoding if the IO object's external encoding is BINARY" do
+ it "ignores the internal encoding if the IO object's external encoding is BINARY" do
Encoding.default_external = Encoding::BINARY
Encoding.default_internal = Encoding::UTF_8
@io = new_io @name, 'r'
@io.set_encoding Encoding::BINARY, Encoding::UTF_8
- @io.gets.encoding.should == Encoding::UTF_8
+ @io.gets.encoding.should == Encoding::BINARY
end
end
diff --git a/spec/ruby/core/io/initialize_spec.rb b/spec/ruby/core/io/initialize_spec.rb
index ba5bc117b7..3425e5ac37 100644
--- a/spec/ruby/core/io/initialize_spec.rb
+++ b/spec/ruby/core/io/initialize_spec.rb
@@ -27,23 +27,34 @@ describe "IO#initialize" do
@io.fileno.should == fd
end
+ it "accepts options as keyword arguments" do
+ fd = new_fd @name, "w:utf-8"
+
+ @io.send(:initialize, fd, "w", flags: File::CREAT)
+ @io.fileno.should == fd
+
+ -> {
+ @io.send(:initialize, fd, "w", {flags: File::CREAT})
+ }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 1..2)")
+ end
+
it "raises a TypeError when passed an IO" do
- -> { @io.send :initialize, STDOUT, 'w' }.should raise_error(TypeError)
+ -> { @io.send :initialize, STDOUT, 'w' }.should.raise(TypeError)
end
it "raises a TypeError when passed nil" do
- -> { @io.send :initialize, nil, 'w' }.should raise_error(TypeError)
+ -> { @io.send :initialize, nil, 'w' }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- -> { @io.send :initialize, "4", 'w' }.should raise_error(TypeError)
+ -> { @io.send :initialize, "4", 'w' }.should.raise(TypeError)
end
it "raises IOError on closed stream" do
- -> { @io.send :initialize, IOSpecs.closed_io.fileno }.should raise_error(IOError)
+ -> { @io.send :initialize, IOSpecs.closed_io.fileno }.should.raise(IOError)
end
it "raises an Errno::EBADF when given an invalid file descriptor" do
- -> { @io.send :initialize, -1, 'w' }.should raise_error(Errno::EBADF)
+ -> { @io.send :initialize, -1, 'w' }.should.raise(Errno::EBADF)
end
end
diff --git a/spec/ruby/core/io/inspect_spec.rb b/spec/ruby/core/io/inspect_spec.rb
index c653c307c4..37dc459f22 100644
--- a/spec/ruby/core/io/inspect_spec.rb
+++ b/spec/ruby/core/io/inspect_spec.rb
@@ -8,13 +8,13 @@ describe "IO#inspect" do
it "contains the file descriptor number" do
@r, @w = IO.pipe
- @r.inspect.should include("fd #{@r.fileno}")
+ @r.inspect.should.include?("fd #{@r.fileno}")
end
it "contains \"(closed)\" if the stream is closed" do
@r, @w = IO.pipe
@r.close
- @r.inspect.should include("(closed)")
+ @r.inspect.should.include?("(closed)")
end
it "reports IO as its Method object's owner" do
diff --git a/spec/ruby/core/io/internal_encoding_spec.rb b/spec/ruby/core/io/internal_encoding_spec.rb
index 60afaf2ebd..9963a93f33 100644
--- a/spec/ruby/core/io/internal_encoding_spec.rb
+++ b/spec/ruby/core/io/internal_encoding_spec.rb
@@ -9,25 +9,25 @@ describe :io_internal_encoding, shared: true do
it "returns nil if the internal encoding is not set" do
@io = new_io @name, @object
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
it "returns nil if Encoding.default_internal is changed after the instance is created" do
@io = new_io @name, @object
Encoding.default_internal = Encoding::IBM437
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
it "returns the value set when the instance was created" do
@io = new_io @name, "#{@object}:utf-8:euc-jp"
Encoding.default_internal = Encoding::IBM437
- @io.internal_encoding.should equal(Encoding::EUC_JP)
+ @io.internal_encoding.should.equal?(Encoding::EUC_JP)
end
it "returns the value set by #set_encoding" do
@io = new_io @name, @object
@io.set_encoding(Encoding::US_ASCII, Encoding::IBM437)
- @io.internal_encoding.should equal(Encoding::IBM437)
+ @io.internal_encoding.should.equal?(Encoding::IBM437)
end
end
@@ -39,13 +39,13 @@ describe :io_internal_encoding, shared: true do
it "returns nil" do
@io = new_io @name, @object
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
it "returns nil regardless of Encoding.default_internal changes" do
@io = new_io @name, @object
Encoding.default_internal = Encoding::IBM437
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
end
@@ -57,41 +57,41 @@ describe :io_internal_encoding, shared: true do
it "returns the value of Encoding.default_internal when the instance was created if the internal encoding is not set" do
@io = new_io @name, @object
- @io.internal_encoding.should equal(Encoding::IBM866)
+ @io.internal_encoding.should.equal?(Encoding::IBM866)
end
it "does not change when Encoding.default_internal is changed" do
@io = new_io @name, @object
Encoding.default_internal = Encoding::IBM437
- @io.internal_encoding.should equal(Encoding::IBM866)
+ @io.internal_encoding.should.equal?(Encoding::IBM866)
end
it "returns the internal encoding set when the instance was created" do
@io = new_io @name, "#{@object}:utf-8:euc-jp"
- @io.internal_encoding.should equal(Encoding::EUC_JP)
+ @io.internal_encoding.should.equal?(Encoding::EUC_JP)
end
it "does not change when set and Encoding.default_internal is changed" do
@io = new_io @name, "#{@object}:utf-8:euc-jp"
Encoding.default_internal = Encoding::IBM437
- @io.internal_encoding.should equal(Encoding::EUC_JP)
+ @io.internal_encoding.should.equal?(Encoding::EUC_JP)
end
it "returns the value set by #set_encoding" do
@io = new_io @name, @object
@io.set_encoding(Encoding::US_ASCII, Encoding::IBM437)
- @io.internal_encoding.should equal(Encoding::IBM437)
+ @io.internal_encoding.should.equal?(Encoding::IBM437)
end
it "returns nil when Encoding.default_external is BINARY and the internal encoding is not set" do
Encoding.default_external = Encoding::BINARY
@io = new_io @name, @object
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
it "returns nil when the external encoding is BINARY and the internal encoding is not set" do
@io = new_io @name, "#{@object}:binary"
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
end
end
@@ -113,12 +113,10 @@ describe "IO#internal_encoding" do
Encoding.default_internal = @internal
end
- ruby_version_is '3.1' do
- it "can be retrieved from a closed stream" do
- io = IOSpecs.io_fixture("lines.txt", "r")
- io.close
- io.internal_encoding.should equal(Encoding.default_internal)
- end
+ it "can be retrieved from a closed stream" do
+ io = IOSpecs.io_fixture("lines.txt", "r")
+ io.close
+ io.internal_encoding.should.equal?(Encoding.default_internal)
end
describe "with 'r' mode" do
diff --git a/spec/ruby/core/io/ioctl_spec.rb b/spec/ruby/core/io/ioctl_spec.rb
index 8dcd9eb2c6..15a5d6ec22 100644
--- a/spec/ruby/core/io/ioctl_spec.rb
+++ b/spec/ruby/core/io/ioctl_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
describe "IO#ioctl" do
platform_is_not :windows do
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.ioctl(5, 5) }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.ioctl(5, 5) }.should.raise(IOError)
end
end
@@ -12,10 +12,10 @@ describe "IO#ioctl" do
guard -> { RUBY_PLATFORM.include?("86") } do # x86 / x86_64
it "resizes an empty String to match the output size" do
File.open(__FILE__, 'r') do |f|
- buffer = ''
+ buffer = +''
# FIONREAD in /usr/include/asm-generic/ioctls.h
f.ioctl 0x541B, buffer
- buffer.unpack('I').first.should be_kind_of(Integer)
+ buffer.unpack('I').first.should.is_a?(Integer)
end
end
end
@@ -25,7 +25,7 @@ describe "IO#ioctl" do
-> {
# TIOCGWINSZ in /usr/include/asm-generic/ioctls.h
f.ioctl 0x5413, nil
- }.should raise_error(SystemCallError)
+ }.should.raise(SystemCallError)
end
end
end
diff --git a/spec/ruby/core/io/lineno_spec.rb b/spec/ruby/core/io/lineno_spec.rb
index 99266ecca1..93b505652a 100644
--- a/spec/ruby/core/io/lineno_spec.rb
+++ b/spec/ruby/core/io/lineno_spec.rb
@@ -11,14 +11,14 @@ describe "IO#lineno" do
end
it "raises an IOError on a closed stream" do
- -> { IOSpecs.closed_io.lineno }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.lineno }.should.raise(IOError)
end
it "raises an IOError on a write-only stream" do
name = tmp("io_lineno.txt")
begin
File.open(name, 'w') do |f|
- -> { f.lineno }.should raise_error(IOError)
+ -> { f.lineno }.should.raise(IOError)
end
ensure
rm_r name
@@ -26,9 +26,10 @@ describe "IO#lineno" do
end
it "raises an IOError on a duplexed stream with the read side closed" do
- IO.popen('cat', 'r+') do |p|
+ cmd = platform_is(:windows) ? 'rem' : 'cat'
+ IO.popen(cmd, 'r+') do |p|
p.close_read
- -> { p.lineno }.should raise_error(IOError)
+ -> { p.lineno }.should.raise(IOError)
end
end
@@ -55,14 +56,14 @@ describe "IO#lineno=" do
end
it "raises an IOError on a closed stream" do
- -> { IOSpecs.closed_io.lineno = 5 }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.lineno = 5 }.should.raise(IOError)
end
it "raises an IOError on a write-only stream" do
name = tmp("io_lineno.txt")
begin
File.open(name, 'w') do |f|
- -> { f.lineno = 0 }.should raise_error(IOError)
+ -> { f.lineno = 0 }.should.raise(IOError)
end
ensure
rm_r name
@@ -70,9 +71,10 @@ describe "IO#lineno=" do
end
it "raises an IOError on a duplexed stream with the read side closed" do
- IO.popen('cat', 'r+') do |p|
+ cmd = platform_is(:windows) ? 'rem' : 'cat'
+ IO.popen(cmd, 'r+') do |p|
p.close_read
- -> { p.lineno = 0 }.should raise_error(IOError)
+ -> { p.lineno = 0 }.should.raise(IOError)
end
end
@@ -92,8 +94,13 @@ describe "IO#lineno=" do
@io.lineno.should == 92233
end
- it "raises TypeError on nil argument" do
- -> { @io.lineno = nil }.should raise_error(TypeError)
+ it "raises TypeError if cannot convert argument to Integer implicitly" do
+ -> { @io.lineno = "1" }.should.raise(TypeError, 'no implicit conversion of String into Integer')
+ -> { @io.lineno = nil }.should raise_consistent_error(TypeError, 'no implicit conversion of nil into Integer')
+ end
+
+ it "does not accept Integers that don't fit in a C int" do
+ -> { @io.lineno = 2**32 }.should.raise(RangeError)
end
it "sets the current line number to the given value" do
diff --git a/spec/ruby/core/io/lines_spec.rb b/spec/ruby/core/io/lines_spec.rb
deleted file mode 100644
index 5b29a1d07e..0000000000
--- a/spec/ruby/core/io/lines_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- encoding: utf-8 -*-
-require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-
-ruby_version_is ''...'3.0' do
- describe "IO#lines" do
- before :each do
- @io = IOSpecs.io_fixture "lines.txt"
- @verbose, $VERBOSE = $VERBOSE, nil
- end
-
- after :each do
- $VERBOSE = @verbose
- @io.close if @io
- end
-
- it "returns an Enumerator" do
- @io.lines.should be_an_instance_of(Enumerator)
- end
-
- describe "when no block is given" do
- it "returns an Enumerator" do
- @io.lines.should be_an_instance_of(Enumerator)
- end
-
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- @io.lines.size.should == nil
- end
- end
- end
- end
-
- it "returns a line when accessed" do
- enum = @io.lines
- enum.first.should == IOSpecs.lines[0]
- end
-
- it "yields each line to the passed block" do
- ScratchPad.record []
- @io.lines { |s| ScratchPad << s }
- ScratchPad.recorded.should == IOSpecs.lines
- end
- end
-end
diff --git a/spec/ruby/core/io/new_spec.rb b/spec/ruby/core/io/new_spec.rb
index 3597098caf..979ac0efcb 100644
--- a/spec/ruby/core/io/new_spec.rb
+++ b/spec/ruby/core/io/new_spec.rb
@@ -1,8 +1,16 @@
require_relative '../../spec_helper'
require_relative 'shared/new'
+# NOTE: should be synchronized with library/stringio/initialize_spec.rb
+
describe "IO.new" do
it_behaves_like :io_new, :new
+
+ it "does not use the given block and warns to use IO::open" do
+ -> {
+ @io = IO.send(@method, @fd) { raise }
+ }.should complain(/warning: IO::new\(\) does not take block; use IO::open\(\) instead/)
+ end
end
describe "IO.new" do
diff --git a/spec/ruby/core/io/nonblock_spec.rb b/spec/ruby/core/io/nonblock_spec.rb
index e81ac10c58..99dc0cafd0 100644
--- a/spec/ruby/core/io/nonblock_spec.rb
+++ b/spec/ruby/core/io/nonblock_spec.rb
@@ -12,43 +12,21 @@ platform_is_not :windows do
end
end
- ruby_version_is ""..."3.0" do
- it "returns false for pipe by default" do
- r, w = IO.pipe
- begin
- r.nonblock?.should == false
- w.nonblock?.should == false
- ensure
- r.close
- w.close
- end
- end
-
- it "returns false for socket by default" do
- require 'socket'
- TCPServer.open(0) do |socket|
- socket.nonblock?.should == false
- end
+ it "returns true for pipe by default" do
+ r, w = IO.pipe
+ begin
+ r.nonblock?.should == true
+ w.nonblock?.should == true
+ ensure
+ r.close
+ w.close
end
end
- ruby_version_is "3.0" do
- it "returns true for pipe by default" do
- r, w = IO.pipe
- begin
- r.nonblock?.should == true
- w.nonblock?.should == true
- ensure
- r.close
- w.close
- end
- end
-
- it "returns true for socket by default" do
- require 'socket'
- TCPServer.open(0) do |socket|
- socket.nonblock?.should == true
- end
+ it "returns true for socket by default" do
+ require 'socket'
+ TCPServer.open(0) do |socket|
+ socket.nonblock?.should == true
end
end
end
diff --git a/spec/ruby/core/io/open_spec.rb b/spec/ruby/core/io/open_spec.rb
index d3a3961df7..ff22d14685 100644
--- a/spec/ruby/core/io/open_spec.rb
+++ b/spec/ruby/core/io/open_spec.rb
@@ -32,11 +32,24 @@ describe "IO.open" do
super()
ScratchPad.record :called
end
- io.closed?.should be_false
+ io.closed?.should == false
end
ScratchPad.recorded.should == :called
end
+ it "propagate an exception in the block after calling #close" do
+ -> do
+ IO.open(@fd, "w") do |io|
+ IOSpecs.io_mock(io, :close) do
+ super()
+ ScratchPad.record :called
+ end
+ raise Exception
+ end
+ end.should.raise(Exception)
+ ScratchPad.recorded.should == :called
+ end
+
it "propagates an exception raised by #close that is not a StandardError" do
-> do
IO.open(@fd, "w") do |io|
@@ -46,7 +59,7 @@ describe "IO.open" do
raise Exception
end
end
- end.should raise_error(Exception)
+ end.should.raise(Exception)
ScratchPad.recorded.should == :called
end
@@ -59,7 +72,7 @@ describe "IO.open" do
raise StandardError
end
end
- end.should raise_error(StandardError)
+ end.should.raise(StandardError)
ScratchPad.recorded.should == :called
end
diff --git a/spec/ruby/core/io/output_spec.rb b/spec/ruby/core/io/output_spec.rb
index 2aafb305f4..0decf8c95b 100644
--- a/spec/ruby/core/io/output_spec.rb
+++ b/spec/ruby/core/io/output_spec.rb
@@ -16,7 +16,7 @@ describe "IO#<<" do
it "raises an error if the stream is closed" do
io = IOSpecs.closed_io
- -> { io << "test" }.should raise_error(IOError)
+ -> { io << "test" }.should.raise(IOError)
end
it "returns self" do
diff --git a/spec/ruby/core/io/path_spec.rb b/spec/ruby/core/io/path_spec.rb
new file mode 100644
index 0000000000..798adb2163
--- /dev/null
+++ b/spec/ruby/core/io/path_spec.rb
@@ -0,0 +1,12 @@
+require_relative '../../spec_helper'
+
+describe "IO#path" do
+ it "returns the path of the file associated with the IO object" do
+ path = tmp("io_path.txt")
+ File.open(path, "w") do |file|
+ IO.new(file.fileno, path: file.path, autoclose: false).path.should == file.path
+ end
+ ensure
+ File.unlink(path)
+ end
+end
diff --git a/spec/ruby/core/io/pid_spec.rb b/spec/ruby/core/io/pid_spec.rb
index bc09fe7c3b..04956887ff 100644
--- a/spec/ruby/core/io/pid_spec.rb
+++ b/spec/ruby/core/io/pid_spec.rb
@@ -25,11 +25,11 @@ describe "IO#pid" do
end
it "returns the ID of a process associated with stream" do
- @io.pid.should_not be_nil
+ @io.pid.should_not == nil
end
it "raises an IOError on closed stream" do
@io.close
- -> { @io.pid }.should raise_error(IOError)
+ -> { @io.pid }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/pipe_spec.rb b/spec/ruby/core/io/pipe_spec.rb
index 2f2cf06f4d..9f1b01a5cd 100644
--- a/spec/ruby/core/io/pipe_spec.rb
+++ b/spec/ruby/core/io/pipe_spec.rb
@@ -16,14 +16,25 @@ describe "IO.pipe" do
it "returns two IO objects" do
@r, @w = IO.pipe
- @r.should be_kind_of(IO)
- @w.should be_kind_of(IO)
+ @r.should.is_a?(IO)
+ @w.should.is_a?(IO)
end
it "returns instances of a subclass when called on a subclass" do
@r, @w = IOSpecs::SubIO.pipe
- @r.should be_an_instance_of(IOSpecs::SubIO)
- @w.should be_an_instance_of(IOSpecs::SubIO)
+ @r.should.instance_of?(IOSpecs::SubIO)
+ @w.should.instance_of?(IOSpecs::SubIO)
+ end
+
+ it "does not use IO.new method to create pipes and allows its overriding" do
+ ScratchPad.record []
+
+ # so redefined .new is not called, but original #initialize is
+ @r, @w = IOSpecs::SubIOWithRedefinedNew.pipe
+ ScratchPad.recorded.should == [:call_original_initialize, :call_original_initialize] # called 2 times - for each pipe (r and w)
+
+ @r.should.instance_of?(IOSpecs::SubIOWithRedefinedNew)
+ @w.should.instance_of?(IOSpecs::SubIOWithRedefinedNew)
end
end
@@ -31,8 +42,8 @@ describe "IO.pipe" do
describe "passed a block" do
it "yields two IO objects" do
IO.pipe do |r, w|
- r.should be_kind_of(IO)
- w.should be_kind_of(IO)
+ r.should.is_a?(IO)
+ w.should.is_a?(IO)
end
end
@@ -56,7 +67,7 @@ describe "IO.pipe" do
w = _w
raise RuntimeError
end
- end.should raise_error(RuntimeError)
+ end.should.raise(RuntimeError)
r.should.closed?
w.should.closed?
end
@@ -89,7 +100,7 @@ describe "IO.pipe" do
IO.pipe do |r, w|
r.external_encoding.should == Encoding::ISO_8859_1
- r.internal_encoding.should be_nil
+ r.internal_encoding.should == nil
end
end
@@ -109,14 +120,14 @@ describe "IO.pipe" do
IO.pipe do |r, w|
r.external_encoding.should == Encoding::UTF_8
- r.internal_encoding.should be_nil
+ r.internal_encoding.should == nil
end
end
it "sets the external encoding of the read end when passed an Encoding argument" do
IO.pipe(Encoding::UTF_8) do |r, w|
r.external_encoding.should == Encoding::UTF_8
- r.internal_encoding.should be_nil
+ r.internal_encoding.should == nil
end
end
@@ -130,14 +141,14 @@ describe "IO.pipe" do
it "sets the external encoding of the read end when passed the name of an Encoding" do
IO.pipe("UTF-8") do |r, w|
r.external_encoding.should == Encoding::UTF_8
- r.internal_encoding.should be_nil
+ r.internal_encoding.should == nil
end
end
it "accepts 'bom|' prefix for external encoding" do
IO.pipe("BOM|UTF-8") do |r, w|
r.external_encoding.should == Encoding::UTF_8
- r.internal_encoding.should be_nil
+ r.internal_encoding.should == nil
end
end
@@ -202,13 +213,13 @@ describe "IO.pipe" do
it "sets no external encoding for the write end" do
IO.pipe(Encoding::UTF_8) do |r, w|
- w.external_encoding.should be_nil
+ w.external_encoding.should == nil
end
end
it "sets no internal encoding for the write end" do
IO.pipe(Encoding::UTF_8) do |r, w|
- w.external_encoding.should be_nil
+ w.external_encoding.should == nil
end
end
end
diff --git a/spec/ruby/core/io/popen_spec.rb b/spec/ruby/core/io/popen_spec.rb
index e9d32c5c7d..b5747bf255 100644
--- a/spec/ruby/core/io/popen_spec.rb
+++ b/spec/ruby/core/io/popen_spec.rb
@@ -21,7 +21,7 @@ describe "IO.popen" do
it "returns an open IO" do
@io = IO.popen(ruby_cmd('exit'), "r")
- @io.closed?.should be_false
+ @io.closed?.should == false
end
it "reads a read-only pipe" do
@@ -31,7 +31,7 @@ describe "IO.popen" do
it "raises IOError when writing a read-only pipe" do
@io = IO.popen('echo foo', "r")
- -> { @io.write('bar') }.should raise_error(IOError)
+ -> { @io.write('bar') }.should.raise(IOError)
@io.read.should == "foo\n"
end
@@ -52,7 +52,7 @@ describe "IO.popen" do
it "raises IOError when reading a write-only pipe" do
@io = IO.popen(ruby_cmd('IO.copy_stream(STDIN,STDOUT)'), "w")
- -> { @io.read }.should raise_error(IOError)
+ -> { @io.read }.should.raise(IOError)
end
it "reads and writes a read/write pipe" do
@@ -86,7 +86,7 @@ describe "IO.popen" do
it "returns an instance of a subclass when called on a subclass" do
@io = IOSpecs::SubIO.popen(ruby_cmd('exit'), "r")
- @io.should be_an_instance_of(IOSpecs::SubIO)
+ @io.should.instance_of?(IOSpecs::SubIO)
end
it "coerces mode argument with #to_str" do
@@ -95,27 +95,43 @@ describe "IO.popen" do
@io = IO.popen(ruby_cmd('exit 0'), mode)
end
+ it "accepts a path using the chdir: keyword argument" do
+ path = File.dirname(@fname)
+
+ @io = IO.popen(ruby_cmd("puts Dir.pwd"), "r", chdir: path)
+ @io.read.chomp.should == path
+ end
+
+ it "accepts a path using the chdir: keyword argument and a coercible path" do
+ path = File.dirname(@fname)
+ object = mock("path")
+ object.should_receive(:to_path).and_return(path)
+
+ @io = IO.popen(ruby_cmd("puts Dir.pwd"), "r", chdir: object)
+ @io.read.chomp.should == path
+ end
+
describe "with a block" do
it "yields an open IO to the block" do
IO.popen(ruby_cmd('exit'), "r") do |io|
- io.closed?.should be_false
+ io.closed?.should == false
end
end
it "yields an instance of a subclass when called on a subclass" do
IOSpecs::SubIO.popen(ruby_cmd('exit'), "r") do |io|
- io.should be_an_instance_of(IOSpecs::SubIO)
+ io.should.instance_of?(IOSpecs::SubIO)
end
end
it "closes the IO after yielding" do
io = IO.popen(ruby_cmd('exit'), "r") { |_io| _io }
- io.closed?.should be_true
+ io.closed?.should == true
end
it "allows the IO to be closed inside the block" do
io = IO.popen(ruby_cmd('exit'), 'r') { |_io| _io.close; _io }
- io.closed?.should be_true
+ io.closed?.should == true
end
it "returns the value of the block" do
@@ -153,7 +169,7 @@ describe "IO.popen" do
it "sets the internal encoding to nil if it's the same as the external encoding" do
@io = IO.popen(ruby_cmd('exit'), external_encoding: Encoding::EUC_JP,
internal_encoding: Encoding::EUC_JP)
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
context "with a leading ENV Hash" do
diff --git a/spec/ruby/core/io/pread_spec.rb b/spec/ruby/core/io/pread_spec.rb
index 43071d6a31..cfb8dc4c68 100644
--- a/spec/ruby/core/io/pread_spec.rb
+++ b/spec/ruby/core/io/pread_spec.rb
@@ -1,50 +1,138 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
-platform_is_not :windows do
- describe "IO#pread" do
- before :each do
- @fname = tmp("io_pread.txt")
- @contents = "1234567890"
- touch(@fname) { |f| f.write @contents }
- @file = File.open(@fname, "r+")
- end
+describe "IO#pread" do
+ before :each do
+ @fname = tmp("io_pread.txt")
+ @contents = "1234567890"
+ touch(@fname) { |f| f.write @contents }
+ @file = File.open(@fname, "r+")
+ end
- after :each do
- @file.close
- rm_r @fname
- end
+ after :each do
+ @file.close
+ rm_r @fname
+ end
- it "accepts a length, and an offset" do
- @file.pread(4, 0).should == "1234"
- @file.pread(3, 4).should == "567"
- end
+ it "accepts a length, and an offset" do
+ @file.pread(4, 0).should == "1234"
+ @file.pread(3, 4).should == "567"
+ end
- it "accepts a length, an offset, and an output buffer" do
- buffer = "foo"
- @file.pread(3, 4, buffer)
- buffer.should == "567"
- end
+ it "accepts a length, an offset, and an output buffer" do
+ buffer = +"foo"
+ @file.pread(3, 4, buffer).should.equal?(buffer)
+ buffer.should == "567"
+ end
- it "does not advance the file pointer" do
- @file.pread(4, 0).should == "1234"
- @file.read.should == "1234567890"
- end
+ it "shrinks the buffer in case of less bytes read" do
+ buffer = +"foo"
+ @file.pread(1, 0, buffer)
+ buffer.should == "1"
+ end
- it "raises EOFError if end-of-file is reached" do
- -> { @file.pread(1, 10) }.should raise_error(EOFError)
- end
+ it "grows the buffer in case of more bytes read" do
+ buffer = +"foo"
+ @file.pread(5, 0, buffer)
+ buffer.should == "12345"
+ end
- it "raises IOError when file is not open in read mode" do
- File.open(@fname, "w") do |file|
- -> { file.pread(1, 1) }.should raise_error(IOError)
- end
- end
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @file.pread(10, 0, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
+
+ it "does not advance the file pointer" do
+ @file.pread(4, 0).should == "1234"
+ @file.read.should == "1234567890"
+ end
+
+ it "ignores the current offset" do
+ @file.pos = 3
+ @file.pread(4, 0).should == "1234"
+ end
+
+ it "returns an empty string for maxlen = 0" do
+ @file.pread(0, 4).should == ""
+ end
+
+ it "returns a buffer for maxlen = 0 when buffer specified" do
+ buffer = +"foo"
+ @file.pread(0, 4, buffer).should.equal?(buffer)
+ buffer.should == "foo"
+ end
+
+ it "ignores the offset for maxlen = 0, even if it is out of file bounds" do
+ @file.pread(0, 400).should == ""
+ end
+
+ it "does not reset the buffer when reading with maxlen = 0" do
+ buffer = +"foo"
+ @file.pread(0, 4, buffer)
+ buffer.should == "foo"
+
+ @file.pread(0, 400, buffer)
+ buffer.should == "foo"
+ end
+
+ it "converts maxlen to Integer using #to_int" do
+ maxlen = mock('maxlen')
+ maxlen.should_receive(:to_int).and_return(4)
+ @file.pread(maxlen, 0).should == "1234"
+ end
+
+ it "converts offset to Integer using #to_int" do
+ offset = mock('offset')
+ offset.should_receive(:to_int).and_return(0)
+ @file.pread(4, offset).should == "1234"
+ end
+
+ it "converts a buffer to String using to_str" do
+ buffer = mock('buffer')
+ buffer.should_receive(:to_str).at_least(1).and_return(+"foo")
+ @file.pread(4, 0, buffer)
+ buffer.should_not.is_a?(String)
+ buffer.to_str.should == "1234"
+ end
+
+ it "raises TypeError if maxlen is not an Integer and cannot be coerced into Integer" do
+ maxlen = Object.new
+ -> { @file.pread(maxlen, 0) }.should.raise(TypeError, 'no implicit conversion of Object into Integer')
+ end
- it "raises IOError when file is closed" do
- file = File.open(@fname, "r+")
- file.close
- -> { file.pread(1, 1) }.should raise_error(IOError)
+ it "raises TypeError if offset is not an Integer and cannot be coerced into Integer" do
+ offset = Object.new
+ -> { @file.pread(4, offset) }.should.raise(TypeError, 'no implicit conversion of Object into Integer')
+ end
+
+ it "raises ArgumentError for negative values of maxlen" do
+ -> { @file.pread(-4, 0) }.should.raise(ArgumentError, 'negative string size (or size too big)')
+ end
+
+ it "raised Errno::EINVAL for negative values of offset" do
+ -> { @file.pread(4, -1) }.should.raise(Errno::EINVAL, /Invalid argument/)
+ end
+
+ it "raises TypeError if the buffer is not a String and cannot be coerced into String" do
+ buffer = Object.new
+ -> { @file.pread(4, 0, buffer) }.should.raise(TypeError, 'no implicit conversion of Object into String')
+ end
+
+ it "raises EOFError if end-of-file is reached" do
+ -> { @file.pread(1, 10) }.should.raise(EOFError)
+ end
+
+ it "raises IOError when file is not open in read mode" do
+ File.open(@fname, "w") do |file|
+ -> { file.pread(1, 1) }.should.raise(IOError)
end
end
+
+ it "raises IOError when file is closed" do
+ file = File.open(@fname, "r+")
+ file.close
+ -> { file.pread(1, 1) }.should.raise(IOError)
+ end
end
diff --git a/spec/ruby/core/io/print_spec.rb b/spec/ruby/core/io/print_spec.rb
index 04e971ef6d..065cb3b8cb 100644
--- a/spec/ruby/core/io/print_spec.rb
+++ b/spec/ruby/core/io/print_spec.rb
@@ -3,16 +3,27 @@ require_relative 'fixtures/classes'
describe "IO#print" do
before :each do
- @old_separator = $\
- suppress_warning {$\ = '->'}
+ @old_record_separator = $\
+ @old_field_separator = $,
+ suppress_warning {
+ $\ = '->'
+ $, = '^^'
+ }
@name = tmp("io_print")
end
after :each do
- suppress_warning {$\ = @old_separator}
+ suppress_warning {
+ $\ = @old_record_separator
+ $, = @old_field_separator
+ }
rm_r @name
end
+ it "returns nil" do
+ touch(@name) { |f| f.print.should == nil }
+ end
+
it "writes $_.to_s followed by $\\ (if any) to the stream if no arguments given" do
o = mock('o')
o.should_receive(:to_s).and_return("mockmockmock")
@@ -38,16 +49,18 @@ describe "IO#print" do
IO.read(@name).should == "hello#{$\}"
end
- it "writes each obj.to_s to the stream and appends $\\ (if any) given multiple objects" do
+ it "writes each obj.to_s to the stream separated by $, (if any) and appends $\\ (if any) given multiple objects" do
o, o2 = Object.new, Object.new
def o.to_s(); 'o'; end
def o2.to_s(); 'o2'; end
- touch(@name) { |f| f.print(o, o2) }
- IO.read(@name).should == "#{o.to_s}#{o2.to_s}#{$\}"
+ suppress_warning {
+ touch(@name) { |f| f.print(o, o2) }
+ }
+ IO.read(@name).should == "#{o.to_s}#{$,}#{o2.to_s}#{$\}"
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.print("stuff") }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.print("stuff") }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/printf_spec.rb b/spec/ruby/core/io/printf_spec.rb
index baa00f14ce..d5519bdaa3 100644
--- a/spec/ruby/core/io/printf_spec.rb
+++ b/spec/ruby/core/io/printf_spec.rb
@@ -27,6 +27,6 @@ describe "IO#printf" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.printf("stuff") }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.printf("stuff") }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/puts_spec.rb b/spec/ruby/core/io/puts_spec.rb
index 9a708fffef..df526ea56a 100644
--- a/spec/ruby/core/io/puts_spec.rb
+++ b/spec/ruby/core/io/puts_spec.rb
@@ -6,7 +6,7 @@ describe "IO#puts" do
@before_separator = $/
@name = tmp("io_puts.txt")
@io = new_io @name
- ScratchPad.record ""
+ ScratchPad.record(+"")
def @io.write(str)
ScratchPad << str
end
@@ -33,7 +33,7 @@ describe "IO#puts" do
ScratchPad.recorded.should == "\n"
end
- it "writes empty string with a newline when when given nil as multiple args" do
+ it "writes empty string with a newline when given nil as multiple args" do
@io.puts(nil, nil).should == nil
ScratchPad.recorded.should == "\n\n"
end
@@ -111,7 +111,7 @@ describe "IO#puts" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.puts("stuff") }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.puts("stuff") }.should.raise(IOError)
end
it "writes crlf when IO is opened with newline: :crlf" do
diff --git a/spec/ruby/core/io/pwrite_spec.rb b/spec/ruby/core/io/pwrite_spec.rb
index fe29d1e1f6..c318d551bc 100644
--- a/spec/ruby/core/io/pwrite_spec.rb
+++ b/spec/ruby/core/io/pwrite_spec.rb
@@ -1,43 +1,67 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
-platform_is_not :windows do
- describe "IO#pwrite" do
- before :each do
- @fname = tmp("io_pwrite.txt")
- @file = File.open(@fname, "w+")
- end
+describe "IO#pwrite" do
+ before :each do
+ @fname = tmp("io_pwrite.txt")
+ @file = File.open(@fname, "w+")
+ end
- after :each do
- @file.close
- rm_r @fname
- end
+ after :each do
+ @file.close
+ rm_r @fname
+ end
- it "returns the number of bytes written" do
- @file.pwrite("foo", 0).should == 3
- end
+ it "returns the number of bytes written" do
+ @file.pwrite("foo", 0).should == 3
+ end
- it "accepts a string and an offset" do
- @file.pwrite("foo", 2)
- @file.pread(3, 2).should == "foo"
- end
+ it "accepts a string and an offset" do
+ @file.pwrite("foo", 2)
+ @file.pread(3, 2).should == "foo"
+ end
- it "does not advance the pointer in the file" do
- @file.pwrite("bar", 3)
- @file.write("foo")
- @file.pread(6, 0).should == "foobar"
- end
+ it "does not advance the pointer in the file" do
+ @file.pwrite("bar", 3)
+ @file.write("foo")
+ @file.pread(6, 0).should == "foobar"
+ end
- it "raises IOError when file is not open in write mode" do
- File.open(@fname, "r") do |file|
- -> { file.pwrite("foo", 1) }.should raise_error(IOError)
- end
- end
+ it "calls #to_s on the object to be written" do
+ object = mock("to_s")
+ object.should_receive(:to_s).and_return("foo")
+ @file.pwrite(object, 0)
+ @file.pread(3, 0).should == "foo"
+ end
- it "raises IOError when file is closed" do
- file = File.open(@fname, "w+")
- file.close
- -> { file.pwrite("foo", 1) }.should raise_error(IOError)
+ it "calls #to_int on the offset" do
+ offset = mock("to_int")
+ offset.should_receive(:to_int).and_return(2)
+ @file.pwrite("foo", offset)
+ @file.pread(3, 2).should == "foo"
+ end
+
+ it "raises IOError when file is not open in write mode" do
+ File.open(@fname, "r") do |file|
+ -> { file.pwrite("foo", 1) }.should.raise(IOError, "not opened for writing")
end
end
+
+ it "raises IOError when file is closed" do
+ file = File.open(@fname, "w+")
+ file.close
+ -> { file.pwrite("foo", 1) }.should.raise(IOError, "closed stream")
+ end
+
+ it "raises a NoMethodError if object does not respond to #to_s" do
+ -> {
+ @file.pwrite(BasicObject.new, 0)
+ }.should.raise(NoMethodError, /undefined method [`']to_s'/)
+ end
+
+ it "raises a TypeError if the offset cannot be converted to an Integer" do
+ -> {
+ @file.pwrite("foo", Object.new)
+ }.should.raise(TypeError, "no implicit conversion of Object into Integer")
+ end
end
diff --git a/spec/ruby/core/io/read_nonblock_spec.rb b/spec/ruby/core/io/read_nonblock_spec.rb
index e50531d336..511cf03263 100644
--- a/spec/ruby/core/io/read_nonblock_spec.rb
+++ b/spec/ruby/core/io/read_nonblock_spec.rb
@@ -12,12 +12,12 @@ describe "IO#read_nonblock" do
end
it "raises an exception extending IO::WaitReadable when there is no data" do
- -> { @read.read_nonblock(5) }.should raise_error(IO::WaitReadable) { |e|
+ -> { @read.read_nonblock(5) }.should.raise(IO::WaitReadable) { |e|
platform_is_not :windows do
- e.should be_kind_of(Errno::EAGAIN)
+ e.should.is_a?(Errno::EAGAIN)
end
platform_is :windows do
- e.should be_kind_of(Errno::EWOULDBLOCK)
+ e.should.is_a?(Errno::EWOULDBLOCK)
end
}
end
@@ -36,7 +36,7 @@ describe "IO#read_nonblock" do
@read.read_nonblock(5)
- @read.read_nonblock(5, exception: false).should be_nil
+ @read.read_nonblock(5, exception: false).should == nil
end
end
end
@@ -55,6 +55,27 @@ describe "IO#read_nonblock" do
@read.read_nonblock(4).should == "hell"
end
+ it "reads after ungetc with data in the buffer" do
+ @write.write("foobar")
+ @read.set_encoding(
+ 'utf-8', universal_newline: false
+ )
+ c = @read.getc
+ @read.ungetc(c)
+ @read.read_nonblock(3).should == "foo"
+ @read.read_nonblock(3).should == "bar"
+ end
+
+ it "raises an exception after ungetc with data in the buffer and character conversion enabled" do
+ @write.write("foobar")
+ @read.set_encoding(
+ 'utf-8', universal_newline: true
+ )
+ c = @read.getc
+ @read.ungetc(c)
+ -> { @read.read_nonblock(3).should == "foo" }.should.raise(IOError)
+ end
+
it "returns less data if that is all that is available" do
@write << "hello"
@read.read_nonblock(10).should == "hello"
@@ -70,22 +91,41 @@ describe "IO#read_nonblock" do
@read.read_nonblock(1).should == "1"
end
+ it "raises ArgumentError when length is less than 0" do
+ -> { @read.read_nonblock(-1) }.should.raise(ArgumentError)
+ end
+
it "reads into the passed buffer" do
- buffer = ""
+ buffer = +""
@write.write("1")
@read.read_nonblock(1, buffer)
buffer.should == "1"
end
it "returns the passed buffer" do
- buffer = ""
+ buffer = +""
@write.write("1")
output = @read.read_nonblock(1, buffer)
- output.should equal(buffer)
+ output.should.equal?(buffer)
+ end
+
+ it "discards the existing buffer content upon successful read" do
+ buffer = +"existing content"
+ @write.write("hello world")
+ @write.close
+ @read.read_nonblock(11, buffer)
+ buffer.should == "hello world"
+ end
+
+ it "discards the existing buffer content upon error" do
+ buffer = +"existing content"
+ @write.close
+ -> { @read.read_nonblock(1, buffer) }.should.raise(EOFError)
+ buffer.should.empty?
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.read_nonblock(5) }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.read_nonblock(5) }.should.raise(IOError)
end
it "raises EOFError when the end is reached" do
@@ -94,6 +134,15 @@ describe "IO#read_nonblock" do
@read.read_nonblock(5)
- -> { @read.read_nonblock(5) }.should raise_error(EOFError)
+ -> { @read.read_nonblock(5) }.should.raise(EOFError)
+ end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @write.write("abc")
+ @write.close
+ @read.read_nonblock(10, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
end
end
diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb
index 841e693f37..dd787c9b60 100644
--- a/spec/ruby/core/io/read_spec.rb
+++ b/spec/ruby/core/io/read_spec.rb
@@ -23,6 +23,15 @@ describe "IO.read" do
IO.read(p)
end
+ # https://bugs.ruby-lang.org/issues/19354
+ it "accepts options as keyword arguments" do
+ IO.read(@fname, 3, 0, mode: "r+").should == @contents[0, 3]
+
+ -> {
+ IO.read(@fname, 3, 0, {mode: "r+"})
+ }.should.raise(ArgumentError, /wrong number of arguments/)
+ end
+
it "accepts an empty options Hash" do
IO.read(@fname, **{}).should == @contents
end
@@ -36,11 +45,11 @@ describe "IO.read" do
end
it "raises an IOError if the options Hash specifies write mode" do
- -> { IO.read(@fname, 3, 0, mode: "w") }.should raise_error(IOError)
+ -> { IO.read(@fname, 3, 0, mode: "w") }.should.raise(IOError)
end
it "raises an IOError if the options Hash specifies append only mode" do
- -> { IO.read(@fname, mode: "a") }.should raise_error(IOError)
+ -> { IO.read(@fname, mode: "a") }.should.raise(IOError)
end
it "reads the file if the options Hash includes read mode" do
@@ -55,6 +64,24 @@ describe "IO.read" do
IO.read(@fname, mode: "a+").should == @contents
end
+ platform_is_not :windows do
+ end
+
+ it "disregards other options if :open_args is given" do
+ string = IO.read(@fname,mode: "w", encoding: Encoding::UTF_32LE, open_args: ["r", encoding: Encoding::UTF_8])
+ string.encoding.should == Encoding::UTF_8
+ end
+
+ it "doesn't require mode to be specified in :open_args" do
+ string = IO.read(@fname, nil, 0, open_args: [{encoding: Encoding::US_ASCII}])
+ string.encoding.should == Encoding::US_ASCII
+ end
+
+ it "doesn't require mode to be specified in :open_args even if flags option passed" do
+ string = IO.read(@fname, nil, 0, open_args: [{encoding: Encoding::US_ASCII, flags: File::CREAT}])
+ string.encoding.should == Encoding::US_ASCII
+ end
+
it "treats second nil argument as no length limit" do
IO.read(@fname, nil).should == @contents
IO.read(@fname, nil, 5).should == IO.read(@fname, @contents.length, 5)
@@ -77,22 +104,31 @@ describe "IO.read" do
IO.read(@fname, 1, 10).should == nil
end
+ it "returns an empty string when reading zero bytes" do
+ IO.read(@fname, 0).should == ''
+ end
+
+ it "returns a String in BINARY when passed a size" do
+ IO.read(@fname, 1).encoding.should == Encoding::BINARY
+ IO.read(@fname, 0).encoding.should == Encoding::BINARY
+ end
+
it "raises an Errno::ENOENT when the requested file does not exist" do
rm_r @fname
- -> { IO.read @fname }.should raise_error(Errno::ENOENT)
+ -> { IO.read @fname }.should.raise(Errno::ENOENT)
end
it "raises a TypeError when not passed a String type" do
- -> { IO.read nil }.should raise_error(TypeError)
+ -> { IO.read nil }.should.raise(TypeError)
end
it "raises an ArgumentError when not passed a valid length" do
- -> { IO.read @fname, -1 }.should raise_error(ArgumentError)
+ -> { IO.read @fname, -1 }.should.raise(ArgumentError)
end
- it "raises an Errno::EINVAL when not passed a valid offset" do
- -> { IO.read @fname, 0, -1 }.should raise_error(Errno::EINVAL)
- -> { IO.read @fname, -1, -1 }.should raise_error(Errno::EINVAL)
+ it "raises an ArgumentError when not passed a valid offset" do
+ -> { IO.read @fname, 0, -1 }.should.raise(ArgumentError)
+ -> { IO.read @fname, -1, -1 }.should.raise(ArgumentError)
end
it "uses the external encoding specified via the :external_encoding option" do
@@ -104,57 +140,89 @@ describe "IO.read" do
str = IO.read(@fname, encoding: Encoding::ISO_8859_1)
str.encoding.should == Encoding::ISO_8859_1
end
-end
-describe "IO.read from a pipe" do
- it "runs the rest as a subprocess and returns the standard output" do
- cmd = "|sh -c 'echo hello'"
- platform_is :windows do
- cmd = "|cmd.exe /C echo hello"
+ platform_is :windows do
+ it "reads the file in text mode" do
+ # 0x1A is CTRL+Z and is EOF in Windows text mode.
+ File.binwrite(@fname, "\x1Abbb")
+ IO.read(@fname).should.empty?
end
- IO.read(cmd).should == "hello\n"
end
+end
- platform_is_not :windows do
- it "opens a pipe to a fork if the rest is -" do
- str = IO.read("|-")
- if str # parent
- str.should == "hello from child\n"
- else #child
- puts "hello from child"
- exit!
+ruby_version_is ""..."4.0" do
+ describe "IO.read from a pipe" do
+ it "runs the rest as a subprocess and returns the standard output" do
+ cmd = "|sh -c 'echo hello'"
+ platform_is :windows do
+ cmd = "|cmd.exe /C echo hello"
+ end
+
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read(cmd).should == "hello\n"
end
end
- end
- it "reads only the specified number of bytes requested" do
- cmd = "|sh -c 'echo hello'"
- platform_is :windows do
- cmd = "|cmd.exe /C echo hello"
+ platform_is_not :windows do
+ it "opens a pipe to a fork if the rest is -" do
+ str = nil
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ str = IO.read("|-")
+ end
+
+ if str # parent
+ str.should == "hello from child\n"
+ else #child
+ puts "hello from child"
+ exit!
+ end
+ end
end
- IO.read(cmd, 1).should == "h"
- end
- platform_is_not :windows do
- it "raises Errno::ESPIPE if passed an offset" do
- -> {
- IO.read("|sh -c 'echo hello'", 1, 1)
- }.should raise_error(Errno::ESPIPE)
+ it "reads only the specified number of bytes requested" do
+ cmd = "|sh -c 'echo hello'"
+ platform_is :windows do
+ cmd = "|cmd.exe /C echo hello"
+ end
+
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read(cmd, 1).should == "h"
+ end
end
- end
-quarantine! do # The process tried to write to a nonexistent pipe.
- platform_is :windows do
- # TODO: It should raise Errno::ESPIPE on Windows as well
- # once https://bugs.ruby-lang.org/issues/12230 is fixed.
- it "raises Errno::EINVAL if passed an offset" do
+ platform_is_not :windows do
+ it "raises Errno::ESPIPE if passed an offset" do
+ -> {
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read("|sh -c 'echo hello'", 1, 1)
+ end
+ }.should.raise(Errno::ESPIPE)
+ end
+ end
+
+ quarantine! do # The process tried to write to a nonexistent pipe.
+ platform_is :windows do
+ # TODO: It should raise Errno::ESPIPE on Windows as well
+ # once https://bugs.ruby-lang.org/issues/12230 is fixed.
+ it "raises Errno::EINVAL if passed an offset" do
+ -> {
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read("|cmd.exe /C echo hello", 1, 1)
+ end
+ }.should.raise(Errno::EINVAL)
+ end
+ end
+ end
+
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation" do
+ cmd = "|echo ok"
-> {
- IO.read("|cmd.exe /C echo hello", 1, 1)
- }.should raise_error(Errno::EINVAL)
+ IO.read(cmd)
+ }.should complain(/IO process creation with a leading '\|'/)
end
end
end
-end
describe "IO.read on an empty file" do
before :each do
@@ -197,21 +265,53 @@ describe "IO#read" do
@io.read(4).should == '7890'
end
+ it "treats first nil argument as no length limit" do
+ @io.read(nil).should == @contents
+ end
+
+ it "raises an ArgumentError when not passed a valid length" do
+ -> { @io.read(-1) }.should.raise(ArgumentError)
+ end
+
it "clears the output buffer if there is nothing to read" do
@io.pos = 10
- buf = 'non-empty string'
+ buf = +'non-empty string'
@io.read(10, buf).should == nil
buf.should == ''
+
+ buf = +'non-empty string'
+
+ @io.read(nil, buf).should == ""
+
+ buf.should == ''
+
+ buf = +'non-empty string'
+
+ @io.read(0, buf).should == ""
+
+ buf.should == ''
+ end
+
+ it "raise FrozenError if the output buffer is frozen" do
+ @io.read
+ -> { @io.read(0, 'frozen-string'.freeze) }.should.raise(FrozenError)
+ -> { @io.read(1, 'frozen-string'.freeze) }.should.raise(FrozenError)
+ -> { @io.read(nil, 'frozen-string'.freeze) }.should.raise(FrozenError)
+ end
+
+ it "raise FrozenError if the output buffer is frozen (2)" do
+ @io.read
+ -> { @io.read(1, ''.freeze) }.should.raise(FrozenError)
end
it "consumes zero bytes when reading zero bytes" do
@io.read(0).should == ''
@io.pos.should == 0
- @io.getc.chr.should == '1'
+ @io.getc.should == '1'
end
it "is at end-of-file when everything has been read" do
@@ -224,50 +324,72 @@ describe "IO#read" do
end
it "places the specified number of bytes in the buffer" do
- buf = ""
+ buf = +""
@io.read 5, buf
buf.should == "12345"
end
it "expands the buffer when too small" do
- buf = "ABCDE"
+ buf = +"ABCDE"
@io.read nil, buf
buf.should == @contents
end
it "overwrites the buffer" do
- buf = "ABCDEFGHIJ"
+ buf = +"ABCDEFGHIJ"
@io.read nil, buf
buf.should == @contents
end
it "truncates the buffer when too big" do
- buf = "ABCDEFGHIJKLMNO"
+ buf = +"ABCDEFGHIJKLMNO"
@io.read nil, buf
buf.should == @contents
@io.rewind
- buf = "ABCDEFGHIJKLMNO"
+ buf = +"ABCDEFGHIJKLMNO"
@io.read 5, buf
buf.should == @contents[0..4]
end
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @io.read(10, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
+
+ # https://bugs.ruby-lang.org/issues/20416
+ it "does not preserve the encoding of the given buffer when max length is not provided" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @io.read(nil, buffer)
+
+ buffer.encoding.should_not == Encoding::ISO_8859_1
+ end
+
it "returns the given buffer" do
- buf = ""
+ buf = +""
- @io.read(nil, buf).should equal buf
+ @io.read(nil, buf).should.equal? buf
+ end
+
+ it "returns the given buffer when there is nothing to read" do
+ buf = +""
+
+ @io.read
+ @io.read(nil, buf).should.equal? buf
end
it "coerces the second argument to string and uses it as a buffer" do
- buf = "ABCDE"
+ buf = +"ABCDE"
obj = mock("buff")
obj.should_receive(:to_str).any_number_of_times.and_return(buf)
- @io.read(15, obj).should_not equal obj
+ @io.read(15, obj).should_not.equal? obj
buf.should == @contents
end
@@ -301,9 +423,12 @@ describe "IO#read" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.read }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.read }.should.raise(IOError)
end
+ it "raises ArgumentError when length is less than 0" do
+ -> { @io.read(-1) }.should.raise(ArgumentError)
+ end
platform_is_not :windows do
it "raises IOError when stream is closed by another thread" do
@@ -319,7 +444,7 @@ describe "IO#read" do
Thread.pass until t.stop?
r.close
t.join
- t.value.should be_kind_of(IOError)
+ t.value.should.is_a?(IOError)
w.close
end
end
@@ -384,13 +509,6 @@ describe "IO#read in binary mode" do
xE2 = [226].pack('C*')
result.should == ("abc" + xE2 + "def").force_encoding(Encoding::BINARY)
end
-
- it "does not transcode file contents when an internal encoding is specified" do
- result = File.open(@name, "r:binary:utf-8") { |f| f.read }.chomp
- result.encoding.should == Encoding::BINARY
- xE2 = [226].pack('C*')
- result.should == ("abc" + xE2 + "def").force_encoding(Encoding::BINARY)
- end
end
describe "IO#read in text mode" do
@@ -460,20 +578,20 @@ describe :io_read_internal_encoding, shared: true do
end
it "sets the String encoding to the internal encoding" do
- @io.read.encoding.should equal(Encoding::UTF_8)
+ @io.read.encoding.should.equal?(Encoding::UTF_8)
end
describe "when passed nil for limit" do
it "sets the buffer to a transcoded String" do
- result = @io.read(nil, buf = "")
- buf.should equal(result)
+ result = @io.read(nil, buf = +"")
+ buf.should.equal?(result)
buf.should == "ありがとう\n"
end
it "sets the buffer's encoding to the internal encoding" do
- buf = "".force_encoding Encoding::ISO_8859_1
+ buf = "".dup.force_encoding Encoding::ISO_8859_1
@io.read(nil, buf)
- buf.encoding.should equal(Encoding::UTF_8)
+ buf.encoding.should.equal?(Encoding::UTF_8)
end
end
end
@@ -484,23 +602,24 @@ describe :io_read_size_internal_encoding, shared: true do
end
it "returns a String in BINARY when passed a size" do
- @io.read(4).encoding.should equal(Encoding::BINARY)
+ @io.read(4).encoding.should.equal?(Encoding::BINARY)
+ @io.read(0).encoding.should.equal?(Encoding::BINARY)
end
it "does not change the buffer's encoding when passed a limit" do
- buf = "".force_encoding Encoding::ISO_8859_1
+ buf = "".dup.force_encoding Encoding::ISO_8859_1
@io.read(4, buf)
buf.should == [164, 162, 164, 234].pack('C*').force_encoding(Encoding::ISO_8859_1)
- buf.encoding.should equal(Encoding::ISO_8859_1)
+ buf.encoding.should.equal?(Encoding::ISO_8859_1)
end
it "truncates the buffer but does not change the buffer's encoding when no data remains" do
- buf = "abc".force_encoding Encoding::ISO_8859_1
+ buf = "abc".dup.force_encoding Encoding::ISO_8859_1
@io.read
- @io.read(1, buf).should be_nil
+ @io.read(1, buf).should == nil
buf.size.should == 0
- buf.encoding.should equal(Encoding::ISO_8859_1)
+ buf.encoding.should.equal?(Encoding::ISO_8859_1)
end
end
@@ -518,7 +637,7 @@ describe "IO#read" do
end
it "sets the String encoding to Encoding.default_external" do
- @io.read.encoding.should equal(Encoding.default_external)
+ @io.read.encoding.should.equal?(Encoding.default_external)
end
end
@@ -537,7 +656,7 @@ describe "IO#read" do
end
it "sets the String encoding to the external encoding" do
- @io.read.encoding.should equal(Encoding::EUC_JP)
+ @io.read.encoding.should.equal?(Encoding::EUC_JP)
end
it_behaves_like :io_read_size_internal_encoding, nil
diff --git a/spec/ruby/core/io/readbyte_spec.rb b/spec/ruby/core/io/readbyte_spec.rb
index 14426c28ac..07da1da919 100644
--- a/spec/ruby/core/io/readbyte_spec.rb
+++ b/spec/ruby/core/io/readbyte_spec.rb
@@ -19,6 +19,6 @@ describe "IO#readbyte" do
@io.seek(999999)
-> do
@io.readbyte
- end.should raise_error EOFError
+ end.should.raise EOFError
end
end
diff --git a/spec/ruby/core/io/readchar_spec.rb b/spec/ruby/core/io/readchar_spec.rb
index b5f762a846..29d14880ff 100644
--- a/spec/ruby/core/io/readchar_spec.rb
+++ b/spec/ruby/core/io/readchar_spec.rb
@@ -1,6 +1,16 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+describe :io_readchar_internal_encoding, shared: true do
+ it "returns a transcoded String" do
+ @io.readchar.should == "あ"
+ end
+
+ it "sets the String encoding to the internal encoding" do
+ @io.readchar.encoding.should.equal?(Encoding::UTF_8)
+ end
+end
+
describe "IO#readchar" do
before :each do
@io = IOSpecs.io_fixture "lines.txt"
@@ -21,11 +31,67 @@ describe "IO#readchar" do
it "raises an EOFError when invoked at the end of the stream" do
@io.read
- -> { @io.readchar }.should raise_error(EOFError)
+ -> { @io.readchar }.should.raise(EOFError)
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.readchar }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.readchar }.should.raise(IOError)
+ end
+end
+
+describe "IO#readchar with internal encoding" do
+ after :each do
+ @io.close if @io
+ end
+
+ describe "not specified" do
+ before :each do
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", "r:euc-jp"
+ end
+
+ it "does not transcode the String" do
+ @io.readchar.should == ("あ").encode(Encoding::EUC_JP)
+ end
+
+ it "sets the String encoding to the external encoding" do
+ @io.readchar.encoding.should.equal?(Encoding::EUC_JP)
+ end
+ end
+
+ describe "specified by open mode" do
+ before :each do
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", "r:euc-jp:utf-8"
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+
+ describe "specified by mode: option" do
+ before :each do
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", mode: "r:euc-jp:utf-8"
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+
+ describe "specified by internal_encoding: option" do
+ before :each do
+ options = { mode: "r",
+ internal_encoding: "utf-8",
+ external_encoding: "euc-jp" }
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", options
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+
+ describe "specified by encoding: option" do
+ before :each do
+ options = { mode: "r", encoding: "euc-jp:utf-8" }
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", options
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
end
end
@@ -39,6 +105,6 @@ describe "IO#readchar" do
end
it "raises EOFError on empty stream" do
- -> { @io.readchar }.should raise_error(EOFError)
+ -> { @io.readchar }.should.raise(EOFError)
end
end
diff --git a/spec/ruby/core/io/readline_spec.rb b/spec/ruby/core/io/readline_spec.rb
index ca30f31e39..009687710a 100644
--- a/spec/ruby/core/io/readline_spec.rb
+++ b/spec/ruby/core/io/readline_spec.rb
@@ -29,11 +29,11 @@ describe "IO#readline" do
it "raises EOFError on end of stream" do
IOSpecs.lines.length.times { @io.readline }
- -> { @io.readline }.should raise_error(EOFError)
+ -> { @io.readline }.should.raise(EOFError)
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.readline }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.readline }.should.raise(IOError)
end
it "assigns the returned line to $_" do
@@ -51,6 +51,10 @@ describe "IO#readline" do
it "returns an empty string when passed 0 as a limit" do
@io.readline(0).should == ""
end
+
+ it "does not accept Integers that don't fit in a C off_t" do
+ -> { @io.readline(2**128) }.should.raise(RangeError)
+ end
end
describe "when passed separator and limit" do
@@ -69,14 +73,12 @@ describe "IO#readline" do
@io.readline(chomp: true).should == IOSpecs.lines_without_newline_characters[0]
end
- ruby_version_is "3.0" do
- it "raises exception when options passed as Hash" do
- -> { @io.readline({ chomp: true }) }.should raise_error(TypeError)
+ it "raises exception when options passed as Hash" do
+ -> { @io.readline({ chomp: true }) }.should.raise(TypeError)
- -> {
- @io.readline("\n", 1, { chomp: true })
- }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
- end
+ -> {
+ @io.readline("\n", 1, { chomp: true })
+ }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
end
end
end
diff --git a/spec/ruby/core/io/readlines_spec.rb b/spec/ruby/core/io/readlines_spec.rb
index 15af6debbe..640e253200 100644
--- a/spec/ruby/core/io/readlines_spec.rb
+++ b/spec/ruby/core/io/readlines_spec.rb
@@ -17,7 +17,7 @@ describe "IO#readlines" do
it "raises an IOError if the stream is closed" do
@io.close
- -> { @io.readlines }.should raise_error(IOError)
+ -> { @io.readlines }.should.raise(IOError)
end
describe "when passed no arguments" do
@@ -37,12 +37,12 @@ describe "IO#readlines" do
describe "when passed no arguments" do
it "updates self's position" do
@io.readlines
- @io.pos.should eql(137)
+ @io.pos.should.eql?(137)
end
it "updates self's lineno based on the number of lines read" do
@io.readlines
- @io.lineno.should eql(9)
+ @io.lineno.should.eql?(9)
end
it "does not change $_" do
@@ -81,12 +81,12 @@ describe "IO#readlines" do
it "updates self's lineno based on the number of lines read" do
@io.readlines("r")
- @io.lineno.should eql(5)
+ @io.lineno.should.eql?(5)
end
it "updates self's position based on the number of characters read" do
@io.readlines("r")
- @io.pos.should eql(137)
+ @io.pos.should.eql?(137)
end
it "does not change $_" do
@@ -104,7 +104,11 @@ describe "IO#readlines" do
describe "when passed limit" do
it "raises ArgumentError when passed 0 as a limit" do
- -> { @io.readlines(0) }.should raise_error(ArgumentError)
+ -> { @io.readlines(0) }.should.raise(ArgumentError)
+ end
+
+ it "does not accept Integers that don't fit in a C off_t" do
+ -> { @io.readlines(2**128) }.should.raise(RangeError)
end
end
@@ -113,14 +117,18 @@ describe "IO#readlines" do
@io.readlines(chomp: true).should == IOSpecs.lines_without_newline_characters
end
- ruby_version_is "3.0" do
- it "raises exception when options passed as Hash" do
- -> { @io.readlines({ chomp: true }) }.should raise_error(TypeError)
+ it "raises exception when options passed as Hash" do
+ -> { @io.readlines({ chomp: true }) }.should.raise(TypeError)
- -> {
- @io.readlines("\n", 1, { chomp: true })
- }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
- end
+ -> {
+ @io.readlines("\n", 1, { chomp: true })
+ }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
+ end
+ end
+
+ describe "when passed arbitrary keyword argument" do
+ it "tolerates it" do
+ @io.readlines(chomp: true, foo: :bar).should == IOSpecs.lines_without_newline_characters
end
end
end
@@ -137,13 +145,13 @@ describe "IO#readlines" do
it "raises an IOError if the stream is opened for append only" do
-> do
File.open(@name, "a:utf-8") { |f| f.readlines }
- end.should raise_error(IOError)
+ end.should.raise(IOError)
end
it "raises an IOError if the stream is opened for write only" do
-> do
File.open(@name, "w:utf-8") { |f| f.readlines }
- end.should raise_error(IOError)
+ end.should.raise(IOError)
end
end
@@ -166,29 +174,46 @@ describe "IO.readlines" do
$_.should == "test"
end
- describe "when passed a string that starts with a |" do
- it "gets data from the standard out of the subprocess" do
- cmd = "|sh -c 'echo hello;echo line2'"
- platform_is :windows do
- cmd = "|cmd.exe /C echo hello&echo line2"
- end
- lines = IO.readlines(cmd)
- lines.should == ["hello\n", "line2\n"]
- end
+ ruby_version_is ""..."4.0" do
+ describe "when passed a string that starts with a |" do
+ it "gets data from the standard out of the subprocess" do
+ cmd = "|sh -c 'echo hello;echo line2'"
+ platform_is :windows do
+ cmd = "|cmd.exe /C echo hello&echo line2"
+ end
- platform_is_not :windows do
- it "gets data from a fork when passed -" do
- lines = IO.readlines("|-")
+ lines = nil
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ lines = IO.readlines(cmd)
+ end
+ lines.should == ["hello\n", "line2\n"]
+ end
- if lines # parent
- lines.should == ["hello\n", "from a fork\n"]
- else
- puts "hello"
- puts "from a fork"
- exit!
+ platform_is_not :windows do
+ it "gets data from a fork when passed -" do
+ lines = nil
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ lines = IO.readlines("|-")
+ end
+
+ if lines # parent
+ lines.should == ["hello\n", "from a fork\n"]
+ else
+ puts "hello"
+ puts "from a fork"
+ exit!
+ end
end
end
end
+
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation given a path with a pipe" do
+ cmd = "|echo ok"
+ -> {
+ IO.readlines(cmd)
+ }.should complain(/IO process creation with a leading '\|'/)
+ end
end
it_behaves_like :io_readlines, :readlines
@@ -212,7 +237,7 @@ describe "IO.readlines" do
it "encodes lines using the default external encoding" do
Encoding.default_external = Encoding::UTF_8
lines = IO.readlines(@name)
- lines.all? { |s| s.encoding == Encoding::UTF_8 }.should be_true
+ lines.all? { |s| s.encoding == Encoding::UTF_8 }.should == true
end
it "encodes lines using the default internal encoding, when set" do
@@ -220,13 +245,13 @@ describe "IO.readlines" do
Encoding.default_internal = Encoding::UTF_16
suppress_warning {$/ = $/.encode Encoding::UTF_16}
lines = IO.readlines(@name)
- lines.all? { |s| s.encoding == Encoding::UTF_16 }.should be_true
+ lines.all? { |s| s.encoding == Encoding::UTF_16 }.should == true
end
it "ignores the default internal encoding if the external encoding is BINARY" do
Encoding.default_external = Encoding::BINARY
Encoding.default_internal = Encoding::UTF_8
lines = IO.readlines(@name)
- lines.all? { |s| s.encoding == Encoding::BINARY }.should be_true
+ lines.all? { |s| s.encoding == Encoding::BINARY }.should == true
end
end
diff --git a/spec/ruby/core/io/readpartial_spec.rb b/spec/ruby/core/io/readpartial_spec.rb
index 2b33a0d5b1..d3f5545c8f 100644
--- a/spec/ruby/core/io/readpartial_spec.rb
+++ b/spec/ruby/core/io/readpartial_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -15,10 +15,10 @@ describe "IO#readpartial" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.readpartial(10) }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.readpartial(10) }.should.raise(IOError)
@rd.close
- -> { @rd.readpartial(10) }.should raise_error(IOError)
+ -> { @rd.readpartial(10) }.should.raise(IOError)
end
it "reads at most the specified number of bytes" do
@@ -59,10 +59,10 @@ describe "IO#readpartial" do
end
it "discards the existing buffer content upon successful read" do
- buffer = "existing"
+ buffer = +"existing content"
@wr.write("hello world")
@wr.close
- @rd.readpartial(11, buffer)
+ @rd.readpartial(11, buffer).should.equal?(buffer)
buffer.should == "hello world"
end
@@ -70,27 +70,46 @@ describe "IO#readpartial" do
@wr.write("abc")
@wr.close
@rd.readpartial(10).should == 'abc'
- -> { @rd.readpartial(10) }.should raise_error(EOFError)
+ -> { @rd.readpartial(10) }.should.raise(EOFError)
end
it "discards the existing buffer content upon error" do
- buffer = 'hello'
+ buffer = +'hello'
@wr.close
- -> { @rd.readpartial(1, buffer) }.should raise_error(EOFError)
- buffer.should be_empty
+ -> { @rd.readpartial(1, buffer) }.should.raise(EOFError)
+ buffer.should.empty?
end
it "raises IOError if the stream is closed" do
@wr.close
- -> { @rd.readpartial(1) }.should raise_error(IOError)
+ -> { @rd.readpartial(1) }.should.raise(IOError)
end
it "raises ArgumentError if the negative argument is provided" do
- -> { @rd.readpartial(-1) }.should raise_error(ArgumentError)
+ -> { @rd.readpartial(-1) }.should.raise(ArgumentError)
end
it "immediately returns an empty string if the length argument is 0" do
@rd.readpartial(0).should == ""
end
+ it "raises IOError if the stream is closed and the length argument is 0" do
+ @rd.close
+ -> { @rd.readpartial(0) }.should.raise(IOError, "closed stream")
+ end
+
+ it "clears and returns the given buffer if the length argument is 0" do
+ buffer = +"existing content"
+ @rd.readpartial(0, buffer).should == buffer
+ buffer.should == ""
+ end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @wr.write("abc")
+ @wr.close
+ @rd.readpartial(10, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
end
diff --git a/spec/ruby/core/io/reopen_spec.rb b/spec/ruby/core/io/reopen_spec.rb
index 8ff0f217f4..3b972d8978 100644
--- a/spec/ruby/core/io/reopen_spec.rb
+++ b/spec/ruby/core/io/reopen_spec.rb
@@ -27,35 +27,35 @@ describe "IO#reopen" do
it "changes the class of the instance to the class of the object returned by #to_io" do
obj = mock("io")
obj.should_receive(:to_io).and_return(@other_io)
- @io.reopen(obj).should be_an_instance_of(File)
+ @io.reopen(obj).should.instance_of?(File)
end
it "raises an IOError if the object returned by #to_io is closed" do
obj = mock("io")
obj.should_receive(:to_io).and_return(IOSpecs.closed_io)
- -> { @io.reopen obj }.should raise_error(IOError)
+ -> { @io.reopen obj }.should.raise(IOError)
end
it "raises a TypeError if #to_io does not return an IO instance" do
obj = mock("io")
obj.should_receive(:to_io).and_return("something else")
- -> { @io.reopen obj }.should raise_error(TypeError)
+ -> { @io.reopen obj }.should.raise(TypeError)
end
it "raises an IOError when called on a closed stream with an object" do
@io.close
obj = mock("io")
obj.should_not_receive(:to_io)
- -> { @io.reopen(STDOUT) }.should raise_error(IOError)
+ -> { @io.reopen(STDOUT) }.should.raise(IOError)
end
it "raises an IOError if the IO argument is closed" do
- -> { @io.reopen(IOSpecs.closed_io) }.should raise_error(IOError)
+ -> { @io.reopen(IOSpecs.closed_io) }.should.raise(IOError)
end
it "raises an IOError when called on a closed stream with an IO" do
@io.close
- -> { @io.reopen(STDOUT) }.should raise_error(IOError)
+ -> { @io.reopen(STDOUT) }.should.raise(IOError)
end
end
@@ -77,12 +77,12 @@ describe "IO#reopen with a String" do
it "does not raise an exception when called on a closed stream with a path" do
@io.close
@io.reopen @name, "r"
- @io.closed?.should be_false
+ @io.closed?.should == false
@io.gets.should == "Line 1: One\n"
end
it "returns self" do
- @io.reopen(@name).should equal(@io)
+ @io.reopen(@name).should.equal?(@io)
end
it "positions a newly created instance at the beginning of the new stream" do
@@ -188,7 +188,7 @@ describe "IO#reopen with a String" do
it "raises an Errno::ENOENT if the file does not exist and the IO is not opened in write mode" do
@io = new_io @name, "r"
- -> { @io.reopen(@other_name) }.should raise_error(Errno::ENOENT)
+ -> { @io.reopen(@other_name) }.should.raise(Errno::ENOENT)
end
end
@@ -214,9 +214,9 @@ describe "IO#reopen with an IO at EOF" do
end
it "resets the EOF status to false" do
- @io.eof?.should be_true
+ @io.eof?.should == true
@io.reopen @other_io
- @io.eof?.should be_false
+ @io.eof?.should == false
end
end
@@ -244,7 +244,7 @@ describe "IO#reopen with an IO" do
# MRI actually changes the class of @io in the call to #reopen
# but does not preserve the existing singleton class of @io.
def @io.to_io; flunk; end
- @io.reopen(@other_io).should be_an_instance_of(IO)
+ @io.reopen(@other_io).should.instance_of?(IO)
end
it "does not change the object_id" do
@@ -303,7 +303,7 @@ describe "IO#reopen with an IO" do
it "may change the class of the instance" do
@io.reopen @other_io
- @io.should be_an_instance_of(File)
+ @io.should.instance_of?(File)
end
it "sets path equals to the other IO's path if other IO is File" do
diff --git a/spec/ruby/core/io/rewind_spec.rb b/spec/ruby/core/io/rewind_spec.rb
index 649041afaf..43834ef307 100644
--- a/spec/ruby/core/io/rewind_spec.rb
+++ b/spec/ruby/core/io/rewind_spec.rb
@@ -18,6 +18,17 @@ describe "IO#rewind" do
@io.readline.should == "Voici la ligne une.\n"
end
+ it "positions the instance to the beginning of output for write-only IO" do
+ name = tmp("io_rewind_spec")
+ io = File.open(name, "w")
+ io.write("Voici la ligne une.\n")
+ io.rewind
+ io.pos.should == 0
+ ensure
+ io.close
+ rm_r name
+ end
+
it "positions the instance to the beginning of input and clears EOF" do
value = @io.read
@io.rewind
@@ -32,7 +43,11 @@ describe "IO#rewind" do
@io.lineno.should == 0
end
+ it "returns 0" do
+ @io.rewind.should == 0
+ end
+
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.rewind }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.rewind }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/seek_spec.rb b/spec/ruby/core/io/seek_spec.rb
index 2fa4a73ac9..d26629fb89 100644
--- a/spec/ruby/core/io/seek_spec.rb
+++ b/spec/ruby/core/io/seek_spec.rb
@@ -17,7 +17,7 @@ describe "IO#seek" do
end
it "moves the read position relative to the current position with SEEK_CUR" do
- -> { @io.seek(-1) }.should raise_error(Errno::EINVAL)
+ -> { @io.seek(-1) }.should.raise(Errno::EINVAL)
@io.seek(10, IO::SEEK_CUR)
@io.readline.should == "igne une.\n"
@io.seek(-5, IO::SEEK_CUR)
diff --git a/spec/ruby/core/io/select_spec.rb b/spec/ruby/core/io/select_spec.rb
index 4603c1fbbc..0a43fc6f5f 100644
--- a/spec/ruby/core/io/select_spec.rb
+++ b/spec/ruby/core/io/select_spec.rb
@@ -18,6 +18,10 @@ describe "IO.select" do
@wr.syswrite("be ready")
IO.pipe do |_, wr|
result = IO.select [@rd], [wr], nil, 0
+ unless result
+ # On some platforms (e.g., Windows), pipe readiness may not be immediate
+ result = IO.select [@rd], [wr], nil, 2
+ end
result.should == [[@rd], [wr], []]
end
end
@@ -55,8 +59,8 @@ describe "IO.select" do
end
end
- it "returns supplied objects correctly even when monitoring the same object in different arrays" do
- filename = tmp("IO_select_pipe_file") + $$.to_s
+ it "returns supplied objects correctly when monitoring the same object in different arrays" do
+ filename = tmp("IO_select_pipe_file")
io = File.open(filename, 'w+')
result = IO.select [io], [io], nil, 0
result.should == [[io], [io], []]
@@ -64,6 +68,17 @@ describe "IO.select" do
rm_r filename
end
+ it "returns the pipe read end in read set if the pipe write end is closed concurrently" do
+ main = Thread.current
+ t = Thread.new {
+ Thread.pass until main.stop?
+ @wr.close
+ }
+ IO.select([@rd]).should == [[@rd], [], []]
+ ensure
+ t.join
+ end
+
it "invokes to_io on supplied objects that are not IO and returns the supplied objects" do
# make some data available
@wr.write("foobar")
@@ -80,41 +95,96 @@ describe "IO.select" do
end
it "raises TypeError if supplied objects are not IO" do
- -> { IO.select([Object.new]) }.should raise_error(TypeError)
- -> { IO.select(nil, [Object.new]) }.should raise_error(TypeError)
+ -> { IO.select([Object.new]) }.should.raise(TypeError)
+ -> { IO.select(nil, [Object.new]) }.should.raise(TypeError)
obj = mock("io")
obj.should_receive(:to_io).any_number_of_times.and_return(nil)
- -> { IO.select([obj]) }.should raise_error(TypeError)
- -> { IO.select(nil, [obj]) }.should raise_error(TypeError)
+ -> { IO.select([obj]) }.should.raise(TypeError)
+ -> { IO.select(nil, [obj]) }.should.raise(TypeError)
end
it "raises a TypeError if the specified timeout value is not Numeric" do
- -> { IO.select([@rd], nil, nil, Object.new) }.should raise_error(TypeError)
+ -> { IO.select([@rd], nil, nil, Object.new) }.should.raise(TypeError)
end
it "raises TypeError if the first three arguments are not Arrays" do
- -> { IO.select(Object.new)}.should raise_error(TypeError)
- -> { IO.select(nil, Object.new)}.should raise_error(TypeError)
- -> { IO.select(nil, nil, Object.new)}.should raise_error(TypeError)
+ -> { IO.select(Object.new)}.should.raise(TypeError)
+ -> { IO.select(nil, Object.new)}.should.raise(TypeError)
+ -> { IO.select(nil, nil, Object.new)}.should.raise(TypeError)
end
it "raises an ArgumentError when passed a negative timeout" do
- -> { IO.select(nil, nil, nil, -5)}.should raise_error(ArgumentError)
+ -> { IO.select(nil, nil, nil, -5)}.should.raise(ArgumentError, "time interval must not be negative")
+ end
+
+ ruby_version_is "4.0" do
+ it "raises an ArgumentError when passed negative infinity as timeout" do
+ -> { IO.select(nil, nil, nil, -Float::INFINITY)}.should.raise(ArgumentError, "time interval must not be negative")
+ end
+ end
+
+ it "raises an RangeError when passed NaN as timeout" do
+ -> { IO.select(nil, nil, nil, Float::NAN)}.should.raise(RangeError, "NaN out of Time range")
+ end
+
+ describe "returns the available descriptors when the file descriptor" do
+ it "is in both read and error arrays" do
+ @wr.write("foobar")
+ result = IO.select([@rd], nil, [@rd])
+ result.should == [[@rd], [], []]
+ end
+
+ it "is in both write and error arrays" do
+ result = IO.select(nil, [@wr], [@wr])
+ result.should == [[], [@wr], []]
+ end
+
+ it "is in both read and write arrays" do
+ filename = tmp("IO_select_read_write_file")
+ w = File.open(filename, 'w+')
+ begin
+ IO.select([w], [w], []).should == [[w], [w], []]
+ ensure
+ w.close
+ rm_r filename
+ end
+
+ IO.select([@wr], [@wr], []).should == [[], [@wr], []]
+
+ @wr.write("foobar")
+ # CRuby on macOS returns [[@rd], [@rd], []], weird but we accept it here, probably only for pipe read-end
+ [
+ [[@rd], [], []],
+ [[@rd], [@rd], []]
+ ].should.include? IO.select([@rd], [@rd], [])
+ end
end
end
-describe "IO.select when passed nil for timeout" do
- it "sleeps forever and sets the thread status to 'sleep'" do
- t = Thread.new do
- IO.select(nil, nil, nil, nil)
+describe "IO.select with infinite timeout" do
+ describe :io_select_infinite_timeout, shared: true do
+ it "sleeps forever and sets the thread status to 'sleep'" do
+ t = Thread.new do
+ IO.select(nil, nil, nil, @method)
+ end
+
+ Thread.pass while t.status && t.status != "sleep"
+ t.join unless t.status
+ t.status.should == "sleep"
+ t.kill
+ t.join
end
+ end
- Thread.pass while t.status && t.status != "sleep"
- t.join unless t.status
- t.status.should == "sleep"
- t.kill
- t.join
+ describe "IO.select when passed nil for timeout" do
+ it_behaves_like :io_select_infinite_timeout, nil
+ end
+
+ ruby_version_is "4.0" do
+ describe "IO.select when passed Float::INFINITY for timeout" do
+ it_behaves_like :io_select_infinite_timeout, Float::INFINITY
+ end
end
end
diff --git a/spec/ruby/core/io/set_encoding_by_bom_spec.rb b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
index b52d3a943a..5436879f11 100644
--- a/spec/ruby/core/io/set_encoding_by_bom_spec.rb
+++ b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
@@ -12,51 +12,238 @@ describe "IO#set_encoding_by_bom" do
rm_r @name
end
+ it "returns nil if not readable" do
+ not_readable_io = new_io(@name, 'wb')
+
+ not_readable_io.set_encoding_by_bom.should == nil
+ not_readable_io.external_encoding.should == Encoding::ASCII_8BIT
+ ensure
+ not_readable_io.close
+ end
+
it "returns the result encoding if found BOM UTF-8 sequence" do
+ File.binwrite(@name, "\u{FEFF}")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_8
+ @io.external_encoding.should == Encoding::UTF_8
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
File.binwrite(@name, "\u{FEFF}abc")
@io.set_encoding_by_bom.should == Encoding::UTF_8
@io.external_encoding.should == Encoding::UTF_8
+ @io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_16LE sequence" do
+ File.binwrite(@name, "\xFF\xFE")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
File.binwrite(@name, "\xFF\xFEabc")
@io.set_encoding_by_bom.should == Encoding::UTF_16LE
@io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_16BE sequence" do
- File.binwrite(@name, "\xFE\xFFabc")
+ File.binwrite(@name, "\xFE\xFF")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ @io.external_encoding.should == Encoding::UTF_16BE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.binwrite(@name, "\xFE\xFFabcd")
@io.set_encoding_by_bom.should == Encoding::UTF_16BE
@io.external_encoding.should == Encoding::UTF_16BE
+ @io.read.b.should == "abcd".b
end
it "returns the result encoding if found BOM UTF_32LE sequence" do
+ File.binwrite(@name, "\xFF\xFE\x00\x00")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_32LE
+ @io.external_encoding.should == Encoding::UTF_32LE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
File.binwrite(@name, "\xFF\xFE\x00\x00abc")
@io.set_encoding_by_bom.should == Encoding::UTF_32LE
@io.external_encoding.should == Encoding::UTF_32LE
+ @io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_32BE sequence" do
- File.binwrite(@name, "\x00\x00\xFE\xFFabc")
+ File.binwrite(@name, "\x00\x00\xFE\xFF")
@io.set_encoding_by_bom.should == Encoding::UTF_32BE
@io.external_encoding.should == Encoding::UTF_32BE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.binwrite(@name, "\x00\x00\xFE\xFFabcd")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_32BE
+ @io.external_encoding.should == Encoding::UTF_32BE
+ @io.read.b.should == "abcd".b
+ end
+
+ it "returns nil if io is empty" do
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "returns nil if UTF-8 BOM sequence is incomplete" do
+ File.write(@name, "\xEF")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEF".b
+ @io.rewind
+
+ File.write(@name, "\xEFa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEFa".b
+ @io.rewind
+
+ File.write(@name, "\xEF\xBB")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEF\xBB".b
+ @io.rewind
+
+ File.write(@name, "\xEF\xBBa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEF\xBBa".b
+ end
+
+ it "returns nil if UTF-16BE BOM sequence is incomplete" do
+ File.write(@name, "\xFE")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFE".b
+ @io.rewind
+
+ File.write(@name, "\xFEa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFEa".b
+ end
+
+ it "returns nil if UTF-16LE/UTF-32LE BOM sequence is incomplete" do
+ File.write(@name, "\xFF")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFF".b
+ @io.rewind
+
+ File.write(@name, "\xFFa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFFa".b
+ end
+
+ it "returns UTF-16LE if UTF-32LE BOM sequence is incomplete" do
+ File.write(@name, "\xFF\xFE")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.write(@name, "\xFF\xFE\x00")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "\x00".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.write(@name, "\xFF\xFE\x00a")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "\x00a".b
+ end
+
+ it "returns nil if UTF-32BE BOM sequence is incomplete" do
+ File.write(@name, "\x00")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00".b
+ @io.rewind
+
+ File.write(@name, "\x00a")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00a".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00a")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00a".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00\xFE")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00\xFE".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00\xFEa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00\xFEa".b
end
it "returns nil if found BOM sequence not provided" do
File.write(@name, "abc")
@io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read(3).should == "abc".b
end
it 'returns exception if io not in binary mode' do
not_binary_io = new_io(@name, 'r')
- -> { not_binary_io.set_encoding_by_bom }.should raise_error(ArgumentError, 'ASCII incompatible encoding needs binmode')
+ -> { not_binary_io.set_encoding_by_bom }.should.raise(ArgumentError, 'ASCII incompatible encoding needs binmode')
ensure
not_binary_io.close
end
@@ -64,12 +251,12 @@ describe "IO#set_encoding_by_bom" do
it 'returns exception if encoding already set' do
@io.set_encoding("utf-8")
- -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding is set to UTF-8 already')
+ -> { @io.set_encoding_by_bom }.should.raise(ArgumentError, 'encoding is set to UTF-8 already')
end
it 'returns exception if encoding conversion is already set' do
@io.set_encoding(Encoding::UTF_8, Encoding::UTF_16BE)
- -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding conversion is set')
+ -> { @io.set_encoding_by_bom }.should.raise(ArgumentError, 'encoding conversion is set')
end
end
diff --git a/spec/ruby/core/io/set_encoding_spec.rb b/spec/ruby/core/io/set_encoding_spec.rb
index 5aec6a96c3..237251de5b 100644
--- a/spec/ruby/core/io/set_encoding_spec.rb
+++ b/spec/ruby/core/io/set_encoding_spec.rb
@@ -1,12 +1,25 @@
require_relative '../../spec_helper'
describe :io_set_encoding_write, shared: true do
- it "sets the encodings to nil" do
+ it "sets the encodings to nil when they were set previously" do
@io = new_io @name, "#{@object}:ibm437:ibm866"
@io.set_encoding nil, nil
- @io.external_encoding.should be_nil
- @io.internal_encoding.should be_nil
+ @io.external_encoding.should == nil
+ @io.internal_encoding.should == nil
+ end
+
+ it "sets the encodings to nil when the IO is built with no explicit encoding" do
+ @io = new_io @name, @object
+
+ # Checking our assumptions first
+ @io.external_encoding.should == nil
+ @io.internal_encoding.should == nil
+
+ @io.set_encoding nil, nil
+
+ @io.external_encoding.should == nil
+ @io.internal_encoding.should == nil
end
it "prevents the encodings from changing when Encoding defaults are changed" do
@@ -16,8 +29,8 @@ describe :io_set_encoding_write, shared: true do
Encoding.default_external = Encoding::IBM437
Encoding.default_internal = Encoding::IBM866
- @io.external_encoding.should be_nil
- @io.internal_encoding.should be_nil
+ @io.external_encoding.should == nil
+ @io.internal_encoding.should == nil
end
it "sets the encodings to the current Encoding defaults" do
@@ -38,6 +51,7 @@ describe "IO#set_encoding when passed nil, nil" do
@external = Encoding.default_external
@internal = Encoding.default_internal
+ # The defaults
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = nil
@@ -61,8 +75,8 @@ describe "IO#set_encoding when passed nil, nil" do
Encoding.default_internal = Encoding::IBM866
@io.set_encoding nil, nil
- @io.external_encoding.should equal(Encoding::IBM437)
- @io.internal_encoding.should equal(Encoding::IBM866)
+ @io.external_encoding.should.equal?(Encoding::IBM437)
+ @io.internal_encoding.should.equal?(Encoding::IBM866)
end
it "prevents the #internal_encoding from changing when Encoding.default_internal is changed" do
@@ -71,7 +85,7 @@ describe "IO#set_encoding when passed nil, nil" do
Encoding.default_internal = Encoding::IBM437
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
it "allows the #external_encoding to change when Encoding.default_external is changed" do
@@ -80,17 +94,17 @@ describe "IO#set_encoding when passed nil, nil" do
Encoding.default_external = Encoding::IBM437
- @io.external_encoding.should equal(Encoding::IBM437)
+ @io.external_encoding.should.equal?(Encoding::IBM437)
end
end
describe "with 'rb' mode" do
it "returns Encoding.default_external" do
@io = new_io @name, "rb"
- @io.external_encoding.should equal(Encoding::BINARY)
+ @io.external_encoding.should.equal?(Encoding::BINARY)
@io.set_encoding nil, nil
- @io.external_encoding.should equal(Encoding.default_external)
+ @io.external_encoding.should.equal?(Encoding.default_external)
end
end
@@ -113,6 +127,22 @@ describe "IO#set_encoding when passed nil, nil" do
describe "with 'a+' mode" do
it_behaves_like :io_set_encoding_write, nil, "a+"
end
+
+ describe "with standard IOs" do
+ it "correctly resets them" do
+ STDOUT.external_encoding.should == nil
+ STDOUT.internal_encoding.should == nil
+
+ begin
+ STDOUT.set_encoding(Encoding::US_ASCII, Encoding::ISO_8859_1)
+ ensure
+ STDOUT.set_encoding(nil, nil)
+ end
+
+ STDOUT.external_encoding.should == nil
+ STDOUT.internal_encoding.should == nil
+ end
+ end
end
describe "IO#set_encoding" do
@@ -128,13 +158,13 @@ describe "IO#set_encoding" do
end
it "returns self" do
- @io.set_encoding(Encoding::UTF_8).should equal(@io)
+ @io.set_encoding(Encoding::UTF_8).should.equal?(@io)
end
it "sets the external encoding when passed an Encoding argument" do
@io.set_encoding(Encoding::UTF_8)
@io.external_encoding.should == Encoding::UTF_8
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
it "sets the external and internal encoding when passed two Encoding arguments" do
@@ -146,19 +176,19 @@ describe "IO#set_encoding" do
it "sets the external encoding when passed the name of an Encoding" do
@io.set_encoding("utf-8")
@io.external_encoding.should == Encoding::UTF_8
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
it "ignores the internal encoding if the same as external when passed Encoding objects" do
@io.set_encoding(Encoding::UTF_8, Encoding::UTF_8)
@io.external_encoding.should == Encoding::UTF_8
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
it "ignores the internal encoding if the same as external when passed encoding names separated by ':'" do
@io.set_encoding("utf-8:utf-8")
@io.external_encoding.should == Encoding::UTF_8
- @io.internal_encoding.should be_nil
+ @io.internal_encoding.should == nil
end
it "sets the external and internal encoding when passed the names of Encodings separated by ':'" do
@@ -188,4 +218,21 @@ describe "IO#set_encoding" do
@io.external_encoding.should == Encoding::UTF_8
@io.internal_encoding.should == Encoding::UTF_16BE
end
+
+ it "saves encoding options passed as a hash in the last argument" do
+ File.write(@name, "\xff")
+ io = File.open(@name)
+ io.set_encoding(Encoding::EUC_JP, Encoding::SHIFT_JIS, invalid: :replace, replace: ".")
+ io.read.should == "."
+ ensure
+ io.close
+ end
+
+ it "raises ArgumentError when no arguments are given" do
+ -> { @io.set_encoding() }.should.raise(ArgumentError)
+ end
+
+ it "raises ArgumentError when too many arguments are given" do
+ -> { @io.set_encoding(1, 2, 3) }.should.raise(ArgumentError)
+ end
end
diff --git a/spec/ruby/core/io/shared/binwrite.rb b/spec/ruby/core/io/shared/binwrite.rb
index 3649bb47ff..64793b1936 100644
--- a/spec/ruby/core/io/shared/binwrite.rb
+++ b/spec/ruby/core/io/shared/binwrite.rb
@@ -21,6 +21,14 @@ describe :io_binwrite, shared: true do
IO.send(@method, @filename, "abcde").should == 5
end
+ it "accepts options as a keyword argument" do
+ IO.send(@method, @filename, "hi", 0, flags: File::CREAT).should == 2
+
+ -> {
+ IO.send(@method, @filename, "hi", 0, {flags: File::CREAT})
+ }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 2..3)")
+ end
+
it "creates a file if missing" do
fn = @filename + "xxx"
begin
@@ -67,8 +75,13 @@ describe :io_binwrite, shared: true do
File.read(@filename).should == "\0\0foo"
end
+ it "accepts a :flags option without :mode one" do
+ IO.send(@method, @filename, "hello, world!", flags: File::CREAT)
+ File.read(@filename).should == "hello, world!"
+ end
+
it "raises an error if readonly mode is specified" do
- -> { IO.send(@method, @filename, "abcde", mode: "r") }.should raise_error(IOError)
+ -> { IO.send(@method, @filename, "abcde", mode: "r") }.should.raise(IOError)
end
it "truncates if empty :opts provided and offset skipped" do
diff --git a/spec/ruby/core/io/shared/chars.rb b/spec/ruby/core/io/shared/chars.rb
index 266566f221..efd4d5ee10 100644
--- a/spec/ruby/core/io/shared/chars.rb
+++ b/spec/ruby/core/io/shared/chars.rb
@@ -24,7 +24,7 @@ describe :io_chars, shared: true do
describe "when no block is given" do
it "returns an Enumerator" do
enum = @io.send(@method)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.first(5).should == ["V", "o", "i", "c", "i"]
end
@@ -38,19 +38,19 @@ describe :io_chars, shared: true do
end
it "returns itself" do
- @io.send(@method) { |c| }.should equal(@io)
+ @io.send(@method) { |c| }.should.equal?(@io)
end
it "returns an enumerator for a closed stream" do
- IOSpecs.closed_io.send(@method).should be_an_instance_of(Enumerator)
+ IOSpecs.closed_io.send(@method).should.instance_of?(Enumerator)
end
it "raises an IOError when an enumerator created on a closed stream is accessed" do
- -> { IOSpecs.closed_io.send(@method).first }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.send(@method).first }.should.raise(IOError)
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.send(@method) {} }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.send(@method) {} }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/shared/codepoints.rb b/spec/ruby/core/io/shared/codepoints.rb
index 6872846c1a..21c756986f 100644
--- a/spec/ruby/core/io/shared/codepoints.rb
+++ b/spec/ruby/core/io/shared/codepoints.rb
@@ -13,7 +13,7 @@ describe :io_codepoints, shared: true do
describe "when no block is given" do
it "returns an Enumerator" do
- @enum.should be_an_instance_of(Enumerator)
+ @enum.should.instance_of?(Enumerator)
end
describe "returned Enumerator" do
@@ -39,7 +39,7 @@ describe :io_codepoints, shared: true do
it "raises an error if reading invalid sequence" do
@io.pos = 60 # inside of a multibyte sequence
- -> { @enum.first }.should raise_error(ArgumentError)
+ -> { @enum.first }.should.raise(ArgumentError)
end
it "does not change $_" do
@@ -49,6 +49,6 @@ describe :io_codepoints, shared: true do
end
it "raises an IOError when self is not readable" do
- -> { IOSpecs.closed_io.send(@method).to_a }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.send(@method).to_a }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/shared/each.rb b/spec/ruby/core/io/shared/each.rb
index 607e7de03e..ae60c3506a 100644
--- a/spec/ruby/core/io/shared/each.rb
+++ b/spec/ruby/core/io/shared/each.rb
@@ -24,7 +24,7 @@ describe :io_each, shared: true do
end
it "returns self" do
- @io.send(@method) { |l| l }.should equal(@io)
+ @io.send(@method) { |l| l }.should.equal?(@io)
end
it "does not change $_" do
@@ -33,12 +33,8 @@ describe :io_each, shared: true do
$_.should == "test"
end
- it "returns self" do
- @io.send(@method) { |l| l }.should equal(@io)
- end
-
it "raises an IOError when self is not readable" do
- -> { IOSpecs.closed_io.send(@method) {} }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.send(@method) {} }.should.raise(IOError)
end
it "makes line count accessible via lineno" do
@@ -54,7 +50,7 @@ describe :io_each, shared: true do
describe "when no block is given" do
it "returns an Enumerator" do
enum = @io.send(@method)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.each { |l| ScratchPad << l }
ScratchPad.recorded.should == IOSpecs.lines
@@ -74,9 +70,13 @@ describe :io_each, shared: true do
describe "when limit is 0" do
it "raises an ArgumentError" do
# must pass block so Enumerator is evaluated and raises
- -> { @io.send(@method, 0){} }.should raise_error(ArgumentError)
+ -> { @io.send(@method, 0){} }.should.raise(ArgumentError)
end
end
+
+ it "does not accept Integers that don't fit in a C off_t" do
+ -> { @io.send(@method, 2**128){} }.should.raise(RangeError)
+ end
end
describe "when passed a String containing one space as a separator" do
@@ -113,13 +113,20 @@ describe :io_each, shared: true do
@io.send(@method, "") { |s| ScratchPad << s }
ScratchPad.recorded.should == IOSpecs.paragraphs
end
+
+ it "discards leading newlines" do
+ @io.readline
+ @io.readline
+ @io.send(@method, "") { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.paragraphs[1..-1]
+ end
end
describe "with both separator and limit" do
describe "when no block is given" do
it "returns an Enumerator" do
enum = @io.send(@method, nil, 1024)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.each { |l| ScratchPad << l }
ScratchPad.recorded.should == [IOSpecs.lines.join]
@@ -136,7 +143,7 @@ describe :io_each, shared: true do
describe "when a block is given" do
it "accepts an empty block" do
- @io.send(@method, nil, 1024) {}.should equal(@io)
+ @io.send(@method, nil, 1024) {}.should.equal?(@io)
end
describe "when passed nil as a separator" do
@@ -152,6 +159,13 @@ describe :io_each, shared: true do
@io.send(@method, "", 1024) { |s| ScratchPad << s }
ScratchPad.recorded.should == IOSpecs.paragraphs
end
+
+ it "discards leading newlines" do
+ @io.readline
+ @io.readline
+ @io.send(@method, "", 1024) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.paragraphs[1..-1]
+ end
end
end
end
@@ -162,16 +176,14 @@ describe :io_each, shared: true do
ScratchPad.recorded.should == IOSpecs.lines_without_newline_characters
end
- ruby_version_is "3.0" do
- it "raises exception when options passed as Hash" do
- -> {
- @io.send(@method, { chomp: true }) { |s| }
- }.should raise_error(TypeError)
+ it "raises exception when options passed as Hash" do
+ -> {
+ @io.send(@method, { chomp: true }) { |s| }
+ }.should.raise(TypeError)
- -> {
- @io.send(@method, "\n", 1, { chomp: true }) { |s| }
- }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
- end
+ -> {
+ @io.send(@method, "\n", 1, { chomp: true }) { |s| }
+ }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
end
end
@@ -190,20 +202,10 @@ describe :io_each, shared: true do
end
describe "when passed chomp and nil as a separator" do
- ruby_version_is "3.2" do
- it "yields self's content" do
- @io.pos = 100
- @io.send(@method, nil, chomp: true) { |s| ScratchPad << s }
- ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six.\n"]
- end
- end
-
- ruby_version_is ""..."3.2" do
- it "yields self's content without trailing new line character" do
- @io.pos = 100
- @io.send(@method, nil, chomp: true) { |s| ScratchPad << s }
- ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six."]
- end
+ it "yields self's content" do
+ @io.pos = 100
+ @io.send(@method, nil, chomp: true) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six.\n"]
end
end
@@ -220,6 +222,14 @@ describe :io_each, shared: true do
]
end
end
+
+ describe "when passed too many arguments" do
+ it "raises ArgumentError" do
+ -> {
+ @io.send(@method, "", 1, "excess argument", chomp: true) {}
+ }.should.raise(ArgumentError)
+ end
+ end
end
describe :io_each_default_separator, shared: true do
diff --git a/spec/ruby/core/io/shared/gets_ascii.rb b/spec/ruby/core/io/shared/gets_ascii.rb
index 2a8fe3c9a5..2bd5470d99 100644
--- a/spec/ruby/core/io/shared/gets_ascii.rb
+++ b/spec/ruby/core/io/shared/gets_ascii.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :io_gets_ascii, shared: true do
describe "with ASCII separator" do
before :each do
diff --git a/spec/ruby/core/io/shared/new.rb b/spec/ruby/core/io/shared/new.rb
index f2a0970a40..6f318ddee5 100644
--- a/spec/ruby/core/io/shared/new.rb
+++ b/spec/ruby/core/io/shared/new.rb
@@ -1,5 +1,7 @@
require_relative '../fixtures/classes'
+# NOTE: should be synchronized with library/stringio/initialize_spec.rb
+
# This group of specs may ONLY contain specs that do successfully create
# an IO instance from the file descriptor returned by #new_fd helper.
describe :io_new, shared: true do
@@ -20,7 +22,7 @@ describe :io_new, shared: true do
it "creates an IO instance from an Integer argument" do
@io = IO.send(@method, @fd, "w")
- @io.should be_an_instance_of(IO)
+ @io.should.instance_of?(IO)
end
it "creates an IO instance when STDOUT is closed" do
@@ -30,7 +32,7 @@ describe :io_new, shared: true do
begin
@io = IO.send(@method, @fd, "w")
- @io.should be_an_instance_of(IO)
+ @io.should.instance_of?(IO)
ensure
STDOUT = stdout
rm_r stdout_file
@@ -47,7 +49,7 @@ describe :io_new, shared: true do
begin
@io = IO.send(@method, @fd, "w")
- @io.should be_an_instance_of(IO)
+ @io.should.instance_of?(IO)
ensure
STDERR = stderr
rm_r stderr_file
@@ -59,7 +61,16 @@ describe :io_new, shared: true do
obj = mock("file descriptor")
obj.should_receive(:to_int).and_return(@fd)
@io = IO.send(@method, obj, "w")
- @io.should be_an_instance_of(IO)
+ @io.should.instance_of?(IO)
+ end
+
+ it "accepts options as keyword arguments" do
+ @io = IO.send(@method, @fd, "w", flags: File::CREAT)
+ @io.write("foo").should == 3
+
+ -> {
+ IO.send(@method, @fd, "w", {flags: File::CREAT})
+ }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 1..2)")
end
it "accepts a :mode option" do
@@ -197,21 +208,30 @@ describe :io_new, shared: true do
@io.internal_encoding.to_s.should == 'IBM866'
end
- ruby_version_is ''...'3.0' do
- it "accepts nil options" do
- @io = suppress_keyword_warning do
- IO.send(@method, @fd, 'w', nil)
- end
- @io.write("foo").should == 3
- end
+ it "does not use binary encoding when mode encoding is specified along with binmode: true option" do
+ @io = IO.send(@method, @fd, 'w:iso-8859-1', binmode: true)
+ @io.external_encoding.to_s.should == 'ISO-8859-1'
end
- ruby_version_is '3.0' do
- it "raises ArgumentError for nil options" do
- -> {
- IO.send(@method, @fd, 'w', nil)
- }.should raise_error(ArgumentError)
- end
+ it "does not use textmode argument when mode encoding is specified" do
+ @io = IO.send(@method, @fd, 'w:ascii-8bit', textmode: true)
+ @io.external_encoding.to_s.should == 'ASCII-8BIT'
+ end
+
+ it "does not use binmode argument when external encoding is specified via the :external_encoding option" do
+ @io = IO.send(@method, @fd, 'w', binmode: true, external_encoding: 'iso-8859-1')
+ @io.external_encoding.to_s.should == 'ISO-8859-1'
+ end
+
+ it "does not use textmode argument when external encoding is specified via the :external_encoding option" do
+ @io = IO.send(@method, @fd, 'w', textmode: true, external_encoding: 'ascii-8bit')
+ @io.external_encoding.to_s.should == 'ASCII-8BIT'
+ end
+
+ it "raises ArgumentError for nil options" do
+ -> {
+ IO.send(@method, @fd, 'w', nil)
+ }.should.raise(ArgumentError)
end
it "coerces mode with #to_str" do
@@ -294,109 +314,100 @@ describe :io_new_errors, shared: true do
end
it "raises an Errno::EBADF if the file descriptor is not valid" do
- -> { IO.send(@method, -1, "w") }.should raise_error(Errno::EBADF)
+ -> { IO.send(@method, -1, "w") }.should.raise(Errno::EBADF)
end
it "raises an IOError if passed a closed stream" do
- -> { IO.send(@method, IOSpecs.closed_io.fileno, 'w') }.should raise_error(IOError)
+ -> { IO.send(@method, IOSpecs.closed_io.fileno, 'w') }.should.raise(IOError)
end
platform_is_not :windows do
it "raises an Errno::EINVAL if the new mode is not compatible with the descriptor's current mode" do
- -> { IO.send(@method, @fd, "r") }.should raise_error(Errno::EINVAL)
+ -> { IO.send(@method, @fd, "r") }.should.raise(Errno::EINVAL)
end
end
it "raises ArgumentError if passed an empty mode string" do
- -> { IO.send(@method, @fd, "") }.should raise_error(ArgumentError)
+ -> { IO.send(@method, @fd, "") }.should.raise(ArgumentError)
end
it "raises an error if passed modes two ways" do
-> {
IO.send(@method, @fd, "w", mode: "w")
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises an error if passed encodings two ways" do
-> {
@io = IO.send(@method, @fd, 'w:ISO-8859-1', encoding: 'ISO-8859-1')
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, 'w:ISO-8859-1', external_encoding: 'ISO-8859-1')
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
+ -> {
+ @io = IO.send(@method, @fd, 'w:ISO-8859-1', internal_encoding: 'ISO-8859-1')
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, 'w:ISO-8859-1:UTF-8', internal_encoding: 'ISO-8859-1')
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises an error if passed matching binary/text mode two ways" do
-> {
@io = IO.send(@method, @fd, "wb", binmode: true)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, "wt", textmode: true)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, "wb", textmode: false)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, "wt", binmode: false)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises an error if passed conflicting binary/text mode two ways" do
-> {
@io = IO.send(@method, @fd, "wb", binmode: false)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, "wt", textmode: false)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, "wb", textmode: true)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, "wt", binmode: true)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises an error when trying to set both binmode and textmode" do
-> {
@io = IO.send(@method, @fd, "w", textmode: true, binmode: true)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, File::Constants::WRONLY, textmode: true, binmode: true)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises ArgumentError if not passed a hash or nil for options" do
-> {
@io = IO.send(@method, @fd, 'w', false)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, false, false)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
@io = IO.send(@method, @fd, nil, false)
- }.should raise_error(ArgumentError)
- end
-
- ruby_version_is ''...'3.0' do
- it "raises TypeError if passed a hash for mode and nil for options" do
- -> {
- suppress_keyword_warning do
- @io = IO.send(@method, @fd, {mode: 'w'}, nil)
- end
- }.should raise_error(TypeError)
- end
+ }.should.raise(ArgumentError)
end
- ruby_version_is '3.0' do
- it "raises ArgumentError if passed a hash for mode and nil for options" do
- -> {
- @io = IO.send(@method, @fd, {mode: 'w'}, nil)
- }.should raise_error(ArgumentError)
- end
+ it "raises ArgumentError if passed a hash for mode and nil for options" do
+ -> {
+ @io = IO.send(@method, @fd, {mode: 'w'}, nil)
+ }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/io/shared/pos.rb b/spec/ruby/core/io/shared/pos.rb
index d83a6c6692..f4d0405863 100644
--- a/spec/ruby/core/io/shared/pos.rb
+++ b/spec/ruby/core/io/shared/pos.rb
@@ -19,7 +19,7 @@ describe :io_pos, shared: true do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.send(@method) }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.send(@method) }.should.raise(IOError)
end
it "resets #eof?" do
@@ -60,13 +60,19 @@ describe :io_set_pos, shared: true do
end
end
- it "does not accept Integers that don't fit in a C long" do
+ it "raises TypeError when cannot convert implicitly argument to Integer" do
File.open @fname do |io|
- -> { io.send @method, 2**128 }.should raise_error(RangeError)
+ -> { io.send @method, Object.new }.should.raise(TypeError, "no implicit conversion of Object into Integer")
+ end
+ end
+
+ it "does not accept Integers that don't fit in a C off_t" do
+ File.open @fname do |io|
+ -> { io.send @method, 2**128 }.should.raise(RangeError)
end
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.send @method, 0 }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.send @method, 0 }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/shared/readlines.rb b/spec/ruby/core/io/shared/readlines.rb
index 479452b71c..f54fccc2e3 100644
--- a/spec/ruby/core/io/shared/readlines.rb
+++ b/spec/ruby/core/io/shared/readlines.rb
@@ -1,11 +1,11 @@
describe :io_readlines, shared: true do
it "raises TypeError if the first parameter is nil" do
- -> { IO.send(@method, nil, &@object) }.should raise_error(TypeError)
+ -> { IO.send(@method, nil, &@object) }.should.raise(TypeError)
end
it "raises an Errno::ENOENT if the file does not exist" do
name = tmp("nonexistent.txt")
- -> { IO.send(@method, name, &@object) }.should raise_error(Errno::ENOENT)
+ -> { IO.send(@method, name, &@object) }.should.raise(Errno::ENOENT)
end
it "yields a single string with entire content when the separator is nil" do
@@ -79,11 +79,13 @@ describe :io_readlines_options_19, shared: true do
(result ? result : ScratchPad.recorded).should == IOSpecs.lines
end
- ruby_bug "#18767", ""..."3.3" do
- describe "when passed limit" do
- it "raises ArgumentError when passed 0 as a limit" do
- -> { IO.send(@method, @name, 0, &@object) }.should raise_error(ArgumentError)
- end
+ it "does not accept Integers that don't fit in a C off_t" do
+ -> { IO.send(@method, @name, 2**128, &@object) }.should.raise(RangeError)
+ end
+
+ describe "when passed limit" do
+ it "raises ArgumentError when passed 0 as a limit" do
+ -> { IO.send(@method, @name, 0, &@object) }.should.raise(ArgumentError)
end
end
end
@@ -95,18 +97,16 @@ describe :io_readlines_options_19, shared: true do
end
it "accepts non-ASCII data as separator" do
- result = IO.send(@method, @name, "\303\250".force_encoding("utf-8"), &@object)
+ result = IO.send(@method, @name, "\303\250".dup.force_encoding("utf-8"), &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_arbitrary_separator
end
end
describe "when the object is an options Hash" do
- ruby_version_is "3.0" do
- it "raises TypeError exception" do
- -> {
- IO.send(@method, @name, { chomp: true }, &@object)
- }.should raise_error(TypeError)
- end
+ it "raises TypeError exception" do
+ -> {
+ IO.send(@method, @name, { chomp: true }, &@object)
+ }.should.raise(TypeError)
end
end
@@ -116,7 +116,7 @@ describe :io_readlines_options_19, shared: true do
-> {
IO.send(@method, @name, obj, &@object)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
end
@@ -170,17 +170,15 @@ describe :io_readlines_options_19, shared: true do
-> {
IO.send(@method, @name, " ", obj, &@object)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
describe "when the second object is an options Hash" do
- ruby_version_is "3.0" do
- it "raises TypeError exception" do
- -> {
- IO.send(@method, @name, "", { chomp: true }, &@object)
- }.should raise_error(TypeError)
- end
+ it "raises TypeError exception" do
+ -> {
+ IO.send(@method, @name, "", { chomp: true }, &@object)
+ }.should.raise(TypeError)
end
end
end
@@ -190,7 +188,7 @@ describe :io_readlines_options_19, shared: true do
it "uses the keyword arguments as options" do
-> do
IO.send(@method, @filename, 10, mode: "w", &@object)
- end.should raise_error(IOError)
+ end.should.raise(IOError)
end
end
@@ -198,7 +196,7 @@ describe :io_readlines_options_19, shared: true do
it "uses the keyword arguments as options" do
-> do
IO.send(@method, @filename, " ", mode: "w", &@object)
- end.should raise_error(IOError)
+ end.should.raise(IOError)
end
end
@@ -209,7 +207,7 @@ describe :io_readlines_options_19, shared: true do
-> do
IO.send(@method, @filename, sep, mode: "w", &@object)
- end.should raise_error(IOError)
+ end.should.raise(IOError)
end
end
end
@@ -239,7 +237,7 @@ describe :io_readlines_options_19, shared: true do
it "uses the keyword arguments as options" do
-> do
IO.send(@method, @filename, " ", 10, mode: "w", &@object)
- end.should raise_error(IOError)
+ end.should.raise(IOError)
end
describe "when passed chomp, nil as a separator, and a limit" do
diff --git a/spec/ruby/core/io/shared/tty.rb b/spec/ruby/core/io/shared/tty.rb
index 89ac08ec86..1dc0e95739 100644
--- a/spec/ruby/core/io/shared/tty.rb
+++ b/spec/ruby/core/io/shared/tty.rb
@@ -19,6 +19,6 @@ describe :io_tty, shared: true do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.send @method }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.send @method }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/shared/write.rb b/spec/ruby/core/io/shared/write.rb
index 270b84ac39..5de9fe4335 100644
--- a/spec/ruby/core/io/shared/write.rb
+++ b/spec/ruby/core/io/shared/write.rb
@@ -23,7 +23,7 @@ describe :io_write, shared: true do
end
it "checks if the file is writable if writing more than zero bytes" do
- -> { @readonly_file.send(@method, "abcde") }.should raise_error(IOError)
+ -> { @readonly_file.send(@method, "abcde") }.should.raise(IOError)
end
it "returns the number of bytes written" do
@@ -66,17 +66,7 @@ describe :io_write, shared: true do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.send(@method, "hello") }.should raise_error(IOError)
- end
-
- it "does not modify the passed argument" do
- File.open(@filename, "w") do |f|
- f.set_encoding(Encoding::IBM437)
- # A character whose codepoint differs between UTF-8 and IBM437
- f.write "ƒ".freeze
- end
-
- File.binread(@filename).bytes.should == [159]
+ -> { IOSpecs.closed_io.send(@method, "hello") }.should.raise(IOError)
end
describe "on a pipe" do
@@ -95,15 +85,70 @@ describe :io_write, shared: true do
@r.read.should == "foo"
end
- # [ruby-core:90895] MJIT worker may leave fd open in a forked child.
- # For instance, MJIT creates a worker before @r.close with fork(), @r.close happens,
- # and the MJIT worker keeps the pipe open until the worker execve().
- # TODO: consider acquiring GVL from MJIT worker.
- guard_not -> { defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? } do
+ # [ruby-core:90895] RJIT worker may leave fd open in a forked child.
+ # For instance, RJIT creates a worker before @r.close with fork(), @r.close happens,
+ # and the RJIT worker keeps the pipe open until the worker execve().
+ # TODO: consider acquiring GVL from RJIT worker.
+ guard_not -> { defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? } do
it "raises Errno::EPIPE if the read end is closed and does not die from SIGPIPE" do
@r.close
- -> { @w.send(@method, "foo") }.should raise_error(Errno::EPIPE, /Broken pipe/)
+ -> { @w.send(@method, "foo") }.should.raise(Errno::EPIPE, /Broken pipe/)
end
end
end
end
+
+describe :io_write_transcode, shared: true do
+ before :each do
+ @transcode_filename = tmp("io_write_transcode")
+ end
+
+ after :each do
+ rm_r @transcode_filename
+ end
+
+ it "transcodes the given string when the external encoding is set and neither is BINARY" do
+ utf8_str = "hello"
+
+ File.open(@transcode_filename, "w", external_encoding: Encoding::UTF_16BE) do |file|
+ file.external_encoding.should == Encoding::UTF_16BE
+ file.send(@method, utf8_str)
+ end
+
+ result = File.binread(@transcode_filename)
+ expected = [0, 104, 0, 101, 0, 108, 0, 108, 0, 111] # UTF-16BE bytes for "hello"
+
+ result.bytes.should == expected
+ end
+
+ it "transcodes the given string when the external encoding is set and the string encoding is BINARY" do
+ str = "été".b
+
+ File.open(@transcode_filename, "w", external_encoding: Encoding::UTF_16BE) do |file|
+ file.external_encoding.should == Encoding::UTF_16BE
+ -> { file.send(@method, str) }.should.raise(Encoding::UndefinedConversionError)
+ end
+ end
+end
+
+describe :io_write_no_transcode, shared: true do
+ before :each do
+ @transcode_filename = tmp("io_write_no_transcode")
+ end
+
+ after :each do
+ rm_r @transcode_filename
+ end
+
+ it "does not transcode the given string even when the external encoding is set" do
+ utf8_str = "hello"
+
+ File.open(@transcode_filename, "w", external_encoding: Encoding::UTF_16BE) do |file|
+ file.external_encoding.should == Encoding::UTF_16BE
+ file.send(@method, utf8_str)
+ end
+
+ result = File.binread(@transcode_filename)
+ result.bytes.should == utf8_str.bytes
+ end
+end
diff --git a/spec/ruby/core/io/stat_spec.rb b/spec/ruby/core/io/stat_spec.rb
index 58eba02b8f..f9fc232ee0 100644
--- a/spec/ruby/core/io/stat_spec.rb
+++ b/spec/ruby/core/io/stat_spec.rb
@@ -3,7 +3,8 @@ require_relative 'fixtures/classes'
describe "IO#stat" do
before :each do
- @io = IO.popen 'cat', "r+"
+ cmd = platform_is(:windows) ? 'rem' : 'cat'
+ @io = IO.popen cmd, "r+"
end
after :each do
@@ -11,14 +12,14 @@ describe "IO#stat" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.stat }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.stat }.should.raise(IOError)
end
it "returns a File::Stat object for the stream" do
- STDOUT.stat.should be_an_instance_of(File::Stat)
+ STDOUT.stat.should.instance_of?(File::Stat)
end
it "can stat pipes" do
- @io.stat.should be_an_instance_of(File::Stat)
+ @io.stat.should.instance_of?(File::Stat)
end
end
diff --git a/spec/ruby/core/io/sync_spec.rb b/spec/ruby/core/io/sync_spec.rb
index 993b7ee244..b537db335b 100644
--- a/spec/ruby/core/io/sync_spec.rb
+++ b/spec/ruby/core/io/sync_spec.rb
@@ -27,7 +27,7 @@ describe "IO#sync=" do
end
it "raises an IOError on closed stream" do
- -> { IOSpecs.closed_io.sync = true }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.sync = true }.should.raise(IOError)
end
end
@@ -45,7 +45,7 @@ describe "IO#sync" do
end
it "raises an IOError on closed stream" do
- -> { IOSpecs.closed_io.sync }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.sync }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/sysopen_spec.rb b/spec/ruby/core/io/sysopen_spec.rb
index 7ad379df3a..325d51ed23 100644
--- a/spec/ruby/core/io/sysopen_spec.rb
+++ b/spec/ruby/core/io/sysopen_spec.rb
@@ -13,16 +13,16 @@ describe "IO.sysopen" do
it "returns the file descriptor for a given path" do
@fd = IO.sysopen(@filename, "w")
- @fd.should be_kind_of(Integer)
- @fd.should_not equal(0)
+ @fd.should.is_a?(Integer)
+ @fd.should_not.equal?(0)
end
# opening a directory is not supported on Windows
platform_is_not :windows do
it "works on directories" do
@fd = IO.sysopen(tmp("")) # /tmp
- @fd.should be_kind_of(Integer)
- @fd.should_not equal(0)
+ @fd.should.is_a?(Integer)
+ @fd.should_not.equal?(0)
end
end
@@ -33,18 +33,18 @@ describe "IO.sysopen" do
end
it "accepts a mode as second argument" do
- -> { @fd = IO.sysopen(@filename, "w") }.should_not raise_error
- @fd.should_not equal(0)
+ -> { @fd = IO.sysopen(@filename, "w") }.should_not.raise
+ @fd.should_not.equal?(0)
end
it "accepts permissions as third argument" do
@fd = IO.sysopen(@filename, "w", 777)
- @fd.should_not equal(0)
+ @fd.should_not.equal?(0)
end
it "accepts mode & permission that are nil" do
touch @filename # create the file
@fd = IO.sysopen(@filename, nil, nil)
- @fd.should_not equal(0)
+ @fd.should_not.equal?(0)
end
end
diff --git a/spec/ruby/core/io/sysread_spec.rb b/spec/ruby/core/io/sysread_spec.rb
index 8201ad47ca..2d58db2250 100644
--- a/spec/ruby/core/io/sysread_spec.rb
+++ b/spec/ruby/core/io/sysread_spec.rb
@@ -6,7 +6,7 @@ describe "IO#sysread on a file" do
@file_name = tmp("IO_sysread_file") + $$.to_s
File.open(@file_name, "w") do |f|
# write some stuff
- f.write("012345678901234567890123456789")
+ f.write("012345678901234567890123456789\nabcdef")
end
@file = File.open(@file_name, "r+")
end
@@ -21,25 +21,25 @@ describe "IO#sysread on a file" do
end
it "reads the specified number of bytes from the file to the buffer" do
- buf = "" # empty buffer
+ buf = +"" # empty buffer
@file.sysread(15, buf).should == buf
buf.should == "012345678901234"
@file.rewind
- buf = "ABCDE" # small buffer
+ buf = +"ABCDE" # small buffer
@file.sysread(15, buf).should == buf
buf.should == "012345678901234"
@file.rewind
- buf = "ABCDE" * 5 # large buffer
+ buf = +"ABCDE" * 5 # large buffer
@file.sysread(15, buf).should == buf
buf.should == "012345678901234"
end
it "coerces the second argument to string and uses it as a buffer" do
- buf = "ABCDE"
+ buf = +"ABCDE"
(obj = mock("buff")).should_receive(:to_str).any_number_of_times.and_return(buf)
@file.sysread(15, obj).should == buf
buf.should == "012345678901234"
@@ -52,7 +52,7 @@ describe "IO#sysread on a file" do
it "raises an error when called after buffered reads" do
@file.readline
- -> { @file.sysread(5) }.should raise_error(IOError)
+ -> { @file.sysread(5) }.should.raise(IOError)
end
it "reads normally even when called immediately after a buffered IO#read" do
@@ -63,13 +63,13 @@ describe "IO#sysread on a file" do
it "does not raise error if called after IO#read followed by IO#write" do
@file.read(5)
@file.write("abcde")
- -> { @file.sysread(5) }.should_not raise_error(IOError)
+ -> { @file.sysread(5) }.should_not.raise(IOError)
end
it "does not raise error if called after IO#read followed by IO#syswrite" do
@file.read(5)
@file.syswrite("abcde")
- -> { @file.sysread(5) }.should_not raise_error(IOError)
+ -> { @file.sysread(5) }.should_not.raise(IOError)
end
it "reads updated content after the flushed buffered IO#write" do
@@ -82,7 +82,37 @@ describe "IO#sysread on a file" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.sysread(5) }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.sysread(5) }.should.raise(IOError)
+ end
+
+ it "immediately returns an empty string if the length argument is 0" do
+ @file.sysread(0).should == ""
+ end
+
+ it "immediately returns the given buffer if the length argument is 0" do
+ buffer = +"existing content"
+ @file.sysread(0, buffer).should == buffer
+ buffer.should == "existing content"
+ end
+
+ it "discards the existing buffer content upon successful read" do
+ buffer = +"existing content"
+ @file.sysread(11, buffer).should.equal?(buffer)
+ buffer.should == "01234567890"
+ end
+
+ it "discards the existing buffer content upon error" do
+ buffer = +"existing content"
+ @file.seek(0, :END)
+ -> { @file.sysread(1, buffer) }.should.raise(EOFError)
+ buffer.should.empty?
+ end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ string = @file.sysread(10, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
end
end
@@ -100,4 +130,8 @@ describe "IO#sysread" do
@write.syswrite "ab"
@read.sysread(3).should == "ab"
end
+
+ it "raises ArgumentError when length is less than 0" do
+ -> { @read.sysread(-1) }.should.raise(ArgumentError)
+ end
end
diff --git a/spec/ruby/core/io/sysseek_spec.rb b/spec/ruby/core/io/sysseek_spec.rb
index e631939bce..2384895dc5 100644
--- a/spec/ruby/core/io/sysseek_spec.rb
+++ b/spec/ruby/core/io/sysseek_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
require_relative 'shared/pos'
describe "IO#sysseek" do
- it_behaves_like :io_set_pos, :seek
+ it_behaves_like :io_set_pos, :sysseek
end
describe "IO#sysseek" do
@@ -23,7 +23,7 @@ describe "IO#sysseek" do
it "raises an error when called after buffered reads" do
@io.readline
- -> { @io.sysseek(-5, IO::SEEK_CUR) }.should raise_error(IOError)
+ -> { @io.sysseek(-5, IO::SEEK_CUR) }.should.raise(IOError)
end
it "seeks normally even when called immediately after a buffered IO#read" do
@@ -41,7 +41,7 @@ describe "IO#sysseek" do
# this is the safest way of checking the EOF when
# sys-* methods are invoked
- -> { @io.sysread(1) }.should raise_error(EOFError)
+ -> { @io.sysread(1) }.should.raise(EOFError)
@io.sysseek(-25, IO::SEEK_END)
@io.sysread(7).should == "cinco.\n"
diff --git a/spec/ruby/core/io/syswrite_spec.rb b/spec/ruby/core/io/syswrite_spec.rb
index a28cc62174..8bf61a27c3 100644
--- a/spec/ruby/core/io/syswrite_spec.rb
+++ b/spec/ruby/core/io/syswrite_spec.rb
@@ -29,6 +29,16 @@ describe "IO#syswrite on a file" do
end
end
+ it "does not modify the passed argument" do
+ File.open(@filename, "w") do |f|
+ f.set_encoding(Encoding::IBM437)
+ # A character whose codepoint differs between UTF-8 and IBM437
+ f.syswrite("ƒ".freeze)
+ end
+
+ File.binread(@filename).bytes.should == [198, 146]
+ end
+
it "warns if called immediately after a buffered IO#write" do
@file.write("abcde")
-> { @file.syswrite("fghij") }.should complain(/syswrite/)
@@ -68,4 +78,5 @@ end
describe "IO#syswrite" do
it_behaves_like :io_write, :syswrite
+ it_behaves_like :io_write_no_transcode, :syswrite
end
diff --git a/spec/ruby/core/io/to_i_spec.rb b/spec/ruby/core/io/to_i_spec.rb
index acf138c663..1d0cf2a1f6 100644
--- a/spec/ruby/core/io/to_i_spec.rb
+++ b/spec/ruby/core/io/to_i_spec.rb
@@ -7,6 +7,6 @@ describe "IO#to_i" do
end
it "raises IOError on closed stream" do
- -> { IOSpecs.closed_io.to_i }.should raise_error(IOError)
+ -> { IOSpecs.closed_io.to_i }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/to_io_spec.rb b/spec/ruby/core/io/to_io_spec.rb
index 55a0977740..0b1809dffa 100644
--- a/spec/ruby/core/io/to_io_spec.rb
+++ b/spec/ruby/core/io/to_io_spec.rb
@@ -11,11 +11,11 @@ describe "IO#to_io" do
end
it "returns self for open stream" do
- @io.to_io.should equal(@io)
+ @io.to_io.should.equal?(@io)
end
it "returns self for closed stream" do
io = IOSpecs.closed_io
- io.to_io.should equal(io)
+ io.to_io.should.equal?(io)
end
end
diff --git a/spec/ruby/core/io/try_convert_spec.rb b/spec/ruby/core/io/try_convert_spec.rb
index 5fbd10b6fa..7600b01b75 100644
--- a/spec/ruby/core/io/try_convert_spec.rb
+++ b/spec/ruby/core/io/try_convert_spec.rb
@@ -13,7 +13,7 @@ describe "IO.try_convert" do
end
it "returns the passed IO object" do
- IO.try_convert(@io).should equal(@io)
+ IO.try_convert(@io).should.equal?(@io)
end
it "does not call #to_io on an IO instance" do
@@ -24,26 +24,26 @@ describe "IO.try_convert" do
it "calls #to_io to coerce an object" do
obj = mock("io")
obj.should_receive(:to_io).and_return(@io)
- IO.try_convert(obj).should equal(@io)
+ IO.try_convert(obj).should.equal?(@io)
end
it "returns nil when the passed object does not respond to #to_io" do
- IO.try_convert(mock("io")).should be_nil
+ IO.try_convert(mock("io")).should == nil
end
it "return nil when BasicObject is passed" do
- IO.try_convert(BasicObject.new).should be_nil
+ IO.try_convert(BasicObject.new).should == nil
end
it "raises a TypeError if the object does not return an IO from #to_io" do
obj = mock("io")
obj.should_receive(:to_io).and_return("io")
- -> { IO.try_convert(obj) }.should raise_error(TypeError)
+ -> { IO.try_convert(obj) }.should raise_consistent_error(TypeError, "can't convert MockObject into IO (MockObject#to_io gives String)")
end
it "propagates an exception raised by #to_io" do
obj = mock("io")
obj.should_receive(:to_io).and_raise(TypeError.new)
- ->{ IO.try_convert(obj) }.should raise_error(TypeError)
+ ->{ IO.try_convert(obj) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/io/ungetbyte_spec.rb b/spec/ruby/core/io/ungetbyte_spec.rb
index 716743a6af..e0615cd76c 100644
--- a/spec/ruby/core/io/ungetbyte_spec.rb
+++ b/spec/ruby/core/io/ungetbyte_spec.rb
@@ -13,12 +13,12 @@ describe "IO#ungetbyte" do
end
it "does nothing when passed nil" do
- @io.ungetbyte(nil).should be_nil
+ @io.ungetbyte(nil).should == nil
@io.getbyte.should == 97
end
it "puts back each byte in a String argument" do
- @io.ungetbyte("cat").should be_nil
+ @io.ungetbyte("cat").should == nil
@io.getbyte.should == 99
@io.getbyte.should == 97
@io.getbyte.should == 116
@@ -29,7 +29,7 @@ describe "IO#ungetbyte" do
str = mock("io ungetbyte")
str.should_receive(:to_str).and_return("dog")
- @io.ungetbyte(str).should be_nil
+ @io.ungetbyte(str).should == nil
@io.getbyte.should == 100
@io.getbyte.should == 111
@io.getbyte.should == 103
@@ -38,17 +38,17 @@ describe "IO#ungetbyte" do
it "never raises RangeError" do
for i in [4095, 0x4f7574206f6620636861722072616e67ff] do
- @io.ungetbyte(i).should be_nil
+ @io.ungetbyte(i).should == nil
@io.getbyte.should == 255
end
end
it "raises IOError on stream not opened for reading" do
- -> { STDOUT.ungetbyte(42) }.should raise_error(IOError, "not opened for reading")
+ -> { STDOUT.ungetbyte(42) }.should.raise(IOError, "not opened for reading")
end
it "raises an IOError if the IO is closed" do
@io.close
- -> { @io.ungetbyte(42) }.should raise_error(IOError)
+ -> { @io.ungetbyte(42) }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/ungetc_spec.rb b/spec/ruby/core/io/ungetc_spec.rb
index 41a455c836..4a9e67f126 100644
--- a/spec/ruby/core/io/ungetc_spec.rb
+++ b/spec/ruby/core/io/ungetc_spec.rb
@@ -100,27 +100,17 @@ describe "IO#ungetc" do
it "makes subsequent unbuffered operations to raise IOError" do
@io.getc
@io.ungetc(100)
- -> { @io.sysread(1) }.should raise_error(IOError)
+ -> { @io.sysread(1) }.should.raise(IOError)
end
- ruby_version_is ""..."3.0" do
- it "does not affect the stream and returns nil when passed nil" do
- @io.getc.should == ?V
- @io.ungetc(nil)
- @io.getc.should == ?o
- end
- end
-
- ruby_version_is "3.0" do
- it "raises TypeError if passed nil" do
- @io.getc.should == ?V
- proc{@io.ungetc(nil)}.should raise_error(TypeError)
- end
+ it "raises TypeError if passed nil" do
+ @io.getc.should == ?V
+ proc{@io.ungetc(nil)}.should.raise(TypeError)
end
it "puts one or more characters back in the stream" do
@io.gets
- @io.ungetc("Aquí ").should be_nil
+ @io.ungetc("Aquí ").should == nil
@io.gets.chomp.should == "Aquí Qui è la linea due."
end
@@ -128,21 +118,21 @@ describe "IO#ungetc" do
chars = mock("io ungetc")
chars.should_receive(:to_str).and_return("Aquí ")
- @io.ungetc(chars).should be_nil
+ @io.ungetc(chars).should == nil
@io.gets.chomp.should == "Aquí Voici la ligne une."
end
it "returns nil when invoked on stream that was not yet read" do
- @io.ungetc(100).should be_nil
+ @io.ungetc(100).should == nil
end
it "raises IOError on stream not opened for reading" do
- -> { STDOUT.ungetc(100) }.should raise_error(IOError, "not opened for reading")
+ -> { STDOUT.ungetc(100) }.should.raise(IOError, "not opened for reading")
end
it "raises IOError on closed stream" do
@io.getc
@io.close
- -> { @io.ungetc(100) }.should raise_error(IOError)
+ -> { @io.ungetc(100) }.should.raise(IOError)
end
end
diff --git a/spec/ruby/core/io/write_nonblock_spec.rb b/spec/ruby/core/io/write_nonblock_spec.rb
index a8b9ce0a36..a6bd43c058 100644
--- a/spec/ruby/core/io/write_nonblock_spec.rb
+++ b/spec/ruby/core/io/write_nonblock_spec.rb
@@ -31,15 +31,26 @@ platform_is_not :windows do
end
end
+ it "does not modify the passed argument" do
+ File.open(@filename, "w") do |f|
+ f.set_encoding(Encoding::IBM437)
+ # A character whose codepoint differs between UTF-8 and IBM437
+ f.write_nonblock("ƒ".freeze)
+ end
+
+ File.binread(@filename).bytes.should == [198, 146]
+ end
+
it "checks if the file is writable if writing zero bytes" do
-> {
- @readonly_file.write_nonblock("")
- }.should raise_error(IOError)
+ @readonly_file.write_nonblock("")
+ }.should.raise(IOError)
end
end
describe "IO#write_nonblock" do
it_behaves_like :io_write, :write_nonblock
+ it_behaves_like :io_write_no_transcode, :write_nonblock
end
end
@@ -56,12 +67,12 @@ describe 'IO#write_nonblock' do
it "raises an exception extending IO::WaitWritable when the write would block" do
-> {
loop { @write.write_nonblock('a' * 10_000) }
- }.should raise_error(IO::WaitWritable) { |e|
+ }.should.raise(IO::WaitWritable) { |e|
platform_is_not :windows do
- e.should be_kind_of(Errno::EAGAIN)
+ e.should.is_a?(Errno::EAGAIN)
end
platform_is :windows do
- e.should be_kind_of(Errno::EWOULDBLOCK)
+ e.should.is_a?(Errno::EWOULDBLOCK)
end
}
end
diff --git a/spec/ruby/core/io/write_spec.rb b/spec/ruby/core/io/write_spec.rb
index f29fdf3a01..1a745ba012 100644
--- a/spec/ruby/core/io/write_spec.rb
+++ b/spec/ruby/core/io/write_spec.rb
@@ -21,11 +21,7 @@ describe "IO#write on a file" do
end
it "does not check if the file is writable if writing zero bytes" do
- -> { @readonly_file.write("") }.should_not raise_error
- end
-
- it "returns a length of 0 when writing a blank string" do
- @file.write('').should == 0
+ -> { @readonly_file.write("") }.should_not.raise
end
before :each do
@@ -40,10 +36,44 @@ describe "IO#write on a file" do
Encoding.default_internal = @internal
end
+ it "returns a length of 0 when writing a blank string" do
+ @file.write('').should == 0
+ end
+
+ it "returns a length of 0 when writing blank strings" do
+ @file.write('', '', '').should == 0
+ end
+
+ it "returns a length of 0 when passed no arguments" do
+ @file.write().should == 0
+ end
+
it "returns the number of bytes written" do
@file.write("hellø").should == 6
end
+ it "does not modify the passed argument" do
+ File.open(@filename, "w") do |f|
+ f.set_encoding(Encoding::IBM437)
+ # A character whose codepoint differs between UTF-8 and IBM437
+ f.write("ƒ".freeze)
+ end
+
+ File.binread(@filename).bytes.should == [159]
+ end
+
+ it "does not modify arguments when passed multiple arguments and external encoding not set" do
+ a, b = "a".freeze, "b".freeze
+
+ File.open(@filename, "w") do |f|
+ f.write(a, b)
+ end
+
+ File.binread(@filename).bytes.should == [97, 98]
+ a.encoding.should == Encoding::UTF_8
+ b.encoding.should == Encoding::UTF_8
+ end
+
it "uses the encoding from the given option for non-ascii encoding" do
File.open(@filename, "w", encoding: Encoding::UTF_32LE) do |file|
file.write("hi").should == 8
@@ -51,15 +81,39 @@ describe "IO#write on a file" do
File.binread(@filename).should == "h\u0000\u0000\u0000i\u0000\u0000\u0000"
end
- it "uses an :open_args option" do
- IO.write(@filename, 'hi', open_args: ["w", nil, {encoding: Encoding::UTF_32LE}]).should == 8
+ it "uses the encoding from the given option for non-ascii encoding even if in binary mode" do
+ File.open(@filename, "w", encoding: Encoding::UTF_32LE, binmode: true) do |file|
+ file.should.binmode?
+ file.write("hi").should == 8
+ end
+ File.binread(@filename).should == "h\u0000\u0000\u0000i\u0000\u0000\u0000"
+
+ File.open(@filename, "wb", encoding: Encoding::UTF_32LE) do |file|
+ file.should.binmode?
+ file.write("hi").should == 8
+ end
+ File.binread(@filename).should == "h\u0000\u0000\u0000i\u0000\u0000\u0000"
+ end
+
+ it "uses the encoding from the given option for non-ascii encoding when multiple arguments passes" do
+ File.open(@filename, "w", encoding: Encoding::UTF_32LE) do |file|
+ file.write("h", "i").should == 8
+ end
+ File.binread(@filename).should == "h\u0000\u0000\u0000i\u0000\u0000\u0000"
+ end
+
+ it "ignores the 'bom|' prefix" do
+ File.open(@filename, "w", encoding: 'bom|utf-8') do |file|
+ file.write("hi")
+ end
+ File.binread(@filename).should == "hi"
end
it "raises a invalid byte sequence error if invalid bytes are being written" do
# pack "\xFEhi" to avoid utf-8 conflict
xFEhi = ([254].pack('C*') + 'hi').force_encoding('utf-8')
File.open(@filename, "w", encoding: Encoding::US_ASCII) do |file|
- -> { file.write(xFEhi) }.should raise_error(Encoding::InvalidByteSequenceError)
+ -> { file.write(xFEhi) }.should.raise(Encoding::InvalidByteSequenceError)
end
end
@@ -72,6 +126,20 @@ describe "IO#write on a file" do
res = "H#{ë}ll#{ö}"
File.binread(@filename).should == res.force_encoding(Encoding::BINARY)
end
+
+ platform_is_not :windows do
+ it "writes binary data if no encoding is given and multiple arguments passed" do
+ File.open(@filename, "w") do |file|
+ file.write("\x87".b, "ą") # 0x87 isn't a valid UTF-8 binary representation of a character
+ end
+ File.binread(@filename).bytes.should == [0x87, 0xC4, 0x85]
+
+ File.open(@filename, "w") do |file|
+ file.write("\x61".encode("utf-32le"), "ą")
+ end
+ File.binread(@filename).bytes.should == [0x61, 0x00, 0x00, 0x00, 0xC4, 0x85]
+ end
+ end
end
describe "IO.write" do
@@ -86,10 +154,38 @@ describe "IO.write" do
File.read(@filename).should == "\0\0hi"
end
+ it "requires mode to be specified in :open_args" do
+ -> {
+ IO.write(@filename, 'hi', open_args: [{encoding: Encoding::UTF_32LE, binmode: true}])
+ }.should.raise(IOError, "not opened for writing")
+
+ IO.write(@filename, 'hi', open_args: ["w", {encoding: Encoding::UTF_32LE, binmode: true}]).should == 8
+ IO.write(@filename, 'hi', open_args: [{encoding: Encoding::UTF_32LE, binmode: true, mode: "w"}]).should == 8
+ end
+
+ it "requires mode to be specified in :open_args even if flags option passed" do
+ -> {
+ IO.write(@filename, 'hi', open_args: [{encoding: Encoding::UTF_32LE, binmode: true, flags: File::CREAT}])
+ }.should.raise(IOError, "not opened for writing")
+
+ IO.write(@filename, 'hi', open_args: ["w", {encoding: Encoding::UTF_32LE, binmode: true, flags: File::CREAT}]).should == 8
+ IO.write(@filename, 'hi', open_args: [{encoding: Encoding::UTF_32LE, binmode: true, flags: File::CREAT, mode: "w"}]).should == 8
+ end
+
it "uses the given encoding and returns the number of bytes written" do
IO.write(@filename, 'hi', mode: "w", encoding: Encoding::UTF_32LE).should == 8
end
+ it "raises ArgumentError if encoding is specified in mode parameter and is given as :encoding option" do
+ -> {
+ IO.write(@filename, 'hi', mode: "w:UTF-16LE:UTF-16BE", encoding: Encoding::UTF_32LE)
+ }.should.raise(ArgumentError, "encoding specified twice")
+
+ -> {
+ IO.write(@filename, 'hi', mode: "w:UTF-16BE", encoding: Encoding::UTF_32LE)
+ }.should.raise(ArgumentError, "encoding specified twice")
+ end
+
it "writes the file with the permissions in the :perm parameter" do
rm_r @filename
IO.write(@filename, 'write :perm spec', mode: "w", perm: 0o755).should == 16
@@ -114,23 +210,39 @@ describe "IO.write" do
rm_r @fifo
end
- it "writes correctly" do
- thr = Thread.new do
- IO.read(@fifo)
- end
- begin
- string = "hi"
- IO.write(@fifo, string).should == string.length
- ensure
- thr.join
+ # rb_cloexec_open() is currently missing a retry on EINTR.
+ # @ioquatix is looking into fixing it. Quarantined until it's done.
+ quarantine! do
+ it "writes correctly" do
+ thr = Thread.new do
+ IO.read(@fifo)
+ end
+ begin
+ string = "hi"
+ IO.write(@fifo, string).should == string.length
+ ensure
+ thr.join
+ end
end
end
end
+
+ ruby_version_is ""..."4.0" do
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation given a path with a pipe" do
+ -> {
+ -> {
+ IO.write("|cat", "xxx")
+ }.should output_to_fd("xxx")
+ }.should complain(/IO process creation with a leading '\|'/)
+ end
+ end
end
end
describe "IO#write" do
it_behaves_like :io_write, :write
+ it_behaves_like :io_write_transcode, :write
it "accepts multiple arguments" do
IO.pipe do |r, w|
@@ -169,25 +281,23 @@ platform_is :windows do
end
end
-ruby_version_is "3.0" do
- describe "IO#write on STDOUT" do
- # https://bugs.ruby-lang.org/issues/14413
- platform_is_not :windows do
- it "raises SignalException SIGPIPE if the stream is closed instead of Errno::EPIPE like other IOs" do
- stderr_file = tmp("stderr")
- begin
- IO.popen([*ruby_exe, "-e", "loop { puts :ok }"], "r", err: stderr_file) do |io|
- io.gets.should == "ok\n"
- io.close
- end
- status = $?
- status.should_not.success?
- status.should.signaled?
- Signal.signame(status.termsig).should == 'PIPE'
- File.read(stderr_file).should.empty?
- ensure
- rm_r stderr_file
+describe "IO#write on STDOUT" do
+ # https://bugs.ruby-lang.org/issues/14413
+ platform_is_not :windows do
+ it "raises SignalException SIGPIPE if the stream is closed instead of Errno::EPIPE like other IOs" do
+ stderr_file = tmp("stderr")
+ begin
+ IO.popen([*ruby_exe, "-e", "loop { puts :ok }"], "r", err: stderr_file) do |io|
+ io.gets.should == "ok\n"
+ io.close
end
+ status = $?
+ status.should_not.success?
+ status.should.signaled?
+ Signal.signame(status.termsig).should == 'PIPE'
+ File.read(stderr_file).should.empty?
+ ensure
+ rm_r stderr_file
end
end
end
diff --git a/spec/ruby/core/kernel/Array_spec.rb b/spec/ruby/core/kernel/Array_spec.rb
index b4a8bb7599..063faf7097 100644
--- a/spec/ruby/core/kernel/Array_spec.rb
+++ b/spec/ruby/core/kernel/Array_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel" do
it "has private instance method Array()" do
- Kernel.should have_private_instance_method(:Array)
+ Kernel.private_instance_methods(false).should.include?(:Array)
end
end
@@ -77,14 +77,14 @@ describe :kernel_Array, shared: true do
obj = mock("Array() string")
obj.should_receive(:to_ary).and_return("string")
- -> { @object.send(@method, obj) }.should raise_error(TypeError)
+ -> { @object.send(@method, obj) }.should.raise(TypeError)
end
it "raises a TypeError if #to_a does not return an Array" do
obj = mock("Array() string")
obj.should_receive(:to_a).and_return("string")
- -> { @object.send(@method, obj) }.should raise_error(TypeError)
+ -> { @object.send(@method, obj) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/kernel/Complex_spec.rb b/spec/ruby/core/kernel/Complex_spec.rb
index 4f043526b8..92ce183cc8 100644
--- a/spec/ruby/core/kernel/Complex_spec.rb
+++ b/spec/ruby/core/kernel/Complex_spec.rb
@@ -1,4 +1,6 @@
require_relative '../../spec_helper'
+require_relative '../../shared/kernel/complex'
+require_relative 'fixtures/Complex'
describe "Kernel.Complex()" do
describe "when passed [Complex, Complex]" do
@@ -17,19 +19,19 @@ describe "Kernel.Complex()" do
describe "when passed [Integer, Integer]" do
it "returns a new Complex number" do
- Complex(1, 2).should be_an_instance_of(Complex)
+ Complex(1, 2).should.instance_of?(Complex)
Complex(1, 2).real.should == 1
Complex(1, 2).imag.should == 2
- Complex(-3, -5).should be_an_instance_of(Complex)
+ Complex(-3, -5).should.instance_of?(Complex)
Complex(-3, -5).real.should == -3
Complex(-3, -5).imag.should == -5
- Complex(3.5, -4.5).should be_an_instance_of(Complex)
+ Complex(3.5, -4.5).should.instance_of?(Complex)
Complex(3.5, -4.5).real.should == 3.5
Complex(3.5, -4.5).imag.should == -4.5
- Complex(bignum_value, 30).should be_an_instance_of(Complex)
+ Complex(bignum_value, 30).should.instance_of?(Complex)
Complex(bignum_value, 30).real.should == bignum_value
Complex(bignum_value, 30).imag.should == 30
end
@@ -39,26 +41,111 @@ describe "Kernel.Complex()" do
it "returns a new Complex number with 0 as the imaginary component" do
# Guard against the Mathn library
guard -> { !defined?(Math.rsqrt) } do
- Complex(1).should be_an_instance_of(Complex)
+ Complex(1).should.instance_of?(Complex)
Complex(1).imag.should == 0
Complex(1).real.should == 1
- Complex(-3).should be_an_instance_of(Complex)
+ Complex(-3).should.instance_of?(Complex)
Complex(-3).imag.should == 0
Complex(-3).real.should == -3
- Complex(-4.5).should be_an_instance_of(Complex)
+ Complex(-4.5).should.instance_of?(Complex)
Complex(-4.5).imag.should == 0
Complex(-4.5).real.should == -4.5
- Complex(bignum_value).should be_an_instance_of(Complex)
+ Complex(bignum_value).should.instance_of?(Complex)
Complex(bignum_value).imag.should == 0
Complex(bignum_value).real.should == bignum_value
end
end
end
- describe "when passed a String" do
+ describe "when passed [String]" do
+ it_behaves_like :kernel_complex, :Complex_method, KernelSpecs
+
+ context "invalid argument" do
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ Complex("79+4i".encode("UTF-16"))
+ }.should.raise(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
+ end
+
+ it "raises ArgumentError for unrecognised Strings" do
+ -> {
+ Complex("ruby")
+ }.should.raise(ArgumentError, 'invalid value for convert(): "ruby"')
+ end
+
+ it "raises ArgumentError for trailing garbage" do
+ -> {
+ Complex("79+4iruby")
+ }.should.raise(ArgumentError, 'invalid value for convert(): "79+4iruby"')
+ end
+
+ it "does not understand Float::INFINITY" do
+ -> {
+ Complex("Infinity")
+ }.should.raise(ArgumentError, 'invalid value for convert(): "Infinity"')
+
+ -> {
+ Complex("-Infinity")
+ }.should.raise(ArgumentError, 'invalid value for convert(): "-Infinity"')
+ end
+
+ it "does not understand Float::NAN" do
+ -> {
+ Complex("NaN")
+ }.should.raise(ArgumentError, 'invalid value for convert(): "NaN"')
+ end
+
+ it "does not understand a sequence of _" do
+ -> {
+ Complex("7__9+4__0i")
+ }.should.raise(ArgumentError, 'invalid value for convert(): "7__9+4__0i"')
+ end
+
+ it "does not allow null-byte" do
+ -> {
+ Complex("1-2i\0")
+ }.should.raise(ArgumentError, "string contains null byte")
+ end
+ end
+
+ context "invalid argument and exception: false passed" do
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ Complex("79+4i".encode("UTF-16"), exception: false)
+ }.should.raise(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
+ end
+
+ it "returns nil for unrecognised Strings" do
+ Complex("ruby", exception: false).should == nil
+ end
+
+ it "returns nil when trailing garbage" do
+ Complex("79+4iruby", exception: false).should == nil
+ end
+
+ it "returns nil for Float::INFINITY" do
+ Complex("Infinity", exception: false).should == nil
+ Complex("-Infinity", exception: false).should == nil
+ end
+
+ it "returns nil for Float::NAN" do
+ Complex("NaN", exception: false).should == nil
+ end
+
+ it "returns nil when there is a sequence of _" do
+ Complex("7__9+4__0i", exception: false).should == nil
+ end
+
+ it "returns nil when String contains null-byte" do
+ Complex("1-2i\0", exception: false).should == nil
+ end
+ end
+ end
+
+ describe "when passes [String, String]" do
it "needs to be reviewed for spec completeness"
end
@@ -73,7 +160,7 @@ describe "Kernel.Complex()" do
it "returns the passed argument" do
n = mock_numeric("unreal")
n.should_receive(:real?).any_number_of_times.and_return(false)
- Complex(n).should equal(n)
+ Complex(n).should.equal?(n)
end
end
@@ -82,8 +169,8 @@ describe "Kernel.Complex()" do
n = mock_numeric("real")
n.should_receive(:real?).any_number_of_times.and_return(true)
result = Complex(n)
- result.real.should equal(n)
- result.imag.should equal(0)
+ result.real.should.equal?(n)
+ result.imag.should.equal?(0)
end
end
@@ -98,7 +185,7 @@ describe "Kernel.Complex()" do
n2.should_receive(:real?).any_number_of_times.and_return(r2)
n2.should_receive(:*).with(Complex(0, 1)).and_return(n3)
n1.should_receive(:+).with(n3).and_return(n4)
- Complex(n1, n2).should equal(n4)
+ Complex(n1, n2).should.equal?(n4)
end
end
end
@@ -110,8 +197,8 @@ describe "Kernel.Complex()" do
n1.should_receive(:real?).any_number_of_times.and_return(true)
n2.should_receive(:real?).any_number_of_times.and_return(true)
result = Complex(n1, n2)
- result.real.should equal(n1)
- result.imag.should equal(n2)
+ result.real.should.equal?(n1)
+ result.imag.should.equal?(n2)
end
end
@@ -120,22 +207,22 @@ describe "Kernel.Complex()" do
n = mock("n")
c = Complex(0, 0)
n.should_receive(:to_c).and_return(c)
- Complex(n).should equal(c)
+ Complex(n).should.equal?(c)
end
end
describe "when passed a non-Numeric second argument" do
it "raises TypeError" do
- -> { Complex(:sym, :sym) }.should raise_error(TypeError)
- -> { Complex(0, :sym) }.should raise_error(TypeError)
+ -> { Complex(:sym, :sym) }.should.raise(TypeError)
+ -> { Complex(0, :sym) }.should.raise(TypeError)
end
end
describe "when passed nil" do
it "raises TypeError" do
- -> { Complex(nil) }.should raise_error(TypeError, "can't convert nil into Complex")
- -> { Complex(0, nil) }.should raise_error(TypeError, "can't convert nil into Complex")
- -> { Complex(nil, 0) }.should raise_error(TypeError, "can't convert nil into Complex")
+ -> { Complex(nil) }.should.raise(TypeError, "can't convert nil into Complex")
+ -> { Complex(0, nil) }.should.raise(TypeError, "can't convert nil into Complex")
+ -> { Complex(nil, 0) }.should.raise(TypeError, "can't convert nil into Complex")
end
end
@@ -154,7 +241,7 @@ describe "Kernel.Complex()" do
describe "and [non-Numeric, Numeric] argument" do
it "throws a TypeError" do
- -> { Complex(:sym, 0, exception: false) }.should raise_error(TypeError, "not a real")
+ -> { Complex(:sym, 0, exception: false) }.should.raise(TypeError, "not a real")
end
end
@@ -182,4 +269,8 @@ describe "Kernel.Complex()" do
end
end
end
+
+ it "freezes its result" do
+ Complex(1).frozen?.should == true
+ end
end
diff --git a/spec/ruby/core/kernel/Float_spec.rb b/spec/ruby/core/kernel/Float_spec.rb
index 015bcb33d6..f5566067ba 100644
--- a/spec/ruby/core/kernel/Float_spec.rb
+++ b/spec/ruby/core/kernel/Float_spec.rb
@@ -6,7 +6,7 @@ describe :kernel_float, shared: true do
float = 1.12
float2 = @object.send(:Float, float)
float2.should == float
- float2.should equal float
+ float2.should.equal? float
end
it "returns a Float for Fixnums" do
@@ -22,26 +22,26 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError for nil" do
- -> { @object.send(:Float, nil) }.should raise_error(TypeError)
+ -> { @object.send(:Float, nil) }.should.raise(TypeError)
end
it "returns the identical NaN for NaN" do
nan = nan_value
- nan.nan?.should be_true
+ nan.nan?.should == true
nan2 = @object.send(:Float, nan)
- nan2.nan?.should be_true
- nan2.should equal(nan)
+ nan2.nan?.should == true
+ nan2.should.equal?(nan)
end
it "returns the same Infinity for Infinity" do
infinity = infinity_value
infinity2 = @object.send(:Float, infinity)
infinity2.should == infinity_value
- infinity.should equal(infinity2)
+ infinity.should.equal?(infinity2)
end
it "converts Strings to floats without calling #to_f" do
- string = "10"
+ string = +"10"
string.should_not_receive(:to_f)
@object.send(:Float, string).should == 10.0
end
@@ -51,30 +51,30 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError for a String of word characters" do
- -> { @object.send(:Float, "float") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "float") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String with string in error message" do
- -> { @object.send(:Float, "foo") }.should raise_error(ArgumentError) { |e|
+ -> { @object.send(:Float, "foo") }.should.raise(ArgumentError) { |e|
e.message.should == 'invalid value for Float(): "foo"'
}
end
it "raises an ArgumentError if there are two decimal points in the String" do
- -> { @object.send(:Float, "10.0.0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "10.0.0") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String of numbers followed by word characters" do
- -> { @object.send(:Float, "10D") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "10D") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String of word characters followed by numbers" do
- -> { @object.send(:Float, "D10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "D10") }.should.raise(ArgumentError)
end
it "is strict about the string form even across newlines" do
- -> { @object.send(:Float, "not a number\n10") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "10\nnot a number") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "not a number\n10") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "10\nnot a number") }.should.raise(ArgumentError)
end
it "converts String subclasses to floats without calling #to_f" do
@@ -96,17 +96,17 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError if a + or - is embedded in a String" do
- -> { @object.send(:Float, "1+1") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "1-1") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1+1") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "1-1") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if a String has a trailing + or -" do
- -> { @object.send(:Float, "11+") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "11-") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "11+") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "11-") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String with a leading _" do
- -> { @object.send(:Float, "_1") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "_1") }.should.raise(ArgumentError)
end
it "returns a value for a String with an embedded _" do
@@ -114,31 +114,31 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError for a String with a trailing _" do
- -> { @object.send(:Float, "10_") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "10_") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String of \\0" do
- -> { @object.send(:Float, "\0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "\0") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String with a leading \\0" do
- -> { @object.send(:Float, "\01") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "\01") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String with an embedded \\0" do
- -> { @object.send(:Float, "1\01") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1\01") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String with a trailing \\0" do
- -> { @object.send(:Float, "1\0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1\0") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String that is just an empty space" do
- -> { @object.send(:Float, " ") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, " ") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a String that with an embedded space" do
- -> { @object.send(:Float, "1 2") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1 2") }.should.raise(ArgumentError)
end
it "returns a value for a String with a leading space" do
@@ -157,13 +157,33 @@ describe :kernel_float, shared: true do
@object.send(:Float, "1\t\n").should == 1.0
end
+ ruby_version_is ""..."3.4" do
+ it "raises ArgumentError if a fractional part is missing" do
+ -> { @object.send(:Float, "1.") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "+1.") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "-1.") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "1.e+0") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "1.e-2") }.should.raise(ArgumentError)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "allows String representation without a fractional part" do
+ @object.send(:Float, "1.").should == 1.0
+ @object.send(:Float, "+1.").should == 1.0
+ @object.send(:Float, "-1.").should == -1.0
+ @object.send(:Float, "1.e+0").should == 1.0
+ @object.send(:Float, "1.e-2").should be_close(0.01, TOLERANCE)
+ end
+ end
+
%w(e E).each do |e|
it "raises an ArgumentError if #{e} is the trailing character" do
- -> { @object.send(:Float, "2#{e}") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "2#{e}") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if #{e} is the leading character" do
- -> { @object.send(:Float, "#{e}2") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "#{e}2") }.should.raise(ArgumentError)
end
it "returns Infinity for '2#{e}1000'" do
@@ -181,18 +201,18 @@ describe :kernel_float, shared: true do
end
it "raises an exception if a space is embedded on either side of the '#{e}'" do
- -> { @object.send(:Float, "2 0#{e}100") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "20#{e}1 00") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "2 0#{e}100") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "20#{e}1 00") }.should.raise(ArgumentError)
end
it "raises an exception if there's a leading _ on either side of the '#{e}'" do
- -> { @object.send(:Float, "_20#{e}100") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "20#{e}_100") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "_20#{e}100") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "20#{e}_100") }.should.raise(ArgumentError)
end
it "raises an exception if there's a trailing _ on either side of the '#{e}'" do
- -> { @object.send(:Float, "20_#{e}100") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "20#{e}100_") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "20_#{e}100") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "20#{e}100_") }.should.raise(ArgumentError)
end
it "allows decimal points on the left side of the '#{e}'" do
@@ -200,63 +220,111 @@ describe :kernel_float, shared: true do
end
it "raises an ArgumentError if there's a decimal point on the right side of the '#{e}'" do
- -> { @object.send(:Float, "20#{e}2.0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "20#{e}2.0") }.should.raise(ArgumentError)
end
end
- describe "for hexadecimal literals with binary exponent" do
- %w(p P).each do |p|
- it "interprets the fractional part (on the left side of '#{p}') in hexadecimal" do
- @object.send(:Float, "0x10#{p}0").should == 16.0
- end
-
- it "interprets the exponent (on the right of '#{p}') in decimal" do
- @object.send(:Float, "0x1#{p}10").should == 1024.0
- end
-
- it "raises an ArgumentError if #{p} is the trailing character" do
- -> { @object.send(:Float, "0x1#{p}") }.should raise_error(ArgumentError)
- end
-
- it "raises an ArgumentError if #{p} is the leading character" do
- -> { @object.send(:Float, "0x#{p}1") }.should raise_error(ArgumentError)
- end
+ context "for hexadecimal literals" do
+ it "interprets the 0x prefix as hexadecimal" do
+ @object.send(:Float, "0x10").should == 16.0
+ @object.send(:Float, "0x0F").should == 15.0
+ @object.send(:Float, "0x0f").should == 15.0
+ end
- it "returns Infinity for '0x1#{p}10000'" do
- @object.send(:Float, "0x1#{p}10000").should == Float::INFINITY
- end
+ it "interprets negative hex value" do
+ @object.send(:Float, "-0x10").should == -16.0
+ end
- it "returns 0 for '0x1#{p}-10000'" do
- @object.send(:Float, "0x1#{p}-10000").should == 0
- end
+ it "accepts embedded _ if the number does not contain a-f" do
+ @object.send(:Float, "0x1_0").should == 16.0
+ end
- it "allows embedded _ in a number on either side of the #{p}" do
- @object.send(:Float, "0x1_0#{p}10").should == 16384.0
- @object.send(:Float, "0x10#{p}1_0").should == 16384.0
- @object.send(:Float, "0x1_0#{p}1_0").should == 16384.0
+ ruby_version_is ""..."3.4.3" do
+ it "does not accept embedded _ if the number contains a-f" do
+ -> { @object.send(:Float, "0x1_0a") }.should.raise(ArgumentError)
+ @object.send(:Float, "0x1_0a", exception: false).should == nil
end
+ end
- it "raises an exception if a space is embedded on either side of the '#{p}'" do
- -> { @object.send(:Float, "0x1 0#{p}10") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "0x10#{p}1 0") }.should raise_error(ArgumentError)
+ ruby_version_is "3.4.3" do
+ it "accepts embedded _ if the number contains a-f" do
+ @object.send(:Float, "0x1_0a").should == 0x10a.to_f
end
+ end
- it "raises an exception if there's a leading _ on either side of the '#{p}'" do
- -> { @object.send(:Float, "0x_10#{p}10") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "0x10#{p}_10") }.should raise_error(ArgumentError)
- end
+ it "does not accept _ before, after or inside the 0x prefix" do
+ -> { @object.send(:Float, "_0x10") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "0_x10") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "0x_10") }.should.raise(ArgumentError)
+ @object.send(:Float, "_0x10", exception: false).should == nil
+ @object.send(:Float, "0_x10", exception: false).should == nil
+ @object.send(:Float, "0x_10", exception: false).should == nil
+ end
- it "raises an exception if there's a trailing _ on either side of the '#{p}'" do
- -> { @object.send(:Float, "0x10_#{p}10") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "0x10#{p}10_") }.should raise_error(ArgumentError)
- end
+ it "parses negative hexadecimal string as negative float" do
+ @object.send(:Float, "-0x7b").should == -123.0
+ end
- it "allows hexadecimal points on the left side of the '#{p}'" do
- @object.send(:Float, "0x1.8#{p}0").should == 1.5
+ ruby_version_is "3.4" do
+ it "accepts a fractional part" do
+ @object.send(:Float, "0x0.8").should == 0.5
end
+ end
- it "raises an ArgumentError if there's a decimal point on the right side of the '#{p}'" do
- -> { @object.send(:Float, "0x1#{p}1.0") }.should raise_error(ArgumentError)
+ describe "with binary exponent" do
+ %w(p P).each do |p|
+ it "interprets the fractional part (on the left side of '#{p}') in hexadecimal" do
+ @object.send(:Float, "0x10#{p}0").should == 16.0
+ end
+
+ it "interprets the exponent (on the right of '#{p}') in decimal" do
+ @object.send(:Float, "0x1#{p}10").should == 1024.0
+ end
+
+ it "raises an ArgumentError if #{p} is the trailing character" do
+ -> { @object.send(:Float, "0x1#{p}") }.should.raise(ArgumentError)
+ end
+
+ it "raises an ArgumentError if #{p} is the leading character" do
+ -> { @object.send(:Float, "0x#{p}1") }.should.raise(ArgumentError)
+ end
+
+ it "returns Infinity for '0x1#{p}10000'" do
+ @object.send(:Float, "0x1#{p}10000").should == Float::INFINITY
+ end
+
+ it "returns 0 for '0x1#{p}-10000'" do
+ @object.send(:Float, "0x1#{p}-10000").should == 0
+ end
+
+ it "allows embedded _ in a number on either side of the #{p}" do
+ @object.send(:Float, "0x1_0#{p}10").should == 16384.0
+ @object.send(:Float, "0x10#{p}1_0").should == 16384.0
+ @object.send(:Float, "0x1_0#{p}1_0").should == 16384.0
+ end
+
+ it "raises an exception if a space is embedded on either side of the '#{p}'" do
+ -> { @object.send(:Float, "0x1 0#{p}10") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "0x10#{p}1 0") }.should.raise(ArgumentError)
+ end
+
+ it "raises an exception if there's a leading _ on either side of the '#{p}'" do
+ -> { @object.send(:Float, "0x_10#{p}10") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "0x10#{p}_10") }.should.raise(ArgumentError)
+ end
+
+ it "raises an exception if there's a trailing _ on either side of the '#{p}'" do
+ -> { @object.send(:Float, "0x10_#{p}10") }.should.raise(ArgumentError)
+ -> { @object.send(:Float, "0x10#{p}10_") }.should.raise(ArgumentError)
+ end
+
+ it "allows hexadecimal points on the left side of the '#{p}'" do
+ @object.send(:Float, "0x1.8#{p}0").should == 1.5
+ end
+
+ it "raises an ArgumentError if there's a decimal point on the right side of the '#{p}'" do
+ -> { @object.send(:Float, "0x1#{p}1.0") }.should.raise(ArgumentError)
+ end
end
end
end
@@ -276,34 +344,34 @@ describe :kernel_float, shared: true do
nan = nan_value
(nan_to_f = mock('NaN')).should_receive(:to_f).once.and_return(nan)
nan2 = @object.send(:Float, nan_to_f)
- nan2.nan?.should be_true
- nan2.should equal(nan)
+ nan2.nan?.should == true
+ nan2.should.equal?(nan)
end
- it "returns the identical Infinity if to_f is called and it returns Infinity" do
+ it "returns the identical Infinity if #to_f is called and it returns Infinity" do
infinity = infinity_value
(infinity_to_f = mock('Infinity')).should_receive(:to_f).once.and_return(infinity)
infinity2 = @object.send(:Float, infinity_to_f)
- infinity2.should equal(infinity)
+ infinity2.should.equal?(infinity)
end
it "raises a TypeError if #to_f is not provided" do
- -> { @object.send(:Float, mock('x')) }.should raise_error(TypeError)
+ -> { @object.send(:Float, mock('x')) }.should.raise(TypeError)
end
it "raises a TypeError if #to_f returns a String" do
(obj = mock('ha!')).should_receive(:to_f).once.and_return('ha!')
- -> { @object.send(:Float, obj) }.should raise_error(TypeError)
+ -> { @object.send(:Float, obj) }.should.raise(TypeError)
end
it "raises a TypeError if #to_f returns an Integer" do
(obj = mock('123')).should_receive(:to_f).once.and_return(123)
- -> { @object.send(:Float, obj) }.should raise_error(TypeError)
+ -> { @object.send(:Float, obj) }.should.raise(TypeError)
end
it "raises a RangeError when passed a Complex argument" do
c = Complex(2, 3)
- -> { @object.send(:Float, c) }.should raise_error(RangeError)
+ -> { @object.send(:Float, c) }.should.raise(RangeError)
end
describe "when passed exception: false" do
@@ -340,6 +408,6 @@ end
describe "Kernel#Float" do
it "is a private method" do
- Kernel.should have_private_instance_method(:Float)
+ Kernel.private_instance_methods(false).should.include?(:Float)
end
end
diff --git a/spec/ruby/core/kernel/Hash_spec.rb b/spec/ruby/core/kernel/Hash_spec.rb
index cbe098a8ac..ee16f56a90 100644
--- a/spec/ruby/core/kernel/Hash_spec.rb
+++ b/spec/ruby/core/kernel/Hash_spec.rb
@@ -13,7 +13,7 @@ end
describe "Kernel" do
it "has private instance method Hash()" do
- Kernel.should have_private_instance_method(:Hash)
+ Kernel.private_instance_methods(false).should.include?(:Hash)
end
end
@@ -43,14 +43,14 @@ describe :kernel_Hash, shared: true do
end
it "raises a TypeError if it doesn't respond to #to_hash" do
- -> { @object.send(@method, mock("")) }.should raise_error(TypeError)
+ -> { @object.send(@method, mock("")) }.should.raise(TypeError)
end
it "raises a TypeError if #to_hash does not return an Hash" do
obj = mock("Hash() string")
obj.should_receive(:to_hash).and_return("string")
- -> { @object.send(@method, obj) }.should raise_error(TypeError)
+ -> { @object.send(@method, obj) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/kernel/Integer_spec.rb b/spec/ruby/core/kernel/Integer_spec.rb
index 2c78e27428..978fd8ef08 100644
--- a/spec/ruby/core/kernel/Integer_spec.rb
+++ b/spec/ruby/core/kernel/Integer_spec.rb
@@ -14,7 +14,9 @@ describe :kernel_integer, shared: true do
obj = mock("object")
obj.should_receive(:to_int).and_return("1")
obj.should_receive(:to_i).and_return(nil)
- -> { Integer(obj) }.should raise_error(TypeError)
+ -> {
+ Integer(obj)
+ }.should raise_consistent_error(TypeError, "can't convert MockObject into Integer (MockObject#to_i gives nil)")
end
it "return a result of to_i when to_int does not return an Integer" do
@@ -24,13 +26,36 @@ describe :kernel_integer, shared: true do
Integer(obj).should == 42
end
+ it "returns a result of to_str" do
+ obj = mock("obj")
+ obj.should_receive(:to_str).and_return("1")
+
+ Integer(obj).should == 1
+ end
+
+ it "returns a result of to_int when both to_int and to_str are defined" do
+ obj = mock("obj")
+ obj.should_receive(:to_int).and_return(1)
+ obj.should_not_receive(:to_str)
+
+ Integer(obj).should == 1
+ end
+
+ it "returns a result of to_str when both to_str and to_i are defined" do
+ obj = mock("obj")
+ obj.should_receive(:to_str).and_return("1")
+ obj.should_not_receive(:to_i)
+
+ Integer(obj).should == 1
+ end
+
it "raises a TypeError when passed nil" do
- -> { Integer(nil) }.should raise_error(TypeError)
+ -> { Integer(nil) }.should.raise(TypeError, "can't convert nil into Integer")
end
it "returns an Integer object" do
- Integer(2).should be_an_instance_of(Integer)
- Integer(9**99).should be_an_instance_of(Integer)
+ Integer(2).should.instance_of?(Integer)
+ Integer(9**99).should.instance_of?(Integer)
end
it "truncates Floats" do
@@ -67,26 +92,32 @@ describe :kernel_integer, shared: true do
it "raises a TypeError if to_i returns a value that is not an Integer" do
obj = mock("object")
obj.should_receive(:to_i).and_return("1")
- -> { Integer(obj) }.should raise_error(TypeError)
+ -> {
+ Integer(obj)
+ }.should raise_consistent_error(TypeError, "can't convert MockObject into Integer (MockObject#to_i gives String)")
end
it "raises a TypeError if no to_int or to_i methods exist" do
obj = mock("object")
- -> { Integer(obj) }.should raise_error(TypeError)
+ -> {
+ Integer(obj)
+ }.should.raise(TypeError, "can't convert MockObject into Integer")
end
it "raises a TypeError if to_int returns nil and no to_i exists" do
obj = mock("object")
obj.should_receive(:to_i).and_return(nil)
- -> { Integer(obj) }.should raise_error(TypeError)
+ -> {
+ Integer(obj)
+ }.should raise_consistent_error(TypeError, "can't convert MockObject into Integer (MockObject#to_i gives nil)")
end
it "raises a FloatDomainError when passed NaN" do
- -> { Integer(nan_value) }.should raise_error(FloatDomainError)
+ -> { Integer(nan_value) }.should.raise(FloatDomainError)
end
it "raises a FloatDomainError when passed Infinity" do
- -> { Integer(infinity_value) }.should raise_error(FloatDomainError)
+ -> { Integer(infinity_value) }.should.raise(FloatDomainError)
end
describe "when passed exception: false" do
@@ -145,21 +176,21 @@ describe :kernel_integer, shared: true do
end
end
-describe "Integer() given a String", shared: true do
+describe :kernel_integer_string, shared: true do
it "raises an ArgumentError if the String is a null byte" do
- -> { Integer("\0") }.should raise_error(ArgumentError)
+ -> { Integer("\0") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the String starts with a null byte" do
- -> { Integer("\01") }.should raise_error(ArgumentError)
+ -> { Integer("\01") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the String ends with a null byte" do
- -> { Integer("1\0") }.should raise_error(ArgumentError)
+ -> { Integer("1\0") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the String contains a null byte" do
- -> { Integer("1\01") }.should raise_error(ArgumentError)
+ -> { Integer("1\01") }.should.raise(ArgumentError)
end
it "ignores leading whitespace" do
@@ -175,13 +206,13 @@ describe "Integer() given a String", shared: true do
end
it "raises an ArgumentError if there are leading _s" do
- -> { Integer("_1") }.should raise_error(ArgumentError)
- -> { Integer("___1") }.should raise_error(ArgumentError)
+ -> { Integer("_1") }.should.raise(ArgumentError)
+ -> { Integer("___1") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there are trailing _s" do
- -> { Integer("1_") }.should raise_error(ArgumentError)
- -> { Integer("1___") }.should raise_error(ArgumentError)
+ -> { Integer("1_") }.should.raise(ArgumentError)
+ -> { Integer("1___") }.should.raise(ArgumentError)
end
it "ignores an embedded _" do
@@ -189,8 +220,8 @@ describe "Integer() given a String", shared: true do
end
it "raises an ArgumentError if there are multiple embedded _s" do
- -> { Integer("1__1") }.should raise_error(ArgumentError)
- -> { Integer("1___1") }.should raise_error(ArgumentError)
+ -> { Integer("1__1") }.should.raise(ArgumentError)
+ -> { Integer("1___1") }.should.raise(ArgumentError)
end
it "ignores a single leading +" do
@@ -198,17 +229,17 @@ describe "Integer() given a String", shared: true do
end
it "raises an ArgumentError if there is a space between the + and number" do
- -> { Integer("+ 1") }.should raise_error(ArgumentError)
+ -> { Integer("+ 1") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there are multiple leading +s" do
- -> { Integer("++1") }.should raise_error(ArgumentError)
- -> { Integer("+++1") }.should raise_error(ArgumentError)
+ -> { Integer("++1") }.should.raise(ArgumentError)
+ -> { Integer("+++1") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there are trailing +s" do
- -> { Integer("1+") }.should raise_error(ArgumentError)
- -> { Integer("1+++") }.should raise_error(ArgumentError)
+ -> { Integer("1+") }.should.raise(ArgumentError)
+ -> { Integer("1+++") }.should.raise(ArgumentError)
end
it "makes the number negative if there's a leading -" do
@@ -216,21 +247,21 @@ describe "Integer() given a String", shared: true do
end
it "raises an ArgumentError if there are multiple leading -s" do
- -> { Integer("--1") }.should raise_error(ArgumentError)
- -> { Integer("---1") }.should raise_error(ArgumentError)
+ -> { Integer("--1") }.should.raise(ArgumentError)
+ -> { Integer("---1") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there are trailing -s" do
- -> { Integer("1-") }.should raise_error(ArgumentError)
- -> { Integer("1---") }.should raise_error(ArgumentError)
+ -> { Integer("1-") }.should.raise(ArgumentError)
+ -> { Integer("1---") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there is a period" do
- -> { Integer("0.0") }.should raise_error(ArgumentError)
+ -> { Integer("0.0") }.should.raise(ArgumentError)
end
it "raises an ArgumentError for an empty String" do
- -> { Integer("") }.should raise_error(ArgumentError)
+ -> { Integer("") }.should.raise(ArgumentError)
end
describe "when passed exception: false" do
@@ -280,7 +311,7 @@ describe "Integer() given a String", shared: true do
end
it "raises an ArgumentError if the number cannot be parsed as hex" do
- -> { Integer("0#{x}g") }.should raise_error(ArgumentError)
+ -> { Integer("0#{x}g") }.should.raise(ArgumentError)
end
end
@@ -301,7 +332,7 @@ describe "Integer() given a String", shared: true do
end
it "raises an ArgumentError if the number cannot be parsed as binary" do
- -> { Integer("0#{b}2") }.should raise_error(ArgumentError)
+ -> { Integer("0#{b}2") }.should.raise(ArgumentError)
end
end
@@ -322,7 +353,7 @@ describe "Integer() given a String", shared: true do
end
it "raises an ArgumentError if the number cannot be parsed as octal" do
- -> { Integer("0#{o}9") }.should raise_error(ArgumentError)
+ -> { Integer("0#{o}9") }.should.raise(ArgumentError)
end
end
@@ -343,26 +374,26 @@ describe "Integer() given a String", shared: true do
end
it "raises an ArgumentError if the number cannot be parsed as decimal" do
- -> { Integer("0#{d}a") }.should raise_error(ArgumentError)
+ -> { Integer("0#{d}a") }.should.raise(ArgumentError)
end
end
end
-describe "Integer() given a String and base", shared: true do
+describe :kernel_integer_string_base, shared: true do
it "raises an ArgumentError if the String is a null byte" do
- -> { Integer("\0", 2) }.should raise_error(ArgumentError)
+ -> { Integer("\0", 2) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the String starts with a null byte" do
- -> { Integer("\01", 3) }.should raise_error(ArgumentError)
+ -> { Integer("\01", 3) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the String ends with a null byte" do
- -> { Integer("1\0", 4) }.should raise_error(ArgumentError)
+ -> { Integer("1\0", 4) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the String contains a null byte" do
- -> { Integer("1\01", 5) }.should raise_error(ArgumentError)
+ -> { Integer("1\01", 5) }.should.raise(ArgumentError)
end
it "ignores leading whitespace" do
@@ -378,13 +409,13 @@ describe "Integer() given a String and base", shared: true do
end
it "raises an ArgumentError if there are leading _s" do
- -> { Integer("_1", 7) }.should raise_error(ArgumentError)
- -> { Integer("___1", 7) }.should raise_error(ArgumentError)
+ -> { Integer("_1", 7) }.should.raise(ArgumentError)
+ -> { Integer("___1", 7) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there are trailing _s" do
- -> { Integer("1_", 12) }.should raise_error(ArgumentError)
- -> { Integer("1___", 12) }.should raise_error(ArgumentError)
+ -> { Integer("1_", 12) }.should.raise(ArgumentError)
+ -> { Integer("1___", 12) }.should.raise(ArgumentError)
end
it "ignores an embedded _" do
@@ -392,8 +423,8 @@ describe "Integer() given a String and base", shared: true do
end
it "raises an ArgumentError if there are multiple embedded _s" do
- -> { Integer("1__1", 4) }.should raise_error(ArgumentError)
- -> { Integer("1___1", 4) }.should raise_error(ArgumentError)
+ -> { Integer("1__1", 4) }.should.raise(ArgumentError)
+ -> { Integer("1___1", 4) }.should.raise(ArgumentError)
end
it "ignores a single leading +" do
@@ -401,17 +432,17 @@ describe "Integer() given a String and base", shared: true do
end
it "raises an ArgumentError if there is a space between the + and number" do
- -> { Integer("+ 1", 3) }.should raise_error(ArgumentError)
+ -> { Integer("+ 1", 3) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there are multiple leading +s" do
- -> { Integer("++1", 3) }.should raise_error(ArgumentError)
- -> { Integer("+++1", 3) }.should raise_error(ArgumentError)
+ -> { Integer("++1", 3) }.should.raise(ArgumentError)
+ -> { Integer("+++1", 3) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there are trailing +s" do
- -> { Integer("1+", 3) }.should raise_error(ArgumentError)
- -> { Integer("1+++", 12) }.should raise_error(ArgumentError)
+ -> { Integer("1+", 3) }.should.raise(ArgumentError)
+ -> { Integer("1+++", 12) }.should.raise(ArgumentError)
end
it "makes the number negative if there's a leading -" do
@@ -419,29 +450,29 @@ describe "Integer() given a String and base", shared: true do
end
it "raises an ArgumentError if there are multiple leading -s" do
- -> { Integer("--1", 9) }.should raise_error(ArgumentError)
- -> { Integer("---1", 9) }.should raise_error(ArgumentError)
+ -> { Integer("--1", 9) }.should.raise(ArgumentError)
+ -> { Integer("---1", 9) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there are trailing -s" do
- -> { Integer("1-", 12) }.should raise_error(ArgumentError)
- -> { Integer("1---", 12) }.should raise_error(ArgumentError)
+ -> { Integer("1-", 12) }.should.raise(ArgumentError)
+ -> { Integer("1---", 12) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if there is a period" do
- -> { Integer("0.0", 3) }.should raise_error(ArgumentError)
+ -> { Integer("0.0", 3) }.should.raise(ArgumentError)
end
it "raises an ArgumentError for an empty String" do
- -> { Integer("", 12) }.should raise_error(ArgumentError)
+ -> { Integer("", 12) }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a base of 1" do
- -> { Integer("1", 1) }.should raise_error(ArgumentError)
+ -> { Integer("1", 1) }.should.raise(ArgumentError)
end
it "raises an ArgumentError for a base of 37" do
- -> { Integer("1", 37) }.should raise_error(ArgumentError)
+ -> { Integer("1", 37) }.should.raise(ArgumentError)
end
it "accepts wholly lowercase alphabetic strings for bases > 10" do
@@ -469,8 +500,8 @@ describe "Integer() given a String and base", shared: true do
end
it "raises an ArgumentError for letters invalid in the given base" do
- -> { Integer('z',19) }.should raise_error(ArgumentError)
- -> { Integer('c00o',2) }.should raise_error(ArgumentError)
+ -> { Integer('z',19) }.should.raise(ArgumentError)
+ -> { Integer('c00o',2) }.should.raise(ArgumentError)
end
%w(x X).each do |x|
@@ -491,12 +522,12 @@ describe "Integer() given a String and base", shared: true do
2.upto(15) do |base|
it "raises an ArgumentError if the number begins with 0#{x} and the base is #{base}" do
- -> { Integer("0#{x}1", base) }.should raise_error(ArgumentError)
+ -> { Integer("0#{x}1", base) }.should.raise(ArgumentError)
end
end
it "raises an ArgumentError if the number cannot be parsed as hex and the base is 16" do
- -> { Integer("0#{x}g", 16) }.should raise_error(ArgumentError)
+ -> { Integer("0#{x}g", 16) }.should.raise(ArgumentError)
end
end
@@ -517,7 +548,7 @@ describe "Integer() given a String and base", shared: true do
end
it "raises an ArgumentError if the number cannot be parsed as binary and the base is 2" do
- -> { Integer("0#{b}2", 2) }.should raise_error(ArgumentError)
+ -> { Integer("0#{b}2", 2) }.should.raise(ArgumentError)
end
end
@@ -538,12 +569,12 @@ describe "Integer() given a String and base", shared: true do
end
it "raises an ArgumentError if the number cannot be parsed as octal and the base is 8" do
- -> { Integer("0#{o}9", 8) }.should raise_error(ArgumentError)
+ -> { Integer("0#{o}9", 8) }.should.raise(ArgumentError)
end
2.upto(7) do |base|
it "raises an ArgumentError if the number begins with 0#{o} and the base is #{base}" do
- -> { Integer("0#{o}1", base) }.should raise_error(ArgumentError)
+ -> { Integer("0#{o}1", base) }.should.raise(ArgumentError)
end
end
end
@@ -565,18 +596,31 @@ describe "Integer() given a String and base", shared: true do
end
it "raises an ArgumentError if the number cannot be parsed as decimal and the base is 10" do
- -> { Integer("0#{d}a", 10) }.should raise_error(ArgumentError)
+ -> { Integer("0#{d}a", 10) }.should.raise(ArgumentError)
end
2.upto(9) do |base|
it "raises an ArgumentError if the number begins with 0#{d} and the base is #{base}" do
- -> { Integer("0#{d}1", base) }.should raise_error(ArgumentError)
+ -> { Integer("0#{d}1", base) }.should.raise(ArgumentError)
end
end
+ end
- it "raises an ArgumentError if a base is given for a non-String value" do
- -> { Integer(98, 15) }.should raise_error(ArgumentError)
- end
+ it "raises an ArgumentError if a base is given for a non-String value" do
+ -> { Integer(98, 15) }.should.raise(ArgumentError, "base specified for non string value")
+ end
+
+ it "tries to convert the base to an integer using to_int" do
+ obj = mock('8')
+ obj.should_receive(:to_int).and_return(8)
+
+ Integer("777", obj).should == 0777
+ end
+
+ it "raises a TypeError if it is not an integer and does not respond to #to_i" do
+ -> {
+ Integer("777", "8")
+ }.should.raise(TypeError, "no implicit conversion of String into Integer")
end
describe "when passed exception: false" do
@@ -599,176 +643,176 @@ end
describe :kernel_Integer, shared: true do
it "raises an ArgumentError when the String contains digits out of range of radix 2" do
str = "23456789abcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 2) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 2) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 3" do
str = "3456789abcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 3) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 3) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 4" do
str = "456789abcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 4) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 4) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 5" do
str = "56789abcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 5) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 5) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 6" do
str = "6789abcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 6) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 6) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 7" do
str = "789abcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 7) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 7) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 8" do
str = "89abcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 8) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 8) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 9" do
str = "9abcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 9) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 9) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 10" do
str = "abcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 10) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 10) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 11" do
str = "bcdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 11) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 11) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 12" do
str = "cdefghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 12) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 12) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 13" do
str = "defghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 13) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 13) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 14" do
str = "efghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 14) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 14) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 15" do
str = "fghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 15) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 15) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 16" do
str = "ghijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 16) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 16) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 17" do
str = "hijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 17) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 17) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 18" do
str = "ijklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 18) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 18) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 19" do
str = "jklmnopqrstuvwxyz"
- -> { @object.send(@method, str, 19) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 19) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 20" do
str = "klmnopqrstuvwxyz"
- -> { @object.send(@method, str, 20) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 20) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 21" do
str = "lmnopqrstuvwxyz"
- -> { @object.send(@method, str, 21) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 21) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 22" do
str = "mnopqrstuvwxyz"
- -> { @object.send(@method, str, 22) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 22) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 23" do
str = "nopqrstuvwxyz"
- -> { @object.send(@method, str, 23) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 23) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 24" do
str = "opqrstuvwxyz"
- -> { @object.send(@method, str, 24) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 24) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 25" do
str = "pqrstuvwxyz"
- -> { @object.send(@method, str, 25) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 25) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 26" do
str = "qrstuvwxyz"
- -> { @object.send(@method, str, 26) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 26) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 27" do
str = "rstuvwxyz"
- -> { @object.send(@method, str, 27) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 27) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 28" do
str = "stuvwxyz"
- -> { @object.send(@method, str, 28) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 28) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 29" do
str = "tuvwxyz"
- -> { @object.send(@method, str, 29) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 29) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 30" do
str = "uvwxyz"
- -> { @object.send(@method, str, 30) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 30) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 31" do
str = "vwxyz"
- -> { @object.send(@method, str, 31) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 31) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 32" do
str = "wxyz"
- -> { @object.send(@method, str, 32) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 32) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 33" do
str = "xyz"
- -> { @object.send(@method, str, 33) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 33) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 34" do
str = "yz"
- -> { @object.send(@method, str, 34) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 34) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 35" do
str = "z"
- -> { @object.send(@method, str, 35) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, str, 35) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the String contains digits out of range of radix 36" do
- -> { @object.send(@method, "{", 36) }.should raise_error(ArgumentError)
+ -> { @object.send(@method, "{", 36) }.should.raise(ArgumentError)
end
end
@@ -777,9 +821,9 @@ describe "Kernel.Integer" do
# TODO: fix these specs
it_behaves_like :kernel_integer, :Integer, Kernel
- it_behaves_like "Integer() given a String", :Integer
+ it_behaves_like :kernel_integer_string, :Integer
- it_behaves_like "Integer() given a String and base", :Integer
+ it_behaves_like :kernel_integer_string_base, :Integer
it "is a public method" do
Kernel.Integer(10).should == 10
@@ -791,11 +835,11 @@ describe "Kernel#Integer" do
# TODO: fix these specs
it_behaves_like :kernel_integer, :Integer, Object.new
- it_behaves_like "Integer() given a String", :Integer
+ it_behaves_like :kernel_integer_string, :Integer
- it_behaves_like "Integer() given a String and base", :Integer
+ it_behaves_like :kernel_integer_string_base, :Integer
it "is a private method" do
- Kernel.should have_private_instance_method(:Integer)
+ Kernel.private_instance_methods(false).should.include?(:Integer)
end
end
diff --git a/spec/ruby/core/kernel/Rational_spec.rb b/spec/ruby/core/kernel/Rational_spec.rb
index 2d1051db7f..b13ab4cf55 100644
--- a/spec/ruby/core/kernel/Rational_spec.rb
+++ b/spec/ruby/core/kernel/Rational_spec.rb
@@ -1,6 +1,236 @@
require_relative '../../spec_helper'
-require_relative '../../shared/rational/Rational'
+require_relative '../rational/fixtures/rational'
describe "Kernel.Rational" do
- it_behaves_like :kernel_Rational, :Rational
+ describe "passed Integer" do
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ it "returns a new Rational number with 1 as the denominator" do
+ Rational(1).should.eql?(Rational(1, 1))
+ Rational(-3).should.eql?(Rational(-3, 1))
+ Rational(bignum_value).should.eql?(Rational(bignum_value, 1))
+ end
+ end
+ end
+
+ describe "passed two integers" do
+ it "returns a new Rational number" do
+ rat = Rational(1, 2)
+ rat.numerator.should == 1
+ rat.denominator.should == 2
+ rat.should.instance_of?(Rational)
+
+ rat = Rational(-3, -5)
+ rat.numerator.should == 3
+ rat.denominator.should == 5
+ rat.should.instance_of?(Rational)
+
+ rat = Rational(bignum_value, 3)
+ rat.numerator.should == bignum_value
+ rat.denominator.should == 3
+ rat.should.instance_of?(Rational)
+ end
+
+ it "reduces the Rational" do
+ rat = Rational(2, 4)
+ rat.numerator.should == 1
+ rat.denominator.should == 2
+
+ rat = Rational(3, 9)
+ rat.numerator.should == 1
+ rat.denominator.should == 3
+ end
+ end
+
+ describe "when passed a String" do
+ it "converts the String to a Rational using the same method as String#to_r" do
+ r = Rational(13, 25)
+ s_r = ".52".to_r
+ r_s = Rational(".52")
+
+ r_s.should == r
+ r_s.should == s_r
+ end
+
+ it "scales the Rational value of the first argument by the Rational value of the second" do
+ Rational(".52", ".6").should == Rational(13, 15)
+ Rational(".52", "1.6").should == Rational(13, 40)
+ end
+
+ it "does not use the same method as Float#to_r" do
+ r = Rational(3, 5)
+ f_r = 0.6.to_r
+ r_s = Rational("0.6")
+
+ r_s.should == r
+ r_s.should_not == f_r
+ end
+ end
+
+ describe "when passed a Numeric" do
+ it "calls #to_r to convert the first argument to a Rational" do
+ num = RationalSpecs::SubNumeric.new(2)
+
+ Rational(num).should == Rational(2)
+ end
+ end
+
+ describe "when passed a Complex" do
+ context "[Complex]" do
+ it "returns a Rational from the real part if the imaginary part is 0" do
+ Rational(Complex(1, 0)).should == Rational(1)
+ end
+
+ it "raises a RangeError if the imaginary part is not 0" do
+ -> { Rational(Complex(1, 2)) }.should.raise(RangeError, "can't convert 1+2i into Rational")
+ end
+ end
+
+ context "[Numeric, Complex]" do
+ it "uses the real part if the imaginary part is 0" do
+ Rational(1, Complex(2, 0)).should == Rational(1, 2)
+ end
+
+ it "divides a numerator by the Complex denominator if the imaginary part is not 0" do
+ Rational(1, Complex(2, 1)).should == Complex(2/5r, -1/5r)
+ end
+ end
+ end
+
+ context "when passed neither a Numeric nor a String" do
+ it "converts to Rational with #to_r method" do
+ obj = Object.new
+ def obj.to_r; 1/2r; end
+
+ Rational(obj).should == 1/2r
+ end
+
+ it "tries to convert to Integer with #to_int method if it does not respond to #to_r" do
+ obj = Object.new
+ def obj.to_int; 1; end
+
+ Rational(obj).should == 1r
+ end
+
+ it "raises TypeError if it neither responds to #to_r nor #to_int method" do
+ -> { Rational([]) }.should.raise(TypeError, "can't convert Array into Rational")
+ -> { Rational({}) }.should.raise(TypeError, "can't convert Hash into Rational")
+ -> { Rational(nil) }.should.raise(TypeError, "can't convert nil into Rational")
+ end
+
+ it "swallows exception raised in #to_int method" do
+ object = Object.new
+ def object.to_int() raise NoMethodError; end
+
+ -> { Rational(object) }.should.raise(TypeError)
+ -> { Rational(object, 1) }.should.raise(TypeError)
+ -> { Rational(1, object) }.should.raise(TypeError)
+ end
+
+ it "raises TypeError if #to_r does not return Rational" do
+ obj = Object.new
+ def obj.to_r; []; end
+
+ -> { Rational(obj) }.should raise_consistent_error(TypeError, "can't convert Object into Rational (Object#to_r gives Array)")
+ end
+ end
+
+ it "raises a ZeroDivisionError if the second argument is 0" do
+ -> { Rational(1, 0) }.should.raise(ZeroDivisionError, "divided by 0")
+ -> { Rational(1, 0.0) }.should.raise(ZeroDivisionError, "divided by 0")
+ end
+
+ it "raises a TypeError if the first argument is nil" do
+ -> { Rational(nil) }.should.raise(TypeError, "can't convert nil into Rational")
+ end
+
+ it "raises a TypeError if the second argument is nil" do
+ -> { Rational(1, nil) }.should.raise(TypeError, "can't convert nil into Rational")
+ end
+
+ it "raises a TypeError if the first argument is a Symbol" do
+ -> { Rational(:sym) }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError if the second argument is a Symbol" do
+ -> { Rational(1, :sym) }.should.raise(TypeError)
+ end
+
+ describe "when passed exception: false" do
+ describe "and [non-Numeric]" do
+ it "swallows an error" do
+ Rational(:sym, exception: false).should == nil
+ Rational("abc", exception: false).should == nil
+ end
+
+ it "swallows an exception raised in #to_r" do
+ obj = Object.new
+ def obj.to_r; raise; end
+ Rational(obj, exception: false).should == nil
+ end
+
+ it "swallows an exception raised in #to_int" do
+ obj = Object.new
+ def obj.to_int; raise; end
+ Rational(obj, exception: false).should == nil
+ end
+ end
+
+ describe "and [non-Numeric, Numeric]" do
+ it "swallows an error" do
+ Rational(:sym, 1, exception: false).should == nil
+ Rational("abc", 1, exception: false).should == nil
+ end
+
+ it "swallows an exception raised in #to_r" do
+ obj = Object.new
+ def obj.to_r; raise; end
+ Rational(obj, 1, exception: false).should == nil
+ end
+
+ it "swallows an exception raised in #to_int" do
+ obj = Object.new
+ def obj.to_int; raise; end
+ Rational(obj, 1, exception: false).should == nil
+ end
+ end
+
+ describe "and [anything, non-Numeric]" do
+ it "swallows an error" do
+ Rational(:sym, :sym, exception: false).should == nil
+ Rational("abc", :sym, exception: false).should == nil
+ end
+
+ it "swallows an exception raised in #to_r" do
+ obj = Object.new
+ def obj.to_r; raise; end
+ Rational(obj, obj, exception: false).should == nil
+ end
+
+ it "swallows an exception raised in #to_int" do
+ obj = Object.new
+ def obj.to_int; raise; end
+ Rational(obj, obj, exception: false).should == nil
+ end
+ end
+
+ describe "and non-Numeric String arguments" do
+ it "swallows an error" do
+ Rational("a", "b", exception: false).should == nil
+ Rational("a", 0, exception: false).should == nil
+ Rational(0, "b", exception: false).should == nil
+ end
+ end
+
+ describe "and nil arguments" do
+ it "swallows an error" do
+ Rational(nil, exception: false).should == nil
+ Rational(nil, nil, exception: false).should == nil
+ end
+ end
+ end
+
+ it "freezes its result" do
+ Rational(1).frozen?.should == true
+ end
end
diff --git a/spec/ruby/core/kernel/String_spec.rb b/spec/ruby/core/kernel/String_spec.rb
index 47ee797be5..a9b0758ad7 100644
--- a/spec/ruby/core/kernel/String_spec.rb
+++ b/spec/ruby/core/kernel/String_spec.rb
@@ -32,7 +32,7 @@ describe :kernel_String, shared: true do
undef_method :to_s
end
- -> { @object.send(@method, obj) }.should raise_error(TypeError)
+ -> { @object.send(@method, obj) }.should.raise(TypeError)
end
# #5158
@@ -44,7 +44,7 @@ describe :kernel_String, shared: true do
end
end
- -> { @object.send(@method, obj) }.should raise_error(TypeError)
+ -> { @object.send(@method, obj) }.should.raise(TypeError)
end
it "raises a TypeError if #to_s is not defined, even though #respond_to?(:to_s) returns true" do
@@ -57,7 +57,7 @@ describe :kernel_String, shared: true do
end
end
- -> { @object.send(@method, obj) }.should raise_error(TypeError)
+ -> { @object.send(@method, obj) }.should.raise(TypeError)
end
it "calls #to_s if #respond_to?(:to_s) returns true" do
@@ -74,14 +74,14 @@ describe :kernel_String, shared: true do
it "raises a TypeError if #to_s does not return a String" do
(obj = mock('123')).should_receive(:to_s).and_return(123)
- -> { @object.send(@method, obj) }.should raise_error(TypeError)
+ -> { @object.send(@method, obj) }.should.raise(TypeError)
end
it "returns the same object if it is already a String" do
- string = "Hello"
+ string = +"Hello"
string.should_not_receive(:to_s)
string2 = @object.send(@method, string)
- string.should equal(string2)
+ string.should.equal?(string2)
end
it "returns the same object if it is an instance of a String subclass" do
@@ -89,7 +89,7 @@ describe :kernel_String, shared: true do
string = subklass.new("Hello")
string.should_not_receive(:to_s)
string2 = @object.send(@method, string)
- string.should equal(string2)
+ string.should.equal?(string2)
end
end
@@ -101,6 +101,6 @@ describe "Kernel#String" do
it_behaves_like :kernel_String, :String, Object.new
it "is a private method" do
- Kernel.should have_private_instance_method(:String)
+ Kernel.private_instance_methods(false).should.include?(:String)
end
end
diff --git a/spec/ruby/core/kernel/__dir___spec.rb b/spec/ruby/core/kernel/__dir___spec.rb
index 324792a408..242adbf48b 100644
--- a/spec/ruby/core/kernel/__dir___spec.rb
+++ b/spec/ruby/core/kernel/__dir___spec.rb
@@ -19,19 +19,9 @@ describe "Kernel#__dir__" do
end
end
- ruby_version_is ""..."3.0" do
- context "when used in eval with top level binding" do
- it "returns the real name of the directory containing the currently-executing file" do
- eval("__dir__", binding).should == File.realpath(File.dirname(__FILE__))
- end
- end
- end
-
- ruby_version_is "3.0" do
- context "when used in eval with top level binding" do
- it "returns nil" do
- eval("__dir__", binding).should == nil
- end
+ context "when used in eval with top level binding" do
+ it "returns nil" do
+ eval("__dir__", binding).should == nil
end
end
end
diff --git a/spec/ruby/core/kernel/abort_spec.rb b/spec/ruby/core/kernel/abort_spec.rb
index f8152718c5..b75138182d 100644
--- a/spec/ruby/core/kernel/abort_spec.rb
+++ b/spec/ruby/core/kernel/abort_spec.rb
@@ -4,7 +4,7 @@ require_relative '../../shared/process/abort'
describe "Kernel#abort" do
it "is a private method" do
- Kernel.should have_private_instance_method(:abort)
+ Kernel.private_instance_methods(false).should.include?(:abort)
end
it_behaves_like :process_abort, :abort, KernelSpecs::Method.new
diff --git a/spec/ruby/core/kernel/at_exit_spec.rb b/spec/ruby/core/kernel/at_exit_spec.rb
index a784c1ae17..fdb0eaf34c 100644
--- a/spec/ruby/core/kernel/at_exit_spec.rb
+++ b/spec/ruby/core/kernel/at_exit_spec.rb
@@ -1,67 +1,16 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../../shared/kernel/at_exit'
describe "Kernel.at_exit" do
- it "is a private method" do
- Kernel.should have_private_instance_method(:at_exit)
- end
-
- it "runs after all other code" do
- ruby_exe("at_exit {print 5}; print 6").should == "65"
- end
-
- it "runs in reverse order of registration" do
- code = "at_exit {print 4};at_exit {print 5}; print 6; at_exit {print 7}"
- ruby_exe(code).should == "6754"
- end
-
- it "allows calling exit inside at_exit handler" do
- code = "at_exit {print 3}; at_exit {print 4; exit; print 5}; at_exit {print 6}"
- ruby_exe(code).should == "643"
- end
-
- it "gives access to the last raised exception" do
- code = <<-EOC
- at_exit do
- puts "The exception matches: \#{$! == $exception} (message=\#{$!.message})"
- end
+ it_behaves_like :kernel_at_exit, :at_exit
- begin
- raise "foo"
- rescue => $exception
- raise
- end
- EOC
-
- result = ruby_exe(code, args: "2>&1", exit_status: 1)
- result.lines.should.include?("The exception matches: true (message=foo)\n")
- end
-
- it "both exceptions in at_exit and in the main script are printed" do
- code = 'at_exit { raise "at_exit_error" }; raise "main_script_error"'
- result = ruby_exe(code, args: "2>&1", exit_status: 1)
- result.should.include?('at_exit_error (RuntimeError)')
- result.should.include?('main_script_error (RuntimeError)')
- end
-
- it "decides the exit status if both at_exit and the main script raise SystemExit" do
- ruby_exe('at_exit { exit 43 }; exit 42', args: "2>&1", exit_status: 43)
- $?.exitstatus.should == 43
- end
-
- it "runs all at_exit even if some raise exceptions" do
- code = 'at_exit { STDERR.puts "last" }; at_exit { exit 43 }; at_exit { STDERR.puts "first" }; exit 42'
- result = ruby_exe(code, args: "2>&1", exit_status: 43)
- result.should == "first\nlast\n"
- $?.exitstatus.should == 43
+ it "is a private method" do
+ Kernel.private_instance_methods(false).should.include?(:at_exit)
end
- it "runs at_exit handlers even if the main script fails to parse" do
- script = fixture(__FILE__, "at_exit.rb")
- result = ruby_exe('{', options: "-r#{script}", args: "2>&1", exit_status: 1)
- $?.should_not.success?
- result.should.include?("at_exit ran\n")
- result.should.include?("syntax error")
+ it "raises ArgumentError if called without a block" do
+ -> { at_exit }.should.raise(ArgumentError, "called without a block")
end
end
diff --git a/spec/ruby/core/kernel/autoload_relative_spec.rb b/spec/ruby/core/kernel/autoload_relative_spec.rb
new file mode 100644
index 0000000000..7d03da8a40
--- /dev/null
+++ b/spec/ruby/core/kernel/autoload_relative_spec.rb
@@ -0,0 +1,114 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+# Specs for Kernel#autoload_relative
+
+ruby_version_is "4.1" do
+ describe "Kernel#autoload_relative" do
+ before :each do
+ @loaded_features = $".dup
+ end
+
+ after :each do
+ $".replace @loaded_features
+ # Clean up constants defined by these tests
+ [:KSAutoloadRelativeA, :KSAutoloadRelativeB, :KSAutoloadRelativeC,
+ :KSAutoloadRelativeE, :KSAutoloadRelativeF, :KSAutoloadRelativeG,
+ :KSAutoloadRelativeH, :KSAutoloadRelativeI].each do |const|
+ KernelSpecs.send(:remove_const, const) if KernelSpecs.const_defined?(const, false)
+ end
+ [:KSAutoloadRelativeD, :NestedTest].each do |const|
+ Object.send(:remove_const, const) if Object.const_defined?(const, false)
+ end
+ end
+
+ it "is a private method" do
+ Kernel.private_instance_methods(false).should.include?(:autoload_relative)
+ end
+
+ it "registers a file to load relative to the current file" do
+ KernelSpecs.autoload_relative :KSAutoloadRelativeA, "fixtures/autoload_relative_b.rb"
+ path = KernelSpecs.autoload?(:KSAutoloadRelativeA)
+ path.should_not == nil
+ path.should.end_with?("autoload_relative_b.rb")
+ File.exist?(path).should == true
+ end
+
+ it "loads the file when the constant is accessed" do
+ KernelSpecs.autoload_relative :KSAutoloadRelativeB, "fixtures/autoload_relative_b.rb"
+ KernelSpecs::KSAutoloadRelativeB.loaded.should == :ksautoload_b
+ end
+
+ it "sets the autoload constant in the constant table" do
+ KernelSpecs.autoload_relative :KSAutoloadRelativeC, "fixtures/autoload_relative_b.rb"
+ KernelSpecs.should.const_defined?(:KSAutoloadRelativeC, false)
+ end
+
+ it "can autoload in instance_eval with a file context" do
+ result = Object.new.instance_eval(<<-CODE, __FILE__, __LINE__)
+ autoload_relative :KSAutoloadRelativeD, "fixtures/autoload_relative_d.rb"
+ KSAutoloadRelativeD.loaded
+ CODE
+ result.should == :ksautoload_d
+ end
+
+ it "raises LoadError if called from eval without file context" do
+ -> {
+ eval('autoload_relative :Foo, "foo.rb"')
+ }.should.raise(LoadError, /autoload_relative called without file context/)
+ end
+
+ it "accepts both string and symbol for constant name" do
+ KernelSpecs.autoload_relative :KSAutoloadRelativeE, "fixtures/autoload_relative_b.rb"
+ KernelSpecs.autoload_relative "KSAutoloadRelativeF", "fixtures/autoload_relative_b.rb"
+
+ KernelSpecs.should.const_defined?(:KSAutoloadRelativeE, false)
+ KernelSpecs.should.const_defined?(:KSAutoloadRelativeF, false)
+ end
+
+ it "returns nil" do
+ KernelSpecs.autoload_relative(:KSAutoloadRelativeG, "fixtures/autoload_relative_b.rb").should == nil
+ end
+
+ it "resolves nested directory paths correctly" do
+ -> {
+ autoload_relative :NestedTest, "../kernel/fixtures/autoload_relative_b.rb"
+ autoload?(:NestedTest)
+ }.should_not.raise
+ end
+
+ it "resolves paths starting with ./" do
+ KernelSpecs.autoload_relative :KSAutoloadRelativeH, "./fixtures/autoload_relative_b.rb"
+ path = KernelSpecs.autoload?(:KSAutoloadRelativeH)
+ path.should_not == nil
+ path.should.end_with?("autoload_relative_b.rb")
+ end
+
+ it "ignores $LOAD_PATH and uses only relative path resolution" do
+ original_load_path = $LOAD_PATH.dup
+ $LOAD_PATH.clear
+ begin
+ KernelSpecs.autoload_relative :KSAutoloadRelativeI, "fixtures/autoload_relative_b.rb"
+ path = KernelSpecs.autoload?(:KSAutoloadRelativeI)
+ path.should_not == nil
+ # Should still resolve even with empty $LOAD_PATH
+ File.exist?(path).should == true
+ ensure
+ $LOAD_PATH.replace(original_load_path)
+ end
+ end
+
+ describe "when Object is frozen" do
+ it "raises a FrozenError before defining the constant" do
+ ruby_exe(<<-RUBY).should.include?("FrozenError")
+ Object.freeze
+ begin
+ autoload_relative :Foo, "autoload_b.rb"
+ rescue => e
+ puts e.class
+ end
+ RUBY
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/kernel/autoload_spec.rb b/spec/ruby/core/kernel/autoload_spec.rb
index 0404caec6d..46783734c4 100644
--- a/spec/ruby/core/kernel/autoload_spec.rb
+++ b/spec/ruby/core/kernel/autoload_spec.rb
@@ -7,7 +7,9 @@ require_relative 'fixtures/classes'
autoload :KSAutoloadA, "autoload_a.rb"
autoload :KSAutoloadB, fixture(__FILE__, "autoload_b.rb")
-autoload :KSAutoloadCallsRequire, "main_autoload_not_exist.rb"
+define_autoload_KSAutoloadCallsRequire = -> {
+ autoload :KSAutoloadCallsRequire, "main_autoload_not_exist.rb"
+}
def check_autoload(const)
autoload? const
@@ -23,7 +25,7 @@ describe "Kernel#autoload" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:autoload)
+ Kernel.private_instance_methods(false).should.include?(:autoload)
end
it "registers a file to load the first time the named constant is accessed" do
@@ -35,7 +37,7 @@ describe "Kernel#autoload" do
end
it "sets the autoload constant in Object's constant table" do
- Object.should have_constant(:KSAutoloadA)
+ Object.should.const_defined?(:KSAutoloadA, false)
end
it "loads the file when the constant is accessed" do
@@ -43,10 +45,11 @@ describe "Kernel#autoload" do
end
it "calls main.require(path) to load the file" do
+ define_autoload_KSAutoloadCallsRequire.call
main = TOPLEVEL_BINDING.eval("self")
main.should_receive(:require).with("main_autoload_not_exist.rb")
# The constant won't be defined since require is mocked to do nothing
- -> { KSAutoloadCallsRequire }.should raise_error(NameError)
+ -> { KSAutoloadCallsRequire }.should.raise(NameError)
end
it "can autoload in instance_eval" do
@@ -99,7 +102,7 @@ end
describe "Kernel#autoload?" do
it "is a private method" do
- Kernel.should have_private_instance_method(:autoload?)
+ Kernel.private_instance_methods(false).should.include?(:autoload?)
end
it "returns the name of the file that will be autoloaded" do
@@ -107,7 +110,7 @@ describe "Kernel#autoload?" do
end
it "returns nil if no file has been registered for a constant" do
- check_autoload(:Manualload).should be_nil
+ check_autoload(:Manualload).should == nil
end
end
@@ -134,7 +137,7 @@ describe "Kernel.autoload" do
end
it "sets the autoload constant in Object's constant table" do
- Object.should have_constant(:KSAutoloadBB)
+ Object.should.const_defined?(:KSAutoloadBB, false)
end
it "calls #to_path on non-String filenames" do
@@ -170,6 +173,6 @@ describe "Kernel.autoload?" do
end
it "returns nil if no file has been registered for a constant" do
- Kernel.autoload?(:Manualload).should be_nil
+ Kernel.autoload?(:Manualload).should == nil
end
end
diff --git a/spec/ruby/core/kernel/backtick_spec.rb b/spec/ruby/core/kernel/backtick_spec.rb
index 834d5636c1..42e0f975f5 100644
--- a/spec/ruby/core/kernel/backtick_spec.rb
+++ b/spec/ruby/core/kernel/backtick_spec.rb
@@ -11,7 +11,7 @@ describe "Kernel#`" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:`)
+ Kernel.private_instance_methods(false).should.include?(:`)
end
it "returns the standard output of the executed sub-process" do
@@ -28,11 +28,11 @@ describe "Kernel#`" do
it "produces a String in the default external encoding" do
Encoding.default_external = Encoding::SHIFT_JIS
- `echo disc`.encoding.should equal(Encoding::SHIFT_JIS)
+ `echo disc`.encoding.should.equal?(Encoding::SHIFT_JIS)
end
it "raises an Errno::ENOENT if the command is not executable" do
- -> { `nonexistent_command` }.should raise_error(Errno::ENOENT)
+ -> { `nonexistent_command` }.should.raise(Errno::ENOENT)
end
platform_is_not :windows do
@@ -43,13 +43,13 @@ describe "Kernel#`" do
it "sets $? to the exit status of the executed sub-process" do
ip = 'world'
`echo disc #{ip}`
- $?.should be_kind_of(Process::Status)
+ $?.should.is_a?(Process::Status)
$?.should_not.stopped?
$?.should.exited?
$?.exitstatus.should == 0
$?.should.success?
`echo disc #{ip}; exit 99`
- $?.should be_kind_of(Process::Status)
+ $?.should.is_a?(Process::Status)
$?.should_not.stopped?
$?.should.exited?
$?.exitstatus.should == 99
@@ -61,13 +61,13 @@ describe "Kernel#`" do
it "sets $? to the exit status of the executed sub-process" do
ip = 'world'
`echo disc #{ip}`
- $?.should be_kind_of(Process::Status)
+ $?.should.is_a?(Process::Status)
$?.should_not.stopped?
$?.should.exited?
$?.exitstatus.should == 0
$?.should.success?
`echo disc #{ip}& exit 99`
- $?.should be_kind_of(Process::Status)
+ $?.should.is_a?(Process::Status)
$?.should_not.stopped?
$?.should.exited?
$?.exitstatus.should == 99
diff --git a/spec/ruby/core/kernel/binding_spec.rb b/spec/ruby/core/kernel/binding_spec.rb
index f1c9c6ec9f..6f27b26f37 100644
--- a/spec/ruby/core/kernel/binding_spec.rb
+++ b/spec/ruby/core/kernel/binding_spec.rb
@@ -9,7 +9,7 @@ end
describe "Kernel#binding" do
it "is a private method" do
- Kernel.should have_private_instance_method(:binding)
+ Kernel.private_instance_methods(false).should.include?(:binding)
end
before :each do
@@ -35,7 +35,7 @@ describe "Kernel#binding" do
end
it "raises a NameError on undefined variable" do
- -> { eval("a_fake_variable", @b1) }.should raise_error(NameError)
+ -> { eval("a_fake_variable", @b1) }.should.raise(NameError)
end
it "uses the closure's self as self in the binding" do
diff --git a/spec/ruby/core/kernel/block_given_spec.rb b/spec/ruby/core/kernel/block_given_spec.rb
index b00bfabfc3..20bb90ae96 100644
--- a/spec/ruby/core/kernel/block_given_spec.rb
+++ b/spec/ruby/core/kernel/block_given_spec.rb
@@ -5,15 +5,20 @@ describe :kernel_block_given, shared: true do
it "returns true if and only if a block is supplied" do
@object.accept_block {}.should == true
@object.accept_block_as_argument {}.should == true
+ @object.accept_block_inside_block {}.should == true
+ @object.accept_block_as_argument_inside_block {}.should == true
@object.accept_block.should == false
@object.accept_block_as_argument.should == false
+ @object.accept_block_inside_block.should == false
+ @object.accept_block_as_argument_inside_block.should == false
end
# Clarify: Based on http://www.ruby-forum.com/topic/137822 it appears
# that Matz wanted this to be true in 1.9.
it "returns false when a method defined by define_method is called with a block" do
@object.defined_block {}.should == false
+ @object.defined_block_inside_block {}.should == false
end
end
@@ -25,7 +30,7 @@ describe "Kernel#block_given?" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:block_given?)
+ Kernel.private_instance_methods(false).should.include?(:block_given?)
end
end
diff --git a/spec/ruby/core/kernel/caller_locations_spec.rb b/spec/ruby/core/kernel/caller_locations_spec.rb
index 5994b28fa3..04cf806ef4 100644
--- a/spec/ruby/core/kernel/caller_locations_spec.rb
+++ b/spec/ruby/core/kernel/caller_locations_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/caller_locations'
describe 'Kernel#caller_locations' do
it 'is a private method' do
- Kernel.should have_private_instance_method(:caller_locations)
+ Kernel.private_instance_methods(false).should.include?(:caller_locations)
end
it 'returns an Array of caller locations' do
@@ -71,14 +71,43 @@ describe 'Kernel#caller_locations' do
end
guard -> { Kernel.instance_method(:tap).source_location } do
- it "includes core library methods defined in Ruby" do
- file, line = Kernel.instance_method(:tap).source_location
- file.should.start_with?('<internal:')
-
- loc = nil
- tap { loc = caller_locations(1, 1)[0] }
- loc.label.should == "tap"
- loc.path.should.start_with? "<internal:"
+ ruby_version_is ""..."3.4" do
+ it "includes core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
+
+ loc = nil
+ tap { loc = caller_locations(1, 1)[0] }
+ loc.label.should == "tap"
+ loc.path.should.start_with? "<internal:"
+ end
+ end
+
+ ruby_version_is "3.4"..."4.0" do
+ it "includes core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
+
+ loc = nil
+ tap { loc = caller_locations(1, 1)[0] }
+ loc.label.should == "Kernel#tap"
+ loc.path.should.start_with? "<internal:"
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "does not include core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
+
+ loc = nil
+ tap { loc = caller_locations(1, 1)[0] }
+ loc.label.should == "Kernel#tap"
+ # CRuby hides the file which defines the method: https://bugs.ruby-lang.org/issues/20968
+ unless loc.path == __FILE__
+ loc.path.should.start_with? "<internal:"
+ end
+ end
end
end
end
diff --git a/spec/ruby/core/kernel/caller_spec.rb b/spec/ruby/core/kernel/caller_spec.rb
index f1ff7044b8..225f6fc458 100644
--- a/spec/ruby/core/kernel/caller_spec.rb
+++ b/spec/ruby/core/kernel/caller_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/caller'
describe 'Kernel#caller' do
it 'is a private method' do
- Kernel.should have_private_instance_method(:caller)
+ Kernel.private_instance_methods(false).should.include?(:caller)
end
it 'returns an Array of caller locations' do
@@ -32,39 +32,90 @@ describe 'Kernel#caller' do
locations = KernelSpecs::CallerTest.locations
line = __LINE__ - 1
- locations[0].should include("#{__FILE__}:#{line}:in")
+ locations[0].should.include?("#{__FILE__}:#{line}:in")
end
it "returns an Array with the block given to #at_exit at the base of the stack" do
path = fixture(__FILE__, "caller_at_exit.rb")
lines = ruby_exe(path).lines
- lines.should == [
- "#{path}:6:in `foo'\n",
- "#{path}:2:in `block in <main>'\n"
- ]
+ lines.size.should == 2
+ lines[0].should =~ /\A#{path}:6:in [`'](?:Object#)?foo'\n\z/
+ lines[1].should =~ /\A#{path}:2:in [`']block in <main>'\n\z/
+ end
+
+ it "can be called with a range" do
+ locations1 = caller(0)
+ locations2 = caller(2..4)
+ locations1[2..4].should == locations2
end
it "works with endless ranges" do
locations1 = KernelSpecs::CallerTest.locations(0)
locations2 = KernelSpecs::CallerTest.locations(eval("(2..)"))
- locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
+ locations2.should == locations1[2..-1]
end
it "works with beginless ranges" do
locations1 = KernelSpecs::CallerTest.locations(0)
locations2 = KernelSpecs::CallerTest.locations((..5))
- locations2.map(&:to_s)[eval("(2..)")].should == locations1[(..5)].map(&:to_s)[eval("(2..)")]
+ locations2[eval("(2..)")].should == locations1[(..5)][eval("(2..)")]
+ end
+
+ it "can be called with a range whose end is negative" do
+ locations1 = caller(0)
+ locations2 = caller(2..-1)
+ locations3 = caller(2..-2)
+ locations1[2..-1].should == locations2
+ locations1[2..-2].should == locations3
+ end
+
+ it "must return nil if omitting more locations than available" do
+ caller(100).should == nil
+ caller(100..-1).should == nil
+ end
+
+ it "must return [] if omitting exactly the number of locations available" do
+ omit = caller(0).length
+ caller(omit).should == []
+ end
+
+ it "must return the same locations when called with 1..-1 and when called with no arguments" do
+ caller.should == caller(1..-1)
end
guard -> { Kernel.instance_method(:tap).source_location } do
- it "includes core library methods defined in Ruby" do
- file, line = Kernel.instance_method(:tap).source_location
- file.should.start_with?('<internal:')
-
- loc = nil
- tap { loc = caller(1, 1)[0] }
- loc.should.end_with? "in `tap'"
- loc.should.start_with? "<internal:"
+ ruby_version_is ""..."3.4" do
+ it "includes core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
+
+ loc = nil
+ tap { loc = caller(1, 1)[0] }
+ loc.should =~ /\A<internal:.*in `tap'\z/
+ end
+ end
+
+ ruby_version_is "3.4"..."4.0" do
+ it "includes core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
+
+ loc = nil
+ tap { loc = caller(1, 1)[0] }
+ loc.should =~ /\A<internal:.*in 'Kernel#tap'\z/
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "does not include core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
+
+ loc = nil
+ tap { loc = caller(1, 1)[0] }
+ # CRuby hides the file which defines the method: https://bugs.ruby-lang.org/issues/20968
+ loc.should =~ /\A(<internal:|#{__FILE__}:).*in 'Kernel#tap'\z/
+ end
end
end
end
diff --git a/spec/ruby/core/kernel/case_compare_spec.rb b/spec/ruby/core/kernel/case_compare_spec.rb
index b8d30960e8..c74bbf63b9 100644
--- a/spec/ruby/core/kernel/case_compare_spec.rb
+++ b/spec/ruby/core/kernel/case_compare_spec.rb
@@ -58,18 +58,18 @@ describe "Kernel#=== for a class with #== overridden to consider other object's
end
it "returns true if #== returns true even if #equal? is false" do
- @o1.should_not equal(@o2)
+ @o1.should_not.equal?(@o2)
(@o1 == @o2).should == true
(@o1 === @o2).should == true
end
it "returns true if #equal? returns true" do
- @o1.should equal(@o1)
+ @o1.should.equal?(@o1)
(@o1 === @o1).should == true
end
it "returns false if neither #== nor #equal? returns true" do
- @o1.should_not equal(@o)
+ @o1.should_not.equal?(@o)
(@o1 == @o).should == false
(@o1 === @o).should == false
end
@@ -83,13 +83,13 @@ describe "Kernel#=== for a class with #equal? overridden to always be false" do
end
it "returns true if #== returns true even if #equal? is false" do
- @o1.should_not equal(@o1)
+ @o1.should_not.equal?(@o1)
(@o1 == @o1).should == true
(@o1 === @o1).should == true
end
it "returns false if neither #== nor #equal? returns true" do
- @o1.should_not equal(@o)
+ @o1.should_not.equal?(@o)
(@o1 == @o).should == false
(@o1 === @o).should == false
end
@@ -105,7 +105,7 @@ describe "Kernel#=== for a class with #== and #equal? overridden to always be fa
it "returns true if the object id is the same even if both #== and #equal? return false" do
@o1.object_id.should == @o1.object_id
- @o1.should_not equal(@o1)
+ @o1.should_not.equal?(@o1)
(@o1 == @o1).should == false
(@o1 === @o1).should == true
@@ -114,7 +114,7 @@ describe "Kernel#=== for a class with #== and #equal? overridden to always be fa
it "returns false if the object id is not the same and both #== and #equal? return false" do
@o1.object_id.should_not == @o2.object_id
- @o1.should_not equal(@o2)
+ @o1.should_not.equal?(@o2)
(@o1 == @o2).should == false
(@o1 === @o2).should == false
diff --git a/spec/ruby/core/kernel/catch_spec.rb b/spec/ruby/core/kernel/catch_spec.rb
index 4060172429..9f02303678 100644
--- a/spec/ruby/core/kernel/catch_spec.rb
+++ b/spec/ruby/core/kernel/catch_spec.rb
@@ -31,11 +31,11 @@ describe "Kernel.catch" do
end
it "raises an ArgumentError if a Symbol is thrown for a String catch value" do
- -> { catch("exit") { throw :exit } }.should raise_error(ArgumentError)
+ -> { catch("exit") { throw :exit } }.should.raise(ArgumentError)
end
it "raises an ArgumentError if a String with different identity is thrown" do
- -> { catch("exit") { throw "exit" } }.should raise_error(ArgumentError)
+ -> { catch("exit".dup) { throw "exit".dup } }.should.raise(ArgumentError)
end
it "catches a Symbol when thrown a matching Symbol" do
@@ -60,7 +60,7 @@ describe "Kernel.catch" do
end
it "yields an object when called without arguments" do
- catch { |tag| tag }.should be_an_instance_of(Object)
+ catch { |tag| tag }.should.instance_of?(Object)
end
it "can be used even in a method different from where throw is called" do
@@ -116,12 +116,12 @@ describe "Kernel.catch" do
end
it "raises LocalJumpError if no block is given" do
- -> { catch :blah }.should raise_error(LocalJumpError)
+ -> { catch :blah }.should.raise(LocalJumpError)
end
end
describe "Kernel#catch" do
it "is a private method" do
- Kernel.should have_private_instance_method(:catch)
+ Kernel.private_instance_methods(false).should.include?(:catch)
end
end
diff --git a/spec/ruby/core/kernel/chomp_spec.rb b/spec/ruby/core/kernel/chomp_spec.rb
index d30e77c35a..434bf652f9 100644
--- a/spec/ruby/core/kernel/chomp_spec.rb
+++ b/spec/ruby/core/kernel/chomp_spec.rb
@@ -26,7 +26,7 @@ end
describe :kernel_chomp_private, shared: true do
it "is a private method" do
- KernelSpecs.has_private_method(@method).should be_true
+ KernelSpecs.has_private_method(@method).should == true
end
end
diff --git a/spec/ruby/core/kernel/chop_spec.rb b/spec/ruby/core/kernel/chop_spec.rb
index 9b91c011bc..bbf3c3f724 100644
--- a/spec/ruby/core/kernel/chop_spec.rb
+++ b/spec/ruby/core/kernel/chop_spec.rb
@@ -14,7 +14,7 @@ end
describe :kernel_chop_private, shared: true do
it "is a private method" do
- KernelSpecs.has_private_method(@method).should be_true
+ KernelSpecs.has_private_method(@method).should == true
end
end
diff --git a/spec/ruby/core/kernel/class_spec.rb b/spec/ruby/core/kernel/class_spec.rb
index 2725bde19b..0a7f774d14 100644
--- a/spec/ruby/core/kernel/class_spec.rb
+++ b/spec/ruby/core/kernel/class_spec.rb
@@ -3,24 +3,24 @@ require_relative 'fixtures/classes'
describe "Kernel#class" do
it "returns the class of the object" do
- Object.new.class.should equal(Object)
+ Object.new.class.should.equal?(Object)
- 1.class.should equal(Integer)
- 3.14.class.should equal(Float)
- :hello.class.should equal(Symbol)
- "hello".class.should equal(String)
- [1, 2].class.should equal(Array)
- { 1 => 2 }.class.should equal(Hash)
+ 1.class.should.equal?(Integer)
+ 3.14.class.should.equal?(Float)
+ :hello.class.should.equal?(Symbol)
+ "hello".class.should.equal?(String)
+ [1, 2].class.should.equal?(Array)
+ { 1 => 2 }.class.should.equal?(Hash)
end
it "returns Class for a class" do
- BasicObject.class.should equal(Class)
- String.class.should equal(Class)
+ BasicObject.class.should.equal?(Class)
+ String.class.should.equal?(Class)
end
it "returns the first non-singleton class" do
- a = "hello"
+ a = +"hello"
def a.my_singleton_method; end
- a.class.should equal(String)
+ a.class.should.equal?(String)
end
end
diff --git a/spec/ruby/core/kernel/clone_spec.rb b/spec/ruby/core/kernel/clone_spec.rb
index a87c7544fe..4ddb23d6e6 100644
--- a/spec/ruby/core/kernel/clone_spec.rb
+++ b/spec/ruby/core/kernel/clone_spec.rb
@@ -25,7 +25,7 @@ describe "Kernel#clone" do
end
clone = instance.clone
- clone.class.should equal klass
+ clone.class.should.equal? klass
end
describe "with no arguments" do
@@ -40,31 +40,23 @@ describe "Kernel#clone" do
it 'copies frozen?' do
o = ''.freeze.clone
- o.frozen?.should be_true
+ o.frozen?.should == true
end
end
describe "with freeze: nil" do
- ruby_version_is ""..."3.0" do
- it "raises ArgumentError" do
- -> { @obj.clone(freeze: nil) }.should raise_error(ArgumentError, /unexpected value for freeze: NilClass/)
- end
- end
-
- ruby_version_is "3.0" do
- it "copies frozen state from the original, like #clone without arguments" do
- o2 = @obj.clone(freeze: nil)
- o2.should_not.frozen?
+ it "copies frozen state from the original, like #clone without arguments" do
+ o2 = @obj.clone(freeze: nil)
+ o2.should_not.frozen?
- @obj.freeze
- o3 = @obj.clone(freeze: nil)
- o3.should.frozen?
- end
+ @obj.freeze
+ o3 = @obj.clone(freeze: nil)
+ o3.should.frozen?
+ end
- it "copies frozen?" do
- o = "".freeze.clone(freeze: nil)
- o.frozen?.should be_true
- end
+ it "copies frozen?" do
+ o = "".freeze.clone(freeze: nil)
+ o.frozen?.should == true
end
end
@@ -74,33 +66,19 @@ describe "Kernel#clone" do
@obj.clone(freeze: true).should.frozen?
end
- ruby_version_is ''...'3.0' do
- it 'does not freeze the copy even if the original is not frozen' do
- @obj.clone(freeze: true).should_not.frozen?
- end
-
- it "calls #initialize_clone with no kwargs" do
- obj = KernelSpecs::CloneFreeze.new
- obj.clone(freeze: true)
- ScratchPad.recorded.should == [obj, {}]
- end
+ it 'freezes the copy even if the original was not frozen' do
+ @obj.clone(freeze: true).should.frozen?
end
- ruby_version_is '3.0' do
- it 'freezes the copy even if the original was not frozen' do
- @obj.clone(freeze: true).should.frozen?
- end
-
- it "calls #initialize_clone with kwargs freeze: true" do
- obj = KernelSpecs::CloneFreeze.new
- obj.clone(freeze: true)
- ScratchPad.recorded.should == [obj, { freeze: true }]
- end
+ it "calls #initialize_clone with kwargs freeze: true" do
+ obj = KernelSpecs::CloneFreeze.new
+ obj.clone(freeze: true)
+ ScratchPad.recorded.should == [obj, { freeze: true }]
+ end
- it "calls #initialize_clone with kwargs freeze: true even if #initialize_clone only takes a single argument" do
- obj = KernelSpecs::Clone.new
- -> { obj.clone(freeze: true) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
- end
+ it "calls #initialize_clone with kwargs freeze: true even if #initialize_clone only takes a single argument" do
+ obj = KernelSpecs::Clone.new
+ -> { obj.clone(freeze: true) }.should.raise(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
end
end
@@ -114,33 +92,23 @@ describe "Kernel#clone" do
@obj.clone(freeze: false).should_not.frozen?
end
- ruby_version_is ''...'3.0' do
- it "calls #initialize_clone with no kwargs" do
- obj = KernelSpecs::CloneFreeze.new
- obj.clone(freeze: false)
- ScratchPad.recorded.should == [obj, {}]
- end
+ it "calls #initialize_clone with kwargs freeze: false" do
+ obj = KernelSpecs::CloneFreeze.new
+ obj.clone(freeze: false)
+ ScratchPad.recorded.should == [obj, { freeze: false }]
end
- ruby_version_is '3.0' do
- it "calls #initialize_clone with kwargs freeze: false" do
- obj = KernelSpecs::CloneFreeze.new
- obj.clone(freeze: false)
- ScratchPad.recorded.should == [obj, { freeze: false }]
- end
-
- it "calls #initialize_clone with kwargs freeze: false even if #initialize_clone only takes a single argument" do
- obj = KernelSpecs::Clone.new
- -> { obj.clone(freeze: false) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
- end
+ it "calls #initialize_clone with kwargs freeze: false even if #initialize_clone only takes a single argument" do
+ obj = KernelSpecs::Clone.new
+ -> { obj.clone(freeze: false) }.should.raise(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
end
end
describe "with freeze: anything else" do
it 'raises ArgumentError when passed not true/false/nil' do
- -> { @obj.clone(freeze: 1) }.should raise_error(ArgumentError, /unexpected value for freeze: Integer/)
- -> { @obj.clone(freeze: "") }.should raise_error(ArgumentError, /unexpected value for freeze: String/)
- -> { @obj.clone(freeze: Object.new) }.should raise_error(ArgumentError, /unexpected value for freeze: Object/)
+ -> { @obj.clone(freeze: 1) }.should.raise(ArgumentError, /unexpected value for freeze: Integer/)
+ -> { @obj.clone(freeze: "") }.should.raise(ArgumentError, /unexpected value for freeze: String/)
+ -> { @obj.clone(freeze: Object.new) }.should.raise(ArgumentError, /unexpected value for freeze: Object/)
end
end
diff --git a/spec/ruby/core/kernel/comparison_spec.rb b/spec/ruby/core/kernel/comparison_spec.rb
index affdc5c00d..48f17e1172 100644
--- a/spec/ruby/core/kernel/comparison_spec.rb
+++ b/spec/ruby/core/kernel/comparison_spec.rb
@@ -15,17 +15,17 @@ describe "Kernel#<=>" do
it "returns nil if self is eql? but not == to the argument" do
obj = mock('has eql?')
obj.should_not_receive(:eql?)
- obj.<=>(Object.new).should be_nil
+ obj.<=>(Object.new).should == nil
end
it "returns nil if self.==(arg) returns nil" do
obj = mock('wrong ==')
obj.should_receive(:==).and_return(nil)
- obj.<=>(Object.new).should be_nil
+ obj.<=>(Object.new).should == nil
end
it "returns nil if self is not == to the argument" do
obj = Object.new
- obj.<=>(3.14).should be_nil
+ obj.<=>(3.14).should == nil
end
end
diff --git a/spec/ruby/core/kernel/define_singleton_method_spec.rb b/spec/ruby/core/kernel/define_singleton_method_spec.rb
index 2d8b1bf413..ec48581db8 100644
--- a/spec/ruby/core/kernel/define_singleton_method_spec.rb
+++ b/spec/ruby/core/kernel/define_singleton_method_spec.rb
@@ -14,14 +14,14 @@ describe "Kernel#define_singleton_method" do
end
it "adds the new method to the methods list" do
- DefineSingletonMethodSpecClass.should have_method(:another_test_method)
+ DefineSingletonMethodSpecClass.should.respond_to?(:another_test_method)
end
it "defines any Child class method from any Parent's class methods" do
um = KernelSpecs::Parent.method(:parent_class_method).unbind
KernelSpecs::Child.send :define_singleton_method, :child_class_method, um
KernelSpecs::Child.child_class_method.should == :foo
- ->{KernelSpecs::Parent.child_class_method}.should raise_error(NoMethodError)
+ ->{KernelSpecs::Parent.child_class_method}.should.raise(NoMethodError)
end
it "will raise when attempting to define an object's singleton method from another object's singleton method" do
@@ -33,7 +33,7 @@ describe "Kernel#define_singleton_method" do
end
end
um = p.method(:singleton_method).unbind
- ->{ other.send :define_singleton_method, :other_singleton_method, um }.should raise_error(TypeError)
+ ->{ other.send :define_singleton_method, :other_singleton_method, um }.should.raise(TypeError)
end
end
@@ -52,11 +52,11 @@ describe "Kernel#define_singleton_method" do
it "raises a TypeError when the given method is no Method/Proc" do
-> {
Class.new { define_singleton_method(:test, "self") }
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
-> {
Class.new { define_singleton_method(:test, 1234) }
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "defines a new singleton method for objects" do
@@ -65,7 +65,7 @@ describe "Kernel#define_singleton_method" do
obj.test.should == "world!"
-> {
Object.new.test
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
it "maintains the Proc's scope" do
@@ -83,7 +83,7 @@ describe "Kernel#define_singleton_method" do
obj = Object.new
-> {
obj.define_singleton_method(:test)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "does not use the caller block when no block is given" do
@@ -94,7 +94,7 @@ describe "Kernel#define_singleton_method" do
-> {
o.define(:foo) { raise "not used" }
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "always defines the method with public visibility" do
@@ -109,6 +109,12 @@ describe "Kernel#define_singleton_method" do
cls.define(:foo) { :ok }
end
cls.foo.should == :ok
- }.should_not raise_error(NoMethodError)
+ }.should_not.raise(NoMethodError)
+ end
+
+ it "cannot define a singleton method with a frozen singleton class" do
+ o = Object.new
+ o.freeze
+ -> { o.define_singleton_method(:foo) { 1 } }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/kernel/dup_spec.rb b/spec/ruby/core/kernel/dup_spec.rb
index 70198abdb7..99de5e3732 100644
--- a/spec/ruby/core/kernel/dup_spec.rb
+++ b/spec/ruby/core/kernel/dup_spec.rb
@@ -25,7 +25,7 @@ describe "Kernel#dup" do
end
dup = instance.dup
- dup.class.should equal klass
+ dup.class.should.equal? klass
end
it "does not copy frozen state from the original" do
@@ -44,7 +44,7 @@ describe "Kernel#dup" do
it "does not copy singleton methods" do
def @obj.special() :the_one end
dup = @obj.dup
- -> { dup.special }.should raise_error(NameError)
+ -> { dup.special }.should.raise(NameError)
end
it "does not copy modules included in the singleton class" do
@@ -53,7 +53,7 @@ describe "Kernel#dup" do
end
dup = @obj.dup
- -> { dup.repr }.should raise_error(NameError)
+ -> { dup.repr }.should.raise(NameError)
end
it "does not copy constants defined in the singleton class" do
@@ -62,6 +62,6 @@ describe "Kernel#dup" do
end
dup = @obj.dup
- -> { class << dup; CLONE; end }.should raise_error(NameError)
+ -> { class << dup; CLONE; end }.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/kernel/eql_spec.rb b/spec/ruby/core/kernel/eql_spec.rb
index e62a601a79..b3289090e5 100644
--- a/spec/ruby/core/kernel/eql_spec.rb
+++ b/spec/ruby/core/kernel/eql_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../shared/kernel/equal'
describe "Kernel#eql?" do
it "is a public instance method" do
- Kernel.should have_public_instance_method(:eql?)
+ Kernel.public_instance_methods(false).should.include?(:eql?)
end
it_behaves_like :object_equal, :eql?
diff --git a/spec/ruby/core/kernel/eval_spec.rb b/spec/ruby/core/kernel/eval_spec.rb
index 9be0f2dfd3..f9ca47866e 100644
--- a/spec/ruby/core/kernel/eval_spec.rb
+++ b/spec/ruby/core/kernel/eval_spec.rb
@@ -5,7 +5,7 @@ EvalSpecs::A.new.c
describe "Kernel#eval" do
it "is a private method" do
- Kernel.should have_private_instance_method(:eval)
+ Kernel.private_instance_methods(false).should.include?(:eval)
end
it "is a module function" do
@@ -76,12 +76,12 @@ describe "Kernel#eval" do
x = 1
bind = proc {}
- -> { eval("x", bind) }.should raise_error(TypeError)
+ -> { eval("x", bind) }.should.raise(TypeError)
end
it "does not make Proc locals visible to evaluated code" do
bind = proc { inner = 4 }
- -> { eval("inner", bind.binding) }.should raise_error(NameError)
+ -> { eval("inner", bind.binding) }.should.raise(NameError)
end
# REWRITE ME: This obscures the real behavior of where locals are stored
@@ -119,7 +119,7 @@ describe "Kernel#eval" do
outer_binding = binding
eval("if false; a = 1; end", outer_binding)
- eval("a", outer_binding).should be_nil
+ eval("a", outer_binding).should == nil
end
it "allows creating a new class in a binding" do
@@ -135,8 +135,8 @@ describe "Kernel#eval" do
it "includes file and line information in syntax error" do
expected = 'speccing.rb'
-> {
- eval('if true',TOPLEVEL_BINDING, expected)
- }.should raise_error(SyntaxError) { |e|
+ eval('if true', TOPLEVEL_BINDING, expected)
+ }.should.raise(SyntaxError) { |e|
e.message.should =~ /#{expected}:1:.+/
}
end
@@ -144,8 +144,8 @@ describe "Kernel#eval" do
it "evaluates string with given filename and negative linenumber" do
expected_file = 'speccing.rb'
-> {
- eval('if true',TOPLEVEL_BINDING, expected_file, -100)
- }.should raise_error(SyntaxError) { |e|
+ eval('if true', TOPLEVEL_BINDING, expected_file, -100)
+ }.should.raise(SyntaxError) { |e|
e.message.should =~ /#{expected_file}:-100:.+/
}
end
@@ -159,39 +159,88 @@ describe "Kernel#eval" do
end
end
- ruby_version_is ""..."3.0" do
- it "uses the filename of the binding if none is provided" do
- eval("__FILE__").should == "(eval)"
- suppress_warning {eval("__FILE__", binding)}.should == __FILE__
- eval("__FILE__", binding, "success").should == "success"
- suppress_warning {eval("eval '__FILE__', binding")}.should == "(eval)"
- suppress_warning {eval("eval '__FILE__', binding", binding)}.should == __FILE__
- suppress_warning {eval("eval '__FILE__', binding", binding, 'success')}.should == 'success'
+ context "parameter forwarding" do
+ it "allows anonymous rest parameter forwarding" do
+ object = Object.new
+ def object.foo(a, b, c)
+ [a, b, c]
+ end
+ def object.bar(*)
+ eval "foo(*)"
+ end
+
+ object.bar(1, 2, 3).should == [1, 2, 3]
end
- it 'uses the given binding file and line for __FILE__ and __LINE__' do
- suppress_warning {
- eval("[__FILE__, __LINE__]", binding).should == [__FILE__, __LINE__]
- }
+ it "allows anonymous keyword parameters forwarding" do
+ object = Object.new
+ def object.foo(a:, b:, c:)
+ [a, b, c]
+ end
+ def object.bar(**)
+ eval "foo(**)"
+ end
+
+ object.bar(a: 1, b: 2, c: 3).should == [1, 2, 3]
end
- end
- ruby_version_is "3.0" do
- it "uses (eval) filename if none is provided" do
- eval("__FILE__").should == "(eval)"
- eval("__FILE__", binding).should == "(eval)"
- eval("__FILE__", binding, "success").should == "success"
- eval("eval '__FILE__', binding").should == "(eval)"
- eval("eval '__FILE__', binding", binding).should == "(eval)"
- eval("eval '__FILE__', binding", binding, 'success').should == '(eval)'
- eval("eval '__FILE__', binding, 'success'", binding).should == 'success'
+ it "allows anonymous block parameter forwarding" do
+ object = Object.new
+ def object.foo(&block)
+ block.call
+ end
+ def object.bar(&)
+ eval "foo(&)"
+ end
+
+ object.bar { :foobar }.should == :foobar
end
- it 'uses (eval) for __FILE__ and 1 for __LINE__ with a binding argument' do
- eval("[__FILE__, __LINE__]", binding).should == ["(eval)", 1]
+ it "allows ... forwarding" do
+ object = Object.new
+ def object.foo(a, b:, &block)
+ [a, b, block.call]
+ end
+ def object.bar(...)
+ eval "foo(...)"
+ end
+
+ object.bar(1, b: 2) { 3 }.should == [1, 2, 3]
+ end
+
+ it "allows parameter forwarding to super" do
+ m = Module.new do
+ def foo(a, b:, &block)
+ [a, b, block.call]
+ end
+ end
+
+ c = Class.new do
+ include m
+
+ def foo(a, b:, &block)
+ eval "super"
+ end
+ end
+
+ object = c.new
+ object.foo(1, b: 2) { 3 }.should == [1, 2, 3]
end
end
+ it "uses (eval at __FILE__:__LINE__) if none is provided" do
+ eval("__FILE__").should == "(eval at #{__FILE__}:#{__LINE__})"
+ eval("__FILE__", binding).should == "(eval at #{__FILE__}:#{__LINE__})"
+ eval("__FILE__", binding, "success").should == "success"
+ eval("eval '__FILE__', binding").should == "(eval at (eval at #{__FILE__}:#{__LINE__}):1)"
+ eval("eval '__FILE__', binding", binding).should == "(eval at (eval at #{__FILE__}:#{__LINE__}):1)"
+ eval("eval '__FILE__', binding", binding, 'success').should == "(eval at success:1)"
+ eval("eval '__FILE__', binding, 'success'", binding).should == 'success'
+ end
+
+ it 'uses (eval at __FILE__:__LINE__) for __FILE__ and 1 for __LINE__ with a binding argument' do
+ eval("[__FILE__, __LINE__]", binding).should == ["(eval at #{__FILE__}:#{__LINE__})", 1]
+ end
# Found via Rubinius bug github:#149
it "does not alter the value of __FILE__ in the binding" do
first_time = EvalSpecs.call_eval
@@ -214,20 +263,34 @@ describe "Kernel#eval" do
# See http://jira.codehaus.org/browse/JRUBY-5163
it "uses the receiver as self inside the eval" do
- eval("self").should equal(self)
- Kernel.eval("self").should equal(Kernel)
+ eval("self").should.equal?(self)
+ Kernel.eval("self").should.equal?(Kernel)
end
it "does not pass the block to the method being eval'ed" do
-> {
eval('KernelSpecs::EvalTest.call_yield') { "content" }
- }.should raise_error(LocalJumpError)
+ }.should.raise(LocalJumpError)
end
it "returns from the scope calling #eval when evaluating 'return'" do
-> { eval("return :eval") }.call.should == :eval
end
+ it "returns from the method calling #eval when evaluating 'return'" do
+ def eval_return(n)
+ eval("return n*2")
+ end
+ -> { eval_return(3) }.call.should == 6
+ end
+
+ it "returns from the method calling #eval when evaluating 'return' in BEGIN" do
+ def eval_return(n)
+ eval("BEGIN {return n*3}")
+ end
+ -> { eval_return(4) }.call.should == 12
+ end
+
it "unwinds through a Proc-style closure and returns from a lambda-style closure in the closure chain" do
code = fixture __FILE__, "eval_return_with_lambda.rb"
ruby_exe(code).chomp.should == "a,b,c,eval,f"
@@ -245,7 +308,40 @@ describe "Kernel#eval" do
it "has the correct default definee when called through Method#call" do
class EvalSpecs
method(:eval).call("def eval_spec_method_call; end")
- EvalSpecs.should have_instance_method(:eval_spec_method_call)
+ EvalSpecs.should.method_defined?(:eval_spec_method_call, false)
+ end
+ end
+
+ it "makes flip-flop operator work correctly" do
+ ScratchPad.record []
+
+ eval "10.times { |i| ScratchPad << i if (i == 4)...(i == 4) }"
+ ScratchPad.recorded.should == [4, 5, 6, 7, 8, 9]
+
+ ScratchPad.clear
+ end
+
+ it "returns nil if given an empty string" do
+ eval("").should == nil
+ end
+
+ context "with shebang" do
+ it "ignores shebang with ruby interpreter" do
+ pid = eval(<<~CODE.b)
+ #!/usr/bin/env ruby
+ Process.pid
+ CODE
+
+ pid.should == Process.pid
+ end
+
+ it "ignores shebang with non-ruby interpreter" do
+ pid = eval(<<~CODE.b)
+ #!/usr/bin/env puma
+ Process.pid
+ CODE
+
+ pid.should == Process.pid
end
end
@@ -266,8 +362,10 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπ")
+ EvalSpecs.constants(false).should.include?(:"Vπ")
EvalSpecs::Vπ.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπ)
end
it "allows an emacs-style magic comment encoding" do
@@ -279,8 +377,10 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπemacs")
+ EvalSpecs.constants(false).should.include?(:"Vπemacs")
EvalSpecs::Vπemacs.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπemacs)
end
it "allows spaces before the magic encoding comment" do
@@ -292,8 +392,10 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπspaces")
+ EvalSpecs.constants(false).should.include?(:"Vπspaces")
EvalSpecs::Vπspaces.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπspaces)
end
it "allows a shebang line before the magic encoding comment" do
@@ -306,8 +408,10 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπshebang")
+ EvalSpecs.constants(false).should.include?(:"Vπshebang")
EvalSpecs::Vπshebang.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπshebang)
end
it "allows a shebang line and some spaces before the magic encoding comment" do
@@ -320,27 +424,30 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπshebang_spaces")
+ EvalSpecs.constants(false).should.include?(:"Vπshebang_spaces")
EvalSpecs::Vπshebang_spaces.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπshebang_spaces)
end
it "allows a magic encoding comment and a subsequent frozen_string_literal magic comment" do
- # Make sure frozen_string_literal is not default true
- eval("'foo'".b).frozen?.should be_false
+ frozen_string_default = "test".frozen?
code = <<CODE.b
# encoding: UTF-8
-# frozen_string_literal: true
+# frozen_string_literal: #{!frozen_string_default}
class EvalSpecs
Vπstring = "frozen"
end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπstring")
+ EvalSpecs.constants(false).should.include?(:"Vπstring")
EvalSpecs::Vπstring.should == "frozen"
EvalSpecs::Vπstring.encoding.should == Encoding::UTF_8
- EvalSpecs::Vπstring.frozen?.should be_true
+ EvalSpecs::Vπstring.frozen?.should == !frozen_string_default
+ ensure
+ EvalSpecs.send(:remove_const, :Vπstring)
end
it "allows a magic encoding comment and a frozen_string_literal magic comment on the same line in emacs style" do
@@ -352,15 +459,18 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπsame_line")
+ EvalSpecs.constants(false).should.include?(:"Vπsame_line")
EvalSpecs::Vπsame_line.should == "frozen"
EvalSpecs::Vπsame_line.encoding.should == Encoding::UTF_8
- EvalSpecs::Vπsame_line.frozen?.should be_true
+ EvalSpecs::Vπsame_line.frozen?.should == true
+ ensure
+ EvalSpecs.send(:remove_const, :Vπsame_line)
end
it "ignores the magic encoding comment if it is after a frozen_string_literal magic comment" do
+ frozen_string_default = "test".frozen?
code = <<CODE.b
-# frozen_string_literal: true
+# frozen_string_literal: #{!frozen_string_default}
# encoding: UTF-8
class EvalSpecs
Vπfrozen_first = "frozen"
@@ -368,29 +478,32 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should_not include(:"Vπfrozen_first")
+ EvalSpecs.constants(false).should_not.include?(:"Vπfrozen_first")
binary_constant = "Vπfrozen_first".b.to_sym
- EvalSpecs.constants(false).should include(binary_constant)
+ EvalSpecs.constants(false).should.include?(binary_constant)
value = EvalSpecs.const_get(binary_constant)
value.should == "frozen"
value.encoding.should == Encoding::BINARY
- value.frozen?.should be_true
+ value.frozen?.should == !frozen_string_default
+ ensure
+ EvalSpecs.send(:remove_const, binary_constant)
end
it "ignores the frozen_string_literal magic comment if it appears after a token and warns if $VERBOSE is true" do
+ frozen_string_default = "test".frozen?
code = <<CODE
some_token_before_magic_comment = :anything
-# frozen_string_literal: true
+# frozen_string_literal: #{!frozen_string_default}
class EvalSpecs
Vπstring_not_frozen = "not frozen"
end
CODE
- -> { eval(code) }.should complain(/warning: `frozen_string_literal' is ignored after any tokens/, verbose: true)
- EvalSpecs::Vπstring_not_frozen.frozen?.should be_false
+ -> { eval(code) }.should complain(/warning: [`']frozen_string_literal' is ignored after any tokens/, verbose: true)
+ EvalSpecs::Vπstring_not_frozen.frozen?.should == frozen_string_default
EvalSpecs.send :remove_const, :Vπstring_not_frozen
-> { eval(code) }.should_not complain(verbose: false)
- EvalSpecs::Vπstring_not_frozen.frozen?.should be_false
+ EvalSpecs::Vπstring_not_frozen.frozen?.should == frozen_string_default
EvalSpecs.send :remove_const, :Vπstring_not_frozen
end
end
diff --git a/spec/ruby/core/kernel/exec_spec.rb b/spec/ruby/core/kernel/exec_spec.rb
index 1b4a7ae6f4..fd8485791a 100644
--- a/spec/ruby/core/kernel/exec_spec.rb
+++ b/spec/ruby/core/kernel/exec_spec.rb
@@ -3,16 +3,16 @@ require_relative 'fixtures/classes'
describe "Kernel#exec" do
it "is a private method" do
- Kernel.should have_private_instance_method(:exec)
+ Kernel.private_instance_methods(false).should.include?(:exec)
end
it "runs the specified command, replacing current process" do
- ruby_exe('exec "echo hello"; puts "fail"', escape: true).should == "hello\n"
+ ruby_exe('exec "echo hello"; puts "fail"').should == "hello\n"
end
end
describe "Kernel.exec" do
it "runs the specified command, replacing current process" do
- ruby_exe('Kernel.exec "echo hello"; puts "fail"', escape: true).should == "hello\n"
+ ruby_exe('Kernel.exec "echo hello"; puts "fail"').should == "hello\n"
end
end
diff --git a/spec/ruby/core/kernel/exit_spec.rb b/spec/ruby/core/kernel/exit_spec.rb
index f168cb375e..864ff84449 100644
--- a/spec/ruby/core/kernel/exit_spec.rb
+++ b/spec/ruby/core/kernel/exit_spec.rb
@@ -4,24 +4,24 @@ require_relative '../../shared/process/exit'
describe "Kernel#exit" do
it "is a private method" do
- Kernel.should have_private_instance_method(:exit)
+ Kernel.private_instance_methods(false).should.include?(:exit)
end
it_behaves_like :process_exit, :exit, KernelSpecs::Method.new
end
+describe "Kernel.exit" do
+ it_behaves_like :process_exit, :exit, Kernel
+end
+
describe "Kernel#exit!" do
it "is a private method" do
- Kernel.should have_private_instance_method(:exit!)
+ Kernel.private_instance_methods(false).should.include?(:exit!)
end
it_behaves_like :process_exit!, :exit!, "self"
end
-describe "Kernel.exit" do
- it_behaves_like :process_exit, :exit, Kernel
-end
-
describe "Kernel.exit!" do
- it_behaves_like :process_exit!, :exit!, Kernel
+ it_behaves_like :process_exit!, :exit!, "Kernel"
end
diff --git a/spec/ruby/core/kernel/extend_spec.rb b/spec/ruby/core/kernel/extend_spec.rb
index 47b22f3a18..a344c7b5ca 100644
--- a/spec/ruby/core/kernel/extend_spec.rb
+++ b/spec/ruby/core/kernel/extend_spec.rb
@@ -53,13 +53,13 @@ describe "Kernel#extend" do
end
it "raises an ArgumentError when no arguments given" do
- -> { Object.new.extend }.should raise_error(ArgumentError)
+ -> { Object.new.extend }.should.raise(ArgumentError)
end
it "raises a TypeError when the argument is not a Module" do
o = mock('o')
klass = Class.new
- -> { o.extend(klass) }.should raise_error(TypeError)
+ -> { o.extend(klass) }.should.raise(TypeError)
end
describe "on frozen instance" do
@@ -69,11 +69,23 @@ describe "Kernel#extend" do
end
it "raises an ArgumentError when no arguments given" do
- -> { @frozen.extend }.should raise_error(ArgumentError)
+ -> { @frozen.extend }.should.raise(ArgumentError)
end
it "raises a FrozenError" do
- -> { @frozen.extend @module }.should raise_error(FrozenError)
+ -> { @frozen.extend @module }.should.raise(FrozenError)
end
end
+
+ it "updated class methods of a module when it extends self and includes another module" do
+ a = Module.new do
+ extend self
+ end
+ b = Module.new do
+ def foo; :foo; end
+ end
+
+ a.include b
+ a.foo.should == :foo
+ end
end
diff --git a/spec/ruby/core/kernel/fail_spec.rb b/spec/ruby/core/kernel/fail_spec.rb
index fab622037e..ac379b67d5 100644
--- a/spec/ruby/core/kernel/fail_spec.rb
+++ b/spec/ruby/core/kernel/fail_spec.rb
@@ -3,11 +3,11 @@ require_relative 'fixtures/classes'
describe "Kernel#fail" do
it "is a private method" do
- Kernel.should have_private_instance_method(:fail)
+ Kernel.private_instance_methods(false).should.include?(:fail)
end
it "raises a RuntimeError" do
- -> { fail }.should raise_error(RuntimeError)
+ -> { fail }.should.raise(RuntimeError)
end
it "accepts an Object with an exception method returning an Exception" do
@@ -15,12 +15,12 @@ describe "Kernel#fail" do
def obj.exception(msg)
StandardError.new msg
end
- -> { fail obj, "..." }.should raise_error(StandardError, "...")
+ -> { fail obj, "..." }.should.raise(StandardError, "...")
end
it "instantiates the specified exception class" do
error_class = Class.new(RuntimeError)
- -> { fail error_class }.should raise_error(error_class)
+ -> { fail error_class }.should.raise(error_class)
end
it "uses the specified message" do
@@ -33,7 +33,7 @@ describe "Kernel#fail" do
else
raise Exception
end
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
end
end
diff --git a/spec/ruby/core/kernel/fixtures/Complex.rb b/spec/ruby/core/kernel/fixtures/Complex.rb
new file mode 100644
index 0000000000..bf14d55ad5
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/Complex.rb
@@ -0,0 +1,5 @@
+module KernelSpecs
+ def self.Complex_method(string)
+ Complex(string)
+ end
+end
diff --git a/spec/ruby/core/kernel/fixtures/at_exit.rb b/spec/ruby/core/kernel/fixtures/at_exit.rb
deleted file mode 100644
index 9c11a7ad6c..0000000000
--- a/spec/ruby/core/kernel/fixtures/at_exit.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-at_exit do
- STDERR.puts "at_exit ran"
-end
diff --git a/spec/ruby/core/kernel/fixtures/autoload_relative_b.rb b/spec/ruby/core/kernel/fixtures/autoload_relative_b.rb
new file mode 100644
index 0000000000..6de6f5091d
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/autoload_relative_b.rb
@@ -0,0 +1,7 @@
+module KernelSpecs
+ module KSAutoloadRelativeB
+ def self.loaded
+ :ksautoload_b
+ end
+ end
+end
diff --git a/spec/ruby/core/kernel/fixtures/autoload_relative_d.rb b/spec/ruby/core/kernel/fixtures/autoload_relative_d.rb
new file mode 100644
index 0000000000..5b6b5e1fa2
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/autoload_relative_d.rb
@@ -0,0 +1,5 @@
+module KSAutoloadRelativeD
+ def self.loaded
+ :ksautoload_d
+ end
+end
diff --git a/spec/ruby/core/kernel/fixtures/classes.rb b/spec/ruby/core/kernel/fixtures/classes.rb
index 541a4c075e..ad82f3cef5 100644
--- a/spec/ruby/core/kernel/fixtures/classes.rb
+++ b/spec/ruby/core/kernel/fixtures/classes.rb
@@ -180,6 +180,25 @@ module KernelSpecs
alias aliased_pub_method pub_method
end
+ class BasicA < BasicObject
+ define_method(:respond_to?, ::Kernel.instance_method(:respond_to?))
+
+ def pub_method; :public_method; end
+
+ def undefed_method; :undefed_method; end
+ undef_method :undefed_method
+
+ protected
+ def protected_method; :protected_method; end
+
+ private
+ def private_method; :private_method; end
+ end
+
+ class MissingA < A
+ undef :respond_to_missing?
+ end
+
class VisibilityChange
class << self
private :new
@@ -219,10 +238,28 @@ module KernelSpecs
block_given?
end
+ def self.accept_block_inside_block()
+ yield_self {
+ block_given?
+ }
+ end
+
+ def self.accept_block_as_argument_inside_block(&block)
+ yield_self {
+ block_given?
+ }
+ end
+
class << self
define_method(:defined_block) do
block_given?
end
+
+ define_method(:defined_block_inside_block) do
+ yield_self {
+ block_given?
+ }
+ end
end
end
@@ -235,10 +272,28 @@ module KernelSpecs
self.send(:block_given?)
end
+ def self.accept_block_inside_block
+ yield_self {
+ self.send(:block_given?)
+ }
+ end
+
+ def self.accept_block_as_argument_inside_block(&block)
+ yield_self {
+ self.send(:block_given?)
+ }
+ end
+
class << self
define_method(:defined_block) do
self.send(:block_given?)
end
+
+ define_method(:defined_block_inside_block) do
+ yield_self {
+ self.send(:block_given?)
+ }
+ end
end
end
@@ -251,10 +306,28 @@ module KernelSpecs
Kernel.block_given?
end
+ def self.accept_block_inside_block
+ yield_self {
+ Kernel.block_given?
+ }
+ end
+
+ def self.accept_block_as_argument_inside_block(&block)
+ yield_self {
+ Kernel.block_given?
+ }
+ end
+
class << self
define_method(:defined_block) do
Kernel.block_given?
end
+
+ define_method(:defined_block_inside_block) do
+ yield_self {
+ Kernel.block_given?
+ }
+ end
end
end
diff --git a/spec/ruby/core/kernel/fixtures/warn_core_method.rb b/spec/ruby/core/kernel/fixtures/warn_core_method.rb
index f5dee6b668..fd82562404 100644
--- a/spec/ruby/core/kernel/fixtures/warn_core_method.rb
+++ b/spec/ruby/core/kernel/fixtures/warn_core_method.rb
@@ -1,6 +1,6 @@
raise 'should be run without RubyGems' if defined?(Gem)
-def deprecated(n=1)
+public def deprecated(n=1)
# puts nil, caller(0), nil
warn "use X instead", uplevel: n
end
diff --git a/spec/ruby/core/kernel/fork_spec.rb b/spec/ruby/core/kernel/fork_spec.rb
index b37f9980e0..4a2c848202 100644
--- a/spec/ruby/core/kernel/fork_spec.rb
+++ b/spec/ruby/core/kernel/fork_spec.rb
@@ -4,7 +4,7 @@ require_relative '../../shared/process/fork'
describe "Kernel#fork" do
it "is a private method" do
- Kernel.should have_private_instance_method(:fork)
+ Kernel.private_instance_methods(false).should.include?(:fork)
end
it_behaves_like :process_fork, :fork, KernelSpecs::Method.new
diff --git a/spec/ruby/core/kernel/format_spec.rb b/spec/ruby/core/kernel/format_spec.rb
index e8b031e480..35c752b1ab 100644
--- a/spec/ruby/core/kernel/format_spec.rb
+++ b/spec/ruby/core/kernel/format_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
# NOTE: most specs are in sprintf_spec.rb, this is just an alias
describe "Kernel#format" do
it "is a private method" do
- Kernel.should have_private_instance_method(:format)
+ Kernel.private_instance_methods(false).should.include?(:format)
end
end
@@ -12,4 +12,36 @@ describe "Kernel.format" do
it "is accessible as a module function" do
Kernel.format("%s", "hello").should == "hello"
end
+
+ describe "when $VERBOSE is true" do
+ it "warns if too many arguments are passed" do
+ code = <<~RUBY
+ $VERBOSE = true
+ format("test", 1)
+ RUBY
+
+ ruby_exe(code, args: "2>&1").should.include?("warning: too many arguments for format string")
+ end
+
+ it "does not warns if too many keyword arguments are passed" do
+ code = <<~RUBY
+ $VERBOSE = true
+ format("test %{test}", test: 1, unused: 2)
+ RUBY
+
+ ruby_exe(code, args: "2>&1").should_not.include?("warning")
+ end
+
+ ruby_bug "#20593", ""..."3.4" do
+ it "doesn't warns if keyword arguments are passed and none are used" do
+ code = <<~RUBY
+ $VERBOSE = true
+ format("test", test: 1)
+ format("test", {})
+ RUBY
+
+ ruby_exe(code, args: "2>&1").should_not.include?("warning")
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/freeze_spec.rb b/spec/ruby/core/kernel/freeze_spec.rb
index fa32d321cf..079617dce4 100644
--- a/spec/ruby/core/kernel/freeze_spec.rb
+++ b/spec/ruby/core/kernel/freeze_spec.rb
@@ -4,46 +4,46 @@ require_relative 'fixtures/classes'
describe "Kernel#freeze" do
it "prevents self from being further modified" do
o = mock('o')
- o.frozen?.should be_false
+ o.frozen?.should == false
o.freeze
- o.frozen?.should be_true
+ o.frozen?.should == true
end
it "returns self" do
o = Object.new
- o.freeze.should equal(o)
+ o.freeze.should.equal?(o)
end
describe "on integers" do
it "has no effect since they are already frozen" do
- 1.frozen?.should be_true
+ 1.frozen?.should == true
1.freeze
bignum = bignum_value
- bignum.frozen?.should be_true
+ bignum.frozen?.should == true
bignum.freeze
end
end
describe "on a Float" do
it "has no effect since it is already frozen" do
- 1.2.frozen?.should be_true
+ 1.2.frozen?.should == true
1.2.freeze
end
end
describe "on a Symbol" do
it "has no effect since it is already frozen" do
- :sym.frozen?.should be_true
+ :sym.frozen?.should == true
:sym.freeze
end
end
describe "on true, false and nil" do
it "has no effect since they are already frozen" do
- nil.frozen?.should be_true
- true.frozen?.should be_true
- false.frozen?.should be_true
+ nil.frozen?.should == true
+ true.frozen?.should == true
+ false.frozen?.should == true
nil.freeze
true.freeze
@@ -54,7 +54,7 @@ describe "Kernel#freeze" do
describe "on a Complex" do
it "has no effect since it is already frozen" do
c = Complex(1.3, 3.1)
- c.frozen?.should be_true
+ c.frozen?.should == true
c.freeze
end
end
@@ -62,7 +62,7 @@ describe "Kernel#freeze" do
describe "on a Rational" do
it "has no effect since it is already frozen" do
r = Rational(1, 3)
- r.frozen?.should be_true
+ r.frozen?.should == true
r.freeze
end
end
@@ -72,13 +72,13 @@ describe "Kernel#freeze" do
def mutate; @foo = 1; end
end.new
o.freeze
- -> {o.mutate}.should raise_error(RuntimeError)
+ -> {o.mutate}.should.raise(RuntimeError)
end
it "causes instance_variable_set to raise RuntimeError" do
o = Object.new
o.freeze
- -> {o.instance_variable_set(:@foo, 1)}.should raise_error(RuntimeError)
+ -> {o.instance_variable_set(:@foo, 1)}.should.raise(RuntimeError)
end
it "freezes an object's singleton class" do
diff --git a/spec/ruby/core/kernel/frozen_spec.rb b/spec/ruby/core/kernel/frozen_spec.rb
index a4cec4263d..8b8fad3de7 100644
--- a/spec/ruby/core/kernel/frozen_spec.rb
+++ b/spec/ruby/core/kernel/frozen_spec.rb
@@ -12,9 +12,9 @@ describe "Kernel#frozen?" do
describe "on true, false and nil" do
it "returns true" do
- true.frozen?.should be_true
- false.frozen?.should be_true
- nil.frozen?.should be_true
+ true.frozen?.should == true
+ false.frozen?.should == true
+ nil.frozen?.should == true
end
end
@@ -25,8 +25,8 @@ describe "Kernel#frozen?" do
end
it "returns true" do
- @fixnum.frozen?.should be_true
- @bignum.frozen?.should be_true
+ @fixnum.frozen?.should == true
+ @bignum.frozen?.should == true
end
end
@@ -36,7 +36,7 @@ describe "Kernel#frozen?" do
end
it "returns true" do
- @float.frozen?.should be_true
+ @float.frozen?.should == true
end
end
@@ -46,31 +46,31 @@ describe "Kernel#frozen?" do
end
it "returns true" do
- @symbol.frozen?.should be_true
+ @symbol.frozen?.should == true
end
end
describe "on a Complex" do
it "returns true" do
c = Complex(1.3, 3.1)
- c.frozen?.should be_true
+ c.frozen?.should == true
end
it "literal returns true" do
c = eval "1.3i"
- c.frozen?.should be_true
+ c.frozen?.should == true
end
end
describe "on a Rational" do
it "returns true" do
r = Rational(1, 3)
- r.frozen?.should be_true
+ r.frozen?.should == true
end
it "literal returns true" do
r = eval "1/3r"
- r.frozen?.should be_true
+ r.frozen?.should == true
end
end
end
diff --git a/spec/ruby/core/kernel/gets_spec.rb b/spec/ruby/core/kernel/gets_spec.rb
index 104613dbfa..1b2b36fbb9 100644
--- a/spec/ruby/core/kernel/gets_spec.rb
+++ b/spec/ruby/core/kernel/gets_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel#gets" do
it "is a private method" do
- Kernel.should have_private_instance_method(:gets)
+ Kernel.private_instance_methods(false).should.include?(:gets)
end
it "calls ARGF.gets" do
diff --git a/spec/ruby/core/kernel/global_variables_spec.rb b/spec/ruby/core/kernel/global_variables_spec.rb
index 8bce8e25b7..d41bdff49a 100644
--- a/spec/ruby/core/kernel/global_variables_spec.rb
+++ b/spec/ruby/core/kernel/global_variables_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel.global_variables" do
it "is a private method" do
- Kernel.should have_private_instance_method(:global_variables)
+ Kernel.private_instance_methods(false).should.include?(:global_variables)
end
before :all do
@@ -11,13 +11,13 @@ describe "Kernel.global_variables" do
end
it "finds subset starting with std" do
- global_variables.grep(/std/).should include(:$stderr, :$stdin, :$stdout)
+ global_variables.grep(/std/).to_set.should >= Set[:$stderr, :$stdin, :$stdout]
a = global_variables.size
gvar_name = "$foolish_global_var#{@i += 1}"
global_variables.include?(gvar_name.to_sym).should == false
eval("#{gvar_name} = 1")
global_variables.size.should == a+1
- global_variables.should include(gvar_name.to_sym)
+ global_variables.should.include?(gvar_name.to_sym)
end
end
diff --git a/spec/ruby/core/kernel/gsub_spec.rb b/spec/ruby/core/kernel/gsub_spec.rb
index a0cb9f2a70..e05349e2b5 100644
--- a/spec/ruby/core/kernel/gsub_spec.rb
+++ b/spec/ruby/core/kernel/gsub_spec.rb
@@ -6,20 +6,20 @@ require_relative 'fixtures/classes'
ruby_version_is ""..."1.9" do
describe "Kernel#gsub" do
it "is a private method" do
- Kernel.should have_private_instance_method(:gsub)
+ Kernel.private_instance_methods(false).should.include?(:gsub)
end
it "raises a TypeError if $_ is not a String" do
-> {
$_ = 123
gsub(/./, "!")
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "when matches sets $_ to a new string, leaving the former value unaltered" do
orig_value = $_ = "hello"
gsub("ello", "ola")
- $_.should_not equal(orig_value)
+ $_.should_not.equal?(orig_value)
$_.should == "hola"
orig_value.should == "hello"
end
@@ -86,7 +86,7 @@ ruby_version_is ""..."1.9" do
describe "Kernel#gsub!" do
it "is a private method" do
- Kernel.should have_private_instance_method(:gsub!)
+ Kernel.private_instance_methods(false).should.include?(:gsub!)
end
end
diff --git a/spec/ruby/core/kernel/initialize_clone_spec.rb b/spec/ruby/core/kernel/initialize_clone_spec.rb
index 2d889f5aad..0033eadffb 100644
--- a/spec/ruby/core/kernel/initialize_clone_spec.rb
+++ b/spec/ruby/core/kernel/initialize_clone_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Kernel#initialize_clone" do
it "is a private instance method" do
- Kernel.should have_private_instance_method(:initialize_clone)
+ Kernel.private_instance_methods(false).should.include?(:initialize_clone)
end
it "returns the receiver" do
@@ -18,11 +18,9 @@ describe "Kernel#initialize_clone" do
a.send(:initialize_clone, b)
end
- ruby_version_is "3.0" do
- it "accepts a :freeze keyword argument for obj.clone(freeze: value)" do
- a = Object.new
- b = Object.new
- a.send(:initialize_clone, b, freeze: true).should == a
- end
+ it "accepts a :freeze keyword argument for obj.clone(freeze: value)" do
+ a = Object.new
+ b = Object.new
+ a.send(:initialize_clone, b, freeze: true).should == a
end
end
diff --git a/spec/ruby/core/kernel/initialize_copy_spec.rb b/spec/ruby/core/kernel/initialize_copy_spec.rb
index fe08d184ad..ebac0c14de 100644
--- a/spec/ruby/core/kernel/initialize_copy_spec.rb
+++ b/spec/ruby/core/kernel/initialize_copy_spec.rb
@@ -1,17 +1,24 @@
require_relative '../../spec_helper'
describe "Kernel#initialize_copy" do
+ it "returns self" do
+ obj = Object.new
+ obj.send(:initialize_copy, obj).should.equal?(obj)
+ end
+
it "does nothing if the argument is the same as the receiver" do
obj = Object.new
obj.send(:initialize_copy, obj).should.equal?(obj)
- obj.freeze
+
+ obj = Object.new.freeze
obj.send(:initialize_copy, obj).should.equal?(obj)
+
1.send(:initialize_copy, 1).should.equal?(1)
end
it "raises FrozenError if the receiver is frozen" do
- -> { Object.new.freeze.send(:initialize_copy, Object.new) }.should raise_error(FrozenError)
- -> { 1.send(:initialize_copy, Object.new) }.should raise_error(FrozenError)
+ -> { Object.new.freeze.send(:initialize_copy, Object.new) }.should.raise(FrozenError)
+ -> { 1.send(:initialize_copy, Object.new) }.should.raise(FrozenError)
end
it "raises TypeError if the objects are of different class" do
@@ -20,10 +27,10 @@ describe "Kernel#initialize_copy" do
a = klass.new
b = sub.new
message = 'initialize_copy should take same class object'
- -> { a.send(:initialize_copy, b) }.should raise_error(TypeError, message)
- -> { b.send(:initialize_copy, a) }.should raise_error(TypeError, message)
+ -> { a.send(:initialize_copy, b) }.should.raise(TypeError, message)
+ -> { b.send(:initialize_copy, a) }.should.raise(TypeError, message)
- -> { a.send(:initialize_copy, 1) }.should raise_error(TypeError, message)
- -> { a.send(:initialize_copy, 1.0) }.should raise_error(TypeError, message)
+ -> { a.send(:initialize_copy, 1) }.should.raise(TypeError, message)
+ -> { a.send(:initialize_copy, 1.0) }.should.raise(TypeError, message)
end
end
diff --git a/spec/ruby/core/kernel/initialize_dup_spec.rb b/spec/ruby/core/kernel/initialize_dup_spec.rb
index 6dff34b7ad..f144647eb8 100644
--- a/spec/ruby/core/kernel/initialize_dup_spec.rb
+++ b/spec/ruby/core/kernel/initialize_dup_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Kernel#initialize_dup" do
it "is a private instance method" do
- Kernel.should have_private_instance_method(:initialize_dup)
+ Kernel.private_instance_methods(false).should.include?(:initialize_dup)
end
it "returns the receiver" do
diff --git a/spec/ruby/core/kernel/inspect_spec.rb b/spec/ruby/core/kernel/inspect_spec.rb
index 1f9ce834ab..8fc3ab51cd 100644
--- a/spec/ruby/core/kernel/inspect_spec.rb
+++ b/spec/ruby/core/kernel/inspect_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel#inspect" do
it "returns a String" do
- Object.new.inspect.should be_an_instance_of(String)
+ Object.new.inspect.should.instance_of?(String)
end
it "does not call #to_s if it is defined" do
@@ -26,6 +26,78 @@ describe "Kernel#inspect" do
class << obj
undef_method :class
end
- obj.inspect.should be_kind_of(String)
+ obj.inspect.should.is_a?(String)
+ end
+
+ ruby_version_is "4.0" do
+ it "calls #instance_variables_to_inspect private method to know which variables to display" do
+ obj = Object.new
+ obj.instance_eval do
+ @host = "localhost"
+ @user = "root"
+ @password = "hunter2"
+ end
+ obj.singleton_class.class_eval do
+ private def instance_variables_to_inspect = %i[@host @user @does_not_exist]
+ end
+
+ inspected = obj.inspect.sub(/^#<Object:0x[0-9a-f]+/, '#<Object:0x00')
+ inspected.should == '#<Object:0x00 @host="localhost", @user="root">'
+
+ obj = Object.new
+ obj.instance_eval do
+ @host = "localhost"
+ @user = "root"
+ @password = "hunter2"
+ end
+ obj.singleton_class.class_eval do
+ private def instance_variables_to_inspect = []
+ end
+
+ inspected = obj.inspect.sub(/^#<Object:0x[0-9a-f]+/, '#<Object:0x00')
+ inspected.should == "#<Object:0x00>"
+ end
+
+ it "displays all instance variables if #instance_variables_to_inspect returns nil" do
+ obj = Object.new
+ obj.instance_eval do
+ @host = "localhost"
+ @user = "root"
+ @password = "hunter2"
+ end
+ obj.singleton_class.class_eval do
+ private def instance_variables_to_inspect = nil
+ end
+
+ inspected = obj.inspect.sub(/^#<Object:0x[0-9a-f]+/, '#<Object:0x00')
+ inspected.should == %{#<Object:0x00 @host="localhost", @user="root", @password="hunter2">}
+ end
+
+ it "displays all instance variables if #instance_variables_to_inspect is not defined" do
+ obj = BasicObject.new
+ obj.instance_eval do
+ @host = "localhost"
+ @user = "root"
+ @password = "hunter2"
+ end
+ method_inspect = Kernel.instance_method(:inspect)
+
+ inspected = method_inspect.bind(obj).call.sub(/^#<BasicObject:0x[0-9a-f]+/, '#<BasicObject:0x00')
+ inspected.should == %{#<BasicObject:0x00 @host="localhost", @user="root", @password="hunter2">}
+ end
+
+ it "raises an error if #instance_variables_to_inspect returns an invalid value" do
+ obj = Object.new
+ obj.instance_eval do
+ @host = "localhost"
+ @user = "root"
+ @password = "hunter2"
+ end
+ obj.singleton_class.class_eval do
+ private def instance_variables_to_inspect = {}
+ end
+
+ ->{ obj.inspect }.should.raise(TypeError, "Expected #instance_variables_to_inspect to return an Array or nil, but it returned Hash")
+ end
end
end
diff --git a/spec/ruby/core/kernel/instance_of_spec.rb b/spec/ruby/core/kernel/instance_of_spec.rb
index d1170d5047..8d19974aa3 100644
--- a/spec/ruby/core/kernel/instance_of_spec.rb
+++ b/spec/ruby/core/kernel/instance_of_spec.rb
@@ -33,8 +33,8 @@ describe "Kernel#instance_of?" do
end
it "raises a TypeError if given an object that is not a Class nor a Module" do
- -> { @o.instance_of?(Object.new) }.should raise_error(TypeError)
- -> { @o.instance_of?('KernelSpecs::InstanceClass') }.should raise_error(TypeError)
- -> { @o.instance_of?(1) }.should raise_error(TypeError)
+ -> { @o.instance_of?(Object.new) }.should.raise(TypeError)
+ -> { @o.instance_of?('KernelSpecs::InstanceClass') }.should.raise(TypeError)
+ -> { @o.instance_of?(1) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/kernel/instance_variable_defined_spec.rb b/spec/ruby/core/kernel/instance_variable_defined_spec.rb
index 2ebb582b43..512f811393 100644
--- a/spec/ruby/core/kernel/instance_variable_defined_spec.rb
+++ b/spec/ruby/core/kernel/instance_variable_defined_spec.rb
@@ -8,21 +8,21 @@ describe "Kernel#instance_variable_defined?" do
describe "when passed a String" do
it "returns false if the instance variable is not defined" do
- @instance.instance_variable_defined?("@goodbye").should be_false
+ @instance.instance_variable_defined?("@goodbye").should == false
end
it "returns true if the instance variable is defined" do
- @instance.instance_variable_defined?("@greeting").should be_true
+ @instance.instance_variable_defined?("@greeting").should == true
end
end
describe "when passed a Symbol" do
it "returns false if the instance variable is not defined" do
- @instance.instance_variable_defined?(:@goodbye).should be_false
+ @instance.instance_variable_defined?(:@goodbye).should == false
end
it "returns true if the instance variable is defined" do
- @instance.instance_variable_defined?(:@greeting).should be_true
+ @instance.instance_variable_defined?(:@greeting).should == true
end
end
@@ -30,12 +30,12 @@ describe "Kernel#instance_variable_defined?" do
-> do
obj = mock("kernel instance_variable_defined?")
@instance.instance_variable_defined? obj
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "returns false if the instance variable is not defined for different types" do
[nil, false, true, 1, 2.0, :test, "test"].each do |obj|
- obj.instance_variable_defined?("@goodbye").should be_false
+ obj.instance_variable_defined?("@goodbye").should == false
end
end
end
diff --git a/spec/ruby/core/kernel/instance_variable_get_spec.rb b/spec/ruby/core/kernel/instance_variable_get_spec.rb
index f1d2a45df8..8404c94192 100644
--- a/spec/ruby/core/kernel/instance_variable_get_spec.rb
+++ b/spec/ruby/core/kernel/instance_variable_get_spec.rb
@@ -20,29 +20,29 @@ describe "Kernel#instance_variable_get" do
end
it "returns nil when the referred instance variable does not exist" do
- @obj.instance_variable_get(:@does_not_exist).should be_nil
+ @obj.instance_variable_get(:@does_not_exist).should == nil
end
it "raises a TypeError when the passed argument does not respond to #to_str" do
- -> { @obj.instance_variable_get(Object.new) }.should raise_error(TypeError)
+ -> { @obj.instance_variable_get(Object.new) }.should.raise(TypeError)
end
it "raises a TypeError when the passed argument can't be converted to a String" do
obj = mock("to_str")
obj.stub!(:to_str).and_return(123)
- -> { @obj.instance_variable_get(obj) }.should raise_error(TypeError)
+ -> { @obj.instance_variable_get(obj) }.should.raise(TypeError)
end
it "raises a NameError when the conversion result does not start with an '@'" do
obj = mock("to_str")
obj.stub!(:to_str).and_return("test")
- -> { @obj.instance_variable_get(obj) }.should raise_error(NameError)
+ -> { @obj.instance_variable_get(obj) }.should.raise(NameError)
end
it "raises a NameError when passed just '@'" do
obj = mock("to_str")
obj.stub!(:to_str).and_return('@')
- -> { @obj.instance_variable_get(obj) }.should raise_error(NameError)
+ -> { @obj.instance_variable_get(obj) }.should.raise(NameError)
end
end
@@ -57,20 +57,20 @@ describe "Kernel#instance_variable_get when passed Symbol" do
end
it "raises a NameError when passed :@ as an instance variable name" do
- -> { @obj.instance_variable_get(:"@") }.should raise_error(NameError)
+ -> { @obj.instance_variable_get(:"@") }.should.raise(NameError)
end
it "raises a NameError when the passed Symbol does not start with an '@'" do
- -> { @obj.instance_variable_get(:test) }.should raise_error(NameError)
+ -> { @obj.instance_variable_get(:test) }.should.raise(NameError)
end
it "raises a NameError when the passed Symbol is an invalid instance variable name" do
- -> { @obj.instance_variable_get(:"@0") }.should raise_error(NameError)
+ -> { @obj.instance_variable_get(:"@0") }.should.raise(NameError)
end
it "returns nil or raises for frozen objects" do
nil.instance_variable_get(:@foo).should == nil
- -> { nil.instance_variable_get(:foo) }.should raise_error(NameError)
+ -> { nil.instance_variable_get(:foo) }.should.raise(NameError)
:foo.instance_variable_get(:@foo).should == nil
end
end
@@ -86,15 +86,15 @@ describe "Kernel#instance_variable_get when passed String" do
end
it "raises a NameError when the passed String does not start with an '@'" do
- -> { @obj.instance_variable_get("test") }.should raise_error(NameError)
+ -> { @obj.instance_variable_get("test") }.should.raise(NameError)
end
it "raises a NameError when the passed String is an invalid instance variable name" do
- -> { @obj.instance_variable_get("@0") }.should raise_error(NameError)
+ -> { @obj.instance_variable_get("@0") }.should.raise(NameError)
end
it "raises a NameError when passed '@' as an instance variable name" do
- -> { @obj.instance_variable_get("@") }.should raise_error(NameError)
+ -> { @obj.instance_variable_get("@") }.should.raise(NameError)
end
end
@@ -105,7 +105,7 @@ describe "Kernel#instance_variable_get when passed Integer" do
end
it "raises a TypeError" do
- -> { @obj.instance_variable_get(10) }.should raise_error(TypeError)
- -> { @obj.instance_variable_get(-10) }.should raise_error(TypeError)
+ -> { @obj.instance_variable_get(10) }.should.raise(TypeError)
+ -> { @obj.instance_variable_get(-10) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/kernel/instance_variable_set_spec.rb b/spec/ruby/core/kernel/instance_variable_set_spec.rb
index 2c25f4366f..bf165a824e 100644
--- a/spec/ruby/core/kernel/instance_variable_set_spec.rb
+++ b/spec/ruby/core/kernel/instance_variable_set_spec.rb
@@ -18,26 +18,26 @@ describe "Kernel#instance_variable_set" do
it "raises a NameError exception if the argument is not of form '@x'" do
no_dog = Class.new
- -> { no_dog.new.instance_variable_set(:c, "cat") }.should raise_error(NameError)
+ -> { no_dog.new.instance_variable_set(:c, "cat") }.should.raise(NameError)
end
it "raises a NameError exception if the argument is an invalid instance variable name" do
digit_dog = Class.new
- -> { digit_dog.new.instance_variable_set(:"@0", "cat") }.should raise_error(NameError)
+ -> { digit_dog.new.instance_variable_set(:"@0", "cat") }.should.raise(NameError)
end
it "raises a NameError when the argument is '@'" do
dog_at = Class.new
- -> { dog_at.new.instance_variable_set(:"@", "cat") }.should raise_error(NameError)
+ -> { dog_at.new.instance_variable_set(:"@", "cat") }.should.raise(NameError)
end
it "raises a TypeError if the instance variable name is an Integer" do
- -> { "".instance_variable_set(1, 2) }.should raise_error(TypeError)
+ -> { "".instance_variable_set(1, 2) }.should.raise(TypeError)
end
it "raises a TypeError if the instance variable name is an object that does not respond to to_str" do
class KernelSpecs::A; end
- -> { "".instance_variable_set(KernelSpecs::A.new, 3) }.should raise_error(TypeError)
+ -> { "".instance_variable_set(KernelSpecs::A.new, 3) }.should.raise(TypeError)
end
it "raises a NameError if the passed object, when coerced with to_str, does not start with @" do
@@ -46,11 +46,11 @@ describe "Kernel#instance_variable_set" do
":c"
end
end
- -> { "".instance_variable_set(KernelSpecs::B.new, 4) }.should raise_error(NameError)
+ -> { "".instance_variable_set(KernelSpecs::B.new, 4) }.should.raise(NameError)
end
it "raises a NameError if pass an object that cannot be a symbol" do
- -> { "".instance_variable_set(:c, 1) }.should raise_error(NameError)
+ -> { "".instance_variable_set(:c, 1) }.should.raise(NameError)
end
it "accepts as instance variable name any instance of a class that responds to to_str" do
@@ -78,16 +78,16 @@ describe "Kernel#instance_variable_set" do
end
it "keeps stored object after any exceptions" do
- -> { @frozen.instance_variable_set(:@ivar, :replacement) }.should raise_error(Exception)
- @frozen.ivar.should equal(:origin)
+ -> { @frozen.instance_variable_set(:@ivar, :replacement) }.should.raise(Exception)
+ @frozen.ivar.should.equal?(:origin)
end
it "raises a FrozenError when passed replacement is identical to stored object" do
- -> { @frozen.instance_variable_set(:@ivar, :origin) }.should raise_error(FrozenError)
+ -> { @frozen.instance_variable_set(:@ivar, :origin) }.should.raise(FrozenError)
end
it "raises a FrozenError when passed replacement is different from stored object" do
- -> { @frozen.instance_variable_set(:@ivar, :replacement) }.should raise_error(FrozenError)
+ -> { @frozen.instance_variable_set(:@ivar, :replacement) }.should.raise(FrozenError)
end
it "accepts unicode instance variable names" do
@@ -97,9 +97,9 @@ describe "Kernel#instance_variable_set" do
end
it "raises for frozen objects" do
- -> { nil.instance_variable_set(:@foo, 42) }.should raise_error(FrozenError)
- -> { nil.instance_variable_set(:foo, 42) }.should raise_error(NameError)
- -> { :foo.instance_variable_set(:@foo, 42) }.should raise_error(FrozenError)
+ -> { nil.instance_variable_set(:@foo, 42) }.should.raise(FrozenError)
+ -> { nil.instance_variable_set(:foo, 42) }.should.raise(NameError)
+ -> { :foo.instance_variable_set(:@foo, 42) }.should.raise(FrozenError)
end
end
end
diff --git a/spec/ruby/core/kernel/instance_variables_spec.rb b/spec/ruby/core/kernel/instance_variables_spec.rb
index 677d8bb7b2..75c1d8f752 100644
--- a/spec/ruby/core/kernel/instance_variables_spec.rb
+++ b/spec/ruby/core/kernel/instance_variables_spec.rb
@@ -11,7 +11,7 @@ describe "Kernel#instance_variables" do
it "returns the correct array if an instance variable is added" do
a = 0
- ->{ a.instance_variable_set("@test", 1) }.should raise_error(RuntimeError)
+ ->{ a.instance_variable_set("@test", 1) }.should.raise(RuntimeError)
end
end
diff --git a/spec/ruby/core/kernel/is_a_spec.rb b/spec/ruby/core/kernel/is_a_spec.rb
index dc69766f83..bd8c96529a 100644
--- a/spec/ruby/core/kernel/is_a_spec.rb
+++ b/spec/ruby/core/kernel/is_a_spec.rb
@@ -2,5 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/kind_of'
describe "Kernel#is_a?" do
- it_behaves_like :kernel_kind_of , :is_a?
+ it_behaves_like :kernel_kind_of, :is_a?
end
diff --git a/spec/ruby/core/kernel/iterator_spec.rb b/spec/ruby/core/kernel/iterator_spec.rb
deleted file mode 100644
index 3fe8317f26..0000000000
--- a/spec/ruby/core/kernel/iterator_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-
-ruby_version_is ""..."3.0" do
- describe "Kernel#iterator?" do
- it "is a private method" do
- Kernel.should have_private_instance_method(:iterator?)
- end
- end
-
- describe "Kernel.iterator?" do
- it "needs to be reviewed for spec completeness"
- end
-end
diff --git a/spec/ruby/core/kernel/itself_spec.rb b/spec/ruby/core/kernel/itself_spec.rb
index c906d7c3e8..c1f01fdc5e 100644
--- a/spec/ruby/core/kernel/itself_spec.rb
+++ b/spec/ruby/core/kernel/itself_spec.rb
@@ -4,6 +4,6 @@ require_relative 'fixtures/classes'
describe "Kernel#itself" do
it "returns the receiver itself" do
foo = Object.new
- foo.itself.should equal foo
+ foo.itself.should.equal? foo
end
end
diff --git a/spec/ruby/core/kernel/kind_of_spec.rb b/spec/ruby/core/kernel/kind_of_spec.rb
index 734035620c..c988edccb5 100644
--- a/spec/ruby/core/kernel/kind_of_spec.rb
+++ b/spec/ruby/core/kernel/kind_of_spec.rb
@@ -2,5 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/kind_of'
describe "Kernel#kind_of?" do
- it_behaves_like :kernel_kind_of , :kind_of?
+ it_behaves_like :kernel_kind_of, :kind_of?
end
diff --git a/spec/ruby/core/kernel/lambda_spec.rb b/spec/ruby/core/kernel/lambda_spec.rb
index 2aa4d4f2fb..6ab89c2bbb 100644
--- a/spec/ruby/core/kernel/lambda_spec.rb
+++ b/spec/ruby/core/kernel/lambda_spec.rb
@@ -8,90 +8,52 @@ describe "Kernel.lambda" do
it_behaves_like :kernel_lambda, :lambda
it "is a private method" do
- Kernel.should have_private_instance_method(:lambda)
+ Kernel.private_instance_methods(false).should.include?(:lambda)
end
it "creates a lambda-style Proc if given a literal block" do
l = lambda { 42 }
- l.lambda?.should be_true
+ l.lambda?.should == true
end
it "creates a lambda-style Proc if given a literal block via #send" do
l = send(:lambda) { 42 }
- l.lambda?.should be_true
+ l.lambda?.should == true
end
it "creates a lambda-style Proc if given a literal block via #__send__" do
l = __send__(:lambda) { 42 }
- l.lambda?.should be_true
- end
-
- it "creates a lambda-style Proc if given a literal block via Kernel.public_send" do
- suppress_warning do
- l = Kernel.public_send(:lambda) { 42 }
- l.lambda?.should be_true
- end
- end
-
- it "returns the passed Proc if given an existing Proc" do
- some_proc = proc {}
- l = suppress_warning {lambda(&some_proc)}
- l.should equal(some_proc)
- l.lambda?.should be_false
- end
-
- it "creates a lambda-style Proc when called with zsuper" do
- suppress_warning do
- l = KernelSpecs::LambdaSpecs::ForwardBlockWithZSuper.new.lambda { 42 }
- l.lambda?.should be_true
- l.call.should == 42
-
- lambda { l.call(:extra) }.should raise_error(ArgumentError)
- end
- end
-
- it "returns the passed Proc if given an existing Proc through super" do
- some_proc = proc { }
- l = KernelSpecs::LambdaSpecs::SuperAmpersand.new.lambda(&some_proc)
- l.should equal(some_proc)
- l.lambda?.should be_false
- end
-
- it "does not create lambda-style Procs when captured with #method" do
- kernel_lambda = method(:lambda)
- l = suppress_warning {kernel_lambda.call { 42 }}
- l.lambda?.should be_false
- l.call(:extra).should == 42
+ l.lambda?.should == true
end
it "checks the arity of the call when no args are specified" do
l = lambda { :called }
l.call.should == :called
- lambda { l.call(1) }.should raise_error(ArgumentError)
- lambda { l.call(1, 2) }.should raise_error(ArgumentError)
+ lambda { l.call(1) }.should.raise(ArgumentError)
+ lambda { l.call(1, 2) }.should.raise(ArgumentError)
end
it "checks the arity when 1 arg is specified" do
l = lambda { |a| :called }
l.call(1).should == :called
- lambda { l.call }.should raise_error(ArgumentError)
- lambda { l.call(1, 2) }.should raise_error(ArgumentError)
+ lambda { l.call }.should.raise(ArgumentError)
+ lambda { l.call(1, 2) }.should.raise(ArgumentError)
end
it "does not check the arity when passing a Proc with &" do
l = lambda { || :called }
p = proc { || :called }
- lambda { l.call(1) }.should raise_error(ArgumentError)
+ lambda { l.call(1) }.should.raise(ArgumentError)
p.call(1).should == :called
end
it "accepts 0 arguments when used with ||" do
lambda {
lambda { || }.call(1)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "strictly checks the arity when 0 or 2..inf args are specified" do
@@ -99,15 +61,15 @@ describe "Kernel.lambda" do
lambda {
l.call
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
lambda {
l.call(1)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
lambda {
l.call(1,2)
- }.should_not raise_error(ArgumentError)
+ }.should_not.raise(ArgumentError)
end
it "returns from the lambda itself, not the creation site of the lambda" do
@@ -117,7 +79,7 @@ describe "Kernel.lambda" do
@reached_end_of_method = true
end
test
- @reached_end_of_method.should be_true
+ @reached_end_of_method.should == true
end
it "allows long returns to flow through it" do
@@ -132,19 +94,17 @@ describe "Kernel.lambda" do
2
end
end
- klass.new.lambda { 42 }.should be_an_instance_of Proc
+ klass.new.lambda { 42 }.should.instance_of? Proc
klass.new.ret.should == 1
end
- ruby_version_is "3.0" do
- context "when called without a literal block" do
- it "warns when proc isn't a lambda" do
- -> { lambda(&proc{}) }.should complain("#{__FILE__}:#{__LINE__}: warning: lambda without a literal block is deprecated; use the proc without lambda instead\n")
- end
+ context "when called without a literal block" do
+ it "raises when proc isn't a lambda" do
+ -> { lambda(&proc{}) }.should.raise(ArgumentError, /the lambda method requires a literal block/)
+ end
- it "doesn't warn when proc is lambda" do
- -> { lambda(&lambda{}) }.should_not complain(verbose: true)
- end
+ it "doesn't warn when proc is lambda" do
+ -> { lambda(&lambda{}) }.should_not complain(verbose: true)
end
end
end
diff --git a/spec/ruby/core/kernel/load_spec.rb b/spec/ruby/core/kernel/load_spec.rb
index a165cc4acd..890aab8c27 100644
--- a/spec/ruby/core/kernel/load_spec.rb
+++ b/spec/ruby/core/kernel/load_spec.rb
@@ -13,7 +13,7 @@ describe "Kernel#load" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:load)
+ Kernel.private_instance_methods(false).should.include?(:load)
end
it_behaves_like :kernel_require_basic, :load, CodeLoadingSpecs::Method.new
diff --git a/spec/ruby/core/kernel/local_variables_spec.rb b/spec/ruby/core/kernel/local_variables_spec.rb
index f6f1e15f52..40c343f7e4 100644
--- a/spec/ruby/core/kernel/local_variables_spec.rb
+++ b/spec/ruby/core/kernel/local_variables_spec.rb
@@ -7,14 +7,13 @@ describe "Kernel#local_variables" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:local_variables)
+ Kernel.private_instance_methods(false).should.include?(:local_variables)
end
it "contains locals as they are added" do
a = 1
b = 2
- local_variables.should include(:a, :b)
- local_variables.length.should == 2
+ local_variables.sort.should == [:a, :b]
end
it "is accessible from bindings" do
@@ -25,14 +24,12 @@ describe "Kernel#local_variables" do
end
foo_binding = local_var_foo()
res = eval("local_variables",foo_binding)
- res.should include(:a, :b)
- res.length.should == 2
+ res.sort.should == [:a, :b]
end
it "is accessible in eval" do
eval "a=1; b=2; ScratchPad.record local_variables"
- ScratchPad.recorded.should include(:a, :b)
- ScratchPad.recorded.length.should == 2
+ ScratchPad.recorded.sort.should == [:a, :b]
end
it "includes only unique variable names" do
diff --git a/spec/ruby/core/kernel/loop_spec.rb b/spec/ruby/core/kernel/loop_spec.rb
index 7c76c7d28e..c2976e5cc5 100644
--- a/spec/ruby/core/kernel/loop_spec.rb
+++ b/spec/ruby/core/kernel/loop_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel.loop" do
it "is a private method" do
- Kernel.should have_private_instance_method(:loop)
+ Kernel.private_instance_methods(false).should.include?(:loop)
end
it "calls block until it is terminated by a break" do
@@ -30,7 +30,7 @@ describe "Kernel.loop" do
it "returns an enumerator if no block given" do
enum = loop
- enum.instance_of?(Enumerator).should be_true
+ enum.instance_of?(Enumerator).should == true
cnt = 0
enum.each do |*args|
raise "Args should be empty #{args.inspect}" unless args.empty?
@@ -55,7 +55,7 @@ describe "Kernel.loop" do
end
it "does not rescue other errors" do
- ->{ loop do raise StandardError end }.should raise_error( StandardError )
+ ->{ loop do raise StandardError end }.should.raise( StandardError )
end
it "returns StopIteration#result, the result value of a finished iterator" do
diff --git a/spec/ruby/core/kernel/match_spec.rb b/spec/ruby/core/kernel/match_spec.rb
index aa25006163..cd6330fe91 100644
--- a/spec/ruby/core/kernel/match_spec.rb
+++ b/spec/ruby/core/kernel/match_spec.rb
@@ -1,30 +1,7 @@
require_relative '../../spec_helper'
describe "Kernel#=~" do
- ruby_version_is ''...'3.2' do
- it "returns nil matching any object" do
- o = Object.new
-
- suppress_warning do
- (o =~ /Object/).should be_nil
- (o =~ 'Object').should be_nil
- (o =~ Object).should be_nil
- (o =~ Object.new).should be_nil
- (o =~ nil).should be_nil
- (o =~ true).should be_nil
- end
- end
-
- it "is deprecated" do
- -> do
- Object.new =~ /regexp/
- end.should complain(/deprecated Object#=~ is called on Object/, verbose: true)
- end
- end
-
- ruby_version_is '3.2' do
- it "is no longer defined" do
- Object.new.should_not.respond_to?(:=~)
- end
+ it "is no longer defined" do
+ Object.new.should_not.respond_to?(:=~)
end
end
diff --git a/spec/ruby/core/kernel/method_spec.rb b/spec/ruby/core/kernel/method_spec.rb
index caf2ec948b..9187b8c7e7 100644
--- a/spec/ruby/core/kernel/method_spec.rb
+++ b/spec/ruby/core/kernel/method_spec.rb
@@ -11,12 +11,12 @@ describe "Kernel#method" do
it "can be called on a private method" do
@obj.send(:private_method).should == :private_method
- @obj.method(:private_method).should be_an_instance_of(Method)
+ @obj.method(:private_method).should.instance_of?(Method)
end
it "can be called on a protected method" do
@obj.send(:protected_method).should == :protected_method
- @obj.method(:protected_method).should be_an_instance_of(Method)
+ @obj.method(:protected_method).should.instance_of?(Method)
end
it "will see an alias of the original method as == when in a derived class" do
@@ -29,9 +29,9 @@ describe "Kernel#method" do
m.call.should == :defined
end
- it "can be called even if we only repond_to_missing? method, true" do
+ it "can be called even if we only respond_to_missing? method, true" do
m = KernelSpecs::RespondViaMissing.new.method(:handled_privately)
- m.should be_an_instance_of(Method)
+ m.should.instance_of?(Method)
m.call(1, 2, 3).should == "Done handled_privately([1, 2, 3])"
end
@@ -45,7 +45,7 @@ describe "Kernel#method" do
end
end
m = cls.new.method(:foo)
- -> { m.call }.should raise_error(ArgumentError)
+ -> { m.call }.should.raise(ArgumentError)
cls = Class.new do
def respond_to_missing?(name, *)
@@ -58,4 +58,31 @@ describe "Kernel#method" do
m = cls.new.method(:bar)
m.call.should == :bar
end
+
+ describe "converts the given name to a String using #to_str" do
+ it "calls #to_str to convert the given name to a String" do
+ name = mock("method-name")
+ name.should_receive(:to_str).and_return("hash")
+ Object.method(name).should == Object.method(:hash)
+ end
+
+ it "raises a TypeError if the given name can't be converted to a String" do
+ -> { Object.method(nil) }.should.raise(TypeError)
+ -> { Object.method([]) }.should.raise(TypeError)
+ end
+
+ it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to a String" do
+ name = mock("method-name")
+ name.should_receive(:to_str).and_raise(NoMethodError)
+ -> { Object.method(name) }.should.raise(NoMethodError)
+
+ name = mock("method-name")
+ name.should_receive(:to_str).and_raise(NoMethodError)
+ begin
+ raise RuntimeError.new
+ rescue => cause
+ -> { Object.method(name) }.should.raise(NoMethodError, cause:)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/methods_spec.rb b/spec/ruby/core/kernel/methods_spec.rb
index fb7a7e8be9..cfa22aa05a 100644
--- a/spec/ruby/core/kernel/methods_spec.rb
+++ b/spec/ruby/core/kernel/methods_spec.rb
@@ -5,67 +5,67 @@ require_relative '../../fixtures/reflection'
# TODO: rewrite
describe "Kernel#methods" do
it "returns singleton methods defined by obj.meth" do
- KernelSpecs::Methods.methods(false).should include(:ichi)
+ KernelSpecs::Methods.methods(false).should.include?(:ichi)
end
it "returns singleton methods defined in 'class << self'" do
- KernelSpecs::Methods.methods(false).should include(:san)
+ KernelSpecs::Methods.methods(false).should.include?(:san)
end
it "returns private singleton methods defined by obj.meth" do
- KernelSpecs::Methods.methods(false).should include(:shi)
+ KernelSpecs::Methods.methods(false).should.include?(:shi)
end
it "returns singleton methods defined in 'class << self' when it follows 'private'" do
- KernelSpecs::Methods.methods(false).should include(:roku)
+ KernelSpecs::Methods.methods(false).should.include?(:roku)
end
it "does not return private singleton methods defined in 'class << self'" do
- KernelSpecs::Methods.methods(false).should_not include(:shichi)
+ KernelSpecs::Methods.methods(false).should_not.include?(:shichi)
end
it "returns the publicly accessible methods of the object" do
meths = KernelSpecs::Methods.methods(false)
- meths.should include(:hachi, :ichi, :juu, :juu_ichi,
- :juu_ni, :roku, :san, :shi)
+ meths.to_set.should >= Set[:hachi, :ichi, :juu, :juu_ichi,
+ :juu_ni, :roku, :san, :shi]
KernelSpecs::Methods.new.methods(false).should == []
end
it "returns the publicly accessible methods in the object, its ancestors and mixed-in modules" do
meths = KernelSpecs::Methods.methods(false) & KernelSpecs::Methods.methods
- meths.should include(:hachi, :ichi, :juu, :juu_ichi,
- :juu_ni, :roku, :san, :shi)
+ meths.to_set.should >= Set[:hachi, :ichi, :juu, :juu_ichi,
+ :juu_ni, :roku, :san, :shi]
- KernelSpecs::Methods.new.methods.should include(:ku, :ni, :juu_san)
+ KernelSpecs::Methods.new.methods.to_set.should >= Set[:ku, :ni, :juu_san]
end
it "returns methods added to the metaclass through extend" do
meth = KernelSpecs::Methods.new
- meth.methods.should_not include(:peekaboo)
+ meth.methods.should_not.include?(:peekaboo)
meth.extend(KernelSpecs::Methods::MetaclassMethods)
- meth.methods.should include(:peekaboo)
+ meth.methods.should.include?(:peekaboo)
end
it "does not return undefined singleton methods defined by obj.meth" do
o = KernelSpecs::Child.new
def o.single; end
- o.methods.should include(:single)
+ o.methods.should.include?(:single)
class << o; self; end.send :undef_method, :single
- o.methods.should_not include(:single)
+ o.methods.should_not.include?(:single)
end
it "does not return superclass methods undefined in the object's class" do
- KernelSpecs::Child.new.methods.should_not include(:parent_method)
+ KernelSpecs::Child.new.methods.should_not.include?(:parent_method)
end
it "does not return superclass methods undefined in a superclass" do
- KernelSpecs::Grandchild.new.methods.should_not include(:parent_method)
+ KernelSpecs::Grandchild.new.methods.should_not.include?(:parent_method)
end
it "does not return included module methods undefined in the object's class" do
- KernelSpecs::Grandchild.new.methods.should_not include(:parent_mixin_method)
+ KernelSpecs::Grandchild.new.methods.should_not.include?(:parent_mixin_method)
end
end
diff --git a/spec/ruby/core/kernel/not_match_spec.rb b/spec/ruby/core/kernel/not_match_spec.rb
index 906f18df2c..4ed7ea7b42 100644
--- a/spec/ruby/core/kernel/not_match_spec.rb
+++ b/spec/ruby/core/kernel/not_match_spec.rb
@@ -14,6 +14,10 @@ describe "Kernel#!~" do
(obj !~ :foo).should == false
end
+ it "raises NoMethodError if self does not respond to #=~" do
+ -> { Object.new !~ :foo }.should.raise(NoMethodError)
+ end
+
it 'can be overridden in subclasses' do
obj = KernelSpecs::NotMatch.new
(obj !~ :bar).should == :foo
diff --git a/spec/ruby/core/kernel/open_spec.rb b/spec/ruby/core/kernel/open_spec.rb
index fa9299f9d4..14a3c43cad 100644
--- a/spec/ruby/core/kernel/open_spec.rb
+++ b/spec/ruby/core/kernel/open_spec.rb
@@ -15,61 +15,90 @@ describe "Kernel#open" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:open)
+ Kernel.private_instance_methods(false).should.include?(:open)
end
it "opens a file when given a valid filename" do
@file = open(@name)
- @file.should be_kind_of(File)
+ @file.should.is_a?(File)
end
it "opens a file when called with a block" do
open(@name, "r") { |f| f.gets }.should == @content
end
- platform_is_not :windows, :wasi do
- it "opens an io when path starts with a pipe" do
- @io = open("|date")
- begin
- @io.should be_kind_of(IO)
- @io.read
- ensure
- @io.close
+ ruby_version_is ""..."4.0" do
+ platform_is_not :windows, :wasi do
+ it "opens an io when path starts with a pipe" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @io = open("|date")
+ end
+ begin
+ @io.should.is_a?(IO)
+ @io.read
+ ensure
+ @io.close
+ end
end
- end
- it "opens an io when called with a block" do
- @output = open("|date") { |f| f.read }
- @output.should_not == ''
- end
+ it "opens an io when called with a block" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @output = open("|date") { |f| f.read }
+ end
+ @output.should_not == ''
+ end
- it "opens an io for writing" do
- -> do
- bytes = open("|cat", "w") { |io| io.write(".") }
- bytes.should == 1
- end.should output_to_fd(".")
+ it "opens an io for writing" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ -> {
+ bytes = open("|cat", "w") { |io| io.write(".") }
+ bytes.should == 1
+ }.should output_to_fd(".")
+ end
+ end
end
- end
- platform_is :windows do
- it "opens an io when path starts with a pipe" do
- @io = open("|date /t")
- begin
- @io.should be_kind_of(IO)
- @io.read
- ensure
- @io.close
+ platform_is :windows do
+ it "opens an io when path starts with a pipe" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @io = open("|date /t")
+ end
+ begin
+ @io.should.is_a?(IO)
+ @io.read
+ ensure
+ @io.close
+ end
+ end
+
+ it "opens an io when called with a block" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @output = open("|date /t") { |f| f.read }
+ end
+ @output.should_not == ''
end
end
- it "opens an io when called with a block" do
- @output = open("|date /t") { |f| f.read }
- @output.should_not == ''
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation given a path with a pipe" do
+ cmd = "|echo ok"
+ -> {
+ open(cmd) { |f| f.read }
+ }.should complain(/Kernel#open with a leading '\|'/)
end
end
it "raises an ArgumentError if not passed one argument" do
- -> { open }.should raise_error(ArgumentError)
+ -> { open }.should.raise(ArgumentError)
+ end
+
+ it "accepts options as keyword arguments" do
+ @file = open(@name, "r", 0666, flags: File::CREAT)
+ @file.should.is_a?(File)
+
+ -> {
+ open(@name, "r", 0666, {flags: File::CREAT})
+ }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
describe "when given an object that responds to to_open" do
@@ -77,7 +106,7 @@ describe "Kernel#open" do
ScratchPad.clear
end
- it "calls #to_path to covert the argument to a String before calling #to_str" do
+ it "calls #to_path to convert the argument to a String before calling #to_str" do
obj = mock("open to_path")
obj.should_receive(:to_path).at_least(1).times.and_return(@name)
obj.should_not_receive(:to_str)
@@ -97,7 +126,7 @@ describe "Kernel#open" do
@file = File.open(@name)
obj.should_receive(:to_open).and_return(@file)
@file = open(obj)
- @file.should be_kind_of(File)
+ @file.should.is_a?(File)
end
it "returns the value from #to_open" do
@@ -109,11 +138,21 @@ describe "Kernel#open" do
it "passes its arguments onto #to_open" do
obj = mock('to_open')
- obj.should_receive(:to_open).with(1,2,3)
-
+ obj.should_receive(:to_open).with(1, 2, 3)
open(obj, 1, 2, 3)
end
+ it "passes keyword arguments onto #to_open as keyword arguments if to_open accepts them" do
+ obj = Object.new
+ def obj.to_open(*args, **kw)
+ ScratchPad << {args: args, kw: kw}
+ end
+
+ ScratchPad.record []
+ open(obj, 1, 2, 3, a: "b")
+ ScratchPad.recorded.should == [args: [1, 2, 3], kw: {a: "b"}]
+ end
+
it "passes the return value from #to_open to a block" do
obj = mock('to_open')
obj.should_receive(:to_open).and_return(:value)
@@ -128,37 +167,23 @@ describe "Kernel#open" do
it "raises a TypeError if passed a non-String that does not respond to #to_open" do
obj = mock('non-fileish')
- -> { open(obj) }.should raise_error(TypeError)
- -> { open(nil) }.should raise_error(TypeError)
- -> { open(7) }.should raise_error(TypeError)
+ -> { open(obj) }.should.raise(TypeError)
+ -> { open(nil) }.should.raise(TypeError)
+ -> { open(7) }.should.raise(TypeError)
end
it "accepts nil for mode and permission" do
open(@name, nil, nil) { |f| f.gets }.should == @content
end
- ruby_version_is ""..."3.0" do
- it "works correctly when redefined by open-uri" do
- code = <<~RUBY
+ it "is not redefined by open-uri" do
+ code = <<~RUBY
+ before = Kernel.instance_method(:open)
require 'open-uri'
- obj = Object.new
- def obj.to_open; self; end
- p open(obj) == obj
- RUBY
- ruby_exe(code, args: "2>&1").should == "true\n"
- end
- end
-
- ruby_version_is "3.0" do
- it "is not redefined by open-uri" do
- code = <<~RUBY
- before = Kernel.instance_method(:open)
- require 'open-uri'
- after = Kernel.instance_method(:open)
- p before == after
- RUBY
- ruby_exe(code, args: "2>&1").should == "true\n"
- end
+ after = Kernel.instance_method(:open)
+ p before == after
+ RUBY
+ ruby_exe(code, args: "2>&1").should == "true\n"
end
end
diff --git a/spec/ruby/core/kernel/p_spec.rb b/spec/ruby/core/kernel/p_spec.rb
index 1bdd1740ca..f89716899a 100644
--- a/spec/ruby/core/kernel/p_spec.rb
+++ b/spec/ruby/core/kernel/p_spec.rb
@@ -13,7 +13,7 @@ describe "Kernel#p" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:p)
+ Kernel.private_instance_methods(false).should.include?(:p)
end
# TODO: fix
@@ -76,10 +76,8 @@ describe "Kernel#p" do
-> { p(*[]) }.should output("")
end
-=begin Not sure how to spec this, but wanted to note the behavior here
- it "does not flush if receiver is not a TTY or a File" do
- end
-=end
+ # Not sure how to spec this, but wanted to note the behavior here
+ it "does not flush if receiver is not a TTY or a File"
end
describe "Kernel.p" do
diff --git a/spec/ruby/core/kernel/print_spec.rb b/spec/ruby/core/kernel/print_spec.rb
index 7e7c9b822d..5473d22f71 100644
--- a/spec/ruby/core/kernel/print_spec.rb
+++ b/spec/ruby/core/kernel/print_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel#print" do
it "is a private method" do
- Kernel.should have_private_instance_method(:print)
+ Kernel.private_instance_methods(false).should.include?(:print)
end
it "delegates to $stdout" do
diff --git a/spec/ruby/core/kernel/printf_spec.rb b/spec/ruby/core/kernel/printf_spec.rb
index d8f93ce429..50939b3794 100644
--- a/spec/ruby/core/kernel/printf_spec.rb
+++ b/spec/ruby/core/kernel/printf_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/sprintf'
describe "Kernel#printf" do
it "is a private method" do
- Kernel.should have_private_instance_method(:printf)
+ Kernel.private_instance_methods(false).should.include?(:printf)
end
end
@@ -31,6 +31,13 @@ describe "Kernel.printf" do
object.should_receive(:write).with("string")
Kernel.printf(object, "%s", "string")
end
+
+ it "calls #to_str to convert the format object to a String" do
+ object = mock('format string')
+ object.should_receive(:to_str).and_return("to_str: %i")
+ $stdout.should_receive(:write).with("to_str: 42")
+ Kernel.printf($stdout, object, 42)
+ end
end
describe "Kernel.printf" do
diff --git a/spec/ruby/core/kernel/private_methods_spec.rb b/spec/ruby/core/kernel/private_methods_spec.rb
index 041634d1e5..b0e6d042a9 100644
--- a/spec/ruby/core/kernel/private_methods_spec.rb
+++ b/spec/ruby/core/kernel/private_methods_spec.rb
@@ -6,23 +6,23 @@ require_relative '../../fixtures/reflection'
describe "Kernel#private_methods" do
it "returns a list of the names of privately accessible methods in the object" do
m = KernelSpecs::Methods.private_methods(false)
- m.should include(:shichi)
+ m.should.include?(:shichi)
m = KernelSpecs::Methods.new.private_methods(false)
- m.should include(:juu_shi)
+ m.should.include?(:juu_shi)
end
it "returns a list of the names of privately accessible methods in the object and its ancestors and mixed-in modules" do
m = (KernelSpecs::Methods.private_methods(false) & KernelSpecs::Methods.private_methods)
- m.should include(:shichi)
+ m.should.include?(:shichi)
m = KernelSpecs::Methods.new.private_methods
- m.should include(:juu_shi)
+ m.should.include?(:juu_shi)
end
it "returns private methods mixed in to the metaclass" do
m = KernelSpecs::Methods.new
m.extend(KernelSpecs::Methods::MetaclassMethods)
- m.private_methods.should include(:shoo)
+ m.private_methods.should.include?(:shoo)
end
end
diff --git a/spec/ruby/core/kernel/proc_spec.rb b/spec/ruby/core/kernel/proc_spec.rb
index 231c1f0dfb..1ba662177b 100644
--- a/spec/ruby/core/kernel/proc_spec.rb
+++ b/spec/ruby/core/kernel/proc_spec.rb
@@ -6,20 +6,20 @@ require_relative 'shared/lambda'
describe "Kernel.proc" do
it "is a private method" do
- Kernel.should have_private_instance_method(:proc)
+ Kernel.private_instance_methods(false).should.include?(:proc)
end
it "creates a proc-style Proc if given a literal block" do
l = proc { 42 }
- l.lambda?.should be_false
+ l.lambda?.should == false
end
it "returned the passed Proc if given an existing Proc" do
some_lambda = -> {}
- some_lambda.lambda?.should be_true
+ some_lambda.lambda?.should == true
l = proc(&some_lambda)
- l.should equal(some_lambda)
- l.lambda?.should be_true
+ l.should.equal?(some_lambda)
+ l.lambda?.should == true
end
it_behaves_like :kernel_lambda, :proc
@@ -31,7 +31,7 @@ describe "Kernel.proc" do
@reached_end_of_method = true
end
test
- @reached_end_of_method.should be_nil
+ @reached_end_of_method.should == nil
end
end
@@ -40,19 +40,9 @@ describe "Kernel#proc" do
proc
end
- ruby_version_is ""..."3.0" do
- it "can be created when called with no block" do
- -> {
- some_method { "hello" }
- }.should complain(/Capturing the given block using Kernel#proc is deprecated/)
- end
- end
-
- ruby_version_is "3.0" do
- it "raises an ArgumentError when passed no block" do
- -> {
- some_method { "hello" }
- }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
- end
+ it "raises an ArgumentError when passed no block" do
+ -> {
+ some_method { "hello" }
+ }.should.raise(ArgumentError, 'tried to create Proc object without a block')
end
end
diff --git a/spec/ruby/core/kernel/protected_methods_spec.rb b/spec/ruby/core/kernel/protected_methods_spec.rb
index d3334e886b..aecb9f5ffb 100644
--- a/spec/ruby/core/kernel/protected_methods_spec.rb
+++ b/spec/ruby/core/kernel/protected_methods_spec.rb
@@ -8,21 +8,21 @@ require_relative '../../fixtures/reflection'
# You should use have_protected_method() with the exception of this spec.
describe "Kernel#protected_methods" do
it "returns a list of the names of protected methods accessible in the object" do
- KernelSpecs::Methods.protected_methods(false).sort.should include(:juu_ichi)
- KernelSpecs::Methods.new.protected_methods(false).should include(:ku)
+ KernelSpecs::Methods.protected_methods(false).sort.should.include?(:juu_ichi)
+ KernelSpecs::Methods.new.protected_methods(false).should.include?(:ku)
end
it "returns a list of the names of protected methods accessible in the object and from its ancestors and mixed-in modules" do
l1 = KernelSpecs::Methods.protected_methods(false)
l2 = KernelSpecs::Methods.protected_methods
- (l1 & l2).should include(:juu_ichi)
- KernelSpecs::Methods.new.protected_methods.should include(:ku)
+ (l1 & l2).should.include?(:juu_ichi)
+ KernelSpecs::Methods.new.protected_methods.should.include?(:ku)
end
it "returns methods mixed in to the metaclass" do
m = KernelSpecs::Methods.new
m.extend(KernelSpecs::Methods::MetaclassMethods)
- m.protected_methods.should include(:nopeeking)
+ m.protected_methods.should.include?(:nopeeking)
end
end
diff --git a/spec/ruby/core/kernel/public_method_spec.rb b/spec/ruby/core/kernel/public_method_spec.rb
index c5d54c777e..42b8f797d3 100644
--- a/spec/ruby/core/kernel/public_method_spec.rb
+++ b/spec/ruby/core/kernel/public_method_spec.rb
@@ -13,20 +13,20 @@ describe "Kernel#public_method" do
@obj.send(:private_method).should == :private_method
-> do
@obj.public_method(:private_method)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError when called on a protected method" do
@obj.send(:protected_method).should == :protected_method
-> {
@obj.public_method(:protected_method)
- }.should raise_error(NameError)
+ }.should.raise(NameError)
end
it "raises a NameError if we only repond_to_missing? method, true" do
obj = KernelSpecs::RespondViaMissing.new
-> do
obj.public_method(:handled_privately)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/kernel/public_methods_spec.rb b/spec/ruby/core/kernel/public_methods_spec.rb
index a5512784fb..e334ac9a55 100644
--- a/spec/ruby/core/kernel/public_methods_spec.rb
+++ b/spec/ruby/core/kernel/public_methods_spec.rb
@@ -5,31 +5,30 @@ require_relative '../../fixtures/reflection'
# TODO: rewrite
describe "Kernel#public_methods" do
it "returns a list of the names of publicly accessible methods in the object" do
- KernelSpecs::Methods.public_methods(false).sort.should include(:hachi,
- :ichi, :juu, :juu_ni, :roku, :san, :shi)
- KernelSpecs::Methods.new.public_methods(false).sort.should include(:juu_san, :ni)
+ KernelSpecs::Methods.public_methods(false).to_set.should >= Set[:hachi, :ichi, :juu, :juu_ni, :roku, :san, :shi]
+ KernelSpecs::Methods.new.public_methods(false).to_set.should >= Set[:juu_san, :ni]
end
it "returns a list of names without protected accessible methods in the object" do
- KernelSpecs::Methods.public_methods(false).sort.should_not include(:juu_ichi)
- KernelSpecs::Methods.new.public_methods(false).sort.should_not include(:ku)
+ KernelSpecs::Methods.public_methods(false).sort.should_not.include?(:juu_ichi)
+ KernelSpecs::Methods.new.public_methods(false).sort.should_not.include?(:ku)
end
it "returns a list of the names of publicly accessible methods in the object and its ancestors and mixed-in modules" do
- (KernelSpecs::Methods.public_methods(false) & KernelSpecs::Methods.public_methods).sort.should include(
- :hachi, :ichi, :juu, :juu_ni, :roku, :san, :shi)
+ (KernelSpecs::Methods.public_methods(false) & KernelSpecs::Methods.public_methods).to_set.should >= Set[
+ :hachi, :ichi, :juu, :juu_ni, :roku, :san, :shi]
m = KernelSpecs::Methods.new.public_methods
- m.should include(:ni, :juu_san)
+ m.to_set.should >= Set[:ni, :juu_san]
end
it "returns methods mixed in to the metaclass" do
m = KernelSpecs::Methods.new
m.extend(KernelSpecs::Methods::MetaclassMethods)
- m.public_methods.should include(:peekaboo)
+ m.public_methods.should.include?(:peekaboo)
end
it "returns public methods for immediates" do
- 10.public_methods.should include(:divmod)
+ 10.public_methods.should.include?(:divmod)
end
end
diff --git a/spec/ruby/core/kernel/public_send_spec.rb b/spec/ruby/core/kernel/public_send_spec.rb
index 4dae419ff9..6a4a969c77 100644
--- a/spec/ruby/core/kernel/public_send_spec.rb
+++ b/spec/ruby/core/kernel/public_send_spec.rb
@@ -29,7 +29,7 @@ describe "Kernel#public_send" do
'done'
end
end
- -> { KernelSpecs::Foo.new.public_send(:bar)}.should raise_error(NoMethodError)
+ -> { KernelSpecs::Foo.new.public_send(:bar)}.should.raise(NoMethodError)
end
it "raises a NoMethodError if the named method is private" do
@@ -41,7 +41,7 @@ describe "Kernel#public_send" do
end
-> {
KernelSpecs::Foo.new.public_send(:bar)
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
context 'called from own public method' do
@@ -70,11 +70,11 @@ describe "Kernel#public_send" do
end
it "raises a NoMethodError if the method is protected" do
- -> { @receiver.call_protected_method }.should raise_error(NoMethodError)
+ -> { @receiver.call_protected_method }.should.raise(NoMethodError)
end
it "raises a NoMethodError if the method is private" do
- -> { @receiver.call_private_method }.should raise_error(NoMethodError)
+ -> { @receiver.call_private_method }.should.raise(NoMethodError)
end
end
@@ -88,7 +88,7 @@ describe "Kernel#public_send" do
end
-> {
KernelSpecs::Foo.new.public_send(:aka)
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
it "raises a NoMethodError if the named method is an alias of a protected method" do
@@ -101,15 +101,15 @@ describe "Kernel#public_send" do
end
-> {
KernelSpecs::Foo.new.public_send(:aka)
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
it "includes `public_send` in the backtrace when passed not enough arguments" do
- -> { public_send() }.should raise_error(ArgumentError) { |e| e.backtrace[0].should.include?("`public_send'") }
+ -> { public_send() }.should.raise(ArgumentError) { |e| e.backtrace[0].should =~ /[`'](?:Kernel#)?public_send'/ }
end
it "includes `public_send` in the backtrace when passed a single incorrect argument" do
- -> { public_send(Object.new) }.should raise_error(TypeError) { |e| e.backtrace[0].should.include?("`public_send'") }
+ -> { public_send(Object.new) }.should.raise(TypeError) { |e| e.backtrace[0].should =~ /[`'](?:Kernel#)?public_send'/ }
end
it_behaves_like :basicobject_send, :public_send
diff --git a/spec/ruby/core/kernel/putc_spec.rb b/spec/ruby/core/kernel/putc_spec.rb
index 74bd3765db..e6a20a9af1 100644
--- a/spec/ruby/core/kernel/putc_spec.rb
+++ b/spec/ruby/core/kernel/putc_spec.rb
@@ -4,7 +4,7 @@ require_relative '../../shared/io/putc'
describe "Kernel#putc" do
it "is a private instance method" do
- Kernel.should have_private_instance_method(:putc)
+ Kernel.private_instance_methods(false).should.include?(:putc)
end
end
diff --git a/spec/ruby/core/kernel/puts_spec.rb b/spec/ruby/core/kernel/puts_spec.rb
index 6eb38e8fcf..eed18fcd50 100644
--- a/spec/ruby/core/kernel/puts_spec.rb
+++ b/spec/ruby/core/kernel/puts_spec.rb
@@ -15,7 +15,7 @@ describe "Kernel#puts" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:puts)
+ Kernel.private_instance_methods(false).should.include?(:puts)
end
it "delegates to $stdout.puts" do
diff --git a/spec/ruby/core/kernel/raise_spec.rb b/spec/ruby/core/kernel/raise_spec.rb
index 4f190c120b..6162677e17 100644
--- a/spec/ruby/core/kernel/raise_spec.rb
+++ b/spec/ruby/core/kernel/raise_spec.rb
@@ -4,9 +4,19 @@ require_relative '../../shared/kernel/raise'
describe "Kernel#raise" do
it "is a private method" do
- Kernel.should have_private_instance_method(:raise)
+ Kernel.private_instance_methods.should.include?(:raise)
end
+ # Shared specs expect a public #raise method.
+ public_raiser = Object.new
+ class << public_raiser
+ public :raise
+ end
+ it_behaves_like :kernel_raise, :raise, public_raiser
+ it_behaves_like :kernel_raise_with_cause, :raise, public_raiser
+end
+
+describe "Kernel#raise with previously rescued exception" do
it "re-raises the previously rescued exception if no exception is specified" do
ScratchPad.record nil
@@ -23,35 +33,190 @@ describe "Kernel#raise" do
raise
ScratchPad.record :no_reraise
end
- end.should raise_error(Exception, "outer")
+ end.should.raise(Exception, "outer")
+
+ ScratchPad.recorded.should == nil
+ end
- ScratchPad.recorded.should be_nil
+ it "re-raises a previously rescued exception without overwriting the cause" do
+ begin
+ begin
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ raise "Error 2"
+ end
+ rescue => e2
+ raise "Error 3"
+ end
+ rescue
+ e2.cause.should == e1
+ raise e2
+ end
+ rescue => e
+ e.cause.should == e1
+ end
end
- it "accepts a cause keyword argument that sets the cause" do
- cause = StandardError.new
- -> { raise("error", cause: cause) }.should raise_error(RuntimeError) { |e| e.cause.should == cause }
+ it "re-raises a previously rescued exception with overwriting the cause when it's explicitly specified with :cause option" do
+ e4 = RuntimeError.new("Error 4")
+
+ begin
+ begin
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ raise "Error 2"
+ end
+ rescue => e2
+ raise "Error 3"
+ end
+ rescue
+ e2.cause.should == e1
+ raise e2, cause: e4
+ end
+ rescue => e
+ e.cause.should == e4
+ end
end
- it "accepts a cause keyword argument that overrides the last exception" do
+ it "re-raises a previously rescued exception without overwriting the cause when it's explicitly specified with :cause option and has nil value" do
begin
- raise "first raise"
- rescue => ignored
- cause = StandardError.new
- -> { raise("error", cause: cause) }.should raise_error(RuntimeError) { |e| e.cause.should == cause }
+ begin
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ raise "Error 2"
+ end
+ rescue => e2
+ raise "Error 3"
+ end
+ rescue
+ e2.cause.should == e1
+ raise e2, cause: nil
+ end
+ rescue => e
+ e.cause.should == e1
end
end
- it "raises an ArgumentError when only cause is given" do
- cause = StandardError.new
- -> { raise(cause: cause) }.should raise_error(ArgumentError)
+ it "re-raises a previously rescued exception without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ raise
+ end
+ rescue => e
+ e.should == e1
+ e.cause.should == nil
+ end
end
-end
-describe "Kernel#raise" do
- it_behaves_like :kernel_raise, :raise, Kernel
+ it "re-raises a previously rescued exception that has a cause without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ raise "Error 2"
+ rescue => e2
+ raise
+ end
+ end
+ rescue => e
+ e.should == e2
+ e.cause.should == e1
+ end
+ end
+
+ it "re-raises a previously rescued exception that doesn't have a cause and isn't a cause of any other exception with setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ raise "Error 2"
+ rescue => e2
+ raise "Error 3"
+ end
+ end
+ rescue => e
+ e.message.should == "Error 3"
+ e.cause.should == e2
+ end
+ end
+
+ it "re-raises a previously rescued exception that doesn't have a cause and is a cause of other exception without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ raise "Error 2"
+ rescue => e2
+ e1.cause.should == nil
+ e2.cause.should == e1
+ raise e1
+ end
+ end
+ rescue => e
+ e.should == e1
+ e.cause.should == nil
+ end
+ end
+
+ it "re-raises a previously rescued exception that doesn't have a cause and is a cause of other exception (that wasn't raised explicitly) without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ foo # raises NameError
+ rescue => e2
+ e1.cause.should == nil
+ e2.cause.should == e1
+ raise e1
+ end
+ end
+ rescue => e
+ e.should == e1
+ e.cause.should == nil
+ end
+ end
+
+ it "re-raises a previously rescued exception that has a cause but isn't a cause of any other exception without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ raise "Error 2"
+ rescue => e2
+ begin
+ raise "Error 3", cause: RuntimeError.new("Error 4")
+ rescue => e3
+ e2.cause.should == e1
+ e3.cause.should_not == e2
+ raise e2
+ end
+ end
+ end
+ rescue => e
+ e.should == e2
+ e.cause.should == e1
+ end
+ end
end
describe "Kernel.raise" do
- it "needs to be reviewed for spec completeness"
+ it "is a public method" do
+ Kernel.singleton_class.should.public_method_defined?(:raise)
+ end
+
+ it_behaves_like :kernel_raise, :raise, Kernel
+ it_behaves_like :kernel_raise_with_cause, :raise, Kernel
end
diff --git a/spec/ruby/core/kernel/rand_spec.rb b/spec/ruby/core/kernel/rand_spec.rb
index 355e425792..1bf5e225d9 100644
--- a/spec/ruby/core/kernel/rand_spec.rb
+++ b/spec/ruby/core/kernel/rand_spec.rb
@@ -3,42 +3,42 @@ require_relative 'fixtures/classes'
describe "Kernel#rand" do
it "is a private method" do
- Kernel.should have_private_instance_method(:rand)
+ Kernel.private_instance_methods(false).should.include?(:rand)
end
it "returns a float if no argument is passed" do
- rand.should be_kind_of(Float)
+ rand.should.is_a?(Float)
end
it "returns an integer for an integer argument" do
- rand(77).should be_kind_of(Integer)
+ rand(77).should.is_a?(Integer)
end
it "returns an integer for a float argument greater than 1" do
- rand(1.3).should be_kind_of(Integer)
+ rand(1.3).should.is_a?(Integer)
end
it "returns a float for an argument between -1 and 1" do
- rand(-0.999).should be_kind_of(Float)
- rand(-0.01).should be_kind_of(Float)
- rand(0).should be_kind_of(Float)
- rand(0.01).should be_kind_of(Float)
- rand(0.999).should be_kind_of(Float)
+ rand(-0.999).should.is_a?(Float)
+ rand(-0.01).should.is_a?(Float)
+ rand(0).should.is_a?(Float)
+ rand(0.01).should.is_a?(Float)
+ rand(0.999).should.is_a?(Float)
end
it "ignores the sign of the argument" do
- [0, 1, 2, 3].should include(rand(-4))
+ [0, 1, 2, 3].should.include?(rand(-4))
end
it "never returns a value greater or equal to 1.0 with no arguments" do
1000.times do
- (0...1.0).should include(rand)
+ (0...1.0).should.include?(rand)
end
end
it "never returns a value greater or equal to any passed in max argument" do
1000.times do
- (0...100).to_a.should include(rand(100))
+ (0...100).to_a.should.include?(rand(100))
end
end
@@ -53,32 +53,32 @@ describe "Kernel#rand" do
it "returns an Integer between the two Integers" do
1000.times do
x = rand(4...6)
- x.should be_kind_of(Integer)
- (4...6).should include(x)
+ x.should.is_a?(Integer)
+ (4...6).should.include?(x)
end
end
it "returns a Float between the given Integer and Float" do
1000.times do
x = rand(4...6.5)
- x.should be_kind_of(Float)
- (4...6.5).should include(x)
+ x.should.is_a?(Float)
+ (4...6.5).should.include?(x)
end
end
it "returns a Float between the given Float and Integer" do
1000.times do
x = rand(3.5...6)
- x.should be_kind_of(Float)
- (3.5...6).should include(x)
+ x.should.is_a?(Float)
+ (3.5...6).should.include?(x)
end
end
it "returns a Float between the two given Floats" do
1000.times do
x = rand(3.5...6.5)
- x.should be_kind_of(Float)
- (3.5...6.5).should include(x)
+ x.should.is_a?(Float)
+ (3.5...6.5).should.include?(x)
end
end
end
@@ -87,32 +87,32 @@ describe "Kernel#rand" do
it "returns an Integer between the two Integers" do
1000.times do
x = rand(4..6)
- x.should be_kind_of(Integer)
- (4..6).should include(x)
+ x.should.is_a?(Integer)
+ (4..6).should.include?(x)
end
end
it "returns a Float between the given Integer and Float" do
1000.times do
x = rand(4..6.5)
- x.should be_kind_of(Float)
- (4..6.5).should include(x)
+ x.should.is_a?(Float)
+ (4..6.5).should.include?(x)
end
end
it "returns a Float between the given Float and Integer" do
1000.times do
x = rand(3.5..6)
- x.should be_kind_of(Float)
- (3.5..6).should include(x)
+ x.should.is_a?(Float)
+ (3.5..6).should.include?(x)
end
end
it "returns a Float between the two given Floats" do
1000.times do
x = rand(3.5..6.5)
- x.should be_kind_of(Float)
- (3.5..6.5).should include(x)
+ x.should.is_a?(Float)
+ (3.5..6.5).should.include?(x)
end
end
end
@@ -120,8 +120,8 @@ describe "Kernel#rand" do
context "given an inclusive range between 0 and 1" do
it "returns an Integer between the two Integers" do
x = rand(0..1)
- x.should be_kind_of(Integer)
- (0..1).should include(x)
+ x.should.is_a?(Integer)
+ (0..1).should.include?(x)
end
it "returns a Float if at least one side is Float" do
@@ -130,19 +130,19 @@ describe "Kernel#rand" do
x2 = Random.new(seed).rand(0.0..1.0)
x3 = Random.new(seed).rand(0.0..1)
- x3.should be_kind_of(Float)
- x1.should eql(x3)
- x2.should eql(x3)
+ x3.should.is_a?(Float)
+ x1.should.eql?(x3)
+ x2.should.eql?(x3)
- (0.0..1.0).should include(x3)
+ (0.0..1.0).should.include?(x3)
end
end
context "given an exclusive range between 0 and 1" do
it "returns zero as an Integer" do
x = rand(0...1)
- x.should be_kind_of(Integer)
- x.should eql(0)
+ x.should.is_a?(Integer)
+ x.should.eql?(0)
end
it "returns a Float if at least one side is Float" do
@@ -151,34 +151,34 @@ describe "Kernel#rand" do
x2 = Random.new(seed).rand(0.0...1.0)
x3 = Random.new(seed).rand(0.0...1)
- x3.should be_kind_of(Float)
- x1.should eql(x3)
- x2.should eql(x3)
+ x3.should.is_a?(Float)
+ x1.should.eql?(x3)
+ x2.should.eql?(x3)
- (0.0...1.0).should include(x3)
+ (0.0...1.0).should.include?(x3)
end
end
it "returns a numeric for an range argument where max is < 1" do
- rand(0.25..0.75).should be_kind_of(Numeric)
+ rand(0.25..0.75).should.is_a?(Numeric)
end
it "returns nil when range is backwards" do
- rand(1..0).should be_nil
+ rand(1..0).should == nil
end
it "returns the range start/end when Float range is 0" do
- rand(1.0..1.0).should eql(1.0)
+ rand(1.0..1.0).should.eql?(1.0)
end
it "returns the range start/end when Integer range is 0" do
- rand(42..42).should eql(42)
+ rand(42..42).should.eql?(42)
end
it "supports custom object types" do
- rand(KernelSpecs::CustomRangeInteger.new(1)..KernelSpecs::CustomRangeInteger.new(42)).should be_an_instance_of(KernelSpecs::CustomRangeInteger)
- rand(KernelSpecs::CustomRangeFloat.new(1.0)..KernelSpecs::CustomRangeFloat.new(42.0)).should be_an_instance_of(KernelSpecs::CustomRangeFloat)
- rand(Time.now..Time.now).should be_an_instance_of(Time)
+ rand(KernelSpecs::CustomRangeInteger.new(1)..KernelSpecs::CustomRangeInteger.new(42)).should.instance_of?(KernelSpecs::CustomRangeInteger)
+ rand(KernelSpecs::CustomRangeFloat.new(1.0)..KernelSpecs::CustomRangeFloat.new(42.0)).should.instance_of?(KernelSpecs::CustomRangeFloat)
+ rand(Time.now..Time.now).should.instance_of?(Time)
end
it "is random on boot" do
diff --git a/spec/ruby/core/kernel/readline_spec.rb b/spec/ruby/core/kernel/readline_spec.rb
index dce7b03dc8..86899d78d2 100644
--- a/spec/ruby/core/kernel/readline_spec.rb
+++ b/spec/ruby/core/kernel/readline_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel#readline" do
it "is a private method" do
- Kernel.should have_private_instance_method(:readline)
+ Kernel.private_instance_methods(false).should.include?(:readline)
end
end
diff --git a/spec/ruby/core/kernel/readlines_spec.rb b/spec/ruby/core/kernel/readlines_spec.rb
index 2b6d65fff2..c758014aab 100644
--- a/spec/ruby/core/kernel/readlines_spec.rb
+++ b/spec/ruby/core/kernel/readlines_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel#readlines" do
it "is a private method" do
- Kernel.should have_private_instance_method(:readlines)
+ Kernel.private_instance_methods(false).should.include?(:readlines)
end
end
diff --git a/spec/ruby/core/kernel/remove_instance_variable_spec.rb b/spec/ruby/core/kernel/remove_instance_variable_spec.rb
index 4e5ba5e018..114536064f 100644
--- a/spec/ruby/core/kernel/remove_instance_variable_spec.rb
+++ b/spec/ruby/core/kernel/remove_instance_variable_spec.rb
@@ -9,7 +9,7 @@ describe :kernel_remove_instance_variable, shared: true do
it "removes the instance variable" do
@instance.send :remove_instance_variable, @object
- @instance.instance_variable_defined?(@object).should be_false
+ @instance.instance_variable_defined?(@object).should == false
end
end
@@ -19,39 +19,39 @@ describe "Kernel#remove_instance_variable" do
end
it "is a public method" do
- Kernel.should have_public_instance_method(:remove_instance_variable, false)
+ Kernel.public_instance_methods(false).should.include?(:remove_instance_variable)
end
it "raises a NameError if the instance variable is not defined" do
-> do
@instance.send :remove_instance_variable, :@unknown
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError if the argument is not a valid instance variable name" do
-> do
@instance.send :remove_instance_variable, :"@0"
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a TypeError if passed an Object not defining #to_str" do
-> do
obj = mock("kernel remove_instance_variable")
@instance.send :remove_instance_variable, obj
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a FrozenError if self is frozen" do
o = Object.new
o.freeze
- -> { o.remove_instance_variable(:@foo) }.should raise_error(FrozenError)
- -> { o.remove_instance_variable(:foo) }.should raise_error(NameError)
+ -> { o.remove_instance_variable(:@foo) }.should.raise(FrozenError)
+ -> { o.remove_instance_variable(:foo) }.should.raise(NameError)
end
it "raises for frozen objects" do
- -> { nil.remove_instance_variable(:@foo) }.should raise_error(FrozenError)
- -> { nil.remove_instance_variable(:foo) }.should raise_error(NameError)
- -> { :foo.remove_instance_variable(:@foo) }.should raise_error(FrozenError)
+ -> { nil.remove_instance_variable(:@foo) }.should.raise(FrozenError)
+ -> { nil.remove_instance_variable(:foo) }.should.raise(NameError)
+ -> { :foo.remove_instance_variable(:@foo) }.should.raise(FrozenError)
end
describe "when passed a String" do
diff --git a/spec/ruby/core/kernel/require_relative_spec.rb b/spec/ruby/core/kernel/require_relative_spec.rb
index 5999855de6..332045b200 100644
--- a/spec/ruby/core/kernel/require_relative_spec.rb
+++ b/spec/ruby/core/kernel/require_relative_spec.rb
@@ -5,9 +5,9 @@ describe "Kernel#require_relative with a relative path" do
before :each do
CodeLoadingSpecs.spec_setup
@dir = "../../fixtures/code"
- @abs_dir = File.realpath(@dir, File.dirname(__FILE__))
+ @abs_dir = File.realpath(@dir, __dir__)
@path = "#{@dir}/load_fixture.rb"
- @abs_path = File.realpath(@path, File.dirname(__FILE__))
+ @abs_path = File.realpath(@path, __dir__)
end
after :each do
@@ -27,14 +27,14 @@ describe "Kernel#require_relative with a relative path" do
end
it "loads a path relative to current file" do
- require_relative(@link).should be_true
+ require_relative(@link).should == true
ScratchPad.recorded.should == [:loaded]
end
end
end
it "loads a path relative to the current file" do
- require_relative(@path).should be_true
+ require_relative(@path).should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -42,14 +42,14 @@ describe "Kernel#require_relative with a relative path" do
it "synthetic file base name loads a file base name relative to the working directory" do
Dir.chdir @abs_dir do
- Object.new.instance_eval("require_relative(#{File.basename(@path).inspect})", "foo.rb").should be_true
+ Object.new.instance_eval("require_relative(#{File.basename(@path).inspect})", "foo.rb").should == true
end
ScratchPad.recorded.should == [:loaded]
end
it "synthetic file path loads a relative path relative to the working directory plus the directory of the synthetic path" do
Dir.chdir @abs_dir do
- Object.new.instance_eval("require_relative(File.join('..', #{File.basename(@path).inspect}))", "bar/foo.rb").should be_true
+ Object.new.instance_eval("require_relative(File.join('..', #{File.basename(@path).inspect}))", "bar/foo.rb").should == true
end
ScratchPad.recorded.should == [:loaded]
end
@@ -57,14 +57,14 @@ describe "Kernel#require_relative with a relative path" do
platform_is_not :windows do
it "synthetic relative file path with a Windows path separator specified loads a relative path relative to the working directory" do
Dir.chdir @abs_dir do
- Object.new.instance_eval("require_relative(#{File.basename(@path).inspect})", "bar\\foo.rb").should be_true
+ Object.new.instance_eval("require_relative(#{File.basename(@path).inspect})", "bar\\foo.rb").should == true
end
ScratchPad.recorded.should == [:loaded]
end
end
it "absolute file path loads a path relative to the absolute path" do
- Object.new.instance_eval("require_relative(#{@path.inspect})", __FILE__).should be_true
+ Object.new.instance_eval("require_relative(#{@path.inspect})", __FILE__).should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -74,34 +74,34 @@ describe "Kernel#require_relative with a relative path" do
root = File.dirname(root)
end
root_relative = @abs_path[root.size..-1]
- Object.new.instance_eval("require_relative(#{root_relative.inspect})", "/").should be_true
+ Object.new.instance_eval("require_relative(#{root_relative.inspect})", "/").should == true
ScratchPad.recorded.should == [:loaded]
end
end
it "loads a file defining many methods" do
- require_relative("#{@dir}/methods_fixture.rb").should be_true
+ require_relative("#{@dir}/methods_fixture.rb").should == true
ScratchPad.recorded.should == [:loaded]
end
it "raises a LoadError if the file does not exist" do
- -> { require_relative("#{@dir}/nonexistent.rb") }.should raise_error(LoadError)
+ -> { require_relative("#{@dir}/nonexistent.rb") }.should.raise(LoadError)
ScratchPad.recorded.should == []
end
it "raises a LoadError that includes the missing path" do
missing_path = "#{@dir}/nonexistent.rb"
- expanded_missing_path = File.expand_path(missing_path, File.dirname(__FILE__))
- -> { require_relative(missing_path) }.should raise_error(LoadError) { |e|
- e.message.should include(expanded_missing_path)
+ expanded_missing_path = File.expand_path(missing_path, __dir__)
+ -> { require_relative(missing_path) }.should.raise(LoadError) { |e|
+ e.message.should.include?(expanded_missing_path)
e.path.should == expanded_missing_path
}
ScratchPad.recorded.should == []
end
it "raises a LoadError if basepath does not exist" do
- -> { eval("require_relative('#{@dir}/nonexistent.rb')") }.should raise_error(LoadError)
+ -> { eval("require_relative('#{@dir}/nonexistent.rb')") }.should.raise(LoadError)
end
it "stores the missing path in a LoadError object" do
@@ -117,34 +117,34 @@ describe "Kernel#require_relative with a relative path" do
it "calls #to_str on non-String objects" do
name = mock("load_fixture.rb mock")
name.should_receive(:to_str).and_return(@path)
- require_relative(name).should be_true
+ require_relative(name).should == true
ScratchPad.recorded.should == [:loaded]
end
it "raises a TypeError if argument does not respond to #to_str" do
- -> { require_relative(nil) }.should raise_error(TypeError)
- -> { require_relative(42) }.should raise_error(TypeError)
+ -> { require_relative(nil) }.should.raise(TypeError)
+ -> { require_relative(42) }.should.raise(TypeError)
-> {
require_relative([@path,@path])
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises a TypeError if passed an object that has #to_s but not #to_str" do
name = mock("load_fixture.rb mock")
name.stub!(:to_s).and_return(@path)
- -> { require_relative(name) }.should raise_error(TypeError)
+ -> { require_relative(name) }.should.raise(TypeError)
end
it "raises a TypeError if #to_str does not return a String" do
name = mock("#to_str returns nil")
name.should_receive(:to_str).at_least(1).times.and_return(nil)
- -> { require_relative(name) }.should raise_error(TypeError)
+ -> { require_relative(name) }.should.raise(TypeError)
end
it "calls #to_path on non-String objects" do
name = mock("load_fixture.rb mock")
name.should_receive(:to_path).and_return(@path)
- require_relative(name).should be_true
+ require_relative(name).should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -153,13 +153,13 @@ describe "Kernel#require_relative with a relative path" do
to_path = mock("load_fixture_rb #to_path mock")
name.should_receive(:to_path).and_return(to_path)
to_path.should_receive(:to_str).and_return(@path)
- require_relative(name).should be_true
+ require_relative(name).should == true
ScratchPad.recorded.should == [:loaded]
end
describe "(file extensions)" do
it "loads a .rb extensioned file when passed a non-extensioned path" do
- require_relative("#{@dir}/load_fixture").should be_true
+ require_relative("#{@dir}/load_fixture").should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -168,20 +168,20 @@ describe "Kernel#require_relative with a relative path" do
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.dylib"
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.so"
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.dll"
- require_relative(@path).should be_true
+ require_relative(@path).should == true
ScratchPad.recorded.should == [:loaded]
end
it "does not load a C-extension file if a .rb extensioned file is already loaded" do
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.rb"
- require_relative("#{@dir}/load_fixture").should be_false
+ require_relative("#{@dir}/load_fixture").should == false
ScratchPad.recorded.should == []
end
it "loads a .rb extensioned file when passed a non-.rb extensioned path" do
- require_relative("#{@dir}/load_fixture.ext").should be_true
+ require_relative("#{@dir}/load_fixture.ext").should == true
ScratchPad.recorded.should == [:loaded]
- $LOADED_FEATURES.should include "#{@abs_dir}/load_fixture.ext.rb"
+ $LOADED_FEATURES.should.include? "#{@abs_dir}/load_fixture.ext.rb"
end
it "loads a .rb extensioned file when a complex-extensioned C-extension file of the same name is loaded" do
@@ -189,22 +189,22 @@ describe "Kernel#require_relative with a relative path" do
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.dylib"
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.so"
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.dll"
- require_relative("#{@dir}/load_fixture.ext").should be_true
+ require_relative("#{@dir}/load_fixture.ext").should == true
ScratchPad.recorded.should == [:loaded]
- $LOADED_FEATURES.should include "#{@abs_dir}/load_fixture.ext.rb"
+ $LOADED_FEATURES.should.include? "#{@abs_dir}/load_fixture.ext.rb"
end
it "does not load a C-extension file if a complex-extensioned .rb file is already loaded" do
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.rb"
- require_relative("#{@dir}/load_fixture.ext").should be_false
+ require_relative("#{@dir}/load_fixture.ext").should == false
ScratchPad.recorded.should == []
end
end
describe "($LOADED_FEATURES)" do
it "stores an absolute path" do
- require_relative(@path).should be_true
- $LOADED_FEATURES.should include(@abs_path)
+ require_relative(@path).should == true
+ $LOADED_FEATURES.should.include?(@abs_path)
end
platform_is_not :windows, :wasi do
@@ -231,8 +231,8 @@ describe "Kernel#require_relative with a relative path" do
ScratchPad.recorded.should == [:loaded]
features = $LOADED_FEATURES.select { |path| path.end_with?('load_fixture.rb') }
- features.should include(absolute_path)
- features.should_not include(canonical_path)
+ features.should.include?(absolute_path)
+ features.should_not.include?(canonical_path)
end
it "stores the same path that __FILE__ returns in the required file" do
@@ -249,26 +249,26 @@ describe "Kernel#require_relative with a relative path" do
it "does not store the path if the load fails" do
saved_loaded_features = $LOADED_FEATURES.dup
- -> { require_relative("#{@dir}/raise_fixture.rb") }.should raise_error(RuntimeError)
+ -> { require_relative("#{@dir}/raise_fixture.rb") }.should.raise(RuntimeError)
$LOADED_FEATURES.should == saved_loaded_features
end
it "does not load an absolute path that is already stored" do
$LOADED_FEATURES << @abs_path
- require_relative(@path).should be_false
+ require_relative(@path).should == false
ScratchPad.recorded.should == []
end
it "adds the suffix of the resolved filename" do
- require_relative("#{@dir}/load_fixture").should be_true
- $LOADED_FEATURES.should include("#{@abs_dir}/load_fixture.rb")
+ require_relative("#{@dir}/load_fixture").should == true
+ $LOADED_FEATURES.should.include?("#{@abs_dir}/load_fixture.rb")
end
it "loads a path for a file already loaded with a relative path" do
$LOAD_PATH << File.expand_path(@dir)
$LOADED_FEATURES << "load_fixture.rb" << "load_fixture"
- require_relative(@path).should be_true
- $LOADED_FEATURES.should include(@abs_path)
+ require_relative(@path).should == true
+ $LOADED_FEATURES.should.include?(@abs_path)
ScratchPad.recorded.should == [:loaded]
end
end
@@ -277,7 +277,7 @@ end
describe "Kernel#require_relative with an absolute path" do
before :each do
CodeLoadingSpecs.spec_setup
- @dir = File.expand_path "../../fixtures/code", File.dirname(__FILE__)
+ @dir = File.expand_path "../../fixtures/code", __dir__
@abs_dir = @dir
@path = File.join @dir, "load_fixture.rb"
@abs_path = @path
@@ -288,22 +288,22 @@ describe "Kernel#require_relative with an absolute path" do
end
it "loads a path relative to the current file" do
- require_relative(@path).should be_true
+ require_relative(@path).should == true
ScratchPad.recorded.should == [:loaded]
end
it "loads a file defining many methods" do
- require_relative("#{@dir}/methods_fixture.rb").should be_true
+ require_relative("#{@dir}/methods_fixture.rb").should == true
ScratchPad.recorded.should == [:loaded]
end
it "raises a LoadError if the file does not exist" do
- -> { require_relative("#{@dir}/nonexistent.rb") }.should raise_error(LoadError)
+ -> { require_relative("#{@dir}/nonexistent.rb") }.should.raise(LoadError)
ScratchPad.recorded.should == []
end
it "raises a LoadError if basepath does not exist" do
- -> { eval("require_relative('#{@dir}/nonexistent.rb')") }.should raise_error(LoadError)
+ -> { eval("require_relative('#{@dir}/nonexistent.rb')") }.should.raise(LoadError)
end
it "stores the missing path in a LoadError object" do
@@ -319,34 +319,34 @@ describe "Kernel#require_relative with an absolute path" do
it "calls #to_str on non-String objects" do
name = mock("load_fixture.rb mock")
name.should_receive(:to_str).and_return(@path)
- require_relative(name).should be_true
+ require_relative(name).should == true
ScratchPad.recorded.should == [:loaded]
end
it "raises a TypeError if argument does not respond to #to_str" do
- -> { require_relative(nil) }.should raise_error(TypeError)
- -> { require_relative(42) }.should raise_error(TypeError)
+ -> { require_relative(nil) }.should.raise(TypeError)
+ -> { require_relative(42) }.should.raise(TypeError)
-> {
require_relative([@path,@path])
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises a TypeError if passed an object that has #to_s but not #to_str" do
name = mock("load_fixture.rb mock")
name.stub!(:to_s).and_return(@path)
- -> { require_relative(name) }.should raise_error(TypeError)
+ -> { require_relative(name) }.should.raise(TypeError)
end
it "raises a TypeError if #to_str does not return a String" do
name = mock("#to_str returns nil")
name.should_receive(:to_str).at_least(1).times.and_return(nil)
- -> { require_relative(name) }.should raise_error(TypeError)
+ -> { require_relative(name) }.should.raise(TypeError)
end
it "calls #to_path on non-String objects" do
name = mock("load_fixture.rb mock")
name.should_receive(:to_path).and_return(@path)
- require_relative(name).should be_true
+ require_relative(name).should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -355,13 +355,13 @@ describe "Kernel#require_relative with an absolute path" do
to_path = mock("load_fixture_rb #to_path mock")
name.should_receive(:to_path).and_return(to_path)
to_path.should_receive(:to_str).and_return(@path)
- require_relative(name).should be_true
+ require_relative(name).should == true
ScratchPad.recorded.should == [:loaded]
end
describe "(file extensions)" do
it "loads a .rb extensioned file when passed a non-extensioned path" do
- require_relative("#{@dir}/load_fixture").should be_true
+ require_relative("#{@dir}/load_fixture").should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -370,20 +370,20 @@ describe "Kernel#require_relative with an absolute path" do
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.dylib"
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.so"
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.dll"
- require_relative(@path).should be_true
+ require_relative(@path).should == true
ScratchPad.recorded.should == [:loaded]
end
it "does not load a C-extension file if a .rb extensioned file is already loaded" do
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.rb"
- require_relative("#{@dir}/load_fixture").should be_false
+ require_relative("#{@dir}/load_fixture").should == false
ScratchPad.recorded.should == []
end
it "loads a .rb extensioned file when passed a non-.rb extensioned path" do
- require_relative("#{@dir}/load_fixture.ext").should be_true
+ require_relative("#{@dir}/load_fixture.ext").should == true
ScratchPad.recorded.should == [:loaded]
- $LOADED_FEATURES.should include "#{@abs_dir}/load_fixture.ext.rb"
+ $LOADED_FEATURES.should.include? "#{@abs_dir}/load_fixture.ext.rb"
end
it "loads a .rb extensioned file when a complex-extensioned C-extension file of the same name is loaded" do
@@ -391,46 +391,46 @@ describe "Kernel#require_relative with an absolute path" do
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.dylib"
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.so"
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.dll"
- require_relative("#{@dir}/load_fixture.ext").should be_true
+ require_relative("#{@dir}/load_fixture.ext").should == true
ScratchPad.recorded.should == [:loaded]
- $LOADED_FEATURES.should include "#{@abs_dir}/load_fixture.ext.rb"
+ $LOADED_FEATURES.should.include? "#{@abs_dir}/load_fixture.ext.rb"
end
it "does not load a C-extension file if a complex-extensioned .rb file is already loaded" do
$LOADED_FEATURES << "#{@abs_dir}/load_fixture.ext.rb"
- require_relative("#{@dir}/load_fixture.ext").should be_false
+ require_relative("#{@dir}/load_fixture.ext").should == false
ScratchPad.recorded.should == []
end
end
describe "($LOAD_FEATURES)" do
it "stores an absolute path" do
- require_relative(@path).should be_true
- $LOADED_FEATURES.should include(@abs_path)
+ require_relative(@path).should == true
+ $LOADED_FEATURES.should.include?(@abs_path)
end
it "does not store the path if the load fails" do
saved_loaded_features = $LOADED_FEATURES.dup
- -> { require_relative("#{@dir}/raise_fixture.rb") }.should raise_error(RuntimeError)
+ -> { require_relative("#{@dir}/raise_fixture.rb") }.should.raise(RuntimeError)
$LOADED_FEATURES.should == saved_loaded_features
end
it "does not load an absolute path that is already stored" do
$LOADED_FEATURES << @abs_path
- require_relative(@path).should be_false
+ require_relative(@path).should == false
ScratchPad.recorded.should == []
end
it "adds the suffix of the resolved filename" do
- require_relative("#{@dir}/load_fixture").should be_true
- $LOADED_FEATURES.should include("#{@abs_dir}/load_fixture.rb")
+ require_relative("#{@dir}/load_fixture").should == true
+ $LOADED_FEATURES.should.include?("#{@abs_dir}/load_fixture.rb")
end
it "loads a path for a file already loaded with a relative path" do
$LOAD_PATH << File.expand_path(@dir)
$LOADED_FEATURES << "load_fixture.rb" << "load_fixture"
- require_relative(@path).should be_true
- $LOADED_FEATURES.should include(@abs_path)
+ require_relative(@path).should == true
+ $LOADED_FEATURES.should.include?(@abs_path)
ScratchPad.recorded.should == [:loaded]
end
end
diff --git a/spec/ruby/core/kernel/require_spec.rb b/spec/ruby/core/kernel/require_spec.rb
index dc3da4b7e6..62d954c2bf 100644
--- a/spec/ruby/core/kernel/require_spec.rb
+++ b/spec/ruby/core/kernel/require_spec.rb
@@ -13,7 +13,40 @@ describe "Kernel#require" do
# if this fails, update your rubygems
it "is a private method" do
- Kernel.should have_private_instance_method(:require)
+ Kernel.private_instance_methods(false).should.include?(:require)
+ end
+
+ it "provided features are already required" do
+ provided = %w[complex enumerator fiber rational thread ruby2_keywords]
+ ruby_version_is "4.0" do
+ provided += %w[set pathname]
+ end
+ ruby_version_is "4.1" do
+ provided += %w[monitor]
+ end
+
+ out = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems --disable-did-you-mean')
+ features = out.lines.map(&:chomp)
+
+ # Ignore engine-specific internals
+ case RUBY_ENGINE
+ when "jruby"
+ features -= %w[java.rb jruby/util.rb]
+ when "ruby"
+ so = RbConfig::CONFIG['DLEXT']
+ features -= ["windows_1252.#{so}", "windows_31.#{so}"]
+ features.reject! { |feature| feature.end_with? "encdb.#{so}" }
+ features.reject! { |feature| feature.end_with? "transdb.#{so}" }
+ features.reject! { |feature| feature.include?('-fake') }
+ end
+
+ features_no_ext = features.map { |path| File.basename(path, '.*') }
+ features_no_ext.sort.should == provided.sort
+
+ requires = features
+ code = requires.map { |f| "puts require #{f.inspect}\n" }.join
+ required = ruby_exe(code, options: '--disable-gems')
+ required.should == "false\n" * requires.size
end
it_behaves_like :kernel_require_basic, :require, CodeLoadingSpecs::Method.new
diff --git a/spec/ruby/core/kernel/respond_to_missing_spec.rb b/spec/ruby/core/kernel/respond_to_missing_spec.rb
index cc82031e26..08c9184fb4 100644
--- a/spec/ruby/core/kernel/respond_to_missing_spec.rb
+++ b/spec/ruby/core/kernel/respond_to_missing_spec.rb
@@ -7,7 +7,7 @@ describe "Kernel#respond_to_missing?" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:respond_to_missing?, false)
+ Kernel.private_instance_methods(false).should.include?(:respond_to_missing?)
end
it "is only an instance method" do
@@ -18,7 +18,7 @@ describe "Kernel#respond_to_missing?" do
obj = mock('object')
obj.stub!(:glark)
obj.should_not_receive(:respond_to_missing?)
- obj.respond_to?(:glark).should be_true
+ obj.respond_to?(:glark).should == true
end
it "is called with a 2nd argument of false when #respond_to? is" do
@@ -48,39 +48,39 @@ describe "Kernel#respond_to_missing?" do
it "causes #respond_to? to return true if called and not returning false" do
obj = mock('object')
obj.should_receive(:respond_to_missing?).with(:undefined_method, false).and_return(:glark)
- obj.respond_to?(:undefined_method).should be_true
+ obj.respond_to?(:undefined_method).should == true
end
it "causes #respond_to? to return false if called and returning false" do
obj = mock('object')
obj.should_receive(:respond_to_missing?).with(:undefined_method, false).and_return(false)
- obj.respond_to?(:undefined_method).should be_false
+ obj.respond_to?(:undefined_method).should == false
end
it "causes #respond_to? to return false if called and returning nil" do
obj = mock('object')
obj.should_receive(:respond_to_missing?).with(:undefined_method, false).and_return(nil)
- obj.respond_to?(:undefined_method).should be_false
+ obj.respond_to?(:undefined_method).should == false
end
it "isn't called when obj responds to the given public method" do
@a.should_not_receive(:respond_to_missing?)
- @a.respond_to?(:pub_method).should be_true
+ @a.respond_to?(:pub_method).should == true
end
it "isn't called when obj responds to the given public method, include_private = true" do
@a.should_not_receive(:respond_to_missing?)
- @a.respond_to?(:pub_method, true).should be_true
+ @a.respond_to?(:pub_method, true).should == true
end
it "is called when obj responds to the given protected method, include_private = false" do
@a.should_receive(:respond_to_missing?)
- @a.respond_to?(:protected_method, false).should be_false
+ @a.respond_to?(:protected_method, false).should == false
end
it "isn't called when obj responds to the given protected method, include_private = true" do
@a.should_not_receive(:respond_to_missing?)
- @a.respond_to?(:protected_method, true).should be_true
+ @a.respond_to?(:protected_method, true).should == true
end
it "is called when obj responds to the given private method, include_private = false" do
@@ -90,7 +90,7 @@ describe "Kernel#respond_to_missing?" do
it "isn't called when obj responds to the given private method, include_private = true" do
@a.should_not_receive(:respond_to_missing?)
- @a.respond_to?(:private_method, true).should be_true
+ @a.respond_to?(:private_method, true).should == true
end
it "is called for missing class methods" do
diff --git a/spec/ruby/core/kernel/respond_to_spec.rb b/spec/ruby/core/kernel/respond_to_spec.rb
index 5b3ea3f651..72ab4eebe1 100644
--- a/spec/ruby/core/kernel/respond_to_spec.rb
+++ b/spec/ruby/core/kernel/respond_to_spec.rb
@@ -7,7 +7,7 @@ describe "Kernel#respond_to?" do
end
it "is a public method" do
- Kernel.should have_public_instance_method(:respond_to?, false)
+ Kernel.public_instance_methods(false).should.include?(:respond_to?)
end
it "is only an instance method" do
@@ -25,7 +25,7 @@ describe "Kernel#respond_to?" do
end
it "throws a type error if argument can't be coerced into a Symbol" do
- -> { @a.respond_to?(Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { @a.respond_to?(Object.new) }.should.raise(TypeError, /is not a symbol nor a string/)
end
it "returns false if obj responds to the given protected method" do
@@ -61,7 +61,7 @@ describe "Kernel#respond_to?" do
it "does not change method visibility when finding private method" do
KernelSpecs::VisibilityChange.respond_to?(:new, false).should == false
KernelSpecs::VisibilityChange.respond_to?(:new, true).should == true
- -> { KernelSpecs::VisibilityChange.new }.should raise_error(NoMethodError)
+ -> { KernelSpecs::VisibilityChange.new }.should.raise(NoMethodError)
end
it "indicates if an object responds to a particular message" do
@@ -69,4 +69,31 @@ describe "Kernel#respond_to?" do
KernelSpecs::Foo.new.respond_to?(:bar).should == true
KernelSpecs::Foo.new.respond_to?(:invalid_and_silly_method_name).should == false
end
+
+ context "if object does not have #respond_to_missing?" do
+ it "returns true if object responds to the given public method" do
+ KernelSpecs::BasicA.new.respond_to?(:pub_method).should == true
+ KernelSpecs::MissingA.new.respond_to?(:pub_method).should == true
+ end
+
+ it "returns false if object responds to the given protected method" do
+ KernelSpecs::BasicA.new.respond_to?(:protected_method).should == false
+ KernelSpecs::MissingA.new.respond_to?(:protected_method).should == false
+ end
+
+ it "returns false if object responds to the given private method" do
+ KernelSpecs::BasicA.new.respond_to?(:private_method).should == false
+ KernelSpecs::MissingA.new.respond_to?(:private_method).should == false
+ end
+
+ it "returns false if the given method was undefined" do
+ KernelSpecs::BasicA.new.respond_to?(:undefed_method).should == false
+ KernelSpecs::MissingA.new.respond_to?(:undefed_method).should == false
+ end
+
+ it "returns false if the given method never existed" do
+ KernelSpecs::BasicA.new.respond_to?(:invalid_and_silly_method_name).should == false
+ KernelSpecs::MissingA.new.respond_to?(:invalid_and_silly_method_name).should == false
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/select_spec.rb b/spec/ruby/core/kernel/select_spec.rb
index e0d82f3079..58c963c1a4 100644
--- a/spec/ruby/core/kernel/select_spec.rb
+++ b/spec/ruby/core/kernel/select_spec.rb
@@ -3,16 +3,16 @@ require_relative 'fixtures/classes'
describe "Kernel#select" do
it "is a private method" do
- Kernel.should have_private_instance_method(:select)
+ Kernel.private_instance_methods(false).should.include?(:select)
end
end
describe "Kernel.select" do
it 'does not block when timeout is 0' do
IO.pipe do |read, write|
- IO.select([read], [], [], 0).should == nil
+ select([read], [], [], 0).should == nil
write.write 'data'
- IO.select([read], [], [], 0).should == [[read], [], []]
+ select([read], [], [], 0).should == [[read], [], []]
end
end
end
diff --git a/spec/ruby/core/kernel/set_trace_func_spec.rb b/spec/ruby/core/kernel/set_trace_func_spec.rb
index 1f43e7a009..5201812f2f 100644
--- a/spec/ruby/core/kernel/set_trace_func_spec.rb
+++ b/spec/ruby/core/kernel/set_trace_func_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel#set_trace_func" do
it "is a private method" do
- Kernel.should have_private_instance_method(:set_trace_func)
+ Kernel.private_instance_methods(false).should.include?(:set_trace_func)
end
end
diff --git a/spec/ruby/core/kernel/shared/dup_clone.rb b/spec/ruby/core/kernel/shared/dup_clone.rb
index 4fac6006e1..3fbf918283 100644
--- a/spec/ruby/core/kernel/shared/dup_clone.rb
+++ b/spec/ruby/core/kernel/shared/dup_clone.rb
@@ -40,7 +40,7 @@ describe :kernel_dup_clone, shared: true do
o.obj = array
o2 = o.send(@method)
- o2.obj.should equal(o.obj)
+ o2.obj.should.equal?(o.obj)
end
it "calls #initialize_copy on the NEW object if available, passing in original object" do
@@ -49,7 +49,7 @@ describe :kernel_dup_clone, shared: true do
o.obj.should == :original
o2.obj.should == :init_copy
- o2.original.should equal(o)
+ o2.original.should.equal?(o)
end
it "does not preserve the object_id" do
@@ -81,11 +81,11 @@ describe :kernel_dup_clone, shared: true do
it "returns self for Complex" do
c = Complex(1.3, 3.1)
- c.send(@method).should equal c
+ c.send(@method).should.equal? c
end
it "returns self for Rational" do
r = Rational(1, 3)
- r.send(@method).should equal r
+ r.send(@method).should.equal? r
end
end
diff --git a/spec/ruby/core/kernel/shared/kind_of.rb b/spec/ruby/core/kernel/shared/kind_of.rb
index aef6f1c1d8..a5e0eab08f 100644
--- a/spec/ruby/core/kernel/shared/kind_of.rb
+++ b/spec/ruby/core/kernel/shared/kind_of.rb
@@ -40,10 +40,10 @@ describe :kernel_kind_of, shared: true do
end
it "raises a TypeError if given an object that is not a Class nor a Module" do
- -> { @o.send(@method, 1) }.should raise_error(TypeError)
- -> { @o.send(@method, 'KindaClass') }.should raise_error(TypeError)
- -> { @o.send(@method, :KindaClass) }.should raise_error(TypeError)
- -> { @o.send(@method, Object.new) }.should raise_error(TypeError)
+ -> { @o.send(@method, 1) }.should.raise(TypeError)
+ -> { @o.send(@method, 'KindaClass') }.should.raise(TypeError)
+ -> { @o.send(@method, :KindaClass) }.should.raise(TypeError)
+ -> { @o.send(@method, Object.new) }.should.raise(TypeError)
end
it "does not take into account `class` method overriding" do
diff --git a/spec/ruby/core/kernel/shared/lambda.rb b/spec/ruby/core/kernel/shared/lambda.rb
index c70640082a..83de06bb41 100644
--- a/spec/ruby/core/kernel/shared/lambda.rb
+++ b/spec/ruby/core/kernel/shared/lambda.rb
@@ -5,7 +5,7 @@ describe :kernel_lambda, shared: true do
it "raises an ArgumentError when no block is given" do
suppress_warning do
- -> { send(@method) }.should raise_error(ArgumentError)
+ -> { send(@method) }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/kernel/shared/load.rb b/spec/ruby/core/kernel/shared/load.rb
index 120619abef..20d23a623e 100644
--- a/spec/ruby/core/kernel/shared/load.rb
+++ b/spec/ruby/core/kernel/shared/load.rb
@@ -1,5 +1,6 @@
main = self
+# The big difference is Kernel#load does not attempt to add an extension to the passed path, unlike Kernel#require
describe :kernel_load, shared: true do
before :each do
CodeLoadingSpecs.spec_setup
@@ -10,114 +11,123 @@ describe :kernel_load, shared: true do
CodeLoadingSpecs.spec_cleanup
end
- it "loads a non-extensioned file as a Ruby source file" do
- path = File.expand_path "load_fixture", CODE_LOADING_DIR
- @object.load(path).should be_true
- ScratchPad.recorded.should == [:no_ext]
- end
+ describe "(path resolution)" do
+ # This behavior is specific to Kernel#load, it differs for Kernel#require
+ it "loads a non-extensioned file as a Ruby source file" do
+ path = File.expand_path "load_fixture", CODE_LOADING_DIR
+ @object.load(path).should == true
+ ScratchPad.recorded.should == [:no_ext]
+ end
- it "loads a non .rb extensioned file as a Ruby source file" do
- path = File.expand_path "load_fixture.ext", CODE_LOADING_DIR
- @object.load(path).should be_true
- ScratchPad.recorded.should == [:no_rb_ext]
- end
+ it "loads a non .rb extensioned file as a Ruby source file" do
+ path = File.expand_path "load_fixture.ext", CODE_LOADING_DIR
+ @object.load(path).should == true
+ ScratchPad.recorded.should == [:no_rb_ext]
+ end
- it "loads from the current working directory" do
- Dir.chdir CODE_LOADING_DIR do
- @object.load("load_fixture.rb").should be_true
- ScratchPad.recorded.should == [:loaded]
+ it "loads from the current working directory" do
+ Dir.chdir CODE_LOADING_DIR do
+ @object.load("load_fixture.rb").should == true
+ ScratchPad.recorded.should == [:loaded]
+ end
+ end
+
+ # This behavior is specific to Kernel#load, it differs for Kernel#require
+ it "does not look for a c-extension file when passed a path without extension (when no .rb is present)" do
+ path = File.join CODE_LOADING_DIR, "a", "load_fixture"
+ -> { @object.send(@method, path) }.should.raise(LoadError)
end
end
it "loads a file that recursively requires itself" do
path = File.expand_path "recursive_require_fixture.rb", CODE_LOADING_DIR
-> {
- @object.load(path).should be_true
+ @object.load(path).should == true
}.should complain(/circular require considered harmful/, verbose: true)
ScratchPad.recorded.should == [:loaded, :loaded]
end
it "loads a file that recursively loads itself" do
path = File.expand_path "recursive_load_fixture.rb", CODE_LOADING_DIR
- @object.load(path).should be_true
+ @object.load(path).should == true
ScratchPad.recorded.should == [:loaded, :loaded]
end
it "loads a file each time the method is called" do
- @object.load(@path).should be_true
- @object.load(@path).should be_true
+ @object.load(@path).should == true
+ @object.load(@path).should == true
ScratchPad.recorded.should == [:loaded, :loaded]
end
it "loads a file even when the name appears in $LOADED_FEATURES" do
$LOADED_FEATURES << @path
- @object.load(@path).should be_true
+ @object.load(@path).should == true
ScratchPad.recorded.should == [:loaded]
end
it "loads a file that has been loaded by #require" do
- @object.require(@path).should be_true
- @object.load(@path).should be_true
+ @object.require(@path).should == true
+ @object.load(@path).should == true
ScratchPad.recorded.should == [:loaded, :loaded]
end
it "loads file even after $LOAD_PATH change" do
$LOAD_PATH << CODE_LOADING_DIR
- @object.load("load_fixture.rb").should be_true
+ @object.load("load_fixture.rb").should == true
$LOAD_PATH.unshift CODE_LOADING_DIR + "/gem"
- @object.load("load_fixture.rb").should be_true
+ @object.load("load_fixture.rb").should == true
ScratchPad.recorded.should == [:loaded, :loaded_gem]
end
it "does not cause #require with the same path to fail" do
- @object.load(@path).should be_true
- @object.require(@path).should be_true
+ @object.load(@path).should == true
+ @object.require(@path).should == true
ScratchPad.recorded.should == [:loaded, :loaded]
end
it "does not add the loaded path to $LOADED_FEATURES" do
saved_loaded_features = $LOADED_FEATURES.dup
- @object.load(@path).should be_true
+ @object.load(@path).should == true
$LOADED_FEATURES.should == saved_loaded_features
end
it "raises a LoadError if passed a non-extensioned path that does not exist but a .rb extensioned path does exist" do
path = File.expand_path "load_ext_fixture", CODE_LOADING_DIR
- -> { @object.load(path) }.should raise_error(LoadError)
+ -> { @object.load(path) }.should.raise(LoadError)
end
describe "when passed true for 'wrap'" do
it "loads from an existing path" do
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
- @object.load(path, true).should be_true
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ @object.load(path, true).should == true
end
it "sets the enclosing scope to an anonymous module" do
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true)
- Object.const_defined?(:LoadSpecWrap).should be_false
+ Object.const_defined?(:LoadSpecWrap).should == false
wrap_module = ScratchPad.recorded[1]
- wrap_module.should be_an_instance_of(Module)
+ wrap_module.should.instance_of?(Module)
end
it "allows referencing outside namespaces" do
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true)
- ScratchPad.recorded[0].should equal(String)
+ ScratchPad.recorded[0].should.equal?(String)
end
it "sets self as a copy of the top-level main" do
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true)
top_level = ScratchPad.recorded[2]
top_level.to_s.should == "main"
top_level.method(:to_s).owner.should == top_level.singleton_class
- top_level.should_not equal(main)
- top_level.should be_an_instance_of(Object)
+ top_level.should_not.equal?(main)
+ top_level.should.instance_of?(Object)
end
it "includes modules included in main's singleton class in self's class" do
@@ -127,7 +137,7 @@ describe :kernel_load, shared: true do
main_ancestors = main.singleton_class.ancestors[1..-1]
main_ancestors.first.should == mod
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true)
top_level = ScratchPad.recorded[2]
@@ -149,11 +159,44 @@ describe :kernel_load, shared: true do
end
it "does not pollute the receiver" do
- -> { @object.send(:top_level_method) }.should raise_error(NameError)
+ -> { @object.send(:top_level_method) }.should.raise(NameError)
end
end
end
+ describe "when passed a module for 'wrap'" do
+ it "sets the enclosing scope to the supplied module" do
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
+
+ Object.const_defined?(:LoadSpecWrap).should == false
+ mod.const_defined?(:LoadSpecWrap).should == true
+
+ wrap_module = ScratchPad.recorded[1]
+ wrap_module.should == mod
+ end
+
+ it "makes constants and instance methods in the source file reachable with the supplied module" do
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
+
+ mod::LOAD_WRAP_SPECS_TOP_LEVEL_CONSTANT.should == 1
+ obj = Object.new
+ obj.extend(mod)
+ obj.send(:load_wrap_specs_top_level_method).should == :load_wrap_specs_top_level_method
+ end
+
+ it "makes instance methods in the source file private" do
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
+
+ mod.private_instance_methods.include?(:load_wrap_specs_top_level_method).should == true
+ end
+ end
+
describe "(shell expansion)" do
before :each do
@env_home = ENV["HOME"]
@@ -165,7 +208,7 @@ describe :kernel_load, shared: true do
end
it "expands a tilde to the HOME environment variable as the path to load" do
- @object.require("~/load_fixture.rb").should be_true
+ @object.require("~/load_fixture.rb").should == true
ScratchPad.recorded.should == [:loaded]
end
end
diff --git a/spec/ruby/core/kernel/shared/method.rb b/spec/ruby/core/kernel/shared/method.rb
index 8b6ab23fd3..82abc287d1 100644
--- a/spec/ruby/core/kernel/shared/method.rb
+++ b/spec/ruby/core/kernel/shared/method.rb
@@ -4,26 +4,26 @@ describe :kernel_method, shared: true do
it "returns a method object for a valid method" do
class KernelSpecs::Foo; def bar; 'done'; end; end
m = KernelSpecs::Foo.new.send(@method, :bar)
- m.should be_an_instance_of Method
+ m.should.instance_of? Method
m.call.should == 'done'
end
it "returns a method object for a valid singleton method" do
class KernelSpecs::Foo; def self.bar; 'class done'; end; end
m = KernelSpecs::Foo.send(@method, :bar)
- m.should be_an_instance_of Method
+ m.should.instance_of? Method
m.call.should == 'class done'
end
it "returns a method object if respond_to_missing?(method) is true" do
m = KernelSpecs::RespondViaMissing.new.send(@method, :handled_publicly)
- m.should be_an_instance_of Method
+ m.should.instance_of? Method
m.call(42).should == "Done handled_publicly([42])"
end
it "the returned method object if respond_to_missing?(method) calls #method_missing with a Symbol name" do
m = KernelSpecs::RespondViaMissing.new.send(@method, "handled_publicly")
- m.should be_an_instance_of Method
+ m.should.instance_of? Method
m.call(42).should == "Done handled_publicly([42])"
end
@@ -31,12 +31,12 @@ describe :kernel_method, shared: true do
class KernelSpecs::Foo; def bar; 'done'; end; end
-> {
KernelSpecs::Foo.new.send(@method, :invalid_and_silly_method_name)
- }.should raise_error(NameError)
+ }.should.raise(NameError)
end
it "raises a NameError for an invalid singleton method name" do
class KernelSpecs::Foo; def self.bar; 'done'; end; end
- -> { KernelSpecs::Foo.send(@method, :baz) }.should raise_error(NameError)
+ -> { KernelSpecs::Foo.send(@method, :baz) }.should.raise(NameError)
end
it "changes the method called for super on a target aliased method" do
diff --git a/spec/ruby/core/kernel/shared/require.rb b/spec/ruby/core/kernel/shared/require.rb
index 666ca15e11..6272b00665 100644
--- a/spec/ruby/core/kernel/shared/require.rb
+++ b/spec/ruby/core/kernel/shared/require.rb
@@ -2,26 +2,26 @@ describe :kernel_require_basic, shared: true do
describe "(path resolution)" do
it "loads an absolute path" do
path = File.expand_path "load_fixture.rb", CODE_LOADING_DIR
- @object.send(@method, path).should be_true
+ @object.send(@method, path).should == true
ScratchPad.recorded.should == [:loaded]
end
it "loads a non-canonical absolute path" do
path = File.join CODE_LOADING_DIR, "..", "code", "load_fixture.rb"
- @object.send(@method, path).should be_true
+ @object.send(@method, path).should == true
ScratchPad.recorded.should == [:loaded]
end
it "loads a file defining many methods" do
path = File.expand_path "methods_fixture.rb", CODE_LOADING_DIR
- @object.send(@method, path).should be_true
+ @object.send(@method, path).should == true
ScratchPad.recorded.should == [:loaded]
end
it "raises a LoadError if the file does not exist" do
path = File.expand_path "nonexistent.rb", CODE_LOADING_DIR
File.should_not.exist?(path)
- -> { @object.send(@method, path) }.should raise_error(LoadError)
+ -> { @object.send(@method, path) }.should.raise(LoadError)
ScratchPad.recorded.should == []
end
@@ -42,7 +42,7 @@ describe :kernel_require_basic, shared: true do
it "raises a LoadError" do
File.should.exist?(@path)
- -> { @object.send(@method, @path) }.should raise_error(LoadError)
+ -> { @object.send(@method, @path) }.should.raise(LoadError)
end
end
end
@@ -52,24 +52,24 @@ describe :kernel_require_basic, shared: true do
path = File.expand_path "load_fixture.rb", CODE_LOADING_DIR
name = mock("load_fixture.rb mock")
name.should_receive(:to_str).and_return(path)
- @object.send(@method, name).should be_true
+ @object.send(@method, name).should == true
ScratchPad.recorded.should == [:loaded]
end
it "raises a TypeError if passed nil" do
- -> { @object.send(@method, nil) }.should raise_error(TypeError)
+ -> { @object.send(@method, nil) }.should.raise(TypeError)
end
it "raises a TypeError if passed an Integer" do
- -> { @object.send(@method, 42) }.should raise_error(TypeError)
+ -> { @object.send(@method, 42) }.should.raise(TypeError)
end
it "raises a TypeError if passed an Array" do
- -> { @object.send(@method, []) }.should raise_error(TypeError)
+ -> { @object.send(@method, []) }.should.raise(TypeError)
end
it "raises a TypeError if passed an object that does not provide #to_str" do
- -> { @object.send(@method, mock("not a filename")) }.should raise_error(TypeError)
+ -> { @object.send(@method, mock("not a filename")) }.should.raise(TypeError)
end
it "raises a TypeError if passed an object that has #to_s but not #to_str" do
@@ -77,14 +77,14 @@ describe :kernel_require_basic, shared: true do
name.stub!(:to_s).and_return("load_fixture.rb")
$LOAD_PATH << "."
Dir.chdir CODE_LOADING_DIR do
- -> { @object.send(@method, name) }.should raise_error(TypeError)
+ -> { @object.send(@method, name) }.should.raise(TypeError)
end
end
it "raises a TypeError if #to_str does not return a String" do
name = mock("#to_str returns nil")
name.should_receive(:to_str).at_least(1).times.and_return(nil)
- -> { @object.send(@method, name) }.should raise_error(TypeError)
+ -> { @object.send(@method, name) }.should.raise(TypeError)
end
it "calls #to_path on non-String objects" do
@@ -92,7 +92,7 @@ describe :kernel_require_basic, shared: true do
name.stub!(:to_path).and_return("load_fixture.rb")
$LOAD_PATH << "."
Dir.chdir CODE_LOADING_DIR do
- @object.send(@method, name).should be_true
+ @object.send(@method, name).should == true
end
ScratchPad.recorded.should == [:loaded]
end
@@ -101,7 +101,7 @@ describe :kernel_require_basic, shared: true do
path = File.expand_path "load_fixture.rb", CODE_LOADING_DIR
str = mock("load_fixture.rb mock")
str.should_receive(:to_path).and_return(path)
- @object.send(@method, str).should be_true
+ @object.send(@method, str).should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -111,21 +111,21 @@ describe :kernel_require_basic, shared: true do
to_path = mock("load_fixture_rb #to_path mock")
name.should_receive(:to_path).and_return(to_path)
to_path.should_receive(:to_str).and_return(path)
- @object.send(@method, name).should be_true
+ @object.send(@method, name).should == true
ScratchPad.recorded.should == [:loaded]
end
# "http://redmine.ruby-lang.org/issues/show/2578"
it "loads a ./ relative path from the current working directory with empty $LOAD_PATH" do
Dir.chdir CODE_LOADING_DIR do
- @object.send(@method, "./load_fixture.rb").should be_true
+ @object.send(@method, "./load_fixture.rb").should == true
end
ScratchPad.recorded.should == [:loaded]
end
it "loads a ../ relative path from the current working directory with empty $LOAD_PATH" do
Dir.chdir CODE_LOADING_DIR do
- @object.send(@method, "../code/load_fixture.rb").should be_true
+ @object.send(@method, "../code/load_fixture.rb").should == true
end
ScratchPad.recorded.should == [:loaded]
end
@@ -133,7 +133,7 @@ describe :kernel_require_basic, shared: true do
it "loads a ./ relative path from the current working directory with non-empty $LOAD_PATH" do
$LOAD_PATH << "an_irrelevant_dir"
Dir.chdir CODE_LOADING_DIR do
- @object.send(@method, "./load_fixture.rb").should be_true
+ @object.send(@method, "./load_fixture.rb").should == true
end
ScratchPad.recorded.should == [:loaded]
end
@@ -141,7 +141,7 @@ describe :kernel_require_basic, shared: true do
it "loads a ../ relative path from the current working directory with non-empty $LOAD_PATH" do
$LOAD_PATH << "an_irrelevant_dir"
Dir.chdir CODE_LOADING_DIR do
- @object.send(@method, "../code/load_fixture.rb").should be_true
+ @object.send(@method, "../code/load_fixture.rb").should == true
end
ScratchPad.recorded.should == [:loaded]
end
@@ -149,14 +149,14 @@ describe :kernel_require_basic, shared: true do
it "loads a non-canonical path from the current working directory with non-empty $LOAD_PATH" do
$LOAD_PATH << "an_irrelevant_dir"
Dir.chdir CODE_LOADING_DIR do
- @object.send(@method, "../code/../code/load_fixture.rb").should be_true
+ @object.send(@method, "../code/../code/load_fixture.rb").should == true
end
ScratchPad.recorded.should == [:loaded]
end
it "resolves a filename against $LOAD_PATH entries" do
$LOAD_PATH << CODE_LOADING_DIR
- @object.send(@method, "load_fixture.rb").should be_true
+ @object.send(@method, "load_fixture.rb").should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -164,15 +164,15 @@ describe :kernel_require_basic, shared: true do
obj = mock("to_path")
obj.should_receive(:to_path).at_least(:once).and_return(CODE_LOADING_DIR)
$LOAD_PATH << obj
- @object.send(@method, "load_fixture.rb").should be_true
+ @object.send(@method, "load_fixture.rb").should == true
ScratchPad.recorded.should == [:loaded]
end
it "does not require file twice after $LOAD_PATH change" do
$LOAD_PATH << CODE_LOADING_DIR
- @object.require("load_fixture.rb").should be_true
+ @object.require("load_fixture.rb").should == true
$LOAD_PATH.push CODE_LOADING_DIR + "/gem"
- @object.require("load_fixture.rb").should be_false
+ @object.require("load_fixture.rb").should == false
ScratchPad.recorded.should == [:loaded]
end
@@ -180,7 +180,7 @@ describe :kernel_require_basic, shared: true do
$LOAD_PATH << CODE_LOADING_DIR
-> do
@object.send(@method, "./load_fixture.rb")
- end.should raise_error(LoadError)
+ end.should.raise(LoadError)
ScratchPad.recorded.should == []
end
@@ -188,13 +188,13 @@ describe :kernel_require_basic, shared: true do
$LOAD_PATH << CODE_LOADING_DIR
-> do
@object.send(@method, "../code/load_fixture.rb")
- end.should raise_error(LoadError)
+ end.should.raise(LoadError)
ScratchPad.recorded.should == []
end
it "resolves a non-canonical path against $LOAD_PATH entries" do
$LOAD_PATH << File.dirname(CODE_LOADING_DIR)
- @object.send(@method, "code/../code/load_fixture.rb").should be_true
+ @object.send(@method, "code/../code/load_fixture.rb").should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -203,7 +203,7 @@ describe :kernel_require_basic, shared: true do
sep = File::Separator + File::Separator
path = ["..", "code", "load_fixture.rb"].join(sep)
Dir.chdir CODE_LOADING_DIR do
- @object.send(@method, path).should be_true
+ @object.send(@method, path).should == true
end
ScratchPad.recorded.should == [:loaded]
end
@@ -212,11 +212,39 @@ end
describe :kernel_require, shared: true do
describe "(path resolution)" do
+ it "loads .rb file when passed absolute path without extension" do
+ path = File.expand_path "load_fixture", CODE_LOADING_DIR
+ @object.send(@method, path).should == true
+ # This should _not_ be [:no_ext]
+ ScratchPad.recorded.should == [:loaded]
+ end
+
+ platform_is :linux, :darwin do
+ it "loads c-extension file when passed absolute path without extension when no .rb is present" do
+ # the error message is specific to what dlerror() returns
+ path = File.join CODE_LOADING_DIR, "a", "load_fixture"
+ -> { @object.send(@method, path) }.should.raise(LoadError)
+ end
+ end
+
+ platform_is :darwin do
+ it "loads .bundle file when passed absolute path with .so" do
+ # the error message is specific to what dlerror() returns
+ path = File.join CODE_LOADING_DIR, "a", "load_fixture.so"
+ -> { @object.send(@method, path) }.should.raise(LoadError)
+ end
+ end
+
+ it "does not try an extra .rb if the path already ends in .rb" do
+ path = File.join CODE_LOADING_DIR, "d", "load_fixture.rb"
+ -> { @object.send(@method, path) }.should.raise(LoadError)
+ end
+
# For reference see [ruby-core:24155] in which matz confirms this feature is
# intentional for security reasons.
it "does not load a bare filename unless the current working directory is in $LOAD_PATH" do
Dir.chdir CODE_LOADING_DIR do
- -> { @object.require("load_fixture.rb") }.should raise_error(LoadError)
+ -> { @object.require("load_fixture.rb") }.should.raise(LoadError)
ScratchPad.recorded.should == []
end
end
@@ -225,7 +253,7 @@ describe :kernel_require, shared: true do
Dir.chdir File.dirname(CODE_LOADING_DIR) do
-> do
@object.require("code/load_fixture.rb")
- end.should raise_error(LoadError)
+ end.should.raise(LoadError)
ScratchPad.recorded.should == []
end
end
@@ -233,10 +261,19 @@ describe :kernel_require, shared: true do
it "loads a file that recursively requires itself" do
path = File.expand_path "recursive_require_fixture.rb", CODE_LOADING_DIR
-> {
- @object.require(path).should be_true
+ @object.require(path).should == true
}.should complain(/circular require considered harmful/, verbose: true)
ScratchPad.recorded.should == [:loaded]
end
+
+ it "loads a file concurrently" do
+ path = File.expand_path "concurrent_require_fixture.rb", CODE_LOADING_DIR
+ ScratchPad.record(@object)
+ -> {
+ @object.require(path)
+ }.should_not complain(/circular require considered harmful/, verbose: true)
+ ScratchPad.recorded.join
+ end
end
describe "(non-extensioned path)" do
@@ -247,17 +284,25 @@ describe :kernel_require, shared: true do
end
it "loads a .rb extensioned file when a C-extension file exists on an earlier load path" do
- @object.require("load_fixture").should be_true
+ @object.require("load_fixture").should == true
ScratchPad.recorded.should == [:loaded]
end
- ruby_bug "#16926", ""..."3.0" do
- it "does not load a feature twice when $LOAD_PATH has been modified" do
- $LOAD_PATH.replace [CODE_LOADING_DIR]
- @object.require("load_fixture").should be_true
- $LOAD_PATH.replace [File.expand_path("b", CODE_LOADING_DIR), CODE_LOADING_DIR]
- @object.require("load_fixture").should be_false
- end
+ it "does not load a feature twice when $LOAD_PATH has been modified" do
+ $LOAD_PATH.replace [CODE_LOADING_DIR]
+ @object.require("load_fixture").should == true
+ $LOAD_PATH.replace [File.expand_path("b", CODE_LOADING_DIR), CODE_LOADING_DIR]
+ @object.require("load_fixture").should == false
+ end
+
+ it "stores the missing path in a LoadError object" do
+ path = "abcd1234"
+
+ -> {
+ @object.send(@method, path)
+ }.should.raise(LoadError) { |e|
+ e.path.should == path
+ }
end
end
@@ -265,7 +310,7 @@ describe :kernel_require, shared: true do
it "loads a .rb extensioned file when passed a non-extensioned path" do
path = File.expand_path "load_fixture", CODE_LOADING_DIR
File.should.exist?(path)
- @object.require(path).should be_true
+ @object.require(path).should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -275,21 +320,21 @@ describe :kernel_require, shared: true do
$LOADED_FEATURES << File.expand_path("load_fixture.so", CODE_LOADING_DIR)
$LOADED_FEATURES << File.expand_path("load_fixture.dll", CODE_LOADING_DIR)
path = File.expand_path "load_fixture", CODE_LOADING_DIR
- @object.require(path).should be_true
+ @object.require(path).should == true
ScratchPad.recorded.should == [:loaded]
end
it "does not load a C-extension file if a .rb extensioned file is already loaded" do
$LOADED_FEATURES << File.expand_path("load_fixture.rb", CODE_LOADING_DIR)
path = File.expand_path "load_fixture", CODE_LOADING_DIR
- @object.require(path).should be_false
+ @object.require(path).should == false
ScratchPad.recorded.should == []
end
it "loads a .rb extensioned file when passed a non-.rb extensioned path" do
path = File.expand_path "load_fixture.ext", CODE_LOADING_DIR
File.should.exist?(path)
- @object.require(path).should be_true
+ @object.require(path).should == true
ScratchPad.recorded.should == [:loaded]
end
@@ -299,14 +344,14 @@ describe :kernel_require, shared: true do
$LOADED_FEATURES << File.expand_path("load_fixture.ext.so", CODE_LOADING_DIR)
$LOADED_FEATURES << File.expand_path("load_fixture.ext.dll", CODE_LOADING_DIR)
path = File.expand_path "load_fixture.ext", CODE_LOADING_DIR
- @object.require(path).should be_true
+ @object.require(path).should == true
ScratchPad.recorded.should == [:loaded]
end
it "does not load a C-extension file if a complex-extensioned .rb file is already loaded" do
$LOADED_FEATURES << File.expand_path("load_fixture.ext.rb", CODE_LOADING_DIR)
path = File.expand_path "load_fixture.ext", CODE_LOADING_DIR
- @object.require(path).should be_false
+ @object.require(path).should == false
ScratchPad.recorded.should == []
end
end
@@ -317,8 +362,8 @@ describe :kernel_require, shared: true do
end
it "stores an absolute path" do
- @object.require(@path).should be_true
- $LOADED_FEATURES.should include(@path)
+ @object.require(@path).should == true
+ $LOADED_FEATURES.should.include?(@path)
end
platform_is_not :windows do
@@ -338,23 +383,23 @@ describe :kernel_require, shared: true do
it "does not canonicalize the path and stores a path with symlinks" do
symlink_path = "#{@symlink_to_code_dir}/load_fixture.rb"
canonical_path = "#{CODE_LOADING_DIR}/load_fixture.rb"
- @object.require(symlink_path).should be_true
+ @object.require(symlink_path).should == true
ScratchPad.recorded.should == [:loaded]
features = $LOADED_FEATURES.select { |path| path.end_with?('load_fixture.rb') }
- features.should include(symlink_path)
- features.should_not include(canonical_path)
+ features.should.include?(symlink_path)
+ features.should_not.include?(canonical_path)
end
it "stores the same path that __FILE__ returns in the required file" do
symlink_path = "#{@symlink_to_code_dir}/load_fixture_and__FILE__.rb"
- @object.require(symlink_path).should be_true
+ @object.require(symlink_path).should == true
loaded_feature = $LOADED_FEATURES.last
ScratchPad.recorded.should == [loaded_feature]
end
it "requires only once when a new matching file added to path" do
- @object.require('load_fixture').should be_true
+ @object.require('load_fixture').should == true
ScratchPad.recorded.should == [:loaded]
symlink_to_code_dir_two = tmp("codesymlinktwo")
@@ -362,7 +407,7 @@ describe :kernel_require, shared: true do
begin
$LOAD_PATH.unshift(symlink_to_code_dir_two)
- @object.require('load_fixture').should be_false
+ @object.require('load_fixture').should == false
ensure
rm_r symlink_to_code_dir_two
end
@@ -388,7 +433,7 @@ describe :kernel_require, shared: true do
it "canonicalizes the entry in $LOAD_PATH but not the filename passed to #require" do
$LOAD_PATH.unshift(@symlink_to_dir)
- @object.require("symfile").should be_true
+ @object.require("symfile").should == true
loaded_feature = "#{@dir}/symfile.rb"
ScratchPad.recorded.should == [loaded_feature]
$".last.should == loaded_feature
@@ -400,20 +445,20 @@ describe :kernel_require, shared: true do
it "does not store the path if the load fails" do
$LOAD_PATH << CODE_LOADING_DIR
saved_loaded_features = $LOADED_FEATURES.dup
- -> { @object.require("raise_fixture.rb") }.should raise_error(RuntimeError)
+ -> { @object.require("raise_fixture.rb") }.should.raise(RuntimeError)
$LOADED_FEATURES.should == saved_loaded_features
end
it "does not load an absolute path that is already stored" do
$LOADED_FEATURES << @path
- @object.require(@path).should be_false
+ @object.require(@path).should == false
ScratchPad.recorded.should == []
end
it "does not load a ./ relative path that is already stored" do
$LOADED_FEATURES << "./load_fixture.rb"
Dir.chdir CODE_LOADING_DIR do
- @object.require("./load_fixture.rb").should be_false
+ @object.require("./load_fixture.rb").should == false
end
ScratchPad.recorded.should == []
end
@@ -421,7 +466,7 @@ describe :kernel_require, shared: true do
it "does not load a ../ relative path that is already stored" do
$LOADED_FEATURES << "../load_fixture.rb"
Dir.chdir CODE_LOADING_DIR do
- @object.require("../load_fixture.rb").should be_false
+ @object.require("../load_fixture.rb").should == false
end
ScratchPad.recorded.should == []
end
@@ -429,27 +474,27 @@ describe :kernel_require, shared: true do
it "does not load a non-canonical path that is already stored" do
$LOADED_FEATURES << "code/../code/load_fixture.rb"
$LOAD_PATH << File.dirname(CODE_LOADING_DIR)
- @object.require("code/../code/load_fixture.rb").should be_false
+ @object.require("code/../code/load_fixture.rb").should == false
ScratchPad.recorded.should == []
end
it "respects being replaced with a new array" do
prev = $LOADED_FEATURES.dup
- @object.require(@path).should be_true
- $LOADED_FEATURES.should include(@path)
+ @object.require(@path).should == true
+ $LOADED_FEATURES.should.include?(@path)
$LOADED_FEATURES.replace(prev)
- $LOADED_FEATURES.should_not include(@path)
- @object.require(@path).should be_true
- $LOADED_FEATURES.should include(@path)
+ $LOADED_FEATURES.should_not.include?(@path)
+ @object.require(@path).should == true
+ $LOADED_FEATURES.should.include?(@path)
end
it "does not load twice the same file with and without extension" do
$LOAD_PATH << CODE_LOADING_DIR
- @object.require("load_fixture.rb").should be_true
- @object.require("load_fixture").should be_false
+ @object.require("load_fixture.rb").should == true
+ @object.require("load_fixture").should == false
end
describe "when a non-extensioned file is in $LOADED_FEATURES" do
@@ -459,19 +504,19 @@ describe :kernel_require, shared: true do
it "loads a .rb extensioned file when a non extensioned file is in $LOADED_FEATURES" do
$LOAD_PATH << CODE_LOADING_DIR
- @object.require("load_fixture").should be_true
+ @object.require("load_fixture").should == true
ScratchPad.recorded.should == [:loaded]
end
it "loads a .rb extensioned file from a subdirectory" do
$LOAD_PATH << File.dirname(CODE_LOADING_DIR)
- @object.require("code/load_fixture").should be_true
+ @object.require("code/load_fixture").should == true
ScratchPad.recorded.should == [:loaded]
end
it "returns false if the file is not found" do
Dir.chdir File.dirname(CODE_LOADING_DIR) do
- @object.require("load_fixture").should be_false
+ @object.require("load_fixture").should == false
ScratchPad.recorded.should == []
end
end
@@ -479,7 +524,7 @@ describe :kernel_require, shared: true do
it "returns false when passed a path and the file is not found" do
$LOADED_FEATURES << "code/load_fixture"
Dir.chdir CODE_LOADING_DIR do
- @object.require("code/load_fixture").should be_false
+ @object.require("code/load_fixture").should == false
ScratchPad.recorded.should == []
end
end
@@ -487,16 +532,16 @@ describe :kernel_require, shared: true do
it "stores ../ relative paths as absolute paths" do
Dir.chdir CODE_LOADING_DIR do
- @object.require("../code/load_fixture.rb").should be_true
+ @object.require("../code/load_fixture.rb").should == true
end
- $LOADED_FEATURES.should include(@path)
+ $LOADED_FEATURES.should.include?(@path)
end
it "stores ./ relative paths as absolute paths" do
Dir.chdir CODE_LOADING_DIR do
- @object.require("./load_fixture.rb").should be_true
+ @object.require("./load_fixture.rb").should == true
end
- $LOADED_FEATURES.should include(@path)
+ $LOADED_FEATURES.should.include?(@path)
end
it "collapses duplicate path separators" do
@@ -504,27 +549,27 @@ describe :kernel_require, shared: true do
sep = File::Separator + File::Separator
path = ["..", "code", "load_fixture.rb"].join(sep)
Dir.chdir CODE_LOADING_DIR do
- @object.require(path).should be_true
+ @object.require(path).should == true
end
- $LOADED_FEATURES.should include(@path)
+ $LOADED_FEATURES.should.include?(@path)
end
it "expands absolute paths containing .." do
path = File.join CODE_LOADING_DIR, "..", "code", "load_fixture.rb"
- @object.require(path).should be_true
- $LOADED_FEATURES.should include(@path)
+ @object.require(path).should == true
+ $LOADED_FEATURES.should.include?(@path)
end
it "adds the suffix of the resolved filename" do
$LOAD_PATH << CODE_LOADING_DIR
- @object.require("load_fixture").should be_true
- $LOADED_FEATURES.should include(@path)
+ @object.require("load_fixture").should == true
+ $LOADED_FEATURES.should.include?(@path)
end
it "does not load a non-canonical path for a file already loaded" do
$LOADED_FEATURES << @path
$LOAD_PATH << File.dirname(CODE_LOADING_DIR)
- @object.require("code/../code/load_fixture.rb").should be_false
+ @object.require("code/../code/load_fixture.rb").should == false
ScratchPad.recorded.should == []
end
@@ -532,7 +577,7 @@ describe :kernel_require, shared: true do
$LOADED_FEATURES << @path
$LOAD_PATH << "an_irrelevant_dir"
Dir.chdir CODE_LOADING_DIR do
- @object.require("./load_fixture.rb").should be_false
+ @object.require("./load_fixture.rb").should == false
end
ScratchPad.recorded.should == []
end
@@ -541,51 +586,35 @@ describe :kernel_require, shared: true do
$LOADED_FEATURES << @path
$LOAD_PATH << "an_irrelevant_dir"
Dir.chdir CODE_LOADING_DIR do
- @object.require("../code/load_fixture.rb").should be_false
+ @object.require("../code/load_fixture.rb").should == false
end
ScratchPad.recorded.should == []
end
- provided = %w[complex enumerator rational thread]
- provided << 'ruby2_keywords'
-
- it "#{provided.join(', ')} are already required" do
- features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
- provided.each { |feature|
- features.should =~ /\b#{feature}\.(rb|so|jar)$/
- }
-
- code = provided.map { |f| "puts require #{f.inspect}\n" }.join
- required = ruby_exe(code, options: '--disable-gems')
- required.should == "false\n" * provided.size
- end
-
it "unicode_normalize is part of core and not $LOADED_FEATURES" do
features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
features.lines.each { |feature|
- feature.should_not include("unicode_normalize")
+ feature.should_not.include?("unicode_normalize")
}
- -> { @object.require("unicode_normalize") }.should raise_error(LoadError)
+ -> { @object.require("unicode_normalize") }.should.raise(LoadError)
end
- ruby_version_is "3.0" do
- it "does not load a file earlier on the $LOAD_PATH when other similar features were already loaded" do
- Dir.chdir CODE_LOADING_DIR do
- @object.send(@method, "../code/load_fixture").should be_true
- end
- ScratchPad.recorded.should == [:loaded]
+ it "does not load a file earlier on the $LOAD_PATH when other similar features were already loaded" do
+ Dir.chdir CODE_LOADING_DIR do
+ @object.send(@method, "../code/load_fixture").should == true
+ end
+ ScratchPad.recorded.should == [:loaded]
- $LOAD_PATH.unshift "#{CODE_LOADING_DIR}/b"
- # This loads because the above load was not on the $LOAD_PATH
- @object.send(@method, "load_fixture").should be_true
- ScratchPad.recorded.should == [:loaded, :loaded]
+ $LOAD_PATH.unshift "#{CODE_LOADING_DIR}/b"
+ # This loads because the above load was not on the $LOAD_PATH
+ @object.send(@method, "load_fixture").should == true
+ ScratchPad.recorded.should == [:loaded, :loaded]
- $LOAD_PATH.unshift "#{CODE_LOADING_DIR}/c"
- # This does not load because the above load was on the $LOAD_PATH
- @object.send(@method, "load_fixture").should be_false
- ScratchPad.recorded.should == [:loaded, :loaded]
- end
+ $LOAD_PATH.unshift "#{CODE_LOADING_DIR}/c"
+ # This does not load because the above load was on the $LOAD_PATH
+ @object.send(@method, "load_fixture").should == false
+ ScratchPad.recorded.should == [:loaded, :loaded]
end
end
@@ -602,13 +631,13 @@ describe :kernel_require, shared: true do
# "#3171"
it "performs tilde expansion on a .rb file before storing paths in $LOADED_FEATURES" do
- @object.require("~/load_fixture.rb").should be_true
- $LOADED_FEATURES.should include(@path)
+ @object.require("~/load_fixture.rb").should == true
+ $LOADED_FEATURES.should.include?(@path)
end
it "performs tilde expansion on a non-extensioned file before storing paths in $LOADED_FEATURES" do
- @object.require("~/load_fixture").should be_true
- $LOADED_FEATURES.should include(@path)
+ @object.require("~/load_fixture").should == true
+ $LOADED_FEATURES.should.include?(@path)
end
end
@@ -665,8 +694,8 @@ describe :kernel_require, shared: true do
t1.join
t2.join
- t1_res.should be_true
- t2_res.should be_false
+ t1_res.should == true
+ t2_res.should == false
ScratchPad.recorded.should == [:con_pre, :con_post, :t2_post, :t1_post]
end
@@ -690,8 +719,8 @@ describe :kernel_require, shared: true do
t1.join
t2.join
- t1_res.should be_true
- t2_res.should be_true
+ t1_res.should == true
+ t2_res.should == true
ScratchPad.recorded.should == [:con2_pre, :con3, :con2_post]
end
@@ -709,7 +738,7 @@ describe :kernel_require, shared: true do
-> {
@object.require(@path)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
Thread.pass until fin
ScratchPad.recorded << :t1_post
@@ -730,7 +759,7 @@ describe :kernel_require, shared: true do
t1.join
t2.join
- t2_res.should be_true
+ t2_res.should == true
ScratchPad.recorded.should == [:con_pre, :con_pre, :con_post, :t2_post, :t1_post]
end
@@ -750,7 +779,7 @@ describe :kernel_require, shared: true do
-> {
@object.require(@path)
- }.should raise_error(RuntimeError)
+ }.should.raise(RuntimeError)
raised = true
@@ -778,8 +807,8 @@ describe :kernel_require, shared: true do
t1.join
t2.join
- t1_res.should be_false
- t2_res.should be_true
+ t1_res.should == false
+ t2_res.should == true
ScratchPad.recorded.should == [:con_pre, :con_pre, :con_post, :t2_post, :t1_post]
end
@@ -790,8 +819,28 @@ describe :kernel_require, shared: true do
-> {
@object.send(@method, path)
- }.should raise_error(LoadError) { |e|
+ }.should.raise(LoadError) { |e|
e.path.should == path
}
end
+
+ platform_is :linux, :darwin do
+ it "does not store the missing path in a LoadError object when c-extension file exists but loading fails and passed absolute path without extension" do
+ # the error message is specific to what dlerror() returns
+ path = File.join CODE_LOADING_DIR, "a", "load_fixture"
+ -> { @object.send(@method, path) }.should.raise(LoadError) { |e|
+ e.path.should == nil
+ }
+ end
+ end
+
+ platform_is :darwin do
+ it "does not store the missing path in a LoadError object when c-extension file exists but loading fails and passed absolute path with extension" do
+ # the error message is specific to what dlerror() returns
+ path = File.join CODE_LOADING_DIR, "a", "load_fixture.bundle"
+ -> { @object.send(@method, path) }.should.raise(LoadError) { |e|
+ e.path.should == nil
+ }
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/shared/sprintf.rb b/spec/ruby/core/kernel/shared/sprintf.rb
index 84d472b0d1..b40bd95f59 100644
--- a/spec/ruby/core/kernel/shared/sprintf.rb
+++ b/spec/ruby/core/kernel/shared/sprintf.rb
@@ -22,12 +22,13 @@ describe :kernel_sprintf, shared: true do
@method.call("%d", "112").should == "112"
@method.call("%d", "0127").should == "87"
@method.call("%d", "0xc4").should == "196"
+ @method.call("%d", "0").should == "0"
end
it "raises TypeError exception if cannot convert to Integer" do
-> {
@method.call("%b", Object.new)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
["b", "B"].each do |f|
@@ -104,6 +105,20 @@ describe :kernel_sprintf, shared: true do
@method.call("%X", -1).should == "..F"
end
end
+
+ %w[b B d i u o x X].each do |f|
+ describe f do
+ it "converts to the empty string if precision is 0 and value is 0" do
+ @method.call("%.#{f}", 0).should == ""
+ @method.call("%.0#{f}", 0).should == ""
+ end
+
+ it "pads the empty string if precision is 0 and value is 0" do
+ @method.call("%2.#{f}", 0).should == " "
+ @method.call("%2.0#{f}", 0).should == " "
+ end
+ end
+ end
end
describe "float formats" do
@@ -116,7 +131,7 @@ describe :kernel_sprintf, shared: true do
it "raises TypeError exception if cannot convert to Float" do
-> {
@method.call("%f", Object.new)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
{"e" => "e", "E" => "E"}.each_pair do |f, exp|
@@ -289,21 +304,68 @@ describe :kernel_sprintf, shared: true do
@method.call("%c", "a").should == "a"
end
- it "raises ArgumentError if argument is a string of several characters" do
+ it "displays only the first character if argument is a string of several characters" do
+ @method.call("%c", "abc").should == "a"
+ end
+
+ it "displays only the first character if argument is a string of several multibyte characters" do
+ @method.call("%c", "あいうえお").should == "あ"
+ end
+
+ it "displays no characters if argument is an empty string" do
+ @method.call("%c", "").should == ""
+ end
+
+ it "raises TypeError if argument is not String or Integer and cannot be converted to them" do
+ -> {
+ @method.call("%c", [])
+ }.should raise_consistent_error(TypeError, /no implicit conversion of Array into Integer/)
+ end
+
+ it "raises TypeError if argument is nil" do
-> {
- @method.call("%c", "abc")
- }.should raise_error(ArgumentError)
+ @method.call("%c", nil)
+ }.should raise_consistent_error(TypeError, /no implicit conversion of nil into Integer/)
+ end
+
+ it "tries to convert argument to String with to_str" do
+ obj = BasicObject.new
+ def obj.to_str
+ "a"
+ end
+
+ @method.call("%c", obj).should == "a"
end
- it "raises ArgumentError if argument is an empty string" do
+ it "tries to convert argument to Integer with to_int" do
+ obj = BasicObject.new
+ def obj.to_int
+ 90
+ end
+
+ @method.call("%c", obj).should == "Z"
+ end
+
+ it "raises TypeError if converting to String with to_str returns non-String" do
+ obj = BasicObject.new
+ def obj.to_str
+ :foo
+ end
+
-> {
- @method.call("%c", "")
- }.should raise_error(ArgumentError)
+ @method.call("%c", obj)
+ }.should raise_consistent_error(TypeError, /can't convert BasicObject into String/)
end
- it "supports Unicode characters" do
- @method.call("%c", 1286).should == "Ԇ"
- @method.call("%c", "ش").should == "ش"
+ it "raises TypeError if converting to Integer with to_int returns non-Integer" do
+ obj = BasicObject.new
+ def obj.to_int
+ :foo
+ end
+
+ -> {
+ @method.call("%c", obj)
+ }.should raise_consistent_error(TypeError, /can't convert BasicObject into Integer/)
end
end
@@ -313,6 +375,10 @@ describe :kernel_sprintf, shared: true do
obj.should_receive(:inspect).and_return("<inspect-result>")
@method.call("%p", obj).should == "<inspect-result>"
end
+
+ it "substitutes 'nil' for nil" do
+ @method.call("%p", nil).should == "nil"
+ end
end
describe "s" do
@@ -338,7 +404,7 @@ describe :kernel_sprintf, shared: true do
-> {
@method.call("%s", obj)
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
it "formats a partial substring without including omitted characters" do
@@ -362,11 +428,11 @@ describe :kernel_sprintf, shared: true do
@method.call("%4.6s", "abcdefg").should == "abcdef"
end
- it "formats nli with width" do
+ it "formats nil with width" do
@method.call("%6s", nil).should == " "
end
- it "formats nli with precision" do
+ it "formats nil with precision" do
@method.call("%.6s", nil).should == ""
end
@@ -391,12 +457,12 @@ describe :kernel_sprintf, shared: true do
it "alone raises an ArgumentError" do
-> {
@method.call("%")
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "is escaped by %" do
@method.call("%%").should == "%"
- @method.call("%%d", 10).should == "%d"
+ @method.call("%%d").should == "%d"
end
end
end
@@ -498,7 +564,7 @@ describe :kernel_sprintf, shared: true do
it "raises exception if argument number is bigger than actual arguments list" do
-> {
@method.call("%4$d", 1, 2, 3)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "ignores '-' sign" do
@@ -509,7 +575,7 @@ describe :kernel_sprintf, shared: true do
it "raises ArgumentError exception when absolute and relative argument numbers are mixed" do
-> {
@method.call("%1$d %d", 1, 2)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
end
@@ -541,11 +607,28 @@ describe :kernel_sprintf, shared: true do
@method.call("%#b", 0).should == "0"
@method.call("%#B", 0).should == "0"
- @method.call("%#o", 0).should == "0"
-
@method.call("%#x", 0).should == "0"
@method.call("%#X", 0).should == "0"
end
+
+ it "does nothing for zero argument when combined with zero precision" do
+ @method.call("%#.0b", 0).should == ""
+ @method.call("%#.0B", 0).should == ""
+
+ @method.call("%#.0x", 0).should == ""
+ @method.call("%#.0X", 0).should == ""
+ end
+ end
+
+ context "applies to format o" do
+ it "does nothing for zero argument" do
+ @method.call("%#o", 0).should == "0"
+ @method.call("%#.1o", 0).should == "0"
+ end
+
+ it "increases the precision if precision zero is requested with zero argument" do
+ @method.call("%#.0o", 0).should == "0"
+ end
end
context "applies to formats aAeEfgG" do
@@ -759,7 +842,7 @@ describe :kernel_sprintf, shared: true do
it "raises ArgumentError when is mixed with width" do
-> {
@method.call("%*10d", 10, 112)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
end
end
@@ -858,7 +941,7 @@ describe :kernel_sprintf, shared: true do
it "cannot be mixed with unnamed style" do
-> {
@method.call("%d %<foo>d", 1, foo: "123")
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
end
@@ -878,13 +961,30 @@ describe :kernel_sprintf, shared: true do
it "cannot be mixed with unnamed style" do
-> {
@method.call("%d %{foo}", 1, foo: "123")
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
+ end
+
+ it "respects Hash#default when there is no set key" do
+ @method.call("%{foo}", Hash.new(123)).should == "123"
+ @method.call("%{foo}", Hash.new { 123 }).should == "123"
end
- it "raises KeyError when there is no matching key" do
+ it "raises KeyError when Hash#default returns nil" do
-> {
@method.call("%{foo}", {})
- }.should raise_error(KeyError)
+ }.should.raise(KeyError, 'key{foo} not found')
+
+ -> {
+ @method.call("%{foo}", Hash.new(nil))
+ }.should.raise(KeyError, 'key{foo} not found')
+
+ -> {
+ @method.call("%{foo}", Hash.new { nil })
+ }.should.raise(KeyError, 'key{foo} not found')
+ end
+
+ it "accepts a nil value for an existing key" do
+ @method.call("%{foo}", { foo: nil }).should == ""
end
it "converts value to String with to_s" do
@@ -908,23 +1008,27 @@ describe :kernel_sprintf, shared: true do
it "raises a KeyError" do
-> {
@method.call("%<foo>s", @object)
- }.should raise_error(KeyError)
+ }.should.raise(KeyError)
end
it "sets the Hash as the receiver of KeyError" do
-> {
@method.call("%<foo>s", @object)
- }.should raise_error(KeyError) { |err|
- err.receiver.should equal(@object)
+ }.should.raise(KeyError) { |err|
+ err.receiver.should.equal?(@object)
}
end
it "sets the unmatched key as the key of KeyError" do
-> {
@method.call("%<foo>s", @object)
- }.should raise_error(KeyError) { |err|
+ }.should.raise(KeyError) { |err|
err.key.to_s.should == 'foo'
}
end
end
+
+ it "does not raise error when passed more arguments than needed" do
+ sprintf("%s %d %c", "string", 2, "c", []).should == "string 2 c"
+ end
end
diff --git a/spec/ruby/core/kernel/shared/sprintf_encoding.rb b/spec/ruby/core/kernel/shared/sprintf_encoding.rb
index 5ca66b9083..849c95cbb7 100644
--- a/spec/ruby/core/kernel/shared/sprintf_encoding.rb
+++ b/spec/ruby/core/kernel/shared/sprintf_encoding.rb
@@ -1,36 +1,67 @@
+# Keep encoding-related specs in a separate shared example to be able to skip them in IO/File/StringIO specs.
+# It's difficult to check result's encoding in the test after writing to a file/io buffer.
describe :kernel_sprintf_encoding, shared: true do
it "can produce a string with valid encoding" do
string = @method.call("good day %{valid}", valid: "e")
string.encoding.should == Encoding::UTF_8
- string.valid_encoding?.should be_true
+ string.valid_encoding?.should == true
end
it "can produce a string with invalid encoding" do
string = @method.call("good day %{invalid}", invalid: "\x80")
string.encoding.should == Encoding::UTF_8
- string.valid_encoding?.should be_false
+ string.valid_encoding?.should == false
end
it "returns a String in the same encoding as the format String if compatible" do
- string = "%s".force_encoding(Encoding::KOI8_U)
+ string = "%s".dup.force_encoding(Encoding::KOI8_U)
result = @method.call(string, "dogs")
- result.encoding.should equal(Encoding::KOI8_U)
+ result.encoding.should.equal?(Encoding::KOI8_U)
end
it "returns a String in the argument's encoding if format encoding is more restrictive" do
- string = "foo %s".force_encoding(Encoding::US_ASCII)
- argument = "b\303\274r".force_encoding(Encoding::UTF_8)
+ string = "foo %s".dup.force_encoding(Encoding::US_ASCII)
+ argument = "b\303\274r".dup.force_encoding(Encoding::UTF_8)
result = @method.call(string, argument)
- result.encoding.should equal(Encoding::UTF_8)
+ result.encoding.should.equal?(Encoding::UTF_8)
end
- it "raises Encoding::CompatibilityError if both encodings are ASCII compatible and there ano not ASCII characters" do
+ it "raises Encoding::CompatibilityError if both encodings are ASCII compatible and there are not ASCII characters" do
string = "Ä %s".encode('windows-1252')
argument = "Ђ".encode('windows-1251')
-> {
@method.call(string, argument)
- }.should raise_error(Encoding::CompatibilityError)
+ }.should.raise(Encoding::CompatibilityError)
+ end
+
+ describe "%c" do
+ it "supports Unicode characters" do
+ result = @method.call("%c", 1286)
+ result.should == "Ԇ"
+ result.bytes.should == [212, 134]
+
+ result = @method.call("%c", "ش")
+ result.should == "ش"
+ result.bytes.should == [216, 180]
+ end
+
+ it "raises error when a codepoint isn't representable in an encoding of a format string" do
+ format = "%c".encode("ASCII")
+
+ -> {
+ @method.call(format, 1286)
+ }.should.raise(RangeError, /out of char range/)
+ end
+
+ it "uses the encoding of the format string to interpret codepoints" do
+ format = "%c".dup.force_encoding("euc-jp")
+ result = @method.call(format, 9415601)
+
+ result.encoding.should == Encoding::EUC_JP
+ result.should == "é".encode(Encoding::EUC_JP)
+ result.bytes.should == [143, 171, 177]
+ end
end
end
diff --git a/spec/ruby/core/kernel/shared/then.rb b/spec/ruby/core/kernel/shared/then.rb
index b52075371f..c71393bf50 100644
--- a/spec/ruby/core/kernel/shared/then.rb
+++ b/spec/ruby/core/kernel/shared/then.rb
@@ -1,20 +1,20 @@
describe :kernel_then, shared: true do
it "yields self" do
object = Object.new
- object.send(@method) { |o| o.should equal object }
+ object.send(@method) { |o| o.should.equal? object }
end
it "returns the block return value" do
object = Object.new
- object.send(@method) { 42 }.should equal 42
+ object.send(@method) { 42 }.should.equal? 42
end
it "returns a sized Enumerator when no block given" do
object = Object.new
enum = object.send(@method)
- enum.should be_an_instance_of Enumerator
- enum.size.should equal 1
- enum.peek.should equal object
- enum.first.should equal object
+ enum.should.instance_of? Enumerator
+ enum.size.should.equal? 1
+ enum.peek.should.equal? object
+ enum.first.should.equal? object
end
end
diff --git a/spec/ruby/core/kernel/singleton_class_spec.rb b/spec/ruby/core/kernel/singleton_class_spec.rb
index a8bcd916d1..7915272937 100644
--- a/spec/ruby/core/kernel/singleton_class_spec.rb
+++ b/spec/ruby/core/kernel/singleton_class_spec.rb
@@ -1,3 +1,6 @@
+# truffleruby_primitives: true
+require_relative '../../spec_helper'
+
describe "Kernel#singleton_class" do
it "returns class extended from an object" do
x = Object.new
@@ -18,10 +21,54 @@ describe "Kernel#singleton_class" do
end
it "raises TypeError for Integer" do
- -> { 123.singleton_class }.should raise_error(TypeError)
+ -> { 123.singleton_class }.should.raise(TypeError, "can't define singleton")
+ end
+
+ it "raises TypeError for Float" do
+ -> { 3.14.singleton_class }.should.raise(TypeError, "can't define singleton")
end
it "raises TypeError for Symbol" do
- -> { :foo.singleton_class }.should raise_error(TypeError)
+ -> { :foo.singleton_class }.should.raise(TypeError, "can't define singleton")
+ end
+
+ it "raises TypeError for a frozen deduplicated String" do
+ -> { (-"string").singleton_class }.should.raise(TypeError, "can't define singleton")
+ -> { a = -"string"; a.singleton_class }.should.raise(TypeError, "can't define singleton")
+ -> { a = "string"; (-a).singleton_class }.should.raise(TypeError, "can't define singleton")
+ end
+
+ it "returns a frozen singleton class if object is frozen" do
+ obj = Object.new
+ obj.freeze
+ obj.singleton_class.frozen?.should == true
+ end
+
+ context "for an IO object with a replaced singleton class" do
+ it "looks up singleton methods from the fresh singleton class after an object instance got a new one" do
+ proxy = -> io { io.foo }
+ if RUBY_ENGINE == 'truffleruby'
+ # We need an inline cache with only this object seen, the best way to do that is to use a Primitive
+ sclass = -> io { Primitive.singleton_class(io) }
+ else
+ sclass = -> io { io.singleton_class }
+ end
+
+ io = File.new(__FILE__)
+ io.define_singleton_method(:foo) { "old" }
+ sclass1 = sclass.call(io)
+ proxy.call(io).should == "old"
+
+ # IO#reopen is the only method which can replace an object's singleton class
+ io2 = File.new(__FILE__)
+ io.reopen(io2)
+ io.define_singleton_method(:foo) { "new" }
+ sclass2 = sclass.call(io)
+ sclass2.should_not.equal?(sclass1)
+ proxy.call(io).should == "new"
+ ensure
+ io2.close
+ io.close
+ end
end
end
diff --git a/spec/ruby/core/kernel/singleton_method_spec.rb b/spec/ruby/core/kernel/singleton_method_spec.rb
index 0bdf125ad8..fe8e23eb02 100644
--- a/spec/ruby/core/kernel/singleton_method_spec.rb
+++ b/spec/ruby/core/kernel/singleton_method_spec.rb
@@ -1,10 +1,10 @@
require_relative '../../spec_helper'
describe "Kernel#singleton_method" do
- it "find a method defined on the singleton class" do
+ it "finds a method defined on the singleton class" do
obj = Object.new
def obj.foo; end
- obj.singleton_method(:foo).should be_an_instance_of(Method)
+ obj.singleton_method(:foo).should.instance_of?(Method)
end
it "returns a Method which can be called" do
@@ -23,7 +23,7 @@ describe "Kernel#singleton_method" do
obj.foo.should == 42
-> {
obj.singleton_method(:foo)
- }.should raise_error(NameError) { |e|
+ }.should.raise(NameError) { |e|
# a NameError and not a NoMethodError
e.class.should == NameError
}
@@ -33,9 +33,53 @@ describe "Kernel#singleton_method" do
obj = Object.new
-> {
obj.singleton_method(:not_existing)
- }.should raise_error(NameError) { |e|
+ }.should.raise(NameError) { |e|
# a NameError and not a NoMethodError
e.class.should == NameError
}
end
+
+ ruby_bug "#20620", ""..."3.4" do
+ it "finds a method defined in a module included in the singleton class" do
+ m = Module.new do
+ def foo
+ :foo
+ end
+ end
+
+ obj = Object.new
+ obj.singleton_class.include(m)
+
+ obj.singleton_method(:foo).should.instance_of?(Method)
+ obj.singleton_method(:foo).call.should == :foo
+ end
+
+ it "finds a method defined in a module prepended in the singleton class" do
+ m = Module.new do
+ def foo
+ :foo
+ end
+ end
+
+ obj = Object.new
+ obj.singleton_class.prepend(m)
+
+ obj.singleton_method(:foo).should.instance_of?(Method)
+ obj.singleton_method(:foo).call.should == :foo
+ end
+
+ it "finds a method defined in a module that an object is extended with" do
+ m = Module.new do
+ def foo
+ :foo
+ end
+ end
+
+ obj = Object.new
+ obj.extend(m)
+
+ obj.singleton_method(:foo).should.instance_of?(Method)
+ obj.singleton_method(:foo).call.should == :foo
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/singleton_methods_spec.rb b/spec/ruby/core/kernel/singleton_methods_spec.rb
index a127a439de..a7f6969519 100644
--- a/spec/ruby/core/kernel/singleton_methods_spec.rb
+++ b/spec/ruby/core/kernel/singleton_methods_spec.rb
@@ -8,33 +8,33 @@ describe :kernel_singleton_methods, shared: true do
end
it "returns the names of module methods for a module" do
- ReflectSpecs::M.singleton_methods(*@object).should include(:ms_pro, :ms_pub)
+ ReflectSpecs::M.singleton_methods(*@object).to_set.should >= Set[:ms_pro, :ms_pub]
end
it "does not return private module methods for a module" do
- ReflectSpecs::M.singleton_methods(*@object).should_not include(:ms_pri)
+ ReflectSpecs::M.singleton_methods(*@object).should_not.include?(:ms_pri)
end
it "returns the names of class methods for a class" do
- ReflectSpecs::A.singleton_methods(*@object).should include(:as_pro, :as_pub)
+ ReflectSpecs::A.singleton_methods(*@object).to_set.should >= Set[:as_pro, :as_pub]
end
it "does not return private class methods for a class" do
- ReflectSpecs::A.singleton_methods(*@object).should_not include(:as_pri)
+ ReflectSpecs::A.singleton_methods(*@object).should_not.include?(:as_pri)
end
it "returns the names of singleton methods for an object" do
- ReflectSpecs.os.singleton_methods(*@object).should include(:os_pro, :os_pub)
+ ReflectSpecs.os.singleton_methods(*@object).to_set.should >= Set[:os_pro, :os_pub]
end
end
describe :kernel_singleton_methods_modules, shared: true do
it "does not return any included methods for a module including a module" do
- ReflectSpecs::N.singleton_methods(*@object).should include(:ns_pro, :ns_pub)
+ ReflectSpecs::N.singleton_methods(*@object).to_set.should >= Set[:ns_pro, :ns_pub]
end
it "does not return any included methods for a class including a module" do
- ReflectSpecs::D.singleton_methods(*@object).should include(:ds_pro, :ds_pub)
+ ReflectSpecs::D.singleton_methods(*@object).to_set.should >= Set[:ds_pro, :ds_pub]
end
it "for a module does not return methods in a module prepended to Module itself" do
@@ -44,7 +44,7 @@ describe :kernel_singleton_methods_modules, shared: true do
ancestors = mod.singleton_class.ancestors
ancestors[0...2].should == [ mod.singleton_class, mod ]
- ancestors.should include(SingletonMethodsSpecs::Prepended)
+ ancestors.should.include?(SingletonMethodsSpecs::Prepended)
# Do not search prepended modules of `Module`, as that's a non-singleton class
mod.singleton_methods.should == []
@@ -53,7 +53,7 @@ end
describe :kernel_singleton_methods_supers, shared: true do
it "returns the names of singleton methods for an object extended with a module" do
- ReflectSpecs.oe.singleton_methods(*@object).should include(:m_pro, :m_pub)
+ ReflectSpecs.oe.singleton_methods(*@object).to_set.should >= Set[:m_pro, :m_pub]
end
it "returns a unique list for an object extended with a module" do
@@ -63,15 +63,15 @@ describe :kernel_singleton_methods_supers, shared: true do
end
it "returns the names of singleton methods for an object extended with two modules" do
- ReflectSpecs.oee.singleton_methods(*@object).should include(:m_pro, :m_pub, :n_pro, :n_pub)
+ ReflectSpecs.oee.singleton_methods(*@object).to_set.should >= Set[:m_pro, :m_pub, :n_pro, :n_pub]
end
it "returns the names of singleton methods for an object extended with a module including a module" do
- ReflectSpecs.oei.singleton_methods(*@object).should include(:n_pro, :n_pub, :m_pro, :m_pub)
+ ReflectSpecs.oei.singleton_methods(*@object).to_set.should >= Set[:n_pro, :n_pub, :m_pro, :m_pub]
end
it "returns the names of inherited singleton methods for a subclass" do
- ReflectSpecs::B.singleton_methods(*@object).should include(:as_pro, :as_pub, :bs_pro, :bs_pub)
+ ReflectSpecs::B.singleton_methods(*@object).to_set.should >= Set[:as_pro, :as_pub, :bs_pro, :bs_pub]
end
it "returns a unique list for a subclass" do
@@ -81,7 +81,7 @@ describe :kernel_singleton_methods_supers, shared: true do
end
it "returns the names of inherited singleton methods for a subclass including a module" do
- ReflectSpecs::C.singleton_methods(*@object).should include(:as_pro, :as_pub, :cs_pro, :cs_pub)
+ ReflectSpecs::C.singleton_methods(*@object).to_set.should >= Set[:as_pro, :as_pub, :cs_pro, :cs_pub]
end
it "returns a unique list for a subclass including a module" do
@@ -91,57 +91,62 @@ describe :kernel_singleton_methods_supers, shared: true do
end
it "returns the names of inherited singleton methods for a subclass of a class including a module" do
- ReflectSpecs::E.singleton_methods(*@object).should include(:ds_pro, :ds_pub, :es_pro, :es_pub)
+ ReflectSpecs::E.singleton_methods(*@object).to_set.should >= Set[:ds_pro, :ds_pub, :es_pro, :es_pub]
end
it "returns the names of inherited singleton methods for a subclass of a class that includes a module, where the subclass also includes a module" do
- ReflectSpecs::F.singleton_methods(*@object).should include(:ds_pro, :ds_pub, :fs_pro, :fs_pub)
+ ReflectSpecs::F.singleton_methods(*@object).to_set.should >= Set[:ds_pro, :ds_pub, :fs_pro, :fs_pub]
end
it "returns the names of inherited singleton methods for a class extended with a module" do
- ReflectSpecs::P.singleton_methods(*@object).should include(:m_pro, :m_pub)
+ ReflectSpecs::P.singleton_methods(*@object).to_set.should >= Set[:m_pro, :m_pub]
end
end
describe :kernel_singleton_methods_private_supers, shared: true do
it "does not return private singleton methods for an object extended with a module" do
- ReflectSpecs.oe.singleton_methods(*@object).should_not include(:m_pri)
+ ReflectSpecs.oe.singleton_methods(*@object).should_not.include?(:m_pri)
end
it "does not return private singleton methods for an object extended with two modules" do
- ReflectSpecs.oee.singleton_methods(*@object).should_not include(:m_pri)
+ ReflectSpecs.oee.singleton_methods(*@object).should_not.include?(:m_pri)
end
it "does not return private singleton methods for an object extended with a module including a module" do
- ReflectSpecs.oei.singleton_methods(*@object).should_not include(:n_pri, :m_pri)
+ ReflectSpecs.oei.singleton_methods(*@object).should_not.include?(:n_pri)
+ ReflectSpecs.oei.singleton_methods(*@object).should_not.include?(:m_pri)
end
it "does not return private singleton methods for a class extended with a module" do
- ReflectSpecs::P.singleton_methods(*@object).should_not include(:m_pri)
+ ReflectSpecs::P.singleton_methods(*@object).should_not.include?(:m_pri)
end
it "does not return private inherited singleton methods for a module including a module" do
- ReflectSpecs::N.singleton_methods(*@object).should_not include(:ns_pri)
+ ReflectSpecs::N.singleton_methods(*@object).should_not.include?(:ns_pri)
end
it "does not return private inherited singleton methods for a class including a module" do
- ReflectSpecs::D.singleton_methods(*@object).should_not include(:ds_pri)
+ ReflectSpecs::D.singleton_methods(*@object).should_not.include?(:ds_pri)
end
it "does not return private inherited singleton methods for a subclass" do
- ReflectSpecs::B.singleton_methods(*@object).should_not include(:as_pri, :bs_pri)
+ ReflectSpecs::B.singleton_methods(*@object).should_not.include?(:as_pri)
+ ReflectSpecs::B.singleton_methods(*@object).should_not.include?(:bs_pri)
end
it "does not return private inherited singleton methods for a subclass including a module" do
- ReflectSpecs::C.singleton_methods(*@object).should_not include(:as_pri, :cs_pri)
+ ReflectSpecs::C.singleton_methods(*@object).should_not.include?(:as_pri)
+ ReflectSpecs::C.singleton_methods(*@object).should_not.include?(:cs_pri)
end
it "does not return private inherited singleton methods for a subclass of a class including a module" do
- ReflectSpecs::E.singleton_methods(*@object).should_not include(:ds_pri, :es_pri)
+ ReflectSpecs::E.singleton_methods(*@object).should_not.include?(:ds_pri)
+ ReflectSpecs::E.singleton_methods(*@object).should_not.include?(:es_pri)
end
it "does not return private inherited singleton methods for a subclass of a class that includes a module, where the subclass also includes a module" do
- ReflectSpecs::F.singleton_methods(*@object).should_not include(:ds_pri, :fs_pri)
+ ReflectSpecs::F.singleton_methods(*@object).should_not.include?(:ds_pri)
+ ReflectSpecs::F.singleton_methods(*@object).should_not.include?(:fs_pri)
end
end
@@ -178,15 +183,17 @@ describe "Kernel#singleton_methods" do
end
it "returns the names of singleton methods of the subclass" do
- ReflectSpecs::B.singleton_methods(false).should include(:bs_pro, :bs_pub)
+ ReflectSpecs::B.singleton_methods(false).to_set.should >= Set[:bs_pro, :bs_pub]
end
it "does not return names of inherited singleton methods for a subclass" do
- ReflectSpecs::B.singleton_methods(false).should_not include(:as_pro, :as_pub)
+ ReflectSpecs::B.singleton_methods(false).should_not.include?(:as_pro)
+ ReflectSpecs::B.singleton_methods(false).should_not.include?(:as_pub)
end
it "does not return the names of inherited singleton methods for a class extended with a module" do
- ReflectSpecs::P.singleton_methods(false).should_not include(:m_pro, :m_pub)
+ ReflectSpecs::P.singleton_methods(false).should_not.include?(:m_pro)
+ ReflectSpecs::P.singleton_methods(false).should_not.include?(:m_pub)
end
end
end
diff --git a/spec/ruby/core/kernel/sleep_spec.rb b/spec/ruby/core/kernel/sleep_spec.rb
index 32da6344c1..61d8cc2380 100644
--- a/spec/ruby/core/kernel/sleep_spec.rb
+++ b/spec/ruby/core/kernel/sleep_spec.rb
@@ -1,13 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+require_relative '../fiber/fixtures/scheduler'
describe "Kernel#sleep" do
it "is a private method" do
- Kernel.should have_private_instance_method(:sleep)
+ Kernel.private_instance_methods(false).should.include?(:sleep)
end
it "returns an Integer" do
- sleep(0.001).should be_kind_of(Integer)
+ sleep(0.001).should.is_a?(Integer)
end
it "accepts a Float" do
@@ -22,23 +22,19 @@ describe "Kernel#sleep" do
sleep(Rational(1, 999)).should >= 0
end
- it "accepts any Object that reponds to divmod" do
+ it "accepts any Object that responds to divmod" do
o = Object.new
def o.divmod(*); [0, 0.001]; end
sleep(o).should >= 0
end
it "raises an ArgumentError when passed a negative duration" do
- -> { sleep(-0.1) }.should raise_error(ArgumentError)
- -> { sleep(-1) }.should raise_error(ArgumentError)
- end
-
- it "raises a TypeError when passed nil" do
- -> { sleep(nil) }.should raise_error(TypeError)
+ -> { sleep(-0.1) }.should.raise(ArgumentError)
+ -> { sleep(-1) }.should.raise(ArgumentError)
end
it "raises a TypeError when passed a String" do
- -> { sleep('2') }.should raise_error(TypeError)
+ -> { sleep('2') }.should.raise(TypeError)
end
it "pauses execution indefinitely if not given a duration" do
@@ -55,6 +51,66 @@ describe "Kernel#sleep" do
t.wakeup
t.value.should == 5
end
+
+ it "sleeps with nanosecond precision" do
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ 100.times do
+ sleep(0.0001)
+ end
+ end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ actual_duration = end_time - start_time
+ actual_duration.should > 0.01 # 100 * 0.0001 => 0.01
+ end
+
+ it "accepts a nil duration" do
+ running = false
+ t = Thread.new do
+ running = true
+ sleep(nil)
+ 5
+ end
+
+ Thread.pass until running
+ Thread.pass while t.status and t.status != "sleep"
+
+ t.wakeup
+ t.value.should == 5
+ end
+
+ context "Kernel.sleep with Fiber scheduler" do
+ before :each do
+ Fiber.set_scheduler(FiberSpecs::LoggingScheduler.new)
+ end
+
+ after :each do
+ Fiber.set_scheduler(nil)
+ end
+
+ it "calls the scheduler without arguments when no duration is given" do
+ sleeper = Fiber.new(blocking: false) do
+ sleep
+ end
+ sleeper.resume
+ Fiber.scheduler.events.should == [{ event: :kernel_sleep, fiber: sleeper, args: [] }]
+ end
+
+ it "calls the scheduler with the given duration" do
+ sleeper = Fiber.new(blocking: false) do
+ sleep(0.01)
+ end
+ sleeper.resume
+ Fiber.scheduler.events.should == [{ event: :kernel_sleep, fiber: sleeper, args: [0.01] }]
+ end
+
+ it "does not call the scheduler if the fiber is blocking" do
+ sleeper = Fiber.new(blocking: true) do
+ sleep(0.01)
+ end
+ sleeper.resume
+ Fiber.scheduler.events.should == []
+ end
+ end
end
describe "Kernel.sleep" do
diff --git a/spec/ruby/core/kernel/spawn_spec.rb b/spec/ruby/core/kernel/spawn_spec.rb
index ba05b629d5..3432fc31da 100644
--- a/spec/ruby/core/kernel/spawn_spec.rb
+++ b/spec/ruby/core/kernel/spawn_spec.rb
@@ -6,7 +6,7 @@ require_relative 'fixtures/classes'
# run here as it is redundant and takes too long for little gain.
describe "Kernel#spawn" do
it "is a private method" do
- Kernel.should have_private_instance_method(:spawn)
+ Kernel.private_instance_methods(false).should.include?(:spawn)
end
it "executes the given command" do
diff --git a/spec/ruby/core/kernel/sprintf_spec.rb b/spec/ruby/core/kernel/sprintf_spec.rb
index 7adf71be76..5a4a90ff7a 100644
--- a/spec/ruby/core/kernel/sprintf_spec.rb
+++ b/spec/ruby/core/kernel/sprintf_spec.rb
@@ -3,22 +3,62 @@ require_relative 'fixtures/classes'
require_relative 'shared/sprintf'
require_relative 'shared/sprintf_encoding'
+describe :kernel_sprintf_to_str, shared: true do
+ it "calls #to_str to convert the format object to a String" do
+ obj = mock('format string')
+ obj.should_receive(:to_str).and_return("to_str: %i")
+ @method.call(obj, 42).should == "to_str: 42"
+ end
+end
+
describe "Kernel#sprintf" do
it_behaves_like :kernel_sprintf, -> format, *args {
- sprintf(format, *args)
+ r = nil
+ -> {
+ r = sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
it_behaves_like :kernel_sprintf_encoding, -> format, *args {
- sprintf(format, *args)
+ r = nil
+ -> {
+ r = sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
+ }
+
+ it_behaves_like :kernel_sprintf_to_str, -> format, *args {
+ r = nil
+ -> {
+ r = sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
end
describe "Kernel.sprintf" do
it_behaves_like :kernel_sprintf, -> format, *args {
- Kernel.sprintf(format, *args)
+ r = nil
+ -> {
+ r = Kernel.sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
it_behaves_like :kernel_sprintf_encoding, -> format, *args {
- Kernel.sprintf(format, *args)
+ r = nil
+ -> {
+ r = Kernel.sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
+ }
+
+ it_behaves_like :kernel_sprintf_to_str, -> format, *args {
+ r = nil
+ -> {
+ r = Kernel.sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
end
diff --git a/spec/ruby/core/kernel/srand_spec.rb b/spec/ruby/core/kernel/srand_spec.rb
index 95bb406f46..cbc3a7f4b8 100644
--- a/spec/ruby/core/kernel/srand_spec.rb
+++ b/spec/ruby/core/kernel/srand_spec.rb
@@ -11,7 +11,7 @@ describe "Kernel#srand" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:srand)
+ Kernel.private_instance_methods(false).should.include?(:srand)
end
it "returns the previous seed value" do
@@ -31,7 +31,7 @@ describe "Kernel#srand" do
end
it "defaults number to a random value" do
- -> { srand }.should_not raise_error
+ -> { srand }.should_not.raise
srand.should_not == 0
end
@@ -60,11 +60,11 @@ describe "Kernel#srand" do
end
it "raises a TypeError when passed nil" do
- -> { srand(nil) }.should raise_error(TypeError)
+ -> { srand(nil) }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- -> { srand("7") }.should raise_error(TypeError)
+ -> { srand("7") }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/kernel/sub_spec.rb b/spec/ruby/core/kernel/sub_spec.rb
index 9130bd159c..b175e371dc 100644
--- a/spec/ruby/core/kernel/sub_spec.rb
+++ b/spec/ruby/core/kernel/sub_spec.rb
@@ -6,13 +6,13 @@ require_relative 'fixtures/classes'
ruby_version_is ""..."1.9" do
describe "Kernel#sub" do
it "is a private method" do
- Kernel.should have_private_instance_method(:sub)
+ Kernel.private_instance_methods(false).should.include?(:sub)
end
end
describe "Kernel#sub!" do
it "is a private method" do
- Kernel.should have_private_instance_method(:sub!)
+ Kernel.private_instance_methods(false).should.include?(:sub!)
end
end
diff --git a/spec/ruby/core/kernel/syscall_spec.rb b/spec/ruby/core/kernel/syscall_spec.rb
index 32d07b3ae2..63943cdad5 100644
--- a/spec/ruby/core/kernel/syscall_spec.rb
+++ b/spec/ruby/core/kernel/syscall_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel#syscall" do
it "is a private method" do
- Kernel.should have_private_instance_method(:syscall)
+ Kernel.private_instance_methods(false).should.include?(:syscall)
end
end
diff --git a/spec/ruby/core/kernel/system_spec.rb b/spec/ruby/core/kernel/system_spec.rb
index 9671a650cc..b24956104a 100644
--- a/spec/ruby/core/kernel/system_spec.rb
+++ b/spec/ruby/core/kernel/system_spec.rb
@@ -5,14 +5,14 @@ describe :kernel_system, shared: true do
it "executes the specified command in a subprocess" do
-> { @object.system("echo a") }.should output_to_fd("a\n")
- $?.should be_an_instance_of Process::Status
+ $?.should.instance_of? Process::Status
$?.should.success?
end
it "returns true when the command exits with a zero exit status" do
@object.system(ruby_cmd('exit 0')).should == true
- $?.should be_an_instance_of Process::Status
+ $?.should.instance_of? Process::Status
$?.should.success?
$?.exitstatus.should == 0
end
@@ -20,24 +20,24 @@ describe :kernel_system, shared: true do
it "returns false when the command exits with a non-zero exit status" do
@object.system(ruby_cmd('exit 1')).should == false
- $?.should be_an_instance_of Process::Status
+ $?.should.instance_of? Process::Status
$?.should_not.success?
$?.exitstatus.should == 1
end
it "raises RuntimeError when `exception: true` is given and the command exits with a non-zero exit status" do
- -> { @object.system(ruby_cmd('exit 1'), exception: true) }.should raise_error(RuntimeError)
+ -> { @object.system(ruby_cmd('exit 1'), exception: true) }.should.raise(RuntimeError)
end
it "raises Errno::ENOENT when `exception: true` is given and the specified command does not exist" do
- -> { @object.system('feature_14386', exception: true) }.should raise_error(Errno::ENOENT)
+ -> { @object.system('feature_14386', exception: true) }.should.raise(Errno::ENOENT)
end
it "returns nil when command execution fails" do
- @object.system("sad").should be_nil
+ @object.system("sad").should == nil
- $?.should be_an_instance_of Process::Status
- $?.pid.should be_kind_of(Integer)
+ $?.should.instance_of? Process::Status
+ $?.pid.should.is_a?(Integer)
$?.should_not.success?
end
@@ -64,6 +64,23 @@ describe :kernel_system, shared: true do
end
end
+ platform_is_not :windows do
+ before :each do
+ require 'tmpdir'
+ @shell_command = File.join(Dir.mktmpdir, "noshebang.cmd")
+ File.write(@shell_command, %[echo "$PATH"\n], perm: 0o700)
+ end
+
+ after :each do
+ File.unlink(@shell_command)
+ Dir.rmdir(File.dirname(@shell_command))
+ end
+
+ it "executes with `sh` if the command is executable but not binary and there is no shebang" do
+ -> { @object.system(@shell_command) }.should output_to_fd(ENV['PATH'] + "\n")
+ end
+ end
+
before :each do
ENV['TEST_SH_EXPANSION'] = 'foo'
@shell_var = '$TEST_SH_EXPANSION'
@@ -104,7 +121,7 @@ end
describe "Kernel#system" do
it "is a private method" do
- Kernel.should have_private_instance_method(:system)
+ Kernel.private_instance_methods(false).should.include?(:system)
end
it_behaves_like :kernel_system, :system, KernelSpecs::Method.new
diff --git a/spec/ruby/core/kernel/taint_spec.rb b/spec/ruby/core/kernel/taint_spec.rb
index 9a58bb5f04..9a2efbaea0 100644
--- a/spec/ruby/core/kernel/taint_spec.rb
+++ b/spec/ruby/core/kernel/taint_spec.rb
@@ -2,18 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#taint" do
- ruby_version_is ""..."3.0" do
- it "is a no-op" do
- o = Object.new
- o.taint
- o.should_not.tainted?
- end
-
- it "warns in verbose mode" do
- -> {
- obj = mock("tainted")
- obj.taint
- }.should complain(/Object#taint is deprecated and will be removed in Ruby 3.2/, verbose: true)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:taint)
end
end
diff --git a/spec/ruby/core/kernel/tainted_spec.rb b/spec/ruby/core/kernel/tainted_spec.rb
index 7511c730c9..837eb1dafb 100644
--- a/spec/ruby/core/kernel/tainted_spec.rb
+++ b/spec/ruby/core/kernel/tainted_spec.rb
@@ -2,20 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#tainted?" do
- ruby_version_is ""..."3.0" do
- it "is a no-op" do
- o = mock('o')
- p = mock('p')
- p.taint
- o.should_not.tainted?
- p.should_not.tainted?
- end
-
- it "warns in verbose mode" do
- -> {
- o = mock('o')
- o.tainted?
- }.should complain(/Object#tainted\? is deprecated and will be removed in Ruby 3.2/, verbose: true)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:tainted?)
end
end
diff --git a/spec/ruby/core/kernel/tap_spec.rb b/spec/ruby/core/kernel/tap_spec.rb
index f7720a6dc7..453b9b84d5 100644
--- a/spec/ruby/core/kernel/tap_spec.rb
+++ b/spec/ruby/core/kernel/tap_spec.rb
@@ -4,10 +4,10 @@ require_relative 'fixtures/classes'
describe "Kernel#tap" do
it "always yields self and returns self" do
a = KernelSpecs::A.new
- a.tap{|o| o.should equal(a); 42}.should equal(a)
+ a.tap{|o| o.should.equal?(a); 42}.should.equal?(a)
end
it "raises a LocalJumpError when no block given" do
- -> { 3.tap }.should raise_error(LocalJumpError)
+ -> { 3.tap }.should.raise(LocalJumpError)
end
end
diff --git a/spec/ruby/core/kernel/test_spec.rb b/spec/ruby/core/kernel/test_spec.rb
index abb365aed2..30717dfd98 100644
--- a/spec/ruby/core/kernel/test_spec.rb
+++ b/spec/ruby/core/kernel/test_spec.rb
@@ -3,12 +3,12 @@ require_relative 'fixtures/classes'
describe "Kernel#test" do
before :all do
- @file = File.dirname(__FILE__) + '/fixtures/classes.rb'
- @dir = File.dirname(__FILE__) + '/fixtures'
+ @file = __dir__ + '/fixtures/classes.rb'
+ @dir = __dir__ + '/fixtures'
end
it "is a private method" do
- Kernel.should have_private_instance_method(:test)
+ Kernel.private_instance_methods(false).should.include?(:test)
end
it "returns true when passed ?f if the argument is a regular file" do
@@ -28,7 +28,7 @@ describe "Kernel#test" do
link = tmp("file_symlink.lnk")
File.symlink(@file, link)
begin
- Kernel.test(?l, link).should be_true
+ Kernel.test(?l, link).should == true
ensure
rm_r link
end
@@ -36,11 +36,11 @@ describe "Kernel#test" do
end
it "returns true when passed ?r if the argument is readable by the effective uid" do
- Kernel.test(?r, @file).should be_true
+ Kernel.test(?r, @file).should == true
end
it "returns true when passed ?R if the argument is readable by the real uid" do
- Kernel.test(?R, @file).should be_true
+ Kernel.test(?R, @file).should == true
end
context "writable test" do
@@ -54,11 +54,11 @@ describe "Kernel#test" do
end
it "returns true when passed ?w if the argument is readable by the effective uid" do
- Kernel.test(?w, @tmp_file).should be_true
+ Kernel.test(?w, @tmp_file).should == true
end
it "returns true when passed ?W if the argument is readable by the real uid" do
- Kernel.test(?W, @tmp_file).should be_true
+ Kernel.test(?W, @tmp_file).should == true
end
end
diff --git a/spec/ruby/core/kernel/throw_spec.rb b/spec/ruby/core/kernel/throw_spec.rb
index 64bfccb413..1086126176 100644
--- a/spec/ruby/core/kernel/throw_spec.rb
+++ b/spec/ruby/core/kernel/throw_spec.rb
@@ -7,7 +7,7 @@ describe "Kernel.throw" do
:value
throw :blah
fail("throw didn't transfer the control")
- end.should be_nil
+ end.should == nil
end
it "transfers control to the innermost catch block waiting for the same symbol" do
@@ -42,11 +42,11 @@ describe "Kernel.throw" do
end
it "raises an ArgumentError if there is no catch block for the symbol" do
- -> { throw :blah }.should raise_error(ArgumentError)
+ -> { throw :blah }.should.raise(ArgumentError)
end
it "raises an UncaughtThrowError if there is no catch block for the symbol" do
- -> { throw :blah }.should raise_error(UncaughtThrowError)
+ -> { throw :blah }.should.raise(UncaughtThrowError)
end
it "raises ArgumentError if 3 or more arguments provided" do
@@ -54,13 +54,13 @@ describe "Kernel.throw" do
catch :blah do
throw :blah, :return_value, 2
end
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
catch :blah do
throw :blah, :return_value, 2, 3, 4, 5
end
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "can throw an object" do
@@ -69,12 +69,12 @@ describe "Kernel.throw" do
catch obj do
throw obj
end
- }.should_not raise_error(NameError)
+ }.should_not.raise(NameError)
end
end
describe "Kernel#throw" do
it "is a private method" do
- Kernel.should have_private_instance_method(:throw)
+ Kernel.private_instance_methods(false).should.include?(:throw)
end
end
diff --git a/spec/ruby/core/kernel/trace_var_spec.rb b/spec/ruby/core/kernel/trace_var_spec.rb
index 3c84aa5e60..150c3da266 100644
--- a/spec/ruby/core/kernel/trace_var_spec.rb
+++ b/spec/ruby/core/kernel/trace_var_spec.rb
@@ -14,7 +14,7 @@ describe "Kernel#trace_var" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:trace_var)
+ Kernel.private_instance_methods(false).should.include?(:trace_var)
end
it "hooks assignments to a global variable" do
@@ -49,6 +49,6 @@ describe "Kernel#trace_var" do
it "raises ArgumentError if no block or proc is provided" do
-> do
trace_var :$Kernel_trace_var_global
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/kernel/trap_spec.rb b/spec/ruby/core/kernel/trap_spec.rb
index 4c801a7215..8f44f3af4b 100644
--- a/spec/ruby/core/kernel/trap_spec.rb
+++ b/spec/ruby/core/kernel/trap_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Kernel#trap" do
it "is a private method" do
- Kernel.should have_private_instance_method(:trap)
+ Kernel.private_instance_methods(false).should.include?(:trap)
end
# Behaviour is specified for Signal.trap
diff --git a/spec/ruby/core/kernel/trust_spec.rb b/spec/ruby/core/kernel/trust_spec.rb
index 4665036da6..ef3fa9a3e1 100644
--- a/spec/ruby/core/kernel/trust_spec.rb
+++ b/spec/ruby/core/kernel/trust_spec.rb
@@ -2,19 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#trust" do
- ruby_version_is ""..."3.0" do
- it "is a no-op" do
- o = Object.new.untrust
- o.should_not.untrusted?
- o.trust
- o.should_not.untrusted?
- end
-
- it "warns in verbose mode" do
- -> {
- o = Object.new.untrust
- o.trust
- }.should complain(/Object#trust is deprecated and will be removed in Ruby 3.2/, verbose: true)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:trust)
end
end
diff --git a/spec/ruby/core/kernel/untaint_spec.rb b/spec/ruby/core/kernel/untaint_spec.rb
index 42fe8a4239..47e8544bd4 100644
--- a/spec/ruby/core/kernel/untaint_spec.rb
+++ b/spec/ruby/core/kernel/untaint_spec.rb
@@ -2,19 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#untaint" do
- ruby_version_is ""..."3.0" do
- it "is a no-op" do
- o = Object.new.taint
- o.should_not.tainted?
- o.untaint
- o.should_not.tainted?
- end
-
- it "warns in verbose mode" do
- -> {
- o = Object.new.taint
- o.untaint
- }.should complain(/Object#untaint is deprecated and will be removed in Ruby 3.2/, verbose: true)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:untaint)
end
end
diff --git a/spec/ruby/core/kernel/untrace_var_spec.rb b/spec/ruby/core/kernel/untrace_var_spec.rb
index 1925a3a836..8b219801c8 100644
--- a/spec/ruby/core/kernel/untrace_var_spec.rb
+++ b/spec/ruby/core/kernel/untrace_var_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Kernel#untrace_var" do
it "is a private method" do
- Kernel.should have_private_instance_method(:untrace_var)
+ Kernel.private_instance_methods(false).should.include?(:untrace_var)
end
end
diff --git a/spec/ruby/core/kernel/untrust_spec.rb b/spec/ruby/core/kernel/untrust_spec.rb
index ba0e073cf0..8787ab3fc9 100644
--- a/spec/ruby/core/kernel/untrust_spec.rb
+++ b/spec/ruby/core/kernel/untrust_spec.rb
@@ -2,18 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#untrust" do
- ruby_version_is ""..."3.0" do
- it "is a no-op" do
- o = Object.new
- o.untrust
- o.should_not.untrusted?
- end
-
- it "warns in verbose mode" do
- -> {
- o = Object.new
- o.untrust
- }.should complain(/Object#untrust is deprecated and will be removed in Ruby 3.2/, verbose: true)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:untrust)
end
end
diff --git a/spec/ruby/core/kernel/untrusted_spec.rb b/spec/ruby/core/kernel/untrusted_spec.rb
index 517bd4711b..29261be9c4 100644
--- a/spec/ruby/core/kernel/untrusted_spec.rb
+++ b/spec/ruby/core/kernel/untrusted_spec.rb
@@ -2,19 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#untrusted?" do
- ruby_version_is ""..."3.0" do
- it "is a no-op" do
- o = mock('o')
- o.should_not.untrusted?
- o.untrust
- o.should_not.untrusted?
- end
-
- it "warns in verbose mode" do
- -> {
- o = mock('o')
- o.untrusted?
- }.should complain(/Object#untrusted\? is deprecated and will be removed in Ruby 3.2/, verbose: true)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:untrusted?)
end
end
diff --git a/spec/ruby/core/kernel/warn_spec.rb b/spec/ruby/core/kernel/warn_spec.rb
index 7df6fa72d1..189129dd31 100644
--- a/spec/ruby/core/kernel/warn_spec.rb
+++ b/spec/ruby/core/kernel/warn_spec.rb
@@ -14,7 +14,7 @@ describe "Kernel#warn" do
end
it "is a private method" do
- Kernel.should have_private_instance_method(:warn)
+ Kernel.private_instance_methods(false).should.include?(:warn)
end
it "accepts multiple arguments" do
@@ -112,6 +112,12 @@ describe "Kernel#warn" do
ruby_exe(file, options: "-rrubygems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n"
end
+ it "doesn't show the caller when the uplevel is `nil`" do
+ w = KernelSpecs::WarnInNestedCall.new
+
+ -> { w.f4("foo", nil) }.should output(nil, "foo\n")
+ end
+
guard -> { Kernel.instance_method(:tap).source_location } do
it "skips <internal: core library methods defined in Ruby" do
file, line = Kernel.instance_method(:tap).source_location
@@ -128,36 +134,34 @@ describe "Kernel#warn" do
end
end
- ruby_version_is "3.0" do
- it "accepts :category keyword with a symbol" do
- -> {
- $VERBOSE = true
- warn("message", category: :deprecated)
- }.should output(nil, "message\n")
- end
+ it "accepts :category keyword with a symbol" do
+ -> {
+ $VERBOSE = true
+ warn("message", category: :deprecated)
+ }.should output(nil, "message\n")
+ end
- it "accepts :category keyword with nil" do
- -> {
- $VERBOSE = true
- warn("message", category: nil)
- }.should output(nil, "message\n")
- end
+ it "accepts :category keyword with nil" do
+ -> {
+ $VERBOSE = true
+ warn("message", category: nil)
+ }.should output(nil, "message\n")
+ end
- it "accepts :category keyword with object convertible to symbol" do
- o = Object.new
- def o.to_sym; :deprecated; end
- -> {
- $VERBOSE = true
- warn("message", category: o)
- }.should output(nil, "message\n")
- end
+ it "accepts :category keyword with object convertible to symbol" do
+ o = Object.new
+ def o.to_sym; :deprecated; end
+ -> {
+ $VERBOSE = true
+ warn("message", category: o)
+ }.should output(nil, "message\n")
+ end
- it "raises if :category keyword is not nil and not convertible to symbol" do
- -> {
- $VERBOSE = true
- warn("message", category: Object.new)
- }.should raise_error(TypeError)
- end
+ it "raises if :category keyword is not nil and not convertible to symbol" do
+ -> {
+ $VERBOSE = true
+ warn("message", category: Object.new)
+ }.should.raise(TypeError)
end
it "converts first arg using to_s" do
@@ -190,19 +194,19 @@ describe "Kernel#warn" do
end
it "raises ArgumentError if passed negative value" do
- -> { warn "", uplevel: -2 }.should raise_error(ArgumentError)
- -> { warn "", uplevel: -100 }.should raise_error(ArgumentError)
+ -> { warn "", uplevel: -2 }.should.raise(ArgumentError)
+ -> { warn "", uplevel: -100 }.should.raise(ArgumentError)
end
it "raises ArgumentError if passed -1" do
- -> { warn "", uplevel: -1 }.should raise_error(ArgumentError)
+ -> { warn "", uplevel: -1 }.should.raise(ArgumentError)
end
it "raises TypeError if passed not Integer" do
- -> { warn "", uplevel: "" }.should raise_error(TypeError)
- -> { warn "", uplevel: [] }.should raise_error(TypeError)
- -> { warn "", uplevel: {} }.should raise_error(TypeError)
- -> { warn "", uplevel: Object.new }.should raise_error(TypeError)
+ -> { warn "", uplevel: "" }.should.raise(TypeError)
+ -> { warn "", uplevel: [] }.should.raise(TypeError)
+ -> { warn "", uplevel: {} }.should.raise(TypeError)
+ -> { warn "", uplevel: Object.new }.should.raise(TypeError)
end
end
@@ -212,67 +216,52 @@ describe "Kernel#warn" do
-> { warn('foo', **h) }.should complain("foo\n")
end
- ruby_version_is '3.0' do
- it "calls Warning.warn without keyword arguments if Warning.warn does not accept keyword arguments" do
- verbose = $VERBOSE
- $VERBOSE = false
- class << Warning
- alias_method :_warn, :warn
- def warn(message)
- ScratchPad.record(message)
- end
- end
-
- begin
- ScratchPad.clear
- Kernel.warn("Chunky bacon!")
- ScratchPad.recorded.should == "Chunky bacon!\n"
-
- Kernel.warn("Deprecated bacon!", category: :deprecated)
- ScratchPad.recorded.should == "Deprecated bacon!\n"
- ensure
- class << Warning
- remove_method :warn
- alias_method :warn, :_warn
- remove_method :_warn
- end
- $VERBOSE = verbose
+ it "calls Warning.warn without keyword arguments if Warning.warn does not accept keyword arguments" do
+ verbose = $VERBOSE
+ $VERBOSE = false
+ class << Warning
+ alias_method :_warn, :warn
+ def warn(message)
+ ScratchPad.record(message)
end
end
- it "calls Warning.warn with category: nil if Warning.warn accepts keyword arguments" do
- Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil)
- verbose = $VERBOSE
- $VERBOSE = false
- begin
- Kernel.warn("Chunky bacon!")
- ensure
- $VERBOSE = verbose
+ begin
+ ScratchPad.clear
+ Kernel.warn("Chunky bacon!")
+ ScratchPad.recorded.should == "Chunky bacon!\n"
+
+ Kernel.warn("Deprecated bacon!", category: :deprecated)
+ ScratchPad.recorded.should == "Deprecated bacon!\n"
+ ensure
+ class << Warning
+ remove_method :warn
+ alias_method :warn, :_warn
+ remove_method :_warn
end
+ $VERBOSE = verbose
end
+ end
- it "calls Warning.warn with given category keyword converted to a symbol" do
- Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated)
- verbose = $VERBOSE
- $VERBOSE = false
- begin
- Kernel.warn("Chunky bacon!", category: 'deprecated')
- ensure
- $VERBOSE = verbose
- end
+ it "calls Warning.warn with category: nil if Warning.warn accepts keyword arguments" do
+ Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!")
+ ensure
+ $VERBOSE = verbose
end
end
- ruby_version_is ''...'3.0' do
- it "calls Warning.warn with no keyword arguments" do
- Warning.should_receive(:warn).with("Chunky bacon!\n")
- verbose = $VERBOSE
- $VERBOSE = false
- begin
- Kernel.warn("Chunky bacon!")
- ensure
- $VERBOSE = verbose
- end
+ it "calls Warning.warn with given category keyword converted to a symbol" do
+ Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!", category: 'deprecated')
+ ensure
+ $VERBOSE = verbose
end
end
diff --git a/spec/ruby/core/main/define_method_spec.rb b/spec/ruby/core/main/define_method_spec.rb
index d85c5e8119..5279d078c3 100644
--- a/spec/ruby/core/main/define_method_spec.rb
+++ b/spec/ruby/core/main/define_method_spec.rb
@@ -14,15 +14,15 @@ describe "main#define_method" do
it 'creates a public method in TOPLEVEL_BINDING' do
eval @code, TOPLEVEL_BINDING
- Object.should have_method :boom
+ Object.should.respond_to? :boom
end
it 'creates a public method in script binding' do
eval @code, script_binding
- Object.should have_method :boom
+ Object.should.respond_to? :boom
end
it 'returns the method name as symbol' do
- eval(@code, TOPLEVEL_BINDING).should equal :boom
+ eval(@code, TOPLEVEL_BINDING).should.equal? :boom
end
end
diff --git a/spec/ruby/core/main/fixtures/using.rb b/spec/ruby/core/main/fixtures/using.rb
new file mode 100644
index 0000000000..30713ef309
--- /dev/null
+++ b/spec/ruby/core/main/fixtures/using.rb
@@ -0,0 +1 @@
+using Module.new
diff --git a/spec/ruby/core/main/fixtures/using_in_main.rb b/spec/ruby/core/main/fixtures/using_in_main.rb
new file mode 100644
index 0000000000..a4a71c89cc
--- /dev/null
+++ b/spec/ruby/core/main/fixtures/using_in_main.rb
@@ -0,0 +1,5 @@
+MAIN = self
+
+module X
+ MAIN.send(:using, Module.new)
+end
diff --git a/spec/ruby/core/main/fixtures/using_in_method.rb b/spec/ruby/core/main/fixtures/using_in_method.rb
new file mode 100644
index 0000000000..d9ea2e9ef0
--- /dev/null
+++ b/spec/ruby/core/main/fixtures/using_in_method.rb
@@ -0,0 +1,5 @@
+def foo
+ using Module.new
+end
+
+foo
diff --git a/spec/ruby/core/main/include_spec.rb b/spec/ruby/core/main/include_spec.rb
index 9f5a5f54ea..09f8d4d3b5 100644
--- a/spec/ruby/core/main/include_spec.rb
+++ b/spec/ruby/core/main/include_spec.rb
@@ -4,13 +4,13 @@ require_relative 'fixtures/classes'
describe "main#include" do
it "includes the given Module in Object" do
eval "include MainSpecs::Module", TOPLEVEL_BINDING
- Object.ancestors.should include(MainSpecs::Module)
+ Object.ancestors.should.include?(MainSpecs::Module)
end
context "in a file loaded with wrapping" do
it "includes the given Module in the load wrapper" do
load(File.expand_path("../fixtures/wrapped_include.rb", __FILE__), true)
- Object.ancestors.should_not include(MainSpecs::WrapIncludeModule)
+ Object.ancestors.should_not.include?(MainSpecs::WrapIncludeModule)
end
end
end
diff --git a/spec/ruby/core/main/private_spec.rb b/spec/ruby/core/main/private_spec.rb
index cac0645b40..56a39ae3c1 100644
--- a/spec/ruby/core/main/private_spec.rb
+++ b/spec/ruby/core/main/private_spec.rb
@@ -10,43 +10,33 @@ describe "main#private" do
context "when single argument is passed and it is not an array" do
it "sets the visibility of the given methods to private" do
eval "private :main_public_method", TOPLEVEL_BINDING
- Object.should have_private_method(:main_public_method)
+ Object.private_methods(true).should.include?(:main_public_method)
end
end
context "when multiple arguments are passed" do
it "sets the visibility of the given methods to private" do
eval "private :main_public_method, :main_public_method2", TOPLEVEL_BINDING
- Object.should have_private_method(:main_public_method)
- Object.should have_private_method(:main_public_method2)
+ Object.private_methods(true).should.include?(:main_public_method)
+ Object.private_methods(true).should.include?(:main_public_method2)
end
end
- ruby_version_is "3.0" do
- context "when single argument is passed and is an array" do
- it "sets the visibility of the given methods to private" do
- eval "private [:main_public_method, :main_public_method2]", TOPLEVEL_BINDING
- Object.should have_private_method(:main_public_method)
- Object.should have_private_method(:main_public_method2)
- end
- end
- end
-
- ruby_version_is ''...'3.1' do
- it "returns Object" do
- eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object)
+ context "when single argument is passed and is an array" do
+ it "sets the visibility of the given methods to private" do
+ eval "private [:main_public_method, :main_public_method2]", TOPLEVEL_BINDING
+ Object.private_methods(true).should.include?(:main_public_method)
+ Object.private_methods(true).should.include?(:main_public_method2)
end
end
- ruby_version_is '3.1' do
- it "returns argument" do
- eval("private :main_public_method", TOPLEVEL_BINDING).should equal(:main_public_method)
- end
+ it "returns argument" do
+ eval("private :main_public_method", TOPLEVEL_BINDING).should.equal?(:main_public_method)
end
it "raises a NameError when at least one of given method names is undefined" do
-> do
eval "private :main_public_method, :main_undefined_method", TOPLEVEL_BINDING
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/main/public_spec.rb b/spec/ruby/core/main/public_spec.rb
index 91f045dbab..89368ebb0d 100644
--- a/spec/ruby/core/main/public_spec.rb
+++ b/spec/ruby/core/main/public_spec.rb
@@ -10,44 +10,34 @@ describe "main#public" do
context "when single argument is passed and it is not an array" do
it "sets the visibility of the given methods to public" do
eval "public :main_private_method", TOPLEVEL_BINDING
- Object.should_not have_private_method(:main_private_method)
+ Object.private_methods(true).should_not.include?(:main_private_method)
end
end
context "when multiple arguments are passed" do
it "sets the visibility of the given methods to public" do
eval "public :main_private_method, :main_private_method2", TOPLEVEL_BINDING
- Object.should_not have_private_method(:main_private_method)
- Object.should_not have_private_method(:main_private_method2)
+ Object.private_methods(true).should_not.include?(:main_private_method)
+ Object.private_methods(true).should_not.include?(:main_private_method2)
end
end
- ruby_version_is "3.0" do
- context "when single argument is passed and is an array" do
- it "sets the visibility of the given methods to public" do
- eval "public [:main_private_method, :main_private_method2]", TOPLEVEL_BINDING
- Object.should_not have_private_method(:main_private_method)
- Object.should_not have_private_method(:main_private_method2)
- end
- end
- end
-
- ruby_version_is ''...'3.1' do
- it "returns Object" do
- eval("public :main_private_method", TOPLEVEL_BINDING).should equal(Object)
+ context "when single argument is passed and is an array" do
+ it "sets the visibility of the given methods to public" do
+ eval "public [:main_private_method, :main_private_method2]", TOPLEVEL_BINDING
+ Object.private_methods(true).should_not.include?(:main_private_method)
+ Object.private_methods(true).should_not.include?(:main_private_method2)
end
end
- ruby_version_is '3.1' do
- it "returns argument" do
- eval("public :main_private_method", TOPLEVEL_BINDING).should equal(:main_private_method)
- end
+ it "returns argument" do
+ eval("public :main_private_method", TOPLEVEL_BINDING).should.equal?(:main_private_method)
end
it "raises a NameError when given an undefined name" do
-> do
eval "public :main_undefined_method", TOPLEVEL_BINDING
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/main/ruby2_keywords_spec.rb b/spec/ruby/core/main/ruby2_keywords_spec.rb
index 27ceae3253..d12c0ed4e4 100644
--- a/spec/ruby/core/main/ruby2_keywords_spec.rb
+++ b/spec/ruby/core/main/ruby2_keywords_spec.rb
@@ -4,6 +4,6 @@ require_relative 'fixtures/classes'
describe "main.ruby2_keywords" do
it "is the same as Object.ruby2_keywords" do
main = TOPLEVEL_BINDING.receiver
- main.should have_private_method(:ruby2_keywords)
+ main.private_methods(false).should.include?(:ruby2_keywords)
end
end
diff --git a/spec/ruby/core/main/using_spec.rb b/spec/ruby/core/main/using_spec.rb
index f9f709f7dc..314a6be416 100644
--- a/spec/ruby/core/main/using_spec.rb
+++ b/spec/ruby/core/main/using_spec.rb
@@ -5,11 +5,11 @@ describe "main.using" do
it "requires one Module argument" do
-> do
eval('using', TOPLEVEL_BINDING)
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
-> do
eval('using "foo"', TOPLEVEL_BINDING)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "uses refinements from the given module only in the target file" do
@@ -19,7 +19,7 @@ describe "main.using" do
MainSpecs::DATA[:toplevel].should == 'foo'
-> do
'hello'.foo
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
it "uses refinements from the given module for method calls in the target file" do
@@ -27,7 +27,7 @@ describe "main.using" do
load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__)
-> do
'hello'.foo
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
MainSpecs.call_foo('hello').should == 'foo'
end
@@ -129,4 +129,22 @@ describe "main.using" do
x.call_bar(cls2.new).should == 'bar'
end
+
+ it "raises error when called from method in wrapped script" do
+ -> do
+ load File.expand_path('../fixtures/using_in_method.rb', __FILE__), true
+ end.should.raise(RuntimeError)
+ end
+
+ it "raises error when called on toplevel from module" do
+ -> do
+ load File.expand_path('../fixtures/using_in_main.rb', __FILE__), true
+ end.should.raise(RuntimeError)
+ end
+
+ it "does not raise error when wrapped with module" do
+ -> do
+ load File.expand_path('../fixtures/using.rb', __FILE__), true
+ end.should_not.raise
+ end
end
diff --git a/spec/ruby/core/marshal/dump_spec.rb b/spec/ruby/core/marshal/dump_spec.rb
index 079010e554..9bbb7809af 100644
--- a/spec/ruby/core/marshal/dump_spec.rb
+++ b/spec/ruby/core/marshal/dump_spec.rb
@@ -1,5 +1,6 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
require_relative 'fixtures/marshal_data'
describe "Marshal.dump" do
@@ -37,7 +38,7 @@ describe "Marshal.dump" do
].should be_computed_by(:dump)
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "dumps a positive Fixnum > 31 bits as a Bignum" do
Marshal.dump(2**31 + 1).should == "\x04\bl+\a\x01\x00\x00\x80"
end
@@ -46,6 +47,11 @@ describe "Marshal.dump" do
Marshal.dump(-2**31 - 1).should == "\x04\bl-\a\x01\x00\x00\x80"
end
end
+
+ it "does not use object links for objects repeatedly dumped" do
+ Marshal.dump([0, 0]).should == "\x04\b[\ai\x00i\x00"
+ Marshal.dump([2**16, 2**16]).should == "\x04\b[\ai\x03\x00\x00\x01i\x03\x00\x00\x01"
+ end
end
describe "with a Symbol" do
@@ -75,7 +81,7 @@ describe "Marshal.dump" do
end
it "dumps a binary encoded Symbol" do
- s = "\u2192".force_encoding("binary").to_sym
+ s = "\u2192".dup.force_encoding("binary").to_sym
Marshal.dump(s).should == "\x04\b:\b\xE2\x86\x92"
end
@@ -84,14 +90,19 @@ describe "Marshal.dump" do
symbol1 = "I:\t\xE2\x82\xACa\x06:\x06ET"
symbol2 = "I:\t\xE2\x82\xACb\x06;\x06T"
value = [
- "€a".force_encoding(Encoding::UTF_8).to_sym,
- "€b".force_encoding(Encoding::UTF_8).to_sym
+ "€a".dup.force_encoding(Encoding::UTF_8).to_sym,
+ "€b".dup.force_encoding(Encoding::UTF_8).to_sym
]
Marshal.dump(value).should == "\x04\b[\a#{symbol1}#{symbol2}"
value = [*value, value[0]]
Marshal.dump(value).should == "\x04\b[\b#{symbol1}#{symbol2};\x00"
end
+
+ it "uses symbol links for objects repeatedly dumped" do
+ symbol = :foo
+ Marshal.dump([symbol, symbol]).should == "\x04\b[\a:\bfoo;\x00" # ;\x00 is a link to the symbol object
+ end
end
describe "with an object responding to #marshal_dump" do
@@ -103,17 +114,54 @@ describe "Marshal.dump" do
UserMarshal.should_not_receive(:name)
Marshal.dump(UserMarshal.new)
end
+
+ it "raises TypeError if an Object is an instance of an anonymous class" do
+ -> { Marshal.dump(Class.new(UserMarshal).new) }.should.raise(TypeError, /can't dump anonymous class/)
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ obj = UserMarshal.new
+ Marshal.dump([obj, obj]).should == "\x04\b[\aU:\x10UserMarshal:\tdata@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables of a dumped object after the object itself into the objects table" do
+ value = "<foo>"
+ obj = MarshalSpec::UserMarshalDumpWithIvar.new("string", value)
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\t, that means Integer 4)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bU:)MarshalSpec::UserMarshalDumpWithIvarI[\x06\"\vstring\x06:\t@foo\"\n<foo>@\x06@\t"
+ end
end
describe "with an object responding to #_dump" do
- it "dumps the object returned by #marshal_dump" do
+ it "dumps the String returned by #_dump" do
Marshal.dump(UserDefined.new).should == "\004\bu:\020UserDefined\022\004\b[\a:\nstuff;\000"
end
+ it "dumps the String in non US-ASCII and non UTF-8 encoding" do
+ object = UserDefinedString.new("a".encode("windows-1251"))
+ Marshal.dump(object).should == "\x04\bIu:\x16UserDefinedString\x06a\x06:\rencoding\"\x11Windows-1251"
+ end
+
+ it "dumps the String in multibyte encoding" do
+ object = UserDefinedString.new("a".encode("utf-32le"))
+ Marshal.dump(object).should == "\x04\bIu:\x16UserDefinedString\ta\x00\x00\x00\x06:\rencoding\"\rUTF-32LE"
+ end
+
+ it "ignores overridden name method" do
+ obj = MarshalSpec::UserDefinedWithOverriddenName.new
+ Marshal.dump(obj).should == "\x04\bu:/MarshalSpec::UserDefinedWithOverriddenName\x12\x04\b[\a:\nstuff;\x00"
+ end
+
it "raises a TypeError if _dump returns a non-string" do
m = mock("marshaled")
m.should_receive(:_dump).and_return(0)
- -> { Marshal.dump(m) }.should raise_error(TypeError)
+ -> { Marshal.dump(m) }.should.raise(TypeError)
+ end
+
+ it "raises TypeError if an Object is an instance of an anonymous class" do
+ -> { Marshal.dump(Class.new(UserDefined).new) }.should.raise(TypeError, /can't dump anonymous class/)
end
it "favors marshal_dump over _dump" do
@@ -122,6 +170,48 @@ describe "Marshal.dump" do
m.should_not_receive(:_dump)
Marshal.dump(m)
end
+
+ it "indexes instance variables of a String returned by #_dump at first and then indexes the object itself" do
+ class MarshalSpec::M1::A
+ def _dump(level)
+ s = +"<dump>"
+ s.instance_variable_set(:@foo, "bar")
+ s
+ end
+ end
+
+ a = MarshalSpec::M1::A.new
+
+ # 0-based index of the object a = 2, that is encoded as \x07 and printed as "\a" character.
+ # Objects are serialized in the following order: Array, a, "bar".
+ # But they are indexed in different order: Array (index=0), "bar" (index=1), a (index=2)
+ # So the second occurenc of the object a is encoded as an index 2.
+ reference = "@\a"
+ Marshal.dump([a, a]).should == "\x04\b[\aIu:\x17MarshalSpec::M1::A\v<dump>\x06:\t@foo\"\bbar#{reference}"
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ obj = UserDefined.new
+ Marshal.dump([obj, obj]).should == "\x04\b[\au:\x10UserDefined\x12\x04\b[\a:\nstuff;\x00@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables of a dumped String before the object itself into the objects table" do
+ value = "<foo>"
+ obj = MarshalSpec::UserDefinedDumpWithIVars.new(+"string", value)
+
+ # expect a link to the object (@\a, that means Integer 2) is greater than a link
+ # to the instance variable value (@\x06, that means Integer 1)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bIu:*MarshalSpec::UserDefinedDumpWithIVars\vstring\x06:\t@foo\"\n<foo>@\a@\x06"
+ end
+
+ describe "Core library classes with #_dump returning a String with instance variables" do
+ it "indexes instance variables and then a Time object itself" do
+ t = Time.utc(2022)
+ reference = "@\a"
+
+ Marshal.dump([t, t]).should == "\x04\b[\aIu:\tTime\r \x80\x1E\xC0\x00\x00\x00\x00\x06:\tzoneI\"\bUTC\x06:\x06EF#{reference}"
+ end
+ end
end
describe "with a Class" do
@@ -137,12 +227,28 @@ describe "Marshal.dump" do
Marshal.dump(UserDefined::Nested).should == "\004\bc\030UserDefined::Nested"
end
+ it "ignores overridden name method" do
+ Marshal.dump(MarshalSpec::ClassWithOverriddenName).should == "\x04\bc)MarshalSpec::ClassWithOverriddenName"
+ end
+
+ ruby_version_is "4.0" do
+ it "dumps a class with multibyte characters in name" do
+ source_object = eval("MarshalSpec::MultibyteぁあぃいClass".dup.force_encoding(Encoding::UTF_8))
+ Marshal.dump(source_object).should == "\x04\bIc,MarshalSpec::Multibyte\xE3\x81\x81\xE3\x81\x82\xE3\x81\x83\xE3\x81\x84Class\x06:\x06ET"
+ Marshal.load(Marshal.dump(source_object)) == source_object
+ end
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ Marshal.dump([String, String]).should == "\x04\b[\ac\vString@\x06" # @\x06 is a link to the object
+ end
+
it "raises TypeError with an anonymous Class" do
- -> { Marshal.dump(Class.new) }.should raise_error(TypeError)
+ -> { Marshal.dump(Class.new) }.should.raise(TypeError, /can't dump anonymous class/)
end
it "raises TypeError with a singleton Class" do
- -> { Marshal.dump(class << self; self end) }.should raise_error(TypeError)
+ -> { Marshal.dump(class << self; self end) }.should.raise(TypeError)
end
end
@@ -151,8 +257,24 @@ describe "Marshal.dump" do
Marshal.dump(Marshal).should == "\004\bm\fMarshal"
end
+ it "ignores overridden name method" do
+ Marshal.dump(MarshalSpec::ModuleWithOverriddenName).should == "\x04\bc*MarshalSpec::ModuleWithOverriddenName"
+ end
+
+ ruby_version_is "4.0" do
+ it "dumps a module with multibyte characters in name" do
+ source_object = eval("MarshalSpec::MultibyteけげこごModule".dup.force_encoding(Encoding::UTF_8))
+ Marshal.dump(source_object).should == "\x04\bIm-MarshalSpec::Multibyte\xE3\x81\x91\xE3\x81\x92\xE3\x81\x93\xE3\x81\x94Module\x06:\x06ET"
+ Marshal.load(Marshal.dump(source_object)) == source_object
+ end
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ Marshal.dump([Marshal, Marshal]).should == "\x04\b[\am\fMarshal@\x06" # @\x06 is a link to the object
+ end
+
it "raises TypeError with an anonymous Module" do
- -> { Marshal.dump(Module.new) }.should raise_error(TypeError)
+ -> { Marshal.dump(Module.new) }.should.raise(TypeError, /can't dump anonymous module/)
end
end
@@ -169,6 +291,23 @@ describe "Marshal.dump" do
[Marshal, nan_value, "\004\bf\bnan"],
].should be_computed_by(:dump)
end
+
+ it "may or may not use object links for objects repeatedly dumped" do
+ # it's an MRI implementation detail - on x86 architecture object links
+ # aren't used for Float values but on amd64 - object links are used
+
+ dump = Marshal.dump([0.0, 0.0])
+ ["\x04\b[\af\x060@\x06", "\x04\b[\af\x060f\x060"].should.include?(dump)
+
+ # if object links aren't used - entries in the objects table are still
+ # occupied by Float values
+ if dump == "\x04\b[\af\x060f\x060"
+ s = "string"
+ # an index of "string" ("@\b") in the object table equals 3 (`"\b".ord - 5`),
+ # so `0.0, 0,0` elements occupied indices 1 and 2
+ Marshal.dump([0.0, 0.0, s, s]).should == "\x04\b[\tf\x060f\x060\"\vstring@\b"
+ end
+ end
end
describe "with a Bignum" do
@@ -185,15 +324,81 @@ describe "Marshal.dump" do
[Marshal, -2**64, "\004\bl-\n\000\000\000\000\000\000\000\000\001\000"],
].should be_computed_by(:dump)
end
+
+ it "uses object links for objects repeatedly dumped" do
+ n = 2**64
+ Marshal.dump([n, n]).should == "\x04\b[\al+\n\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00@\x06" # @\x06 is a link to the object
+ end
+
+ it "increases the object links counter" do
+ obj = Object.new
+ object_1_link = "\x06" # representing of (0-based) index=1 (by adding 5 for small Integers)
+ object_2_link = "\x07" # representing of index=2
+
+ # objects: Array, Object, Object
+ Marshal.dump([obj, obj]).should == "\x04\b[\ao:\vObject\x00@#{object_1_link}"
+
+ # objects: Array, Bignum, Object, Object
+ Marshal.dump([2**64, obj, obj]).should == "\x04\b[\bl+\n\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
+ Marshal.dump([2**48, obj, obj]).should == "\x04\b[\bl+\t\x00\x00\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
+ Marshal.dump([2**32, obj, obj]).should == "\x04\b[\bl+\b\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
+ end
+ end
+
+ describe "with a Rational" do
+ it "dumps a Rational" do
+ Marshal.dump(Rational(2, 3)).should == "\x04\bU:\rRational[\ai\ai\b"
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ r = Rational(2, 3)
+ Marshal.dump([r, r]).should == "\x04\b[\aU:\rRational[\ai\ai\b@\x06" # @\x06 is a link to the object
+ end
+ end
+
+ describe "with a Complex" do
+ it "dumps a Complex" do
+ Marshal.dump(Complex(2, 3)).should == "\x04\bU:\fComplex[\ai\ai\b"
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ c = Complex(2, 3)
+ Marshal.dump([c, c]).should == "\x04\b[\aU:\fComplex[\ai\ai\b@\x06" # @\x06 is a link to the object
+ end
+ end
+
+ describe "with a Data" do
+ it "dumps a Data" do
+ Marshal.dump(MarshalSpec::DataSpec::Measure.new(100, 'km')).should == "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm"
+ end
+
+ it "dumps an extended Data" do
+ obj = MarshalSpec::DataSpec::MeasureExtended.new(100, "km")
+ Marshal.dump(obj).should == "\x04\bS:+MarshalSpec::DataSpec::MeasureExtended\a:\vamountii:\tunit\"\akm"
+ end
+
+ it "ignores overridden name method" do
+ obj = MarshalSpec::DataSpec::MeasureWithOverriddenName.new(100, "km")
+ Marshal.dump(obj).should == "\x04\bS:5MarshalSpec::DataSpec::MeasureWithOverriddenName\a:\vamountii:\tunit\"\akm"
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ d = MarshalSpec::DataSpec::Measure.new(100, 'km')
+ Marshal.dump([d, d]).should == "\x04\b[\aS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm@\x06" # @\x06 is a link to the object
+ end
+
+ it "raises TypeError with an anonymous Struct" do
+ -> { Marshal.dump(Data.define(:a).new(1)) }.should.raise(TypeError, /can't dump anonymous class/)
+ end
end
describe "with a String" do
it "dumps a blank String" do
- Marshal.dump("".force_encoding("binary")).should == "\004\b\"\000"
+ Marshal.dump("".dup.force_encoding("binary")).should == "\004\b\"\000"
end
it "dumps a short String" do
- Marshal.dump("short".force_encoding("binary")).should == "\004\b\"\012short"
+ Marshal.dump("short".dup.force_encoding("binary")).should == "\004\b\"\012short"
end
it "dumps a long String" do
@@ -201,7 +406,7 @@ describe "Marshal.dump" do
end
it "dumps a String extended with a Module" do
- Marshal.dump("".extend(Meths).force_encoding("binary")).should == "\004\be:\nMeths\"\000"
+ Marshal.dump("".dup.extend(Meths).force_encoding("binary")).should == "\004\be:\nMeths\"\000"
end
it "dumps a String subclass" do
@@ -212,24 +417,29 @@ describe "Marshal.dump" do
Marshal.dump(UserString.new.extend(Meths).force_encoding("binary")).should == "\004\be:\nMethsC:\017UserString\"\000"
end
+ it "ignores overridden name method when dumps a String subclass" do
+ obj = MarshalSpec::StringWithOverriddenName.new
+ Marshal.dump(obj).should == "\x04\bC:*MarshalSpec::StringWithOverriddenName\"\x00"
+ end
+
it "dumps a String with instance variables" do
- str = ""
+ str = +""
str.instance_variable_set("@foo", "bar")
Marshal.dump(str.force_encoding("binary")).should == "\x04\bI\"\x00\x06:\t@foo\"\bbar"
end
it "dumps a US-ASCII String" do
- str = "abc".force_encoding("us-ascii")
+ str = "abc".dup.force_encoding("us-ascii")
Marshal.dump(str).should == "\x04\bI\"\babc\x06:\x06EF"
end
it "dumps a UTF-8 String" do
- str = "\x6d\xc3\xb6\x68\x72\x65".force_encoding("utf-8")
+ str = "\x6d\xc3\xb6\x68\x72\x65".dup.force_encoding("utf-8")
Marshal.dump(str).should == "\x04\bI\"\vm\xC3\xB6hre\x06:\x06ET"
end
it "dumps a String in another encoding" do
- str = "\x6d\x00\xf6\x00\x68\x00\x72\x00\x65\x00".force_encoding("utf-16le")
+ str = "\x6d\x00\xf6\x00\x68\x00\x72\x00\x65\x00".dup.force_encoding("utf-16le")
result = "\x04\bI\"\x0Fm\x00\xF6\x00h\x00r\x00e\x00\x06:\rencoding\"\rUTF-16LE"
Marshal.dump(str).should == result
end
@@ -237,6 +447,21 @@ describe "Marshal.dump" do
it "dumps multiple strings using symlinks for the :E (encoding) symbol" do
Marshal.dump(["".encode("us-ascii"), "".encode("utf-8")]).should == "\x04\b[\aI\"\x00\x06:\x06EFI\"\x00\x06;\x00T"
end
+
+ it "uses object links for objects repeatedly dumped" do
+ s = "string"
+ Marshal.dump([s, s]).should == "\x04\b[\a\"\vstring@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = +"string"
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bI\"\vstring\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with a Regexp" do
@@ -248,14 +473,26 @@ describe "Marshal.dump" do
Marshal.dump(//im).should == "\x04\bI/\x00\x05\x06:\x06EF"
end
- it "dumps a Regexp with instance variables" do
- o = Regexp.new("")
+ it "dumps a Regexp subclass with instance variables" do
+ o = UserRegexp.new("")
o.instance_variable_set(:@ivar, :ivar)
- Marshal.dump(o).should == "\x04\bI/\x00\x00\a:\x06EF:\n@ivar:\tivar"
+ Marshal.dump(o).should == "\x04\bIC:\x0FUserRegexp/\x00\x00\a:\x06EF:\n@ivar:\tivar"
+ end
+
+ it "dumps an extended Regexp subclass" do
+ Marshal.dump(UserRegexp.new("").extend(Meths)).should == "\x04\bIe:\nMethsC:\x0FUserRegexp/\x00\x00\x06:\x06EF"
end
- it "dumps an extended Regexp" do
- Marshal.dump(Regexp.new("").extend(Meths)).should == "\x04\bIe:\nMeths/\x00\x00\x06:\x06EF"
+ ruby_version_is ""..."4.1" do
+ it "dumps a Regexp with instance variables" do
+ o = Regexp.new("")
+ o.instance_variable_set(:@ivar, :ivar)
+ Marshal.dump(o).should == "\x04\bI/\x00\x00\a:\x06EF:\n@ivar:\tivar"
+ end
+
+ it "dumps an extended Regexp" do
+ Marshal.dump(Regexp.new("").extend(Meths)).should == "\x04\bIe:\nMeths/\x00\x00\x06:\x06EF"
+ end
end
it "dumps a Regexp subclass" do
@@ -263,18 +500,51 @@ describe "Marshal.dump" do
end
it "dumps a binary Regexp" do
- o = Regexp.new("".force_encoding("binary"), Regexp::FIXEDENCODING)
+ o = Regexp.new("".dup.force_encoding("binary"), Regexp::FIXEDENCODING)
Marshal.dump(o).should == "\x04\b/\x00\x10"
end
+ it "dumps an ascii-compatible Regexp" do
+ o = Regexp.new("a".encode("us-ascii"), Regexp::FIXEDENCODING)
+ Marshal.dump(o).should == "\x04\bI/\x06a\x10\x06:\x06EF"
+
+ o = Regexp.new("a".encode("us-ascii"))
+ Marshal.dump(o).should == "\x04\bI/\x06a\x00\x06:\x06EF"
+
+ o = Regexp.new("a".encode("windows-1251"), Regexp::FIXEDENCODING)
+ Marshal.dump(o).should == "\x04\bI/\x06a\x10\x06:\rencoding\"\x11Windows-1251"
+
+ o = Regexp.new("a".encode("windows-1251"))
+ Marshal.dump(o).should == "\x04\bI/\x06a\x00\x06:\x06EF"
+ end
+
it "dumps a UTF-8 Regexp" do
- o = Regexp.new("".force_encoding("utf-8"), Regexp::FIXEDENCODING)
+ o = Regexp.new("".dup.force_encoding("utf-8"), Regexp::FIXEDENCODING)
Marshal.dump(o).should == "\x04\bI/\x00\x10\x06:\x06ET"
+
+ o = Regexp.new("a".dup.force_encoding("utf-8"), Regexp::FIXEDENCODING)
+ Marshal.dump(o).should == "\x04\bI/\x06a\x10\x06:\x06ET"
+
+ o = Regexp.new("\u3042".dup.force_encoding("utf-8"), Regexp::FIXEDENCODING)
+ Marshal.dump(o).should == "\x04\bI/\b\xE3\x81\x82\x10\x06:\x06ET"
end
it "dumps a Regexp in another encoding" do
- o = Regexp.new("".force_encoding("utf-16le"), Regexp::FIXEDENCODING)
+ o = Regexp.new("".dup.force_encoding("utf-16le"), Regexp::FIXEDENCODING)
Marshal.dump(o).should == "\x04\bI/\x00\x10\x06:\rencoding\"\rUTF-16LE"
+
+ o = Regexp.new("a".encode("utf-16le"), Regexp::FIXEDENCODING)
+ Marshal.dump(o).should == "\x04\bI/\aa\x00\x10\x06:\rencoding\"\rUTF-16LE"
+ end
+
+ it "ignores overridden name method when dumps a Regexp subclass" do
+ obj = MarshalSpec::RegexpWithOverriddenName.new("")
+ Marshal.dump(obj).should == "\x04\bIC:*MarshalSpec::RegexpWithOverriddenName/\x00\x00\x06:\x06EF"
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ r = /\A.\Z/
+ Marshal.dump([r, r]).should == "\x04\b[\aI/\n\\A.\\Z\x00\x06:\x06EF@\x06" # @\x06 is a link to the object
end
end
@@ -306,6 +576,26 @@ describe "Marshal.dump" do
it "dumps an extended Array" do
Marshal.dump([].extend(Meths)).should == "\004\be:\nMeths[\000"
end
+
+ it "ignores overridden name method when dumps an Array subclass" do
+ obj = MarshalSpec::ArrayWithOverriddenName.new
+ Marshal.dump(obj).should == "\x04\bC:)MarshalSpec::ArrayWithOverriddenName[\x00"
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ a = [1]
+ Marshal.dump([a, a]).should == "\x04\b[\a[\x06i\x06@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = []
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bI[\x00\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with a Hash" do
@@ -313,6 +603,10 @@ describe "Marshal.dump" do
Marshal.dump({}).should == "\004\b{\000"
end
+ it "dumps a non-empty Hash" do
+ Marshal.dump({a: 1}).should == "\x04\b{\x06:\x06ai\x06"
+ end
+
it "dumps a Hash subclass" do
Marshal.dump(UserHash.new).should == "\004\bC:\rUserHash{\000"
end
@@ -321,8 +615,22 @@ describe "Marshal.dump" do
Marshal.dump(Hash.new(1)).should == "\004\b}\000i\006"
end
+ it "dumps a Hash with compare_by_identity" do
+ h = {}
+ h.compare_by_identity
+
+ Marshal.dump(h).should == "\004\bC:\tHash{\x00"
+ end
+
+ it "dumps a Hash subclass with compare_by_identity" do
+ h = UserHash.new
+ h.compare_by_identity
+
+ Marshal.dump(h).should == "\x04\bC:\rUserHashC:\tHash{\x00"
+ end
+
it "raises a TypeError with hash having default proc" do
- -> { Marshal.dump(Hash.new {}) }.should raise_error(TypeError)
+ -> { Marshal.dump(Hash.new {}) }.should.raise(TypeError, "can't dump hash with default proc")
end
it "dumps a Hash with instance variables" do
@@ -338,6 +646,26 @@ describe "Marshal.dump" do
it "dumps an Hash subclass with a parameter to initialize" do
Marshal.dump(UserHashInitParams.new(1)).should == "\004\bIC:\027UserHashInitParams{\000\006:\a@ai\006"
end
+
+ it "ignores overridden name method when dumps a Hash subclass" do
+ obj = MarshalSpec::HashWithOverriddenName.new
+ Marshal.dump(obj).should == "\x04\bC:(MarshalSpec::HashWithOverriddenName{\x00"
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ h = {a: 1}
+ Marshal.dump([h, h]).should == "\x04\b[\a{\x06:\x06ai\x06@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = {}
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bI{\x00\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with a Struct" do
@@ -366,6 +694,30 @@ describe "Marshal.dump" do
Marshal.dump(obj).should == "\004\be:\nMethsS:\025Struct::Extended\a:\006a[\a;\a\"\ahi:\006b[\a;\000@\a"
Struct.send(:remove_const, :Extended)
end
+
+ it "ignores overridden name method" do
+ obj = MarshalSpec::StructWithOverriddenName.new("member")
+ Marshal.dump(obj).should == "\x04\bS:*MarshalSpec::StructWithOverriddenName\x06:\x06a\"\vmember"
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ s = Struct::Pyramid.new
+ Marshal.dump([s, s]).should == "\x04\b[\aS:\x14Struct::Pyramid\x00@\x06" # @\x06 is a link to the object
+ end
+
+ it "raises TypeError with an anonymous Struct" do
+ -> { Marshal.dump(Struct.new(:a).new(1)) }.should.raise(TypeError, /can't dump anonymous class/)
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = Struct::Pyramid.new
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bIS:\x14Struct::Pyramid\x00\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with an Object" do
@@ -385,7 +737,7 @@ describe "Marshal.dump" do
it "dumps an Object with a non-US-ASCII instance variable" do
obj = Object.new
- ivar = "@é".force_encoding(Encoding::UTF_8).to_sym
+ ivar = "@é".dup.force_encoding(Encoding::UTF_8).to_sym
obj.instance_variable_set(ivar, 1)
Marshal.dump(obj).should == "\x04\bo:\vObject\x06I:\b@\xC3\xA9\x06:\x06ETi\x06"
end
@@ -397,48 +749,105 @@ describe "Marshal.dump" do
Marshal.dump(obj).should == "\004\bo:\x0BObject\x00"
end
- it "dumps an Object if it has a singleton class but no singleton methods" do
+ it "dumps an Object if it has a singleton class but no singleton methods and no singleton instance variables" do
obj = Object.new
obj.singleton_class
Marshal.dump(obj).should == "\004\bo:\x0BObject\x00"
end
- it "raises if an Object has a singleton class and singleton methods" do
+ it "ignores overridden name method" do
+ obj = MarshalSpec::ClassWithOverriddenName.new
+ Marshal.dump(obj).should == "\x04\bo:)MarshalSpec::ClassWithOverriddenName\x00"
+ end
+
+ it "raises TypeError if an Object has a singleton class and singleton methods" do
obj = Object.new
def obj.foo; end
-> {
Marshal.dump(obj)
- }.should raise_error(TypeError, "singleton can't be dumped")
+ }.should.raise(TypeError, "singleton can't be dumped")
+ end
+
+ it "raises TypeError if an Object has a singleton class and singleton instance variables" do
+ obj = Object.new
+ class << obj
+ @v = 1
+ end
+
+ -> {
+ Marshal.dump(obj)
+ }.should.raise(TypeError, "singleton can't be dumped")
+ end
+
+ it "raises TypeError if an Object is an instance of an anonymous class" do
+ anonymous_class = Class.new
+ obj = anonymous_class.new
+
+ -> { Marshal.dump(obj) }.should.raise(TypeError, /can't dump anonymous class/)
+ end
+
+ it "raises TypeError if an Object extends an anonymous module" do
+ anonymous_module = Module.new
+ obj = Object.new
+ obj.extend(anonymous_module)
+
+ -> { Marshal.dump(obj) }.should.raise(TypeError, /can't dump anonymous class/)
end
it "dumps a BasicObject subclass if it defines respond_to?" do
obj = MarshalSpec::BasicObjectSubWithRespondToFalse.new
Marshal.dump(obj).should == "\x04\bo:2MarshalSpec::BasicObjectSubWithRespondToFalse\x00"
end
+
+ it "dumps without marshaling any attached finalizer" do
+ obj = Object.new
+ finalizer = Object.new
+ def finalizer.noop(_)
+ end
+ ObjectSpace.define_finalizer(obj, finalizer.method(:noop))
+ Marshal.load(Marshal.dump(obj)).class.should == Object
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ obj = Object.new
+ Marshal.dump([obj, obj]).should == "\x04\b[\ao:\vObject\x00@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = Object.new
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bo:\vObject\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with a Range" do
- it "dumps a Range inclusive of end (with indeterminant order)" do
+ it "dumps a Range inclusive of end" do
dump = Marshal.dump(1..2)
+ dump.should == "\x04\bo:\nRange\b:\texclF:\nbegini\x06:\bendi\a"
+
load = Marshal.load(dump)
load.should == (1..2)
end
- it "dumps a Range exclusive of end (with indeterminant order)" do
+ it "dumps a Range exclusive of end" do
dump = Marshal.dump(1...2)
+ dump.should == "\x04\bo:\nRange\b:\texclT:\nbegini\x06:\bendi\a"
+
load = Marshal.load(dump)
load.should == (1...2)
end
- ruby_version_is ""..."3.0" do
- it "dumps a Range with extra instance variables" do
- range = (1...3)
- range.instance_variable_set :@foo, 42
- dump = Marshal.dump(range)
- load = Marshal.load(dump)
- load.should == range
- load.instance_variable_get(:@foo).should == 42
- end
+ it "uses object links for objects repeatedly dumped" do
+ r = 1..2
+ Marshal.dump([r, r]).should == "\x04\b[\ao:\nRange\b:\texclF:\nbegini\x06:\bendi\a@\x06" # @\x06 is a link to the object
+ end
+
+ it "raises TypeError with an anonymous Range subclass" do
+ -> { Marshal.dump(Class.new(Range).new(1, 2)) }.should.raise(TypeError, /can't dump anonymous class/)
end
end
@@ -468,7 +877,7 @@ describe "Marshal.dump" do
base = "\x04\bIu:\tTime\r#{@t_dump}\a"
offset = ":\voffseti\x020*"
zone = ":\tzoneI\"\bAST\x06:\x06EF" # Last is 'F' (US-ASCII)
- [ "#{base}#{offset}#{zone}", "#{base}#{zone}#{offset}" ].should include(dump)
+ [ "#{base}#{offset}#{zone}", "#{base}#{zone}#{offset}" ].should.include?(dump)
end
end
@@ -477,6 +886,43 @@ describe "Marshal.dump" do
zone = ":\tzoneI\"\bUTC\x06:\x06EF" # Last is 'F' (US-ASCII)
dump.should == "\x04\bIu:\tTime\r#{@utc_dump}\x06#{zone}"
end
+
+ it "ignores overridden name method" do
+ obj = MarshalSpec::TimeWithOverriddenName.new
+ Marshal.dump(obj).should.include?("MarshalSpec::TimeWithOverriddenName")
+ end
+
+ ruby_version_is "4.0" do
+ it "dumps a Time subclass with multibyte characters in name" do
+ source_object = eval("MarshalSpec::MultibyteぁあぃいTime".dup.force_encoding(Encoding::UTF_8))
+ Marshal.dump(source_object).should == "\x04\bIc+MarshalSpec::Multibyte\xE3\x81\x81\xE3\x81\x82\xE3\x81\x83\xE3\x81\x84Time\x06:\x06ET"
+ Marshal.load(Marshal.dump(source_object)) == source_object
+ end
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ # order of the offset and zone instance variables is a subject to change
+ # and may be different on different CRuby versions
+ base = Regexp.quote("\x04\b[\aIu:\tTime\r\xF5\xEF\e\x80\x00\x00\x00\x00\a")
+ offset = Regexp.quote(":\voffseti\x020*:\tzoneI\"\bAST\x06:\x06EF")
+ zone = Regexp.quote(":\tzoneI\"\bAST\x06:\x06EF:\voffseti\x020*")
+ instance_variables = /#{offset}|#{zone}/
+ Marshal.dump([@t, @t]).should =~ /\A#{base}#{instance_variables}@\a\Z/ # @\a is a link to the object
+ end
+
+ it "adds instance variables before the object itself into the objects table" do
+ obj = @utc
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\b, that means Integer 3) is greater than a link
+ # to the instance variable value (@\x06, that means Integer 1)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bIu:\tTime\r \x00\x1C\xC0\x00\x00\x00\x00\a:\t@foo\"\n<foo>:\tzoneI\"\bUTC\x06:\x06EF@\b@\x06"
+ end
+
+ it "raises TypeError with an anonymous Time subclass" do
+ -> { Marshal.dump(Class.new(Time).now) }.should.raise(TypeError)
+ end
end
describe "with an Exception" do
@@ -508,15 +954,47 @@ describe "Marshal.dump" do
begin
raise RuntimeError, "the consequence"
rescue RuntimeError => e
- e.cause.should equal(cause)
+ e.cause.should.equal?(cause)
exc = e
end
end
reloaded = Marshal.load(Marshal.dump(exc))
- reloaded.cause.should be_an_instance_of(StandardError)
+ reloaded.cause.should.instance_of?(StandardError)
reloaded.cause.message.should == "the cause"
end
+
+ # NoMethodError uses an exception formatter on TruffleRuby and computes a message lazily
+ it "dumps the message for the raised NoMethodError exception" do
+ begin
+ "".foo
+ rescue => e
+ end
+
+ Marshal.dump(e).should =~ /undefined method [`']foo' for ("":String|an instance of String)/
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ e = Exception.new
+ Marshal.dump([e, e]).should == "\x04\b[\ao:\x0EException\a:\tmesg0:\abt0@\x06" # @\x\a is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = Exception.new
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bo:\x0EException\b:\tmesg0:\abt0:\t@foo\"\n<foo>@\x06@\a"
+ end
+
+ it "raises TypeError if an Object is an instance of an anonymous class" do
+ anonymous_class = Class.new(Exception)
+ obj = anonymous_class.new
+
+ -> { Marshal.dump(obj) }.should.raise(TypeError, /can't dump anonymous class/)
+ end
end
it "dumps subsequent appearances of a symbol as a link" do
@@ -536,10 +1014,10 @@ describe "Marshal.dump" do
it "raises an ArgumentError when the recursion limit is exceeded" do
h = {'one' => {'two' => {'three' => 0}}}
- -> { Marshal.dump(h, 3) }.should raise_error(ArgumentError)
- -> { Marshal.dump([h], 4) }.should raise_error(ArgumentError)
- -> { Marshal.dump([], 0) }.should raise_error(ArgumentError)
- -> { Marshal.dump([[[]]], 1) }.should raise_error(ArgumentError)
+ -> { Marshal.dump(h, 3) }.should.raise(ArgumentError)
+ -> { Marshal.dump([h], 4) }.should.raise(ArgumentError)
+ -> { Marshal.dump([], 0) }.should.raise(ArgumentError)
+ -> { Marshal.dump([[[]]], 1) }.should.raise(ArgumentError)
end
it "ignores the recursion limit if the limit is negative" do
@@ -549,7 +1027,6 @@ describe "Marshal.dump" do
end
describe "when passed an IO" do
-
it "writes the serialized data to the IO-Object" do
(obj = mock('test')).should_receive(:write).at_least(1)
Marshal.dump("test", obj)
@@ -562,7 +1039,7 @@ describe "Marshal.dump" do
it "raises an Error when the IO-Object does not respond to #write" do
obj = mock('test')
- -> { Marshal.dump("test", obj) }.should raise_error(TypeError)
+ -> { Marshal.dump("test", obj) }.should.raise(TypeError)
end
@@ -572,36 +1049,34 @@ describe "Marshal.dump" do
obj.should_receive(:binmode).at_least(1)
Marshal.dump("test", obj)
end
-
-
end
describe "when passed a StringIO" do
it "should raise an error" do
require "stringio"
- -> { Marshal.dump(StringIO.new) }.should raise_error(TypeError)
+ -> { Marshal.dump(StringIO.new) }.should.raise(TypeError)
end
end
it "raises a TypeError if marshalling a Method instance" do
- -> { Marshal.dump(Marshal.method(:dump)) }.should raise_error(TypeError)
+ -> { Marshal.dump(Marshal.method(:dump)) }.should.raise(TypeError)
end
it "raises a TypeError if marshalling a Proc" do
- -> { Marshal.dump(proc {}) }.should raise_error(TypeError)
+ -> { Marshal.dump(proc {}) }.should.raise(TypeError)
end
it "raises a TypeError if dumping a IO/File instance" do
- -> { Marshal.dump(STDIN) }.should raise_error(TypeError)
- -> { File.open(__FILE__) { |f| Marshal.dump(f) } }.should raise_error(TypeError)
+ -> { Marshal.dump(STDIN) }.should.raise(TypeError)
+ -> { File.open(__FILE__) { |f| Marshal.dump(f) } }.should.raise(TypeError)
end
it "raises a TypeError if dumping a MatchData instance" do
- -> { Marshal.dump(/(.)/.match("foo")) }.should raise_error(TypeError)
+ -> { Marshal.dump(/(.)/.match("foo")) }.should.raise(TypeError)
end
it "raises a TypeError if dumping a Mutex instance" do
m = Mutex.new
- -> { Marshal.dump(m) }.should raise_error(TypeError)
+ -> { Marshal.dump(m) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/marshal/fixtures/classes.rb b/spec/ruby/core/marshal/fixtures/classes.rb
new file mode 100644
index 0000000000..7c81c64927
--- /dev/null
+++ b/spec/ruby/core/marshal/fixtures/classes.rb
@@ -0,0 +1,4 @@
+module MarshalSpec
+ # empty modules
+ module M1 end
+end
diff --git a/spec/ruby/core/marshal/fixtures/marshal_data.rb b/spec/ruby/core/marshal/fixtures/marshal_data.rb
index 9373ef7ba8..c16d9e4bb6 100644
--- a/spec/ruby/core/marshal/fixtures/marshal_data.rb
+++ b/spec/ruby/core/marshal/fixtures/marshal_data.rb
@@ -1,4 +1,7 @@
-# -*- encoding: binary -*-
+# encoding: binary
+
+require_relative 'marshal_multibyte_data'
+
class UserDefined
class Nested
def ==(other)
@@ -38,7 +41,7 @@ class UserDefinedWithIvar
attr_reader :a, :b, :c
def initialize
- @a = 'stuff'
+ @a = +'stuff'
@a.instance_variable_set :@foo, :UserDefinedWithIvar
@b = 'more'
@c = @b
@@ -78,6 +81,41 @@ class UserDefinedImmediate
end
end
+class UserDefinedString
+ attr_reader :string
+
+ def initialize(string)
+ @string = string
+ end
+
+ def _dump(depth)
+ @string
+ end
+
+ def self._load(data)
+ new(data)
+ end
+end
+
+module MarshalSpec
+ class UserDefinedDumpWithIVars
+ attr_reader :string
+
+ def initialize(string, ivar_value)
+ @string = string
+ @string.instance_variable_set(:@foo, ivar_value)
+ end
+
+ def _dump(depth)
+ @string
+ end
+
+ def self._load(data)
+ new(data)
+ end
+ end
+end
+
class UserPreviouslyDefinedWithInitializedIvar
attr_accessor :field1, :field2
end
@@ -120,6 +158,32 @@ class UserMarshalWithIvar
end
end
+module MarshalSpec
+ class UserMarshalDumpWithIvar
+ attr_reader :data
+
+ def initialize(data, ivar_value)
+ @data = data
+ @ivar_value = ivar_value
+ end
+
+ def marshal_dump
+ obj = [data]
+ obj.instance_variable_set(:@foo, @ivar_value)
+ obj
+ end
+
+ def marshal_load(o)
+ @data = o[0]
+ end
+
+ def ==(other)
+ self.class === other and
+ @data = other.data
+ end
+ end
+end
+
class UserArray < Array
end
@@ -167,12 +231,17 @@ module MarshalSpec
end
end
+ StructToDump = Struct.new(:a, :b)
+
class BasicObjectSubWithRespondToFalse < BasicObject
def respond_to?(method_name, include_all=false)
false
end
end
+ module ModuleToExtendBy
+ end
+
def self.random_data
randomizer = Random.new(42)
1000.times{randomizer.rand} # Make sure we exhaust his first state of 624 random words
@@ -192,6 +261,70 @@ module MarshalSpec
set_swapped_class(nil)
end
+ class ClassWithOverriddenName
+ def self.name
+ "Foo"
+ end
+ end
+
+ class ModuleWithOverriddenName
+ def self.name
+ "Foo"
+ end
+ end
+
+ class TimeWithOverriddenName < Time
+ def self.name
+ "Foo"
+ end
+ end
+
+ class StructWithOverriddenName < Struct.new(:a)
+ def self.name
+ "Foo"
+ end
+ end
+
+ class UserDefinedWithOverriddenName < UserDefined
+ def self.name
+ "Foo"
+ end
+ end
+
+ class StringWithOverriddenName < String
+ def self.name
+ "Foo"
+ end
+ end
+
+ class ArrayWithOverriddenName < Array
+ def self.name
+ "Foo"
+ end
+ end
+
+ class HashWithOverriddenName < Hash
+ def self.name
+ "Foo"
+ end
+ end
+
+ class RegexpWithOverriddenName < Regexp
+ def self.name
+ "Foo"
+ end
+ end
+
+ class ObjectWithFreezeRaisingException < Object
+ def freeze
+ raise
+ end
+ end
+
+ class ObjectWithoutFreeze < Object
+ undef freeze
+ end
+
DATA = {
"nil" => [nil, "\004\b0"],
"1..2" => [(1..2),
@@ -217,7 +350,7 @@ module MarshalSpec
"\004\b\"\012small"],
"String big" => ['big' * 100,
"\004\b\"\002,\001#{'big' * 100}"],
- "String extended" => [''.extend(Meths), # TODO: check for module on load
+ "String extended" => [''.dup.extend(Meths), # TODO: check for module on load
"\004\be:\nMeths\"\000"],
"String subclass" => [UserString.new,
"\004\bC:\017UserString\"\000"],
@@ -324,7 +457,7 @@ module MarshalSpec
"\x04\bI\"\nsmall\x06:\x06EF"],
"String big" => ['big' * 100,
"\x04\bI\"\x02,\x01bigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbigbig\x06:\x06EF"],
- "String extended" => [''.extend(Meths), # TODO: check for module on load
+ "String extended" => [''.dup.extend(Meths), # TODO: check for module on load
"\x04\bIe:\nMeths\"\x00\x06:\x06EF"],
"String subclass" => [UserString.new,
"\004\bC:\017UserString\"\000"],
@@ -398,6 +531,20 @@ module MarshalSpec
"\004\bS:\024Struct::Pyramid\000"],
"Random" => random_data,
}
+
+ module DataSpec
+ Measure = Data.define(:amount, :unit)
+ Empty = Data.define
+
+ MeasureExtended = Class.new(Measure)
+ MeasureExtended.extend(Enumerable)
+
+ class MeasureWithOverriddenName < Measure
+ def self.name
+ "Foo"
+ end
+ end
+ end
end
class ArraySub < Array
diff --git a/spec/ruby/core/marshal/fixtures/marshal_multibyte_data.rb b/spec/ruby/core/marshal/fixtures/marshal_multibyte_data.rb
new file mode 100644
index 0000000000..98a0d43392
--- /dev/null
+++ b/spec/ruby/core/marshal/fixtures/marshal_multibyte_data.rb
@@ -0,0 +1,12 @@
+# -*- encoding: utf-8 -*-
+
+module MarshalSpec
+ class MultibyteぁあぃいClass
+ end
+
+ module MultibyteけげこごModule
+ end
+
+ class MultibyteぁあぃいTime < Time
+ end
+end
diff --git a/spec/ruby/core/marshal/float_spec.rb b/spec/ruby/core/marshal/float_spec.rb
index 5793bbd564..5b2d68d6e1 100644
--- a/spec/ruby/core/marshal/float_spec.rb
+++ b/spec/ruby/core/marshal/float_spec.rb
@@ -40,7 +40,7 @@ end
describe "Marshal.load with Float" do
it "loads NaN" do
- Marshal.load("\004\bf\bnan").should be_nan
+ Marshal.load("\004\bf\bnan").should.nan?
end
it "loads +Infinity" do
diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb
index 98fae44296..02c8e7f0b1 100644
--- a/spec/ruby/core/marshal/shared/load.rb
+++ b/spec/ruby/core/marshal/shared/load.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../fixtures/marshal_data'
describe :marshal_load, shared: true do
@@ -8,7 +8,11 @@ describe :marshal_load, shared: true do
it "raises an ArgumentError when the dumped data is truncated" do
obj = {first: 1, second: 2, third: 3}
- -> { Marshal.send(@method, Marshal.dump(obj)[0, 5]) }.should raise_error(ArgumentError)
+ -> { Marshal.send(@method, Marshal.dump(obj)[0, 5]) }.should.raise(ArgumentError, "marshal data too short")
+ end
+
+ it "raises an ArgumentError when the argument is empty String" do
+ -> { Marshal.send(@method, "") }.should.raise(ArgumentError, "marshal data too short")
end
it "raises an ArgumentError when the dumped class is missing" do
@@ -16,140 +20,165 @@ describe :marshal_load, shared: true do
kaboom = Marshal.dump(KaBoom.new)
Object.send(:remove_const, :KaBoom)
- -> { Marshal.send(@method, kaboom) }.should raise_error(ArgumentError)
+ -> { Marshal.send(@method, kaboom) }.should.raise(ArgumentError)
end
- ruby_version_is "3.1" do
- describe "when called with freeze: true" do
- it "returns frozen strings" do
- string = Marshal.send(@method, Marshal.dump("foo"), freeze: true)
- string.should == "foo"
- string.should.frozen?
+ describe "when called with freeze: true" do
+ it "returns frozen strings" do
+ string = Marshal.send(@method, Marshal.dump("foo"), freeze: true)
+ string.should == "foo"
+ string.should.frozen?
- utf8_string = "foo".encode(Encoding::UTF_8)
- string = Marshal.send(@method, Marshal.dump(utf8_string), freeze: true)
- string.should == utf8_string
- string.should.frozen?
- end
+ utf8_string = "foo".encode(Encoding::UTF_8)
+ string = Marshal.send(@method, Marshal.dump(utf8_string), freeze: true)
+ string.should == utf8_string
+ string.should.frozen?
+ end
+
+ it "returns frozen arrays" do
+ array = Marshal.send(@method, Marshal.dump([1, 2, 3]), freeze: true)
+ array.should == [1, 2, 3]
+ array.should.frozen?
+ end
+
+ it "returns frozen hashes" do
+ hash = Marshal.send(@method, Marshal.dump({foo: 42}), freeze: true)
+ hash.should == {foo: 42}
+ hash.should.frozen?
+ end
+
+ it "returns frozen regexps" do
+ regexp = Marshal.send(@method, Marshal.dump(/foo/), freeze: true)
+ regexp.should == /foo/
+ regexp.should.frozen?
+ end
- it "returns frozen arrays" do
- array = Marshal.send(@method, Marshal.dump([1, 2, 3]), freeze: true)
- array.should == [1, 2, 3]
- array.should.frozen?
+ it "returns frozen structs" do
+ struct = Marshal.send(@method, Marshal.dump(MarshalSpec::StructToDump.new(1, 2)), freeze: true)
+ struct.should == MarshalSpec::StructToDump.new(1, 2)
+ struct.should.frozen?
+ end
+
+ it "returns frozen objects" do
+ source_object = Object.new
+
+ object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ object.should.frozen?
+ end
+
+ describe "deep freezing" do
+ it "returns hashes with frozen keys and values" do
+ key = Object.new
+ value = Object.new
+ source_object = {key => value}
+
+ hash = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ hash.size.should == 1
+ hash.keys[0].should.frozen?
+ hash.values[0].should.frozen?
end
- it "returns frozen hashes" do
- hash = Marshal.send(@method, Marshal.dump({foo: 42}), freeze: true)
- hash.should == {foo: 42}
- hash.should.frozen?
+ it "returns arrays with frozen elements" do
+ object = Object.new
+ source_object = [object]
+
+ array = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ array.size.should == 1
+ array[0].should.frozen?
end
- it "returns frozen regexps" do
- regexp = Marshal.send(@method, Marshal.dump(/foo/), freeze: true)
- regexp.should == /foo/
- regexp.should.frozen?
+ it "returns structs with frozen members" do
+ object1 = Object.new
+ object2 = Object.new
+ source_object = MarshalSpec::StructToDump.new(object1, object2)
+
+ struct = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ struct.a.should.frozen?
+ struct.b.should.frozen?
end
- it "returns frozen objects" do
+ it "returns objects with frozen instance variables" do
source_object = Object.new
- source_object.instance_variable_set(:@foo, "bar")
+ instance_variable = Object.new
+ source_object.instance_variable_set(:@a, instance_variable)
object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
- object.should.frozen?
- object.instance_variable_get(:@foo).should.frozen?
+ object.instance_variable_get(:@a).should != nil
+ object.instance_variable_get(:@a).should.frozen?
end
- it "does not freeze modules" do
- Marshal.send(@method, Marshal.dump(Kernel), freeze: true)
- Kernel.should_not.frozen?
- end
+ it "deduplicates frozen strings" do
+ source_object = ["foo" + "bar", "foobar"]
+ object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
- it "does not freeze classes" do
- Marshal.send(@method, Marshal.dump(Object), freeze: true)
- Object.should_not.frozen?
+ object[0].should.equal?(object[1])
end
+ end
- describe "when called with a proc" do
- it "call the proc with frozen objects" do
- arr = []
- s = 'hi'
- s.instance_variable_set(:@foo, 5)
- st = Struct.new("Brittle", :a).new
- st.instance_variable_set(:@clue, 'none')
- st.a = 0.0
- h = Hash.new('def')
- h['nine'] = 9
- a = [:a, :b, :c]
- a.instance_variable_set(:@two, 2)
- obj = [s, 10, s, s, st, a]
- obj.instance_variable_set(:@zoo, 'ant')
- proc = Proc.new { |o| arr << o; o}
-
- Marshal.send(
- @method,
- "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F",
- proc,
- freeze: true,
- )
-
- arr.should == [
- false, 5, "hi", 10, "hi", "hi", 0.0, false, "none", st,
- :b, :c, 2, a, false, "ant", ["hi", 10, "hi", "hi", st, [:a, :b, :c]],
- ]
-
- arr.each do |v|
- v.should.frozen?
- end
-
- Struct.send(:remove_const, :Brittle)
- end
+ it "does not freeze modules" do
+ object = Marshal.send(@method, Marshal.dump(Kernel), freeze: true)
+ object.should_not.frozen?
+ Kernel.should_not.frozen?
+ end
- it "does not freeze the object returned by the proc" do
- string = Marshal.send(@method, Marshal.dump("foo"), proc { |o| o.upcase }, freeze: true)
- string.should == "FOO"
- string.should_not.frozen?
- end
- end
+ it "does not freeze classes" do
+ object = Marshal.send(@method, Marshal.dump(Object), freeze: true)
+ object.should_not.frozen?
+ Object.should_not.frozen?
end
- end
- describe "when called with a proc" do
- ruby_bug "#18141", ""..."3.1" do
- it "call the proc with fully initialized strings" do
- utf8_string = "foo".encode(Encoding::UTF_8)
- Marshal.send(@method, Marshal.dump(utf8_string), proc { |arg|
- if arg.is_a?(String)
- arg.should == utf8_string
- arg.encoding.should == Encoding::UTF_8
- end
- arg
- })
- end
+ it "does freeze extended objects" do
+ object = Marshal.load("\x04\be:\x0FEnumerableo:\vObject\x00", freeze: true)
+ object.should.frozen?
+ end
- it "no longer mutate the object after it was passed to the proc" do
- string = Marshal.load(Marshal.dump("foo"), :freeze.to_proc)
- string.should.frozen?
- end
+ it "does freeze extended objects with instance variables" do
+ object = Marshal.load("\x04\be:\x0FEnumerableo:\vObject\x06:\n@ivarT", freeze: true)
+ object.should.frozen?
end
- it "returns the value of the proc" do
- Marshal.send(@method, Marshal.dump([1,2]), proc { [3,4] }).should == [3,4]
+ it "returns frozen object having #_dump method" do
+ object = Marshal.send(@method, Marshal.dump(UserDefined.new), freeze: true)
+ object.should.frozen?
end
- ruby_bug "#18141", ""..."3.1" do
- it "calls the proc for recursively visited data" do
- a = [1]
- a << a
- ret = []
- Marshal.send(@method, Marshal.dump(a), proc { |arg| ret << arg.inspect; arg })
- ret[0].should == 1.inspect
- ret[1].should == a.inspect
- ret.size.should == 2
- end
+ it "returns frozen object responding to #marshal_dump and #marshal_load" do
+ object = Marshal.send(@method, Marshal.dump(UserMarshal.new), freeze: true)
+ object.should.frozen?
+ end
+
+ it "returns frozen object extended by a module" do
+ object = Object.new
+ object.extend(MarshalSpec::ModuleToExtendBy)
+
+ object = Marshal.send(@method, Marshal.dump(object), freeze: true)
+ object.should.frozen?
+ end
+
+ it "does not call freeze method" do
+ object = MarshalSpec::ObjectWithFreezeRaisingException.new
+ object = Marshal.send(@method, Marshal.dump(object), freeze: true)
+ object.should.frozen?
+ end
+
+ it "returns frozen object even if object does not respond to freeze method" do
+ object = MarshalSpec::ObjectWithoutFreeze.new
+ object = Marshal.send(@method, Marshal.dump(object), freeze: true)
+ object.should.frozen?
+ end
+
+ it "returns a frozen object when is an instance of String/Array/Regexp/Hash subclass and has instance variables" do
+ source_object = UserString.new
+ source_object.instance_variable_set(:@foo, "bar")
- it "loads an Array with proc" do
+ object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ object.should.frozen?
+ end
+
+ describe "when called with a proc" do
+ it "call the proc with frozen objects" do
arr = []
- s = 'hi'
+ s = +'hi'
s.instance_variable_set(:@foo, 5)
st = Struct.new("Brittle", :a).new
st.instance_variable_set(:@clue, 'none')
@@ -160,16 +189,94 @@ describe :marshal_load, shared: true do
a.instance_variable_set(:@two, 2)
obj = [s, 10, s, s, st, a]
obj.instance_variable_set(:@zoo, 'ant')
- proc = Proc.new { |o| arr << o.dup; o}
+ proc = Proc.new { |o| arr << o; o}
- Marshal.send(@method, "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F", proc)
+ Marshal.send(
+ @method,
+ "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F",
+ proc,
+ freeze: true,
+ )
arr.should == [
false, 5, "hi", 10, "hi", "hi", 0.0, false, "none", st,
:b, :c, 2, a, false, "ant", ["hi", 10, "hi", "hi", st, [:a, :b, :c]],
]
+
+ arr.each do |v|
+ v.should.frozen?
+ end
+
Struct.send(:remove_const, :Brittle)
end
+
+ it "does not freeze the object returned by the proc" do
+ string = Marshal.send(@method, Marshal.dump("foo"), proc { |o| o.upcase }, freeze: true)
+ string.should == "FOO"
+ string.should_not.frozen?
+ end
+ end
+ end
+
+ describe "when called with a proc" do
+ it "call the proc with fully initialized strings" do
+ utf8_string = "foo".encode(Encoding::UTF_8)
+ Marshal.send(@method, Marshal.dump(utf8_string), proc { |arg|
+ if arg.is_a?(String)
+ arg.should == utf8_string
+ arg.encoding.should == Encoding::UTF_8
+ end
+ arg
+ })
+ end
+
+ it "no longer mutate the object after it was passed to the proc" do
+ string = Marshal.load(Marshal.dump("foo"), :freeze.to_proc)
+ string.should.frozen?
+ end
+
+ it "call the proc with extended objects" do
+ objs = []
+ obj = Marshal.load("\x04\be:\x0FEnumerableo:\vObject\x00", Proc.new { |o| objs << o; o })
+ objs.should == [obj]
+ end
+
+ it "returns the value of the proc" do
+ Marshal.send(@method, Marshal.dump([1,2]), proc { [3,4] }).should == [3,4]
+ end
+
+ it "calls the proc for recursively visited data" do
+ a = [1]
+ a << a
+ ret = []
+ Marshal.send(@method, Marshal.dump(a), proc { |arg| ret << arg.inspect; arg })
+ ret[0].should == 1.inspect
+ ret[1].should == a.inspect
+ ret.size.should == 2
+ end
+
+ it "loads an Array with proc" do
+ arr = []
+ s = +'hi'
+ s.instance_variable_set(:@foo, 5)
+ st = Struct.new("Brittle", :a).new
+ st.instance_variable_set(:@clue, 'none')
+ st.a = 0.0
+ h = Hash.new('def')
+ h['nine'] = 9
+ a = [:a, :b, :c]
+ a.instance_variable_set(:@two, 2)
+ obj = [s, 10, s, s, st, a]
+ obj.instance_variable_set(:@zoo, 'ant')
+ proc = Proc.new { |o| arr << o.dup; o}
+
+ Marshal.send(@method, "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F", proc)
+
+ arr.should == [
+ false, 5, "hi", 10, "hi", "hi", 0.0, false, "none", st,
+ :b, :c, 2, a, false, "ant", ["hi", 10, "hi", "hi", st, [:a, :b, :c]],
+ ]
+ Struct.send(:remove_const, :Brittle)
end
end
@@ -190,12 +297,24 @@ describe :marshal_load, shared: true do
UserPreviouslyDefinedWithInitializedIvar.should_receive(:_load).and_return(UserPreviouslyDefinedWithInitializedIvar.new)
marshaled_obj = Marshal.send(@method, dump_str)
- marshaled_obj.should be_an_instance_of(UserPreviouslyDefinedWithInitializedIvar)
- marshaled_obj.field1.should be_nil
- marshaled_obj.field2.should be_nil
+ marshaled_obj.should.instance_of?(UserPreviouslyDefinedWithInitializedIvar)
+ marshaled_obj.field1.should == nil
+ marshaled_obj.field2.should == nil
end
- describe "that return an immediate value" do
+ it "loads the String in non US-ASCII and non UTF-8 encoding" do
+ source_object = UserDefinedString.new("a".encode("windows-1251"))
+ object = Marshal.send(@method, Marshal.dump(source_object))
+ object.string.should == "a".encode("windows-1251")
+ end
+
+ it "loads the String in multibyte encoding" do
+ source_object = UserDefinedString.new("a".encode("utf-32le"))
+ object = Marshal.send(@method, Marshal.dump(source_object))
+ object.string.should == "a".encode("utf-32le")
+ end
+
+ describe "that returns an immediate value" do
it "loads an array containing an instance of the object, followed by multiple instances of another object" do
str = "string"
@@ -233,39 +352,37 @@ describe :marshal_load, shared: true do
end
end
- ruby_bug "#18141", ""..."3.1" do
- it "loads an array containing objects having _dump method, and with proc" do
- arr = []
- myproc = Proc.new { |o| arr << o.dup; o }
- o1 = UserDefined.new;
- o2 = UserDefinedWithIvar.new
- obj = [o1, o2, o1, o2]
+ it "loads an array containing objects having _dump method, and with proc" do
+ arr = []
+ myproc = Proc.new { |o| arr << o.dup; o }
+ o1 = UserDefined.new;
+ o2 = UserDefinedWithIvar.new
+ obj = [o1, o2, o1, o2]
- Marshal.send(@method, "\x04\b[\tu:\x10UserDefined\x18\x04\b[\aI\"\nstuff\x06:\x06EF@\x06u:\x18UserDefinedWithIvar>\x04\b[\bI\"\nstuff\a:\x06EF:\t@foo:\x18UserDefinedWithIvarI\"\tmore\x06;\x00F@\a@\x06@\a", myproc)
+ Marshal.send(@method, "\x04\b[\tu:\x10UserDefined\x18\x04\b[\aI\"\nstuff\x06:\x06EF@\x06u:\x18UserDefinedWithIvar>\x04\b[\bI\"\nstuff\a:\x06EF:\t@foo:\x18UserDefinedWithIvarI\"\tmore\x06;\x00F@\a@\x06@\a", myproc)
- arr[0].should == o1
- arr[1].should == o2
- arr[2].should == obj
- arr.size.should == 3
- end
+ arr[0].should == o1
+ arr[1].should == o2
+ arr[2].should == obj
+ arr.size.should == 3
+ end
- it "loads an array containing objects having marshal_dump method, and with proc" do
- arr = []
- proc = Proc.new { |o| arr << o.dup; o }
- o1 = UserMarshal.new
- o2 = UserMarshalWithIvar.new
+ it "loads an array containing objects having marshal_dump method, and with proc" do
+ arr = []
+ proc = Proc.new { |o| arr << o.dup; o }
+ o1 = UserMarshal.new
+ o2 = UserMarshalWithIvar.new
- Marshal.send(@method, "\004\b[\tU:\020UserMarshal\"\nstuffU:\030UserMarshalWithIvar[\006\"\fmy data@\006@\b", proc)
+ Marshal.send(@method, "\004\b[\tU:\020UserMarshal\"\nstuffU:\030UserMarshalWithIvar[\006\"\fmy data@\006@\b", proc)
- arr[0].should == 'stuff'
- arr[1].should == o1
- arr[2].should == 'my data'
- arr[3].should == ['my data']
- arr[4].should == o2
- arr[5].should == [o1, o2, o1, o2]
+ arr[0].should == 'stuff'
+ arr[1].should == o1
+ arr[2].should == 'my data'
+ arr[3].should == ['my data']
+ arr[4].should == o2
+ arr[5].should == [o1, o2, o1, o2]
- arr.size.should == 6
- end
+ arr.size.should == 6
end
it "assigns classes to nested subclasses of Array correctly" do
@@ -282,24 +399,24 @@ describe :marshal_load, shared: true do
end
it "raises a TypeError with bad Marshal version" do
- marshal_data = '\xff\xff'
+ marshal_data = +'\xff\xff'
marshal_data[0] = (Marshal::MAJOR_VERSION).chr
marshal_data[1] = (Marshal::MINOR_VERSION + 1).chr
- -> { Marshal.send(@method, marshal_data) }.should raise_error(TypeError)
+ -> { Marshal.send(@method, marshal_data) }.should.raise(TypeError)
- marshal_data = '\xff\xff'
+ marshal_data = +'\xff\xff'
marshal_data[0] = (Marshal::MAJOR_VERSION - 1).chr
marshal_data[1] = (Marshal::MINOR_VERSION).chr
- -> { Marshal.send(@method, marshal_data) }.should raise_error(TypeError)
+ -> { Marshal.send(@method, marshal_data) }.should.raise(TypeError)
end
it "raises EOFError on loading an empty file" do
temp_file = tmp("marshal.rubyspec.tmp.#{Process.pid}")
file = File.new(temp_file, "w+")
begin
- -> { Marshal.send(@method, file) }.should raise_error(EOFError)
+ -> { Marshal.send(@method, file) }.should.raise(EOFError)
ensure
file.close
rm_r temp_file
@@ -339,13 +456,13 @@ describe :marshal_load, shared: true do
end
it "loads an array having ivar" do
- s = 'well'
+ s = +'well'
s.instance_variable_set(:@foo, 10)
obj = ['5', s, 'hi'].extend(Meths, MethsMore)
obj.instance_variable_set(:@mix, s)
new_obj = Marshal.send(@method, "\004\bI[\b\"\0065I\"\twell\006:\t@fooi\017\"\ahi\006:\t@mix@\a")
new_obj.should == obj
- new_obj.instance_variable_get(:@mix).should equal new_obj[1]
+ new_obj.instance_variable_get(:@mix).should.equal? new_obj[1]
new_obj[1].instance_variable_get(:@foo).should == 10
end
@@ -385,7 +502,7 @@ describe :marshal_load, shared: true do
end
it "preserves hash ivars when hash contains a string having ivar" do
- s = 'string'
+ s = +'string'
s.instance_variable_set :@string_ivar, 'string ivar'
h = { key: s }
h.instance_variable_set :@hash_ivar, 'hash ivar'
@@ -394,6 +511,36 @@ describe :marshal_load, shared: true do
unmarshalled.instance_variable_get(:@hash_ivar).should == 'hash ivar'
unmarshalled[:key].instance_variable_get(:@string_ivar).should == 'string ivar'
end
+
+ it "preserves compare_by_identity behaviour" do
+ h = { a: 1 }
+ h.compare_by_identity
+ unmarshalled = Marshal.send(@method, Marshal.dump(h))
+ unmarshalled.should.compare_by_identity?
+
+ h = { a: 1 }
+ unmarshalled = Marshal.send(@method, Marshal.dump(h))
+ unmarshalled.should_not.compare_by_identity?
+ end
+
+ it "preserves compare_by_identity behaviour for a Hash subclass" do
+ h = UserHash.new({ a: 1 })
+ h.compare_by_identity
+ unmarshalled = Marshal.send(@method, Marshal.dump(h))
+ unmarshalled.should.compare_by_identity?
+
+ h = UserHash.new({ a: 1 })
+ unmarshalled = Marshal.send(@method, Marshal.dump(h))
+ unmarshalled.should_not.compare_by_identity?
+ end
+
+ it "allocates an instance of the proper class when Hash subclass with compare_by_identity behaviour" do
+ h = UserHash.new({ a: 1 })
+ h.compare_by_identity
+
+ unmarshalled = Marshal.send(@method, Marshal.dump(h))
+ unmarshalled.should.kind_of?(UserHash)
+ end
end
describe "for a Symbol" do
@@ -437,7 +584,7 @@ describe :marshal_load, shared: true do
end
it "loads a binary encoded Symbol" do
- s = "\u2192".force_encoding("binary").to_sym
+ s = "\u2192".dup.force_encoding("binary").to_sym
sym = Marshal.send(@method, "\x04\b:\b\xE2\x86\x92")
sym.should == s
sym.encoding.should == Encoding::BINARY
@@ -451,8 +598,8 @@ describe :marshal_load, shared: true do
value = Marshal.send(@method, dump)
value.map(&:encoding).should == [Encoding::UTF_8, Encoding::UTF_8]
expected = [
- "€a".force_encoding(Encoding::UTF_8).to_sym,
- "€b".force_encoding(Encoding::UTF_8).to_sym
+ "€a".dup.force_encoding(Encoding::UTF_8).to_sym,
+ "€b".dup.force_encoding(Encoding::UTF_8).to_sym
]
value.should == expected
@@ -460,11 +607,19 @@ describe :marshal_load, shared: true do
value.map(&:encoding).should == [Encoding::UTF_8, Encoding::UTF_8, Encoding::UTF_8]
value.should == [*expected, expected[0]]
end
+
+ it "raises ArgumentError when end of byte sequence reached before symbol characters end" do
+ Marshal.dump(:hello).should == "\x04\b:\nhello"
+
+ -> {
+ Marshal.send(@method, "\x04\b:\nhel")
+ }.should.raise(ArgumentError, "marshal data too short")
+ end
end
describe "for a String" do
it "loads a string having ivar with ref to self" do
- obj = 'hi'
+ obj = +'hi'
obj.instance_variable_set(:@self, obj)
Marshal.send(@method, "\004\bI\"\ahi\006:\n@self@\000").should == obj
end
@@ -475,6 +630,12 @@ describe :marshal_load, shared: true do
Marshal.send(@method, StringIO.new(Marshal.dump(obj))).should == obj
end
+ it "sets binmode if it is loading through StringIO stream" do
+ io = StringIO.new("\004\b:\vsymbol")
+ def io.binmode; raise "binmode"; end
+ -> { Marshal.load(io) }.should.raise(RuntimeError, "binmode")
+ end
+
it "loads a string with an ivar" do
str = Marshal.send(@method, "\x04\bI\"\x00\x06:\t@fooI\"\bbar\x06:\x06EF")
str.instance_variable_get("@foo").should == "bar"
@@ -482,40 +643,48 @@ describe :marshal_load, shared: true do
it "loads a String subclass with custom constructor" do
str = Marshal.send(@method, "\x04\bC: UserCustomConstructorString\"\x00")
- str.should be_an_instance_of(UserCustomConstructorString)
+ str.should.instance_of?(UserCustomConstructorString)
end
it "loads a US-ASCII String" do
- str = "abc".force_encoding("us-ascii")
+ str = "abc".dup.force_encoding("us-ascii")
data = "\x04\bI\"\babc\x06:\x06EF"
result = Marshal.send(@method, data)
result.should == str
- result.encoding.should equal(Encoding::US_ASCII)
+ result.encoding.should.equal?(Encoding::US_ASCII)
end
it "loads a UTF-8 String" do
- str = "\x6d\xc3\xb6\x68\x72\x65".force_encoding("utf-8")
+ str = "\x6d\xc3\xb6\x68\x72\x65".dup.force_encoding("utf-8")
data = "\x04\bI\"\vm\xC3\xB6hre\x06:\x06ET"
result = Marshal.send(@method, data)
result.should == str
- result.encoding.should equal(Encoding::UTF_8)
+ result.encoding.should.equal?(Encoding::UTF_8)
end
it "loads a String in another encoding" do
- str = "\x6d\x00\xf6\x00\x68\x00\x72\x00\x65\x00".force_encoding("utf-16le")
+ str = "\x6d\x00\xf6\x00\x68\x00\x72\x00\x65\x00".dup.force_encoding("utf-16le")
data = "\x04\bI\"\x0Fm\x00\xF6\x00h\x00r\x00e\x00\x06:\rencoding\"\rUTF-16LE"
result = Marshal.send(@method, data)
result.should == str
- result.encoding.should equal(Encoding::UTF_16LE)
+ result.encoding.should.equal?(Encoding::UTF_16LE)
end
it "loads a String as BINARY if no encoding is specified at the end" do
- str = "\xC3\xB8".force_encoding("BINARY")
- data = "\x04\b\"\a\xC3\xB8".force_encoding("UTF-8")
+ str = "\xC3\xB8".dup.force_encoding("BINARY")
+ data = "\x04\b\"\a\xC3\xB8".dup.force_encoding("UTF-8")
result = Marshal.send(@method, data)
result.encoding.should == Encoding::BINARY
result.should == str
end
+
+ it "raises ArgumentError when end of byte sequence reached before string characters end" do
+ Marshal.dump("hello").should == "\x04\b\"\nhello"
+
+ -> {
+ Marshal.send(@method, "\x04\b\"\nhel")
+ }.should.raise(ArgumentError, "marshal data too short")
+ end
end
describe "for a Struct" do
@@ -564,6 +733,32 @@ describe :marshal_load, shared: true do
end
end
+ describe "for a Data" do
+ it "loads a Data" do
+ obj = MarshalSpec::DataSpec::Measure.new(100, 'km')
+ dumped = "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm"
+ Marshal.dump(obj).should == dumped
+
+ Marshal.send(@method, dumped).should == obj
+ end
+
+ it "loads an extended Data" do
+ obj = MarshalSpec::DataSpec::MeasureExtended.new(100, "km")
+ dumped = "\x04\bS:+MarshalSpec::DataSpec::MeasureExtended\a:\vamountii:\tunit\"\akm"
+ Marshal.dump(obj).should == dumped
+
+ Marshal.send(@method, dumped).should == obj
+ end
+
+ it "returns a frozen object" do
+ obj = MarshalSpec::DataSpec::Measure.new(100, 'km')
+ dumped = "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm"
+ Marshal.dump(obj).should == dumped
+
+ Marshal.send(@method, dumped).should.frozen?
+ end
+ end
+
describe "for an Exception" do
it "loads a marshalled exception with no message" do
obj = Exception.new
@@ -612,7 +807,7 @@ describe :marshal_load, shared: true do
describe "for an Object" do
it "loads an object" do
- Marshal.send(@method, "\004\bo:\vObject\000").should be_kind_of(Object)
+ Marshal.send(@method, "\004\bo:\vObject\000").should.is_a?(Object)
end
it "loads an extended Object" do
@@ -638,7 +833,7 @@ describe :marshal_load, shared: true do
end
it "loads an Object with a non-US-ASCII instance variable" do
- ivar = "@é".force_encoding(Encoding::UTF_8).to_sym
+ ivar = "@é".dup.force_encoding(Encoding::UTF_8).to_sym
obj = Marshal.send(@method, "\x04\bo:\vObject\x06I:\b@\xC3\xA9\x06:\x06ETi\x06")
obj.instance_variables.should == [ivar]
obj.instance_variables[0].encoding.should == Encoding::UTF_8
@@ -648,7 +843,15 @@ describe :marshal_load, shared: true do
it "raises ArgumentError if the object from an 'o' stream is not dumpable as 'o' type user class" do
-> do
Marshal.send(@method, "\x04\bo:\tFile\001\001:\001\005@path\"\x10/etc/passwd")
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
+ end
+
+ it "raises ArgumentError when end of byte sequence reached before class name end" do
+ Marshal.dump(Object.new).should == "\x04\bo:\vObject\x00"
+
+ -> {
+ Marshal.send(@method, "\x04\bo:\vObj")
+ }.should.raise(ArgumentError, "marshal data too short")
end
end
@@ -676,7 +879,7 @@ describe :marshal_load, shared: true do
end
it "loads a UserObject" do
- Marshal.send(@method, "\004\bo:\017UserObject\000").should be_kind_of(UserObject)
+ Marshal.send(@method, "\004\bo:\017UserObject\000").should.is_a?(UserObject)
end
describe "that extends a core type other than Object or BasicObject" do
@@ -689,26 +892,64 @@ describe :marshal_load, shared: true do
data = Marshal.dump(MarshalSpec::SwappedClass.new)
MarshalSpec.set_swapped_class(Class.new(Array))
- -> { Marshal.send(@method, data) }.should raise_error(ArgumentError)
+ -> { Marshal.send(@method, data) }.should.raise(ArgumentError)
MarshalSpec.set_swapped_class(Class.new)
- -> { Marshal.send(@method, data) }.should raise_error(ArgumentError)
+ -> { Marshal.send(@method, data) }.should.raise(ArgumentError)
end
end
end
describe "for a Regexp" do
- it "loads an extended Regexp" do
- obj = /[a-z]/.dup.extend(Meths, MethsMore)
- new_obj = Marshal.send(@method, "\004\be:\nMethse:\016MethsMore/\n[a-z]\000")
+ ruby_version_is "4.1" do
+ it "raises FrozenError for an extended Regexp" do
+ -> {
+ Marshal.send(@method, "\004\be:\nMethse:\016MethsMore/\n[a-z]\000")
+ }.should.raise(FrozenError)
+ end
+
+ it "raises FrozenError when regexp has instance variables" do
+ -> {
+ Marshal.send(@method, "\x04\bI/\nhello\x00\a:\x06EF:\x11@regexp_ivar[\x06i/")
+ }.should.raise(FrozenError)
+ end
+ end
+
+ ruby_version_is ""..."4.1" do
+ it "loads an extended Regexp" do
+ obj = /[a-z]/.dup.extend(Meths, MethsMore)
+ new_obj = Marshal.send(@method, "\004\be:\nMethse:\016MethsMore/\n[a-z]\000")
+
+ new_obj.should == obj
+ new_obj_metaclass_ancestors = class << new_obj; ancestors; end
+ new_obj_metaclass_ancestors[@num_self_class, 3].should ==
+ [Meths, MethsMore, Regexp]
+ end
+
+ it "restore the regexp instance variables" do
+ obj = Regexp.new("hello")
+ obj.instance_variable_set(:@regexp_ivar, [42])
+
+ new_obj = Marshal.send(@method, "\x04\bI/\nhello\x00\a:\x06EF:\x11@regexp_ivar[\x06i/")
+ new_obj.instance_variables.should == [:@regexp_ivar]
+ new_obj.instance_variable_get(:@regexp_ivar).should == [42]
+ end
+ end
+
+ it "loads a Regexp subclass instance variables" do
+ obj = UserRegexp.new('abc')
+ obj.instance_variable_set(:@noise, 'much')
+
+ new_obj = Marshal.send(@method, Marshal.dump(obj))
new_obj.should == obj
+ new_obj.instance_variable_get(:@noise).should == 'much'
new_obj_metaclass_ancestors = class << new_obj; ancestors; end
- new_obj_metaclass_ancestors[@num_self_class, 3].should ==
- [Meths, MethsMore, Regexp]
+ new_obj_metaclass_ancestors[@num_self_class, 2].should ==
+ [UserRegexp, Regexp]
end
- it "loads a extended_user_regexp having ivar" do
+ it "loads a Regexp subclass instance variables when it is extended with a module" do
obj = UserRegexp.new('').extend(Meths)
obj.instance_variable_set(:@noise, 'much')
@@ -720,6 +961,22 @@ describe :marshal_load, shared: true do
new_obj_metaclass_ancestors[@num_self_class, 3].should ==
[Meths, UserRegexp, Regexp]
end
+
+ it "preserves Regexp encoding" do
+ source_object = Regexp.new("a".encode("utf-32le"))
+ regexp = Marshal.send(@method, Marshal.dump(source_object))
+
+ regexp.encoding.should == Encoding::UTF_32LE
+ regexp.source.should == "a".encode("utf-32le")
+ end
+
+ it "raises ArgumentError when end of byte sequence reached before source string end" do
+ Marshal.dump(/hello world/).should == "\x04\bI/\x10hello world\x00\x06:\x06EF"
+
+ -> {
+ Marshal.send(@method, "\x04\bI/\x10hel")
+ }.should.raise(ArgumentError, "marshal data too short")
+ end
end
describe "for a Float" do
@@ -741,6 +998,14 @@ describe :marshal_load, shared: true do
obj = 1.1867345e+22
Marshal.send(@method, "\004\bf\0361.1867344999999999e+22\000\344@").should == obj
end
+
+ it "raises ArgumentError when end of byte sequence reached before float string representation end" do
+ Marshal.dump(1.3).should == "\x04\bf\b1.3"
+
+ -> {
+ Marshal.send(@method, "\004\bf\v1")
+ }.should.raise(ArgumentError, "marshal data too short")
+ end
end
describe "for an Integer" do
@@ -793,7 +1058,7 @@ describe :marshal_load, shared: true do
"\004\bi\004\0",
"\004\bi\004\0\0",
"\004\bi\004\0\0\0"].each do |invalid|
- -> { Marshal.send(@method, invalid) }.should raise_error(ArgumentError)
+ -> { Marshal.send(@method, invalid) }.should.raise(ArgumentError)
end
end
@@ -806,18 +1071,22 @@ describe :marshal_load, shared: true do
describe "for a Rational" do
it "loads" do
- Marshal.send(@method, Marshal.dump(Rational(1, 3))).should == Rational(1, 3)
+ r = Marshal.send(@method, Marshal.dump(Rational(1, 3)))
+ r.should == Rational(1, 3)
+ r.should.frozen?
end
end
describe "for a Complex" do
it "loads" do
- Marshal.send(@method, Marshal.dump(Complex(4, 3))).should == Complex(4, 3)
+ c = Marshal.send(@method, Marshal.dump(Complex(4, 3)))
+ c.should == Complex(4, 3)
+ c.should.frozen?
end
end
describe "for a Bignum" do
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
context "that is Bignum on 32-bit platforms but Fixnum on 64-bit" do
it "dumps a Fixnum" do
val = Marshal.send(@method, "\004\bl+\ab:wU")
@@ -850,37 +1119,67 @@ describe :marshal_load, shared: true do
t = Time.new
t1, t2 = Marshal.send(@method, Marshal.dump([t, t]))
- t1.should equal t2
+ t1.should.equal? t2
end
- it "loads the zone" do
+ it "keeps the local zone" do
with_timezone 'AST', 3 do
t = Time.local(2012, 1, 1)
Marshal.send(@method, Marshal.dump(t)).zone.should == t.zone
end
end
- it "loads nanoseconds" do
+ it "keeps UTC zone" do
+ t = Time.now.utc
+ t2 = Marshal.send(@method, Marshal.dump(t))
+ t2.should.utc?
+ end
+
+ it "keeps the zone" do
+ t = nil
+
+ with_timezone 'AST', 4 do
+ t = Time.local(2012, 1, 1)
+ end
+
+ with_timezone 'EET', -2 do
+ Marshal.send(@method, Marshal.dump(t)).zone.should == 'AST'
+ end
+ end
+
+ it "keeps utc offset" do
+ t = Time.new(2007,11,1,15,25,0, "+09:00")
+ t2 = Marshal.send(@method, Marshal.dump(t))
+ t2.utc_offset.should == 32400
+ end
+
+ it "keeps nanoseconds" do
t = Time.now
Marshal.send(@method, Marshal.dump(t)).nsec.should == t.nsec
end
+
+ it "does not add any additional instance variable" do
+ t = Time.now
+ t2 = Marshal.send(@method, Marshal.dump(t))
+ t2.instance_variables.should.empty?
+ end
end
describe "for nil" do
it "loads" do
- Marshal.send(@method, "\x04\b0").should be_nil
+ Marshal.send(@method, "\x04\b0").should == nil
end
end
describe "for true" do
it "loads" do
- Marshal.send(@method, "\x04\bT").should be_true
+ Marshal.send(@method, "\x04\bT").should == true
end
end
describe "for false" do
it "loads" do
- Marshal.send(@method, "\x04\bF").should be_false
+ Marshal.send(@method, "\x04\bF").should == false
end
end
@@ -890,11 +1189,19 @@ describe :marshal_load, shared: true do
end
it "raises ArgumentError if given the name of a non-Module" do
- -> { Marshal.send(@method, "\x04\bc\vKernel") }.should raise_error(ArgumentError)
+ -> { Marshal.send(@method, "\x04\bc\vKernel") }.should.raise(ArgumentError)
end
it "raises ArgumentError if given a nonexistent class" do
- -> { Marshal.send(@method, "\x04\bc\vStrung") }.should raise_error(ArgumentError)
+ -> { Marshal.send(@method, "\x04\bc\vStrung") }.should.raise(ArgumentError)
+ end
+
+ it "raises ArgumentError when end of byte sequence reached before class name end" do
+ Marshal.dump(String).should == "\x04\bc\vString"
+
+ -> {
+ Marshal.send(@method, "\x04\bc\vStr")
+ }.should.raise(ArgumentError, "marshal data too short")
end
end
@@ -904,12 +1211,20 @@ describe :marshal_load, shared: true do
end
it "raises ArgumentError if given the name of a non-Class" do
- -> { Marshal.send(@method, "\x04\bm\vString") }.should raise_error(ArgumentError)
+ -> { Marshal.send(@method, "\x04\bm\vString") }.should.raise(ArgumentError)
end
it "loads an old module" do
Marshal.send(@method, "\x04\bM\vKernel").should == Kernel
end
+
+ it "raises ArgumentError when end of byte sequence reached before module name end" do
+ Marshal.dump(Kernel).should == "\x04\bm\vKernel"
+
+ -> {
+ Marshal.send(@method, "\x04\bm\vKer")
+ }.should.raise(ArgumentError, "marshal data too short")
+ end
end
describe "for a wrapped C pointer" do
@@ -943,13 +1258,13 @@ describe :marshal_load, shared: true do
data = "\x04\bd:\x1AUnloadableDumpableDirI\"\x06.\x06:\x06ET"
- -> { Marshal.send(@method, data) }.should raise_error(TypeError)
+ -> { Marshal.send(@method, data) }.should.raise(TypeError)
end
it "raises ArgumentError when the local class is a regular object" do
data = "\004\bd:\020UserDefined\0"
- -> { Marshal.send(@method, data) }.should raise_error(ArgumentError)
+ -> { Marshal.send(@method, data) }.should.raise(ArgumentError)
end
end
@@ -962,7 +1277,7 @@ describe :marshal_load, shared: true do
it "raises an ArgumentError" do
message = "undefined class/module NamespaceTest::SameName"
- -> { Marshal.send(@method, @data) }.should raise_error(ArgumentError, message)
+ -> { Marshal.send(@method, @data) }.should.raise(ArgumentError, message)
end
end
@@ -971,6 +1286,6 @@ describe :marshal_load, shared: true do
@data = Marshal.dump(NamespaceTest::KaBoom.new)
NamespaceTest.send(:remove_const, :KaBoom)
- -> { Marshal.send(@method, @data) }.should raise_error(ArgumentError, /NamespaceTest::KaBoom/)
+ -> { Marshal.send(@method, @data) }.should.raise(ArgumentError, /NamespaceTest::KaBoom/)
end
end
diff --git a/spec/ruby/core/matchdata/allocate_spec.rb b/spec/ruby/core/matchdata/allocate_spec.rb
index 142ce639c2..f41e2d5481 100644
--- a/spec/ruby/core/matchdata/allocate_spec.rb
+++ b/spec/ruby/core/matchdata/allocate_spec.rb
@@ -3,6 +3,6 @@ require_relative '../../spec_helper'
describe "MatchData.allocate" do
it "is undefined" do
# https://bugs.ruby-lang.org/issues/16294
- -> { MatchData.allocate }.should raise_error(NoMethodError)
+ -> { MatchData.allocate }.should.raise(NoMethodError)
end
end
diff --git a/spec/ruby/core/matchdata/begin_spec.rb b/spec/ruby/core/matchdata/begin_spec.rb
index 85c454da56..b4be077ae4 100644
--- a/spec/ruby/core/matchdata/begin_spec.rb
+++ b/spec/ruby/core/matchdata/begin_spec.rb
@@ -12,7 +12,7 @@ describe "MatchData#begin" do
it "returns nil when the nth match isn't found" do
match_data = /something is( not)? (right)/.match("something is right")
- match_data.begin(1).should be_nil
+ match_data.begin(1).should == nil
end
it "returns the character offset for multi-byte strings" do
@@ -36,6 +36,18 @@ describe "MatchData#begin" do
match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
match_data.begin(obj).should == 2
end
+
+ it "raises IndexError if index is out of bounds" do
+ match_data = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ match_data.begin(-1)
+ }.should.raise(IndexError, "index -1 out of matches")
+
+ -> {
+ match_data.begin(3)
+ }.should.raise(IndexError, "index 3 out of matches")
+ end
end
context "when passed a String argument" do
@@ -68,6 +80,14 @@ describe "MatchData#begin" do
match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
match_data.begin("æ").should == 1
end
+
+ it "raises IndexError if there is no group with the provided name" do
+ match_data = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ match_data.begin("y")
+ }.should.raise(IndexError, "undefined group name reference: y")
+ end
end
context "when passed a Symbol argument" do
@@ -100,5 +120,13 @@ describe "MatchData#begin" do
match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
match_data.begin(:æ).should == 1
end
+
+ it "raises IndexError if there is no group with the provided name" do
+ match_data = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ match_data.begin(:y)
+ }.should.raise(IndexError, "undefined group name reference: y")
+ end
end
end
diff --git a/spec/ruby/core/matchdata/bytebegin_spec.rb b/spec/ruby/core/matchdata/bytebegin_spec.rb
new file mode 100644
index 0000000000..fa44ec3b41
--- /dev/null
+++ b/spec/ruby/core/matchdata/bytebegin_spec.rb
@@ -0,0 +1,132 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.4" do
+ describe "MatchData#bytebegin" do
+ context "when passed an integer argument" do
+ it "returns the byte-based offset of the start of the nth element" do
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(0).should == 1
+ match_data.bytebegin(2).should == 2
+ end
+
+ it "returns nil when the nth match isn't found" do
+ match_data = /something is( not)? (right)/.match("something is right")
+ match_data.bytebegin(1).should == nil
+ end
+
+ it "returns the byte-based offset for multi-byte strings" do
+ match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
+ match_data.bytebegin(0).should == 1
+ match_data.bytebegin(2).should == 3
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi-byte strings with unicode regexp" do
+ match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
+ match_data.bytebegin(0).should == 1
+ match_data.bytebegin(2).should == 3
+ end
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(2)
+
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(obj).should == 2
+ end
+
+ it "raises IndexError if index is out of bounds" do
+ match_data = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ match_data.bytebegin(-1)
+ }.should.raise(IndexError, "index -1 out of matches")
+
+ -> {
+ match_data.bytebegin(3)
+ }.should.raise(IndexError, "index 3 out of matches")
+ end
+ end
+
+ context "when passed a String argument" do
+ it "return the byte-based offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin("a").should == 1
+ match_data.bytebegin("b").should == 3
+ end
+
+ it "returns the byte-based offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.bytebegin("a").should == 1
+ match_data.bytebegin("b").should == 4
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.bytebegin("a").should == 1
+ match_data.bytebegin("b").should == 4
+ end
+ end
+
+ it "returns the byte-based offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin("a").should == 3
+ end
+
+ it "returns the byte-based offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin("æ").should == 1
+ end
+
+ it "raises IndexError if there is no group with the provided name" do
+ match_data = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ match_data.bytebegin("y")
+ }.should.raise(IndexError, "undefined group name reference: y")
+ end
+ end
+
+ context "when passed a Symbol argument" do
+ it "return the byte-based offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(:a).should == 1
+ match_data.bytebegin(:b).should == 3
+ end
+
+ it "returns the byte-based offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.bytebegin(:a).should == 1
+ match_data.bytebegin(:b).should == 4
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.bytebegin(:a).should == 1
+ match_data.bytebegin(:b).should == 4
+ end
+ end
+
+ it "returns the byte-based offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(:a).should == 3
+ end
+
+ it "returns the byte-based offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(:æ).should == 1
+ end
+
+ it "raises IndexError if there is no group with the provided name" do
+ match_data = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ match_data.bytebegin(:y)
+ }.should.raise(IndexError, "undefined group name reference: y")
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/matchdata/byteend_spec.rb b/spec/ruby/core/matchdata/byteend_spec.rb
new file mode 100644
index 0000000000..e77cbf8b0d
--- /dev/null
+++ b/spec/ruby/core/matchdata/byteend_spec.rb
@@ -0,0 +1,104 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.4" do
+ describe "MatchData#byteend" do
+ context "when passed an integer argument" do
+ it "returns the byte-based offset of the end of the nth element" do
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.byteend(0).should == 7
+ match_data.byteend(2).should == 3
+ end
+
+ it "returns nil when the nth match isn't found" do
+ match_data = /something is( not)? (right)/.match("something is right")
+ match_data.byteend(1).should == nil
+ end
+
+ it "returns the byte-based offset for multi-byte strings" do
+ match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
+ match_data.byteend(0).should == 8
+ match_data.byteend(2).should == 4
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi-byte strings with unicode regexp" do
+ match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
+ match_data.byteend(0).should == 8
+ match_data.byteend(2).should == 4
+ end
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(2)
+
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.byteend(obj).should == 3
+ end
+ end
+
+ context "when passed a String argument" do
+ it "return the byte-based offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.byteend("a").should == 2
+ match_data.byteend("b").should == 6
+ end
+
+ it "returns the byte-based offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.byteend("a").should == 3
+ match_data.byteend("b").should == 7
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.byteend("a").should == 3
+ match_data.byteend("b").should == 7
+ end
+ end
+
+ it "returns the byte-based offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.byteend("a").should == 6
+ end
+
+ it "returns the byte-based offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.byteend("æ").should == 2
+ end
+ end
+
+ context "when passed a Symbol argument" do
+ it "return the byte-based offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.byteend(:a).should == 2
+ match_data.byteend(:b).should == 6
+ end
+
+ it "returns the byte-based offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.byteend(:a).should == 3
+ match_data.byteend(:b).should == 7
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.byteend(:a).should == 3
+ match_data.byteend(:b).should == 7
+ end
+ end
+
+ it "returns the byte-based offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.byteend(:a).should == 6
+ end
+
+ it "returns the byte-based offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.byteend(:æ).should == 2
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/matchdata/byteoffset_spec.rb b/spec/ruby/core/matchdata/byteoffset_spec.rb
new file mode 100644
index 0000000000..062e84027c
--- /dev/null
+++ b/spec/ruby/core/matchdata/byteoffset_spec.rb
@@ -0,0 +1,93 @@
+require_relative '../../spec_helper'
+
+describe "MatchData#byteoffset" do
+ it "returns beginning and ending byte-based offset of whole matched substring for 0 element" do
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ m.byteoffset(0).should == [1, 7]
+ end
+
+ it "returns beginning and ending byte-based offset of n-th match, all the subsequent elements are capturing groups" do
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+
+ m.byteoffset(2).should == [2, 3]
+ m.byteoffset(3).should == [3, 6]
+ m.byteoffset(4).should == [6, 7]
+ end
+
+ it "accepts String as a reference to a named capture" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ m.byteoffset("f").should == [0, 3]
+ m.byteoffset("b").should == [3, 6]
+ end
+
+ it "accepts Symbol as a reference to a named capture" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ m.byteoffset(:f).should == [0, 3]
+ m.byteoffset(:b).should == [3, 6]
+ end
+
+ it "returns [nil, nil] if a capturing group is optional and doesn't match" do
+ m = /(?<x>q..)?/.match("foobarbaz")
+
+ m.byteoffset("x").should == [nil, nil]
+ m.byteoffset(1).should == [nil, nil]
+ end
+
+ it "returns correct beginning and ending byte-based offset for multi-byte strings" do
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+
+ m.byteoffset(1).should == [3, 6]
+ m.byteoffset(3).should == [6, 9]
+ end
+
+ it "returns [nil, nil] if a capturing group is optional and doesn't match for multi-byte string" do
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+
+ m.byteoffset(2).should == [nil, nil]
+ end
+
+ it "converts argument into integer if is not String nor Symbol" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ obj = Object.new
+ def obj.to_int; 2; end
+
+ m.byteoffset(1r).should == [0, 3]
+ m.byteoffset(1.1).should == [0, 3]
+ m.byteoffset(obj).should == [3, 6]
+ end
+
+ it "raises IndexError if there is no group with the provided name" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.byteoffset("y")
+ }.should.raise(IndexError, "undefined group name reference: y")
+
+ -> {
+ m.byteoffset(:y)
+ }.should.raise(IndexError, "undefined group name reference: y")
+ end
+
+ it "raises IndexError if index is out of bounds" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.byteoffset(-1)
+ }.should.raise(IndexError, "index -1 out of matches")
+
+ -> {
+ m.byteoffset(3)
+ }.should.raise(IndexError, "index 3 out of matches")
+ end
+
+ it "raises TypeError if can't convert argument into Integer" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.byteoffset([])
+ }.should.raise(TypeError, "no implicit conversion of Array into Integer")
+ end
+end
diff --git a/spec/ruby/core/matchdata/captures_spec.rb b/spec/ruby/core/matchdata/captures_spec.rb
index 58d4620709..f829a25481 100644
--- a/spec/ruby/core/matchdata/captures_spec.rb
+++ b/spec/ruby/core/matchdata/captures_spec.rb
@@ -1,15 +1,6 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+require_relative 'shared/captures'
describe "MatchData#captures" do
- it "returns an array of the match captures" do
- /(.)(.)(\d+)(\d)/.match("THX1138.").captures.should == ["H","X","113","8"]
- end
-
- ruby_version_is "3.0" do
- it "returns instances of String when given a String subclass" do
- str = MatchDataSpecs::MyString.new("THX1138: The Movie")
- /(.)(.)(\d+)(\d)/.match(str).captures.each { |c| c.should be_an_instance_of(String) }
- end
- end
+ it_behaves_like :matchdata_captures, :captures
end
diff --git a/spec/ruby/core/matchdata/deconstruct_keys_spec.rb b/spec/ruby/core/matchdata/deconstruct_keys_spec.rb
new file mode 100644
index 0000000000..9126d20394
--- /dev/null
+++ b/spec/ruby/core/matchdata/deconstruct_keys_spec.rb
@@ -0,0 +1,78 @@
+require_relative '../../spec_helper'
+
+describe "MatchData#deconstruct_keys" do
+ it "returns whole hash for nil as an argument" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ m.deconstruct_keys(nil).should == { f: "foo", b: "bar" }
+ end
+
+ it "returns only specified keys" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ m.deconstruct_keys([:f]).should == { f: "foo" }
+ end
+
+ it "requires one argument" do
+ m = /l/.match("l")
+
+ -> {
+ m.deconstruct_keys
+ }.should.raise(ArgumentError, "wrong number of arguments (given 0, expected 1)")
+ end
+
+ it "it raises error when argument is neither nil nor array" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> { m.deconstruct_keys(1) }.should.raise(TypeError, "wrong argument type Integer (expected Array)")
+ -> { m.deconstruct_keys("asd") }.should.raise(TypeError, "wrong argument type String (expected Array)")
+ -> { m.deconstruct_keys(:x) }.should.raise(TypeError, "wrong argument type Symbol (expected Array)")
+ -> { m.deconstruct_keys({}) }.should.raise(TypeError, "wrong argument type Hash (expected Array)")
+ end
+
+ it "returns {} when passed []" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ m.deconstruct_keys([]).should == {}
+ end
+
+ it "does not accept non-Symbol keys" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.deconstruct_keys(['year', :foo])
+ }.should.raise(TypeError, "wrong argument type String (expected Symbol)")
+ end
+
+ it "process keys till the first non-existing one" do
+ m = /(?<f>foo)(?<b>bar)(?<c>baz)/.match("foobarbaz")
+
+ m.deconstruct_keys([:f, :a, :b]).should == { f: "foo" }
+ end
+
+ it "returns {} when there are no named captured groups at all" do
+ m = /foo.+/.match("foobar")
+
+ m.deconstruct_keys(nil).should == {}
+ end
+
+ it "returns {} when passed more keys than named captured groups" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ m.deconstruct_keys([:f, :b, :c]).should == {}
+ end
+
+ it "includes non-participating captures as nil for nil argument" do
+ m = "hello".match(/(?<a>hello)(?<b>world)?/)
+ m.deconstruct_keys(nil).should == { a: "hello", b: nil }
+ end
+
+ it "includes non-participating captures as nil for explicit keys" do
+ m = "hello".match(/(?<a>hello)(?<b>world)?/)
+ m.deconstruct_keys([:a, :b]).should == { a: "hello", b: nil }
+ end
+
+ it "does not stop iterating at a non-participating capture" do
+ m = "hello!".match(/(?<a>hello)(?<b>world)?(?<c>!)/)
+ m.deconstruct_keys([:b, :c, :a]).should == { b: nil, c: "!", a: "hello" }
+ end
+end
diff --git a/spec/ruby/core/matchdata/deconstruct_spec.rb b/spec/ruby/core/matchdata/deconstruct_spec.rb
new file mode 100644
index 0000000000..c55095665d
--- /dev/null
+++ b/spec/ruby/core/matchdata/deconstruct_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/captures'
+
+describe "MatchData#deconstruct" do
+ it_behaves_like :matchdata_captures, :deconstruct
+end
diff --git a/spec/ruby/core/matchdata/element_reference_spec.rb b/spec/ruby/core/matchdata/element_reference_spec.rb
index 8965f902a0..5509371cd2 100644
--- a/spec/ruby/core/matchdata/element_reference_spec.rb
+++ b/spec/ruby/core/matchdata/element_reference_spec.rb
@@ -20,19 +20,42 @@ describe "MatchData#[]" do
# negative index is larger than the number of match values
/(.)(.)(\d+)(\d)/.match("THX1138.")[-30, 2].should == nil
+ # positive index larger than number of match values
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[5, 2].should == []
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[6, 2].should == nil
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[30, 2].should == nil
+
# length argument larger than number of match values is capped to match value length
/(.)(.)(\d+)(\d)/.match("THX1138.")[3, 10].should == %w|113 8|
+
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3, 0].should == []
+
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3, -1].should == nil
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3, -30].should == nil
end
it "supports ranges [start..end]" do
/(.)(.)(\d+)(\d)/.match("THX1138.")[1..3].should == %w|H X 113|
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3..10].should == %w|113 8|
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[-30..2].should == nil
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3..1].should == []
+ end
+
+ it "supports endless ranges [start..]" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3..].should == %w|113 8|
+ end
+
+ it "supports beginningless ranges [..end]" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[..1].should == %w|HX1138 H|
+ end
+
+ it "supports beginningless endless ranges [nil..nil]" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[nil..nil].should == %w|HX1138 H X 113 8|
end
- ruby_version_is "3.0" do
- it "returns instances of String when given a String subclass" do
- str = MatchDataSpecs::MyString.new("THX1138.")
- /(.)(.)(\d+)(\d)/.match(str)[0..-1].each { |m| m.should be_an_instance_of(String) }
- end
+ it "returns instances of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138.")
+ /(.)(.)(\d+)(\d)/.match(str)[0..-1].each { |m| m.should.instance_of?(String) }
end
end
@@ -85,17 +108,17 @@ describe "MatchData#[Symbol]" do
it "raises an IndexError if there is no named match corresponding to the Symbol" do
md = 'haystack'.match(/(?<t>t(?<a>ack))/)
- -> { md[:baz] }.should raise_error(IndexError, /baz/)
+ -> { md[:baz] }.should.raise(IndexError, /baz/)
end
it "raises an IndexError if there is no named match corresponding to the String" do
md = 'haystack'.match(/(?<t>t(?<a>ack))/)
- -> { md['baz'] }.should raise_error(IndexError, /baz/)
+ -> { md['baz'] }.should.raise(IndexError, /baz/)
end
it "returns matches in the String's encoding" do
rex = /(?<t>t(?<a>ack))/u
- md = 'haystack'.force_encoding('euc-jp').match(rex)
+ md = 'haystack'.dup.force_encoding('euc-jp').match(rex)
md[:t].encoding.should == Encoding::EUC_JP
end
end
diff --git a/spec/ruby/core/matchdata/end_spec.rb b/spec/ruby/core/matchdata/end_spec.rb
index d01b0a8b30..4fee24a763 100644
--- a/spec/ruby/core/matchdata/end_spec.rb
+++ b/spec/ruby/core/matchdata/end_spec.rb
@@ -12,7 +12,7 @@ describe "MatchData#end" do
it "returns nil when the nth match isn't found" do
match_data = /something is( not)? (right)/.match("something is right")
- match_data.end(1).should be_nil
+ match_data.end(1).should == nil
end
it "returns the character offset for multi-byte strings" do
diff --git a/spec/ruby/core/matchdata/inspect_spec.rb b/spec/ruby/core/matchdata/inspect_spec.rb
index 5315257677..cacbe10c5d 100644
--- a/spec/ruby/core/matchdata/inspect_spec.rb
+++ b/spec/ruby/core/matchdata/inspect_spec.rb
@@ -6,7 +6,7 @@ describe "MatchData#inspect" do
end
it "returns a String" do
- @match_data.inspect.should be_kind_of(String)
+ @match_data.inspect.should.is_a?(String)
end
it "returns a human readable representation that contains entire matched string and the captures" do
diff --git a/spec/ruby/core/matchdata/integer_at_spec.rb b/spec/ruby/core/matchdata/integer_at_spec.rb
new file mode 100644
index 0000000000..65f73a7bee
--- /dev/null
+++ b/spec/ruby/core/matchdata/integer_at_spec.rb
@@ -0,0 +1,38 @@
+# -*- encoding: utf-8 -*-
+
+require_relative '../../spec_helper'
+
+ruby_version_is "4.1" do
+ describe "MatchData#integer_at" do
+ it "converts the corresponding match to an Integer and returns it when given an Integer" do
+ md = /(\d{4})(\d{2})(\d{2})/.match("20260308")
+ md.integer_at(0).should == 20260308
+ md.integer_at(1).should == 2026
+ md.integer_at(2).should == 3
+ end
+
+ it "returns nil on non-matching index matches" do
+ md = /\b(\d)?\b/.match("THX1138.")
+ md.integer_at(1).should == nil
+ end
+
+ it "returns nil on non-integer matches" do
+ md = /(\w)?/.match("THX1138.")
+ md.integer_at(1).should == nil
+ end
+
+ it "converts the match to an Integer in the given base" do
+ md = /\w+/.match("0c")
+ md.integer_at(0).should == 0
+ md.integer_at(0, 16).should == 12
+ end
+
+ it "converts the match to an Integer in the prefix when given base is zero" do
+ /\w+/.match("010").integer_at(0, 0).should == 010
+ /\w+/.match("0x10").integer_at(0, 0).should == 0x10
+ /\w+/.match("0d10").integer_at(0, 0).should == 0d10
+ /\w+/.match("0o10").integer_at(0, 0).should == 0o10
+ /\w+/.match("0b10").integer_at(0, 0).should == 0b10
+ end
+ end
+end
diff --git a/spec/ruby/core/matchdata/match_length_spec.rb b/spec/ruby/core/matchdata/match_length_spec.rb
index f7785ab1a0..824f94a397 100644
--- a/spec/ruby/core/matchdata/match_length_spec.rb
+++ b/spec/ruby/core/matchdata/match_length_spec.rb
@@ -2,33 +2,31 @@
require_relative '../../spec_helper'
-ruby_version_is "3.1" do
- describe "MatchData#match_length" do
- it "returns the length of the corresponding match when given an Integer" do
- md = /(.)(.)(\d+)(\d)/.match("THX1138.")
+describe "MatchData#match_length" do
+ it "returns the length of the corresponding match when given an Integer" do
+ md = /(.)(.)(\d+)(\d)/.match("THX1138.")
- md.match_length(0).should == 6
- md.match_length(1).should == 1
- md.match_length(2).should == 1
- md.match_length(3).should == 3
- md.match_length(4).should == 1
- end
+ md.match_length(0).should == 6
+ md.match_length(1).should == 1
+ md.match_length(2).should == 1
+ md.match_length(3).should == 3
+ md.match_length(4).should == 1
+ end
- it "returns nil on non-matching index matches" do
- md = /\d+(\w)?/.match("THX1138.")
- md.match_length(1).should == nil
- end
+ it "returns nil on non-matching index matches" do
+ md = /\d+(\w)?/.match("THX1138.")
+ md.match_length(1).should == nil
+ end
- it "returns the length of the corresponding named match when given a Symbol" do
- md = 'haystack'.match(/(?<t>t(?<a>ack))/)
- md.match_length(:a).should == 3
- md.match_length(:t).should == 4
- end
+ it "returns the length of the corresponding named match when given a Symbol" do
+ md = 'haystack'.match(/(?<t>t(?<a>ack))/)
+ md.match_length(:a).should == 3
+ md.match_length(:t).should == 4
+ end
- it "returns nil on non-matching index matches" do
- md = 'haystack'.match(/(?<t>t)(?<a>all)?/)
- md.match_length(:t).should == 1
- md.match_length(:a).should == nil
- end
+ it "returns nil on non-matching index matches" do
+ md = 'haystack'.match(/(?<t>t)(?<a>all)?/)
+ md.match_length(:t).should == 1
+ md.match_length(:a).should == nil
end
end
diff --git a/spec/ruby/core/matchdata/match_spec.rb b/spec/ruby/core/matchdata/match_spec.rb
index 545de6f93f..a16914ea15 100644
--- a/spec/ruby/core/matchdata/match_spec.rb
+++ b/spec/ruby/core/matchdata/match_spec.rb
@@ -2,33 +2,31 @@
require_relative '../../spec_helper'
-ruby_version_is "3.1" do
- describe "MatchData#match" do
- it "returns the corresponding match when given an Integer" do
- md = /(.)(.)(\d+)(\d)/.match("THX1138.")
+describe "MatchData#match" do
+ it "returns the corresponding match when given an Integer" do
+ md = /(.)(.)(\d+)(\d)/.match("THX1138.")
- md.match(0).should == 'HX1138'
- md.match(1).should == 'H'
- md.match(2).should == 'X'
- md.match(3).should == '113'
- md.match(4).should == '8'
- end
+ md.match(0).should == 'HX1138'
+ md.match(1).should == 'H'
+ md.match(2).should == 'X'
+ md.match(3).should == '113'
+ md.match(4).should == '8'
+ end
- it "returns nil on non-matching index matches" do
- md = /\d+(\w)?/.match("THX1138.")
- md.match(1).should == nil
- end
+ it "returns nil on non-matching index matches" do
+ md = /\d+(\w)?/.match("THX1138.")
+ md.match(1).should == nil
+ end
- it "returns the corresponding named match when given a Symbol" do
- md = 'haystack'.match(/(?<t>t(?<a>ack))/)
- md.match(:a).should == 'ack'
- md.match(:t).should == 'tack'
- end
+ it "returns the corresponding named match when given a Symbol" do
+ md = 'haystack'.match(/(?<t>t(?<a>ack))/)
+ md.match(:a).should == 'ack'
+ md.match(:t).should == 'tack'
+ end
- it "returns nil on non-matching index matches" do
- md = 'haystack'.match(/(?<t>t)(?<a>all)?/)
- md.match(:t).should == 't'
- md.match(:a).should == nil
- end
+ it "returns nil on non-matching index matches" do
+ md = 'haystack'.match(/(?<t>t)(?<a>all)?/)
+ md.match(:t).should == 't'
+ md.match(:a).should == nil
end
end
diff --git a/spec/ruby/core/matchdata/named_captures_spec.rb b/spec/ruby/core/matchdata/named_captures_spec.rb
index 9b1e324a24..10b1f884d6 100644
--- a/spec/ruby/core/matchdata/named_captures_spec.rb
+++ b/spec/ruby/core/matchdata/named_captures_spec.rb
@@ -12,4 +12,14 @@ describe 'MatchData#named_captures' do
it 'returns the latest matched capture, even if a later one that does not match exists' do
/\A(?<a>.)(?<b>.)(?<b>.)(?<a>.)?\z/.match('012').named_captures.should == { 'a' => '0', 'b' => '2' }
end
+
+ it 'returns a Hash with Symbol keys when symbolize_names is provided a true value' do
+ /(?<a>.)(?<b>.)?/.match('0').named_captures(symbolize_names: true).should == { a: '0', b: nil }
+ /(?<a>.)(?<b>.)?/.match('0').named_captures(symbolize_names: "truly").should == { a: '0', b: nil }
+ end
+
+ it 'returns a Hash with String keys when symbolize_names is provided a false value' do
+ /(?<a>.)(?<b>.)?/.match('02').named_captures(symbolize_names: false).should == { 'a' => '0', 'b' => '2' }
+ /(?<a>.)(?<b>.)?/.match('02').named_captures(symbolize_names: nil).should == { 'a' => '0', 'b' => '2' }
+ end
end
diff --git a/spec/ruby/core/matchdata/names_spec.rb b/spec/ruby/core/matchdata/names_spec.rb
index 25ca06ced9..dca15985b0 100644
--- a/spec/ruby/core/matchdata/names_spec.rb
+++ b/spec/ruby/core/matchdata/names_spec.rb
@@ -3,12 +3,12 @@ require_relative '../../spec_helper'
describe "MatchData#names" do
it "returns an Array" do
md = 'haystack'.match(/(?<yellow>hay)/)
- md.names.should be_an_instance_of(Array)
+ md.names.should.instance_of?(Array)
end
it "sets each element to a String" do
'haystack'.match(/(?<yellow>hay)/).names.all? do |e|
- e.should be_an_instance_of(String)
+ e.should.instance_of?(String)
end
end
diff --git a/spec/ruby/core/matchdata/offset_spec.rb b/spec/ruby/core/matchdata/offset_spec.rb
index 1ccb54b7a7..5a923d6ce0 100644
--- a/spec/ruby/core/matchdata/offset_spec.rb
+++ b/spec/ruby/core/matchdata/offset_spec.rb
@@ -1,30 +1,102 @@
-# -*- encoding: utf-8 -*-
-
require_relative '../../spec_helper'
describe "MatchData#offset" do
- it "returns a two element array with the begin and end of the nth match" do
- match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
- match_data.offset(0).should == [1, 7]
- match_data.offset(4).should == [6, 7]
+ it "returns beginning and ending character offset of whole matched substring for 0 element" do
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ m.offset(0).should == [1, 7]
+ end
+
+ it "returns beginning and ending character offset of n-th match, all the subsequent elements are capturing groups" do
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+
+ m.offset(2).should == [2, 3]
+ m.offset(3).should == [3, 6]
+ m.offset(4).should == [6, 7]
+ end
+
+ it "accepts String as a reference to a named capture" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ m.offset("f").should == [0, 3]
+ m.offset("b").should == [3, 6]
+ end
+
+ it "accepts Symbol as a reference to a named capture" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ m.offset(:f).should == [0, 3]
+ m.offset(:b).should == [3, 6]
end
- it "returns [nil, nil] when the nth match isn't found" do
- match_data = /something is( not)? (right)/.match("something is right")
- match_data.offset(1).should == [nil, nil]
+ it "returns [nil, nil] if a capturing group is optional and doesn't match" do
+ m = /(?<x>q..)?/.match("foobarbaz")
+
+ m.offset("x").should == [nil, nil]
+ m.offset(1).should == [nil, nil]
end
- it "returns the offset for multi byte strings" do
- match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
- match_data.offset(0).should == [1, 7]
- match_data.offset(4).should == [6, 7]
+ it "returns correct beginning and ending character offset for multi-byte strings" do
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+
+ m.offset(1).should == [1, 2]
+ m.offset(3).should == [2, 3]
end
not_supported_on :opal do
- it "returns the offset for multi byte strings with unicode regexp" do
- match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
- match_data.offset(0).should == [1, 7]
- match_data.offset(4).should == [6, 7]
+ it "returns correct character offset for multi-byte strings with unicode regexp" do
+ m = /\A\u3042(.)(.)?(.)\z/u.match("\u3042\u3043\u3044")
+
+ m.offset(1).should == [1, 2]
+ m.offset(3).should == [2, 3]
end
end
+
+ it "returns [nil, nil] if a capturing group is optional and doesn't match for multi-byte string" do
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+
+ m.offset(2).should == [nil, nil]
+ end
+
+ it "converts argument into integer if is not String nor Symbol" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ obj = Object.new
+ def obj.to_int; 2; end
+
+ m.offset(1r).should == [0, 3]
+ m.offset(1.1).should == [0, 3]
+ m.offset(obj).should == [3, 6]
+ end
+
+ it "raises IndexError if there is no group with the provided name" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.offset("y")
+ }.should.raise(IndexError, "undefined group name reference: y")
+
+ -> {
+ m.offset(:y)
+ }.should.raise(IndexError, "undefined group name reference: y")
+ end
+
+ it "raises IndexError if index is out of bounds" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.offset(-1)
+ }.should.raise(IndexError, "index -1 out of matches")
+
+ -> {
+ m.offset(3)
+ }.should.raise(IndexError, "index 3 out of matches")
+ end
+
+ it "raises TypeError if can't convert argument into Integer" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.offset([])
+ }.should.raise(TypeError, "no implicit conversion of Array into Integer")
+ end
end
diff --git a/spec/ruby/core/matchdata/post_match_spec.rb b/spec/ruby/core/matchdata/post_match_spec.rb
index d3aa4c8900..b50d637124 100644
--- a/spec/ruby/core/matchdata/post_match_spec.rb
+++ b/spec/ruby/core/matchdata/post_match_spec.rb
@@ -8,19 +8,17 @@ describe "MatchData#post_match" do
end
it "sets the encoding to the encoding of the source String" do
- str = "abc".force_encoding Encoding::EUC_JP
- str.match(/b/).post_match.encoding.should equal(Encoding::EUC_JP)
+ str = "abc".dup.force_encoding Encoding::EUC_JP
+ str.match(/b/).post_match.encoding.should.equal?(Encoding::EUC_JP)
end
it "sets an empty result to the encoding of the source String" do
- str = "abc".force_encoding Encoding::ISO_8859_1
- str.match(/c/).post_match.encoding.should equal(Encoding::ISO_8859_1)
+ str = "abc".dup.force_encoding Encoding::ISO_8859_1
+ str.match(/c/).post_match.encoding.should.equal?(Encoding::ISO_8859_1)
end
- ruby_version_is "3.0" do
- it "returns an instance of String when given a String subclass" do
- str = MatchDataSpecs::MyString.new("THX1138: The Movie")
- /(.)(.)(\d+)(\d)/.match(str).post_match.should be_an_instance_of(String)
- end
+ it "returns an instance of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138: The Movie")
+ /(.)(.)(\d+)(\d)/.match(str).post_match.should.instance_of?(String)
end
end
diff --git a/spec/ruby/core/matchdata/pre_match_spec.rb b/spec/ruby/core/matchdata/pre_match_spec.rb
index b43be5fb41..106612a4f7 100644
--- a/spec/ruby/core/matchdata/pre_match_spec.rb
+++ b/spec/ruby/core/matchdata/pre_match_spec.rb
@@ -8,19 +8,17 @@ describe "MatchData#pre_match" do
end
it "sets the encoding to the encoding of the source String" do
- str = "abc".force_encoding Encoding::EUC_JP
- str.match(/b/).pre_match.encoding.should equal(Encoding::EUC_JP)
+ str = "abc".dup.force_encoding Encoding::EUC_JP
+ str.match(/b/).pre_match.encoding.should.equal?(Encoding::EUC_JP)
end
it "sets an empty result to the encoding of the source String" do
- str = "abc".force_encoding Encoding::ISO_8859_1
- str.match(/a/).pre_match.encoding.should equal(Encoding::ISO_8859_1)
+ str = "abc".dup.force_encoding Encoding::ISO_8859_1
+ str.match(/a/).pre_match.encoding.should.equal?(Encoding::ISO_8859_1)
end
- ruby_version_is "3.0" do
- it "returns an instance of String when given a String subclass" do
- str = MatchDataSpecs::MyString.new("THX1138: The Movie")
- /(.)(.)(\d+)(\d)/.match(str).pre_match.should be_an_instance_of(String)
- end
+ it "returns an instance of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138: The Movie")
+ /(.)(.)(\d+)(\d)/.match(str).pre_match.should.instance_of?(String)
end
end
diff --git a/spec/ruby/core/matchdata/regexp_spec.rb b/spec/ruby/core/matchdata/regexp_spec.rb
index 099b59c559..7dcb0e62db 100644
--- a/spec/ruby/core/matchdata/regexp_spec.rb
+++ b/spec/ruby/core/matchdata/regexp_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "MatchData#regexp" do
it "returns a Regexp object" do
m = 'haystack'.match(/hay/)
- m.regexp.should be_an_instance_of(Regexp)
+ m.regexp.should.instance_of?(Regexp)
end
it "returns the pattern used in the match" do
diff --git a/spec/ruby/core/matchdata/shared/captures.rb b/spec/ruby/core/matchdata/shared/captures.rb
new file mode 100644
index 0000000000..de5870f543
--- /dev/null
+++ b/spec/ruby/core/matchdata/shared/captures.rb
@@ -0,0 +1,13 @@
+require_relative '../../../spec_helper'
+require_relative '../fixtures/classes'
+
+describe :matchdata_captures, shared: true do
+ it "returns an array of the match captures" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.").send(@method).should == ["H","X","113","8"]
+ end
+
+ it "returns instances of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138: The Movie")
+ /(.)(.)(\d+)(\d)/.match(str).send(@method).each { |c| c.should.instance_of?(String) }
+ end
+end
diff --git a/spec/ruby/core/matchdata/shared/eql.rb b/spec/ruby/core/matchdata/shared/eql.rb
index e021baa178..e4bb8797b7 100644
--- a/spec/ruby/core/matchdata/shared/eql.rb
+++ b/spec/ruby/core/matchdata/shared/eql.rb
@@ -4,23 +4,23 @@ describe :matchdata_eql, shared: true do
it "returns true if both operands have equal target strings, patterns, and match positions" do
a = 'haystack'.match(/hay/)
b = 'haystack'.match(/hay/)
- a.send(@method, b).should be_true
+ a.send(@method, b).should == true
end
it "returns false if the operands have different target strings" do
a = 'hay'.match(/hay/)
b = 'haystack'.match(/hay/)
- a.send(@method, b).should be_false
+ a.send(@method, b).should == false
end
it "returns false if the operands have different patterns" do
a = 'haystack'.match(/h.y/)
b = 'haystack'.match(/hay/)
- a.send(@method, b).should be_false
+ a.send(@method, b).should == false
end
it "returns false if the argument is not a MatchData object" do
a = 'haystack'.match(/hay/)
- a.send(@method, Object.new).should be_false
+ a.send(@method, Object.new).should == false
end
end
diff --git a/spec/ruby/core/matchdata/string_spec.rb b/spec/ruby/core/matchdata/string_spec.rb
index 420233e1f3..50bbb5a64f 100644
--- a/spec/ruby/core/matchdata/string_spec.rb
+++ b/spec/ruby/core/matchdata/string_spec.rb
@@ -14,11 +14,12 @@ describe "MatchData#string" do
it "returns the same frozen string for every call" do
md = /(.)(.)(\d+)(\d)/.match("THX1138.")
- md.string.should equal(md.string)
+ md.string.should.equal?(md.string)
end
- it "returns a frozen copy of the matched string for gsub(String)" do
- 'he[[o'.gsub!('[', ']')
+ it "returns a frozen copy of the matched string for gsub!(String)" do
+ s = +'he[[o'
+ s.gsub!('[', ']')
$~.string.should == 'he[[o'
$~.string.should.frozen?
end
diff --git a/spec/ruby/core/matchdata/to_a_spec.rb b/spec/ruby/core/matchdata/to_a_spec.rb
index 50f5a161a5..c77fc4ab37 100644
--- a/spec/ruby/core/matchdata/to_a_spec.rb
+++ b/spec/ruby/core/matchdata/to_a_spec.rb
@@ -6,10 +6,8 @@ describe "MatchData#to_a" do
/(.)(.)(\d+)(\d)/.match("THX1138.").to_a.should == ["HX1138", "H", "X", "113", "8"]
end
- ruby_version_is "3.0" do
- it "returns instances of String when given a String subclass" do
- str = MatchDataSpecs::MyString.new("THX1138.")
- /(.)(.)(\d+)(\d)/.match(str)[0..-1].to_a.each { |m| m.should be_an_instance_of(String) }
- end
+ it "returns instances of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138.")
+ /(.)(.)(\d+)(\d)/.match(str)[0..-1].to_a.each { |m| m.should.instance_of?(String) }
end
end
diff --git a/spec/ruby/core/matchdata/to_s_spec.rb b/spec/ruby/core/matchdata/to_s_spec.rb
index aab0955ae1..cbcc5e8a21 100644
--- a/spec/ruby/core/matchdata/to_s_spec.rb
+++ b/spec/ruby/core/matchdata/to_s_spec.rb
@@ -6,10 +6,8 @@ describe "MatchData#to_s" do
/(.)(.)(\d+)(\d)/.match("THX1138.").to_s.should == "HX1138"
end
- ruby_version_is "3.0" do
- it "returns an instance of String when given a String subclass" do
- str = MatchDataSpecs::MyString.new("THX1138.")
- /(.)(.)(\d+)(\d)/.match(str).to_s.should be_an_instance_of(String)
- end
+ it "returns an instance of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138.")
+ /(.)(.)(\d+)(\d)/.match(str).to_s.should.instance_of?(String)
end
end
diff --git a/spec/ruby/core/matchdata/values_at_spec.rb b/spec/ruby/core/matchdata/values_at_spec.rb
index 8f7fdf557c..ba5b0e662c 100644
--- a/spec/ruby/core/matchdata/values_at_spec.rb
+++ b/spec/ruby/core/matchdata/values_at_spec.rb
@@ -1,21 +1,76 @@
require_relative '../../spec_helper'
describe "MatchData#values_at" do
- it "returns an array of the matching value" do
- /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0, 2, -2).should == ["HX1138", "X", "113"]
+ # Should be synchronized with core/array/values_at_spec.rb and core/struct/values_at_spec.rb
+ #
+ # /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").to_a # => ["HX1138", "H", "X", "113", "8"]
+
+ context "when passed a list of Integers" do
+ it "returns an array containing each value given by one of integers" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0, 2, -2).should == ["HX1138", "X", "113"]
+ end
+
+ it "returns nil value for any integer that is out of range" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(5).should == [nil]
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(-6).should == [nil]
+ end
end
- describe "when passed a Range" do
- it "returns an array of the matching value" do
- /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(2..4, 0..1).should == ["X", "113", "8", "HX1138", "H"]
+ context "when passed an integer Range" do
+ it "returns an array containing each value given by the elements of the range" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..2).should == ["HX1138", "H", "X"]
+ end
+
+ it "fills with nil values for range elements larger than the captured values number" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..5).should == ["HX1138", "H", "X", "113", "8", nil]
+ end
+
+ it "raises RangeError if any element of the range is negative and out of range" do
+ -> { /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(-6..3) }.should.raise(RangeError, "-6..3 out of range")
+ end
+
+ it "supports endless Range" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..).should == ["HX1138", "H", "X", "113", "8"]
+ end
+
+ it "supports beginningless Range" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(..2).should == ["HX1138", "H", "X"]
+ end
+
+ it "returns an empty Array when Range is empty" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(2..0).should == []
+ end
+ end
+
+ context "when passed names" do
+ it 'slices captures with the given names' do
+ /(?<a>.)(?<b>.)(?<c>.)/.match('012').values_at(:c, :a).should == ['2', '0']
+ end
+
+ it 'slices captures with the given String names' do
+ /(?<a>.)(?<b>.)(?<c>.)/.match('012').values_at('c', 'a').should == ['2', '0']
end
end
- it 'slices captures with the given names' do
- /(?<a>.)(?<b>.)(?<c>.)/.match('012').values_at(:c, :a).should == ['2', '0']
+ it "supports multiple integer Ranges" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(1..2, 2..3).should == ["H", "X", "X", "113"]
end
- it 'takes names and indices' do
+ it "supports mixing integer Ranges and Integers" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(1..2, 4).should == ["H", "X", "8"]
+ end
+
+ it 'supports mixing of names and indices' do
/\A(?<a>.)(?<b>.)\z/.match('01').values_at(0, 1, 2, :a, :b).should == ['01', '0', '1', '0', '1']
end
+
+ it "returns a new empty Array if no arguments given" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at().should == []
+ end
+
+ it "fails when passed arguments of unsupported types" do
+ -> {
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(Object.new)
+ }.should.raise(TypeError, "no implicit conversion of Object into Integer")
+ end
end
diff --git a/spec/ruby/core/math/acos_spec.rb b/spec/ruby/core/math/acos_spec.rb
index 8b321ab29b..4649dc527c 100644
--- a/spec/ruby/core/math/acos_spec.rb
+++ b/spec/ruby/core/math/acos_spec.rb
@@ -8,7 +8,7 @@ describe "Math.acos" do
end
it "returns a float" do
- Math.acos(1).should be_kind_of(Float )
+ Math.acos(1).should.is_a?(Float )
end
it "returns the arccosine of the argument" do
@@ -21,27 +21,27 @@ describe "Math.acos" do
end
it "raises an Math::DomainError if the argument is greater than 1.0" do
- -> { Math.acos(1.0001) }.should raise_error(Math::DomainError)
+ -> { Math.acos(1.0001) }.should.raise(Math::DomainError)
end
it "raises an Math::DomainError if the argument is less than -1.0" do
- -> { Math.acos(-1.0001) }.should raise_error(Math::DomainError)
+ -> { Math.acos(-1.0001) }.should.raise(Math::DomainError)
end
it "raises a TypeError if the string argument cannot be coerced with Float()" do
- -> { Math.acos("test") }.should raise_error(TypeError)
+ -> { Math.acos("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.acos(nan_value).nan?.should be_true
+ Math.acos(nan_value).nan?.should == true
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.acos(MathSpecs::UserClass.new) }.should raise_error(TypeError)
+ -> { Math.acos(MathSpecs::UserClass.new) }.should.raise(TypeError)
end
it "raises a TypeError if the argument is nil" do
- -> { Math.acos(nil) }.should raise_error(TypeError)
+ -> { Math.acos(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/acosh_spec.rb b/spec/ruby/core/math/acosh_spec.rb
index 6707de95d3..ccacda37e0 100644
--- a/spec/ruby/core/math/acosh_spec.rb
+++ b/spec/ruby/core/math/acosh_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.acosh" do
it "returns a float" do
- Math.acosh(1.0).should be_kind_of(Float)
+ Math.acosh(1.0).should.is_a?(Float)
end
it "returns the principle value of the inverse hyperbolic cosine of the argument" do
@@ -12,21 +12,21 @@ describe "Math.acosh" do
end
it "raises Math::DomainError if the passed argument is less than -1.0 or greater than 1.0" do
- -> { Math.acosh(1.0 - TOLERANCE) }.should raise_error(Math::DomainError)
- -> { Math.acosh(0) }.should raise_error(Math::DomainError)
- -> { Math.acosh(-1.0) }.should raise_error(Math::DomainError)
+ -> { Math.acosh(1.0 - TOLERANCE) }.should.raise(Math::DomainError)
+ -> { Math.acosh(0) }.should.raise(Math::DomainError)
+ -> { Math.acosh(-1.0) }.should.raise(Math::DomainError)
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.acosh("test") }.should raise_error(TypeError)
+ -> { Math.acosh("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.acosh(nan_value).nan?.should be_true
+ Math.acosh(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.acosh(nil) }.should raise_error(TypeError)
+ -> { Math.acosh(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/asin_spec.rb b/spec/ruby/core/math/asin_spec.rb
index 3a674a1147..1386bccc06 100644
--- a/spec/ruby/core/math/asin_spec.rb
+++ b/spec/ruby/core/math/asin_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
# arcsine : (-1.0, 1.0) --> (-PI/2, PI/2)
describe "Math.asin" do
it "returns a float" do
- Math.asin(1).should be_kind_of(Float)
+ Math.asin(1).should.is_a?(Float)
end
it "returns the arcsine of the argument" do
@@ -17,23 +17,23 @@ describe "Math.asin" do
end
it "raises an Math::DomainError if the argument is greater than 1.0" do
- -> { Math.asin(1.0001) }.should raise_error( Math::DomainError)
+ -> { Math.asin(1.0001) }.should.raise( Math::DomainError)
end
it "raises an Math::DomainError if the argument is less than -1.0" do
- -> { Math.asin(-1.0001) }.should raise_error( Math::DomainError)
+ -> { Math.asin(-1.0001) }.should.raise( Math::DomainError)
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.asin("test") }.should raise_error(TypeError)
+ -> { Math.asin("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.asin(nan_value).nan?.should be_true
+ Math.asin(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.asin(nil) }.should raise_error(TypeError)
+ -> { Math.asin(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/asinh_spec.rb b/spec/ruby/core/math/asinh_spec.rb
index ff8210df0a..8aa019f05f 100644
--- a/spec/ruby/core/math/asinh_spec.rb
+++ b/spec/ruby/core/math/asinh_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.asinh" do
it "returns a float" do
- Math.asinh(1.5).should be_kind_of(Float)
+ Math.asinh(1.5).should.is_a?(Float)
end
it "returns the inverse hyperbolic sin of the argument" do
@@ -19,15 +19,15 @@ describe "Math.asinh" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.asinh("test") }.should raise_error(TypeError)
+ -> { Math.asinh("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.asinh(nan_value).nan?.should be_true
+ Math.asinh(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.asinh(nil) }.should raise_error(TypeError)
+ -> { Math.asinh(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/atan2_spec.rb b/spec/ruby/core/math/atan2_spec.rb
index d4ef369d2a..1f1de506c5 100644
--- a/spec/ruby/core/math/atan2_spec.rb
+++ b/spec/ruby/core/math/atan2_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.atan2" do
it "returns a float" do
- Math.atan2(1.2, 0.5).should be_kind_of(Float)
+ Math.atan2(1.2, 0.5).should.is_a?(Float)
end
it "returns the arc tangent of y, x" do
@@ -14,15 +14,15 @@ describe "Math.atan2" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.atan2(1.0, "test") }.should raise_error(TypeError)
- -> { Math.atan2("test", 0.0) }.should raise_error(TypeError)
- -> { Math.atan2("test", "this") }.should raise_error(TypeError)
+ -> { Math.atan2(1.0, "test") }.should.raise(TypeError)
+ -> { Math.atan2("test", 0.0) }.should.raise(TypeError)
+ -> { Math.atan2("test", "this") }.should.raise(TypeError)
end
it "raises a TypeError if the argument is nil" do
- -> { Math.atan2(nil, 1.0) }.should raise_error(TypeError)
- -> { Math.atan2(-1.0, nil) }.should raise_error(TypeError)
- -> { Math.atan2(nil, nil) }.should raise_error(TypeError)
+ -> { Math.atan2(nil, 1.0) }.should.raise(TypeError)
+ -> { Math.atan2(-1.0, nil) }.should.raise(TypeError)
+ -> { Math.atan2(nil, nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/atan_spec.rb b/spec/ruby/core/math/atan_spec.rb
index 15edf68c05..07d04cdf82 100644
--- a/spec/ruby/core/math/atan_spec.rb
+++ b/spec/ruby/core/math/atan_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
# arctangent : (-Inf, Inf) --> (-PI/2, PI/2)
describe "Math.atan" do
it "returns a float" do
- Math.atan(1).should be_kind_of(Float)
+ Math.atan(1).should.is_a?(Float)
end
it "returns the arctangent of the argument" do
@@ -17,15 +17,15 @@ describe "Math.atan" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.atan("test") }.should raise_error(TypeError)
+ -> { Math.atan("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.atan(nan_value).nan?.should be_true
+ Math.atan(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.atan(nil) }.should raise_error(TypeError)
+ -> { Math.atan(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/atanh_spec.rb b/spec/ruby/core/math/atanh_spec.rb
index 21fb209941..edcb8f2e52 100644
--- a/spec/ruby/core/math/atanh_spec.rb
+++ b/spec/ruby/core/math/atanh_spec.rb
@@ -1,6 +1,6 @@
require_relative '../../spec_helper'
-require_relative '../../fixtures/math/common'
-require_relative '../../shared/math/atanh'
+require_relative 'fixtures/common'
+require_relative 'shared/atanh'
describe "Math.atanh" do
it_behaves_like :math_atanh_base, :atanh, Math
diff --git a/spec/ruby/core/math/cbrt_spec.rb b/spec/ruby/core/math/cbrt_spec.rb
index 01cf923c71..4e2383043b 100644
--- a/spec/ruby/core/math/cbrt_spec.rb
+++ b/spec/ruby/core/math/cbrt_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.cbrt" do
it "returns a float" do
- Math.cbrt(1).should be_an_instance_of(Float)
+ Math.cbrt(1).should.instance_of?(Float)
end
it "returns the cubic root of the argument" do
@@ -14,11 +14,11 @@ describe "Math.cbrt" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.cbrt("foobar") }.should raise_error(TypeError)
+ -> { Math.cbrt("foobar") }.should.raise(TypeError)
end
it "raises a TypeError if the argument is nil" do
- -> { Math.cbrt(nil) }.should raise_error(TypeError)
+ -> { Math.cbrt(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/cos_spec.rb b/spec/ruby/core/math/cos_spec.rb
index 3ba7a54c38..e8602cde3c 100644
--- a/spec/ruby/core/math/cos_spec.rb
+++ b/spec/ruby/core/math/cos_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
# cosine : (-Inf, Inf) --> (-1.0, 1.0)
describe "Math.cos" do
it "returns a float" do
- Math.cos(Math::PI).should be_kind_of(Float)
+ Math.cos(Math::PI).should.is_a?(Float)
end
it "returns the cosine of the argument expressed in radians" do
@@ -15,23 +15,31 @@ describe "Math.cos" do
Math.cos(2*Math::PI).should be_close(1.0, TOLERANCE)
end
-
it "raises a TypeError unless the argument is Numeric and has #to_f" do
- -> { Math.cos("test") }.should raise_error(TypeError)
+ -> { Math.cos("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.cos(nan_value).nan?.should be_true
- end
-
- it "raises a TypeError if the argument is nil" do
- -> { Math.cos(nil) }.should raise_error(TypeError)
+ Math.cos(nan_value).nan?.should == true
end
- it "coerces its argument with #to_f" do
- f = mock_numeric('8.2')
- f.should_receive(:to_f).and_return(8.2)
- Math.cos(f).should == Math.cos(8.2)
+ describe "coerces its argument with #to_f" do
+ it "coerces its argument with #to_f" do
+ f = mock_numeric('8.2')
+ f.should_receive(:to_f).and_return(8.2)
+ Math.cos(f).should == Math.cos(8.2)
+ end
+
+ it "raises a TypeError if the given argument can't be converted to a Float" do
+ -> { Math.cos(nil) }.should.raise(TypeError)
+ -> { Math.cos(:abc) }.should.raise(TypeError)
+ end
+
+ it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to a Float" do
+ object = mock_numeric('mock-float')
+ object.should_receive(:to_f).and_raise(NoMethodError)
+ -> { Math.cos(object) }.should.raise(NoMethodError)
+ end
end
end
diff --git a/spec/ruby/core/math/cosh_spec.rb b/spec/ruby/core/math/cosh_spec.rb
index 049e117e56..2093d8a74a 100644
--- a/spec/ruby/core/math/cosh_spec.rb
+++ b/spec/ruby/core/math/cosh_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.cosh" do
it "returns a float" do
- Math.cosh(1.0).should be_kind_of(Float)
+ Math.cosh(1.0).should.is_a?(Float)
end
it "returns the hyperbolic cosine of the argument" do
@@ -14,15 +14,15 @@ describe "Math.cosh" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.cosh("test") }.should raise_error(TypeError)
+ -> { Math.cosh("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.cosh(nan_value).nan?.should be_true
+ Math.cosh(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.cosh(nil) }.should raise_error(TypeError)
+ -> { Math.cosh(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/erf_spec.rb b/spec/ruby/core/math/erf_spec.rb
index b4e6248e43..5384e73ae9 100644
--- a/spec/ruby/core/math/erf_spec.rb
+++ b/spec/ruby/core/math/erf_spec.rb
@@ -5,7 +5,7 @@ require_relative 'fixtures/classes'
# distribution (which is a normalized form of the Gaussian function).
describe "Math.erf" do
it "returns a float" do
- Math.erf(1).should be_kind_of(Float)
+ Math.erf(1).should.is_a?(Float)
end
it "returns the error function of the argument" do
@@ -21,15 +21,15 @@ describe "Math.erf" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.erf("test") }.should raise_error(TypeError)
+ -> { Math.erf("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.erf(nan_value).nan?.should be_true
+ Math.erf(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.erf(nil) }.should raise_error(TypeError)
+ -> { Math.erf(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/erfc_spec.rb b/spec/ruby/core/math/erfc_spec.rb
index e465f5cf58..4e09a68d1e 100644
--- a/spec/ruby/core/math/erfc_spec.rb
+++ b/spec/ruby/core/math/erfc_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
# erfc is the complementary error function
describe "Math.erfc" do
it "returns a float" do
- Math.erf(1).should be_kind_of(Float)
+ Math.erf(1).should.is_a?(Float)
end
it "returns the complementary error function of the argument" do
@@ -20,15 +20,15 @@ describe "Math.erfc" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.erfc("test") }.should raise_error(TypeError)
+ -> { Math.erfc("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.erfc(nan_value).nan?.should be_true
+ Math.erfc(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.erfc(nil) }.should raise_error(TypeError)
+ -> { Math.erfc(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/exp_spec.rb b/spec/ruby/core/math/exp_spec.rb
index 36eb49a8c7..3688482457 100644
--- a/spec/ruby/core/math/exp_spec.rb
+++ b/spec/ruby/core/math/exp_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.exp" do
it "returns a float" do
- Math.exp(1.0).should be_kind_of(Float)
+ Math.exp(1.0).should.is_a?(Float)
end
it "returns the base-e exponential of the argument" do
@@ -14,15 +14,15 @@ describe "Math.exp" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.exp("test") }.should raise_error(TypeError)
+ -> { Math.exp("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.exp(nan_value).nan?.should be_true
+ Math.exp(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.exp(nil) }.should raise_error(TypeError)
+ -> { Math.exp(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/expm1_spec.rb b/spec/ruby/core/math/expm1_spec.rb
new file mode 100644
index 0000000000..35f62b5dbd
--- /dev/null
+++ b/spec/ruby/core/math/expm1_spec.rb
@@ -0,0 +1,37 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "4.0" do
+ describe "Math.expm1" do
+ it "calculates Math.exp(arg) - 1" do
+ Math.expm1(3).should == Math.exp(3) - 1
+ end
+
+ it "preserves precision that can be lost otherwise" do
+ Math.expm1(1.0e-16).should be_close(1.0e-16, TOLERANCE)
+ Math.expm1(1.0e-16).should != 0.0
+ end
+
+ it "raises a TypeError if the argument cannot be coerced with Float()" do
+ -> { Math.expm1("test") }.should.raise(TypeError, "can't convert String into Float")
+ end
+
+ it "returns NaN given NaN" do
+ Math.expm1(nan_value).nan?.should == true
+ end
+
+ it "raises a TypeError if the argument is nil" do
+ -> { Math.expm1(nil) }.should.raise(TypeError, "can't convert nil into Float")
+ end
+
+ it "accepts any argument that can be coerced with Float()" do
+ Math.expm1(MathSpecs::Float.new).should be_close(Math::E - 1, TOLERANCE)
+ end
+ end
+
+ describe "Math#expm1" do
+ it "is accessible as a private instance method" do
+ IncludesMath.new.send(:expm1, 23.1415).should be_close(11226018483.0012, TOLERANCE)
+ end
+ end
+end
diff --git a/spec/ruby/fixtures/math/common.rb b/spec/ruby/core/math/fixtures/common.rb
index 024732fa7a..024732fa7a 100644
--- a/spec/ruby/fixtures/math/common.rb
+++ b/spec/ruby/core/math/fixtures/common.rb
diff --git a/spec/ruby/core/math/frexp_spec.rb b/spec/ruby/core/math/frexp_spec.rb
index 7dfb493d20..6853e4672f 100644
--- a/spec/ruby/core/math/frexp_spec.rb
+++ b/spec/ruby/core/math/frexp_spec.rb
@@ -9,16 +9,16 @@ describe "Math.frexp" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.frexp("test") }.should raise_error(TypeError)
+ -> { Math.frexp("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
frac, _exp = Math.frexp(nan_value)
- frac.nan?.should be_true
+ frac.nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.frexp(nil) }.should raise_error(TypeError)
+ -> { Math.frexp(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/gamma_spec.rb b/spec/ruby/core/math/gamma_spec.rb
index 386162a087..9a0b14448a 100644
--- a/spec/ruby/core/math/gamma_spec.rb
+++ b/spec/ruby/core/math/gamma_spec.rb
@@ -51,7 +51,7 @@ describe "Math.gamma" do
end
it "raises Math::DomainError given -1" do
- -> { Math.gamma(-1) }.should raise_error(Math::DomainError)
+ -> { Math.gamma(-1) }.should.raise(Math::DomainError)
end
# See https://bugs.ruby-lang.org/issues/10642
@@ -60,10 +60,10 @@ describe "Math.gamma" do
end
it "raises Math::DomainError given negative infinity" do
- -> { Math.gamma(-Float::INFINITY) }.should raise_error(Math::DomainError)
+ -> { Math.gamma(-Float::INFINITY) }.should.raise(Math::DomainError)
end
it "returns NaN given NaN" do
- Math.gamma(nan_value).nan?.should be_true
+ Math.gamma(nan_value).nan?.should == true
end
end
diff --git a/spec/ruby/core/math/hypot_spec.rb b/spec/ruby/core/math/hypot_spec.rb
index 3e0ce74597..4ab5bd4e88 100644
--- a/spec/ruby/core/math/hypot_spec.rb
+++ b/spec/ruby/core/math/hypot_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.hypot" do
it "returns a float" do
- Math.hypot(3, 4).should be_kind_of(Float)
+ Math.hypot(3, 4).should.is_a?(Float)
end
it "returns the length of the hypotenuse of a right triangle with legs given by the arguments" do
@@ -16,17 +16,17 @@ describe "Math.hypot" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.hypot("test", "this") }.should raise_error(TypeError)
+ -> { Math.hypot("test", "this") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.hypot(nan_value, 0).nan?.should be_true
- Math.hypot(0, nan_value).nan?.should be_true
- Math.hypot(nan_value, nan_value).nan?.should be_true
+ Math.hypot(nan_value, 0).nan?.should == true
+ Math.hypot(0, nan_value).nan?.should == true
+ Math.hypot(nan_value, nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.hypot(nil, nil) }.should raise_error(TypeError)
+ -> { Math.hypot(nil, nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/ldexp_spec.rb b/spec/ruby/core/math/ldexp_spec.rb
index 6dcf94a663..1864b7455a 100644
--- a/spec/ruby/core/math/ldexp_spec.rb
+++ b/spec/ruby/core/math/ldexp_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.ldexp" do
it "returns a float" do
- Math.ldexp(1.0, 2).should be_kind_of(Float)
+ Math.ldexp(1.0, 2).should.is_a?(Float)
end
it "returns the argument multiplied by 2**n" do
@@ -15,27 +15,27 @@ describe "Math.ldexp" do
end
it "raises a TypeError if the first argument cannot be coerced with Float()" do
- -> { Math.ldexp("test", 2) }.should raise_error(TypeError)
+ -> { Math.ldexp("test", 2) }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.ldexp(nan_value, 0).nan?.should be_true
+ Math.ldexp(nan_value, 0).nan?.should == true
end
it "raises RangeError if NaN is given as the second arg" do
- -> { Math.ldexp(0, nan_value) }.should raise_error(RangeError)
+ -> { Math.ldexp(0, nan_value) }.should.raise(RangeError)
end
it "raises a TypeError if the second argument cannot be coerced with Integer()" do
- -> { Math.ldexp(3.2, "this") }.should raise_error(TypeError)
+ -> { Math.ldexp(3.2, "this") }.should.raise(TypeError)
end
it "raises a TypeError if the first argument is nil" do
- -> { Math.ldexp(nil, 2) }.should raise_error(TypeError)
+ -> { Math.ldexp(nil, 2) }.should.raise(TypeError)
end
it "raises a TypeError if the second argument is nil" do
- -> { Math.ldexp(3.1, nil) }.should raise_error(TypeError)
+ -> { Math.ldexp(3.1, nil) }.should.raise(TypeError)
end
it "accepts any first argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/lgamma_spec.rb b/spec/ruby/core/math/lgamma_spec.rb
index 33e7836448..38f07d0bf8 100644
--- a/spec/ruby/core/math/lgamma_spec.rb
+++ b/spec/ruby/core/math/lgamma_spec.rb
@@ -5,10 +5,8 @@ describe "Math.lgamma" do
Math.lgamma(0).should == [infinity_value, 1]
end
- platform_is_not :windows do
- it "returns [Infinity, 1] when passed -1" do
- Math.lgamma(-1).should == [infinity_value, 1]
- end
+ it "returns [Infinity, ...] when passed -1" do
+ Math.lgamma(-1)[0].should == infinity_value
end
it "returns [Infinity, -1] when passed -0.0" do
@@ -40,15 +38,14 @@ describe "Math.lgamma" do
end
it "raises Math::DomainError when passed -Infinity" do
- -> { Math.lgamma(-infinity_value) }.should raise_error(Math::DomainError)
+ -> { Math.lgamma(-infinity_value) }.should.raise(Math::DomainError)
end
it "returns [Infinity, 1] when passed Infinity" do
Math.lgamma(infinity_value).should == [infinity_value, 1]
end
- it "returns [NaN, 1] when passed NaN" do
- Math.lgamma(nan_value)[0].nan?.should be_true
- Math.lgamma(nan_value)[1].should == 1
+ it "returns [NaN, ...] when passed NaN" do
+ Math.lgamma(nan_value)[0].should.nan?
end
end
diff --git a/spec/ruby/core/math/log10_spec.rb b/spec/ruby/core/math/log10_spec.rb
index c4daedcd5c..7576a67002 100644
--- a/spec/ruby/core/math/log10_spec.rb
+++ b/spec/ruby/core/math/log10_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
# The common logarithm, having base 10
describe "Math.log10" do
it "returns a float" do
- Math.log10(1).should be_kind_of(Float)
+ Math.log10(1).should.is_a?(Float)
end
it "returns the base-10 logarithm of the argument" do
@@ -16,19 +16,23 @@ describe "Math.log10" do
end
it "raises an Math::DomainError if the argument is less than 0" do
- -> { Math.log10(-1e-15) }.should raise_error(Math::DomainError)
+ -> { Math.log10(-1e-15) }.should.raise(Math::DomainError)
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.log10("test") }.should raise_error(TypeError)
+ -> { Math.log10("test") }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError if passed a numerical argument as a string" do
+ -> { Math.log10("1.0") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.log10(nan_value).nan?.should be_true
+ Math.log10(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.log10(nil) }.should raise_error(TypeError)
+ -> { Math.log10(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/log1p_spec.rb b/spec/ruby/core/math/log1p_spec.rb
new file mode 100644
index 0000000000..181b462ded
--- /dev/null
+++ b/spec/ruby/core/math/log1p_spec.rb
@@ -0,0 +1,49 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "4.0" do
+ describe "Math.log1p" do
+ it "calculates Math.log(1 + arg)" do
+ Math.log1p(3).should == Math.log(1 + 3)
+ end
+
+ it "preserves precision that can be lost otherwise" do
+ Math.log1p(1e-16).should be_close(1.0e-16, TOLERANCE)
+ Math.log1p(1e-16).should != 0.0
+ end
+
+ it "raises an Math::DomainError if the argument is less than 1" do
+ -> { Math.log1p(-1-1e-15) }.should.raise(Math::DomainError, "Numerical argument is out of domain - log1p")
+ end
+
+ it "raises a TypeError if the argument cannot be coerced with Float()" do
+ -> { Math.log1p("test") }.should.raise(TypeError, "can't convert String into Float")
+ end
+
+ it "raises a TypeError for numerical values passed as string" do
+ -> { Math.log1p("10") }.should.raise(TypeError, "can't convert String into Float")
+ end
+
+ it "does not accept a second argument for the base" do
+ -> { Math.log1p(9, 3) }.should.raise(ArgumentError, "wrong number of arguments (given 2, expected 1)")
+ end
+
+ it "returns NaN given NaN" do
+ Math.log1p(nan_value).nan?.should == true
+ end
+
+ it "raises a TypeError if the argument is nil" do
+ -> { Math.log1p(nil) }.should.raise(TypeError, "can't convert nil into Float")
+ end
+
+ it "accepts any argument that can be coerced with Float()" do
+ Math.log1p(MathSpecs::Float.new).should be_close(0.6931471805599453, TOLERANCE)
+ end
+ end
+
+ describe "Math#log1p" do
+ it "is accessible as a private instance method" do
+ IncludesMath.new.send(:log1p, 4.21).should be_close(1.65057985576528, TOLERANCE)
+ end
+ end
+end
diff --git a/spec/ruby/core/math/log2_spec.rb b/spec/ruby/core/math/log2_spec.rb
index 3d4d41d130..e38a8bb67f 100644
--- a/spec/ruby/core/math/log2_spec.rb
+++ b/spec/ruby/core/math/log2_spec.rb
@@ -16,23 +16,23 @@ describe "Math.log2" do
end
it "raises Math::DomainError if the argument is less than 0" do
- -> { Math.log2(-1e-15) }.should raise_error( Math::DomainError)
+ -> { Math.log2(-1e-15) }.should.raise( Math::DomainError)
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.log2("test") }.should raise_error(TypeError)
+ -> { Math.log2("test") }.should.raise(TypeError)
end
it "raises a TypeError if passed a numerical argument as a string" do
- -> { Math.log2("1.0") }.should raise_error(TypeError)
+ -> { Math.log2("1.0") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.log2(nan_value).nan?.should be_true
+ Math.log2(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.log2(nil) }.should raise_error(TypeError)
+ -> { Math.log2(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/log_spec.rb b/spec/ruby/core/math/log_spec.rb
index 6c5036ba81..7e0bc13bc6 100644
--- a/spec/ruby/core/math/log_spec.rb
+++ b/spec/ruby/core/math/log_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
# The natural logarithm, having base Math::E
describe "Math.log" do
it "returns a float" do
- Math.log(1).should be_kind_of(Float)
+ Math.log(1).should.is_a?(Float)
end
it "returns the natural logarithm of the argument" do
@@ -16,15 +16,15 @@ describe "Math.log" do
end
it "raises an Math::DomainError if the argument is less than 0" do
- -> { Math.log(-1e-15) }.should raise_error(Math::DomainError)
+ -> { Math.log(-1e-15) }.should.raise(Math::DomainError)
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.log("test") }.should raise_error(TypeError)
+ -> { Math.log("test") }.should.raise(TypeError)
end
it "raises a TypeError for numerical values passed as string" do
- -> { Math.log("10") }.should raise_error(TypeError)
+ -> { Math.log("10") }.should.raise(TypeError)
end
it "accepts a second argument for the base" do
@@ -33,16 +33,16 @@ describe "Math.log" do
end
it "raises a TypeError when the numerical base cannot be coerced to a float" do
- -> { Math.log(10, "2") }.should raise_error(TypeError)
- -> { Math.log(10, nil) }.should raise_error(TypeError)
+ -> { Math.log(10, "2") }.should.raise(TypeError)
+ -> { Math.log(10, nil) }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.log(nan_value).nan?.should be_true
+ Math.log(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.log(nil) }.should raise_error(TypeError)
+ -> { Math.log(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/shared/atanh.rb b/spec/ruby/core/math/shared/atanh.rb
new file mode 100644
index 0000000000..48a6bf836e
--- /dev/null
+++ b/spec/ruby/core/math/shared/atanh.rb
@@ -0,0 +1,44 @@
+describe :math_atanh_base, shared: true do
+ it "returns a float" do
+ @object.send(@method, 0.5).should.instance_of?(Float)
+ end
+
+ it "returns the inverse hyperbolic tangent of the argument" do
+ @object.send(@method, 0.0).should == 0.0
+ @object.send(@method, -0.0).should == -0.0
+ @object.send(@method, 0.5).should be_close(0.549306144334055, TOLERANCE)
+ @object.send(@method, -0.2).should be_close(-0.202732554054082, TOLERANCE)
+ end
+
+ it "raises a TypeError if the argument is nil" do
+ -> { @object.send(@method, nil) }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError if the argument is not a Numeric" do
+ -> { @object.send(@method, "test") }.should.raise(TypeError)
+ end
+
+ it "returns Infinity if x == 1.0" do
+ @object.send(@method, 1.0).should == Float::INFINITY
+ end
+
+ it "return -Infinity if x == -1.0" do
+ @object.send(@method, -1.0).should == -Float::INFINITY
+ end
+end
+
+describe :math_atanh_private, shared: true do
+ it "is a private instance method" do
+ Math.private_instance_methods(false).should.include?(@method)
+ end
+end
+
+describe :math_atanh_no_complex, shared: true do
+ it "raises a Math::DomainError for arguments greater than 1.0" do
+ -> { @object.send(@method, 1.0 + Float::EPSILON) }.should.raise(Math::DomainError)
+ end
+
+ it "raises a Math::DomainError for arguments less than -1.0" do
+ -> { @object.send(@method, -1.0 - Float::EPSILON) }.should.raise(Math::DomainError)
+ end
+end
diff --git a/spec/ruby/core/math/sin_spec.rb b/spec/ruby/core/math/sin_spec.rb
index 8e944bc95f..a9479e3aec 100644
--- a/spec/ruby/core/math/sin_spec.rb
+++ b/spec/ruby/core/math/sin_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
# sine : (-Inf, Inf) --> (-1.0, 1.0)
describe "Math.sin" do
it "returns a float" do
- Math.sin(Math::PI).should be_kind_of(Float)
+ Math.sin(Math::PI).should.is_a?(Float)
end
it "returns the sine of the argument expressed in radians" do
@@ -16,15 +16,15 @@ describe "Math.sin" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.sin("test") }.should raise_error(TypeError)
+ -> { Math.sin("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.sin(nan_value).nan?.should be_true
+ Math.sin(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.sin(nil) }.should raise_error(TypeError)
+ -> { Math.sin(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/sinh_spec.rb b/spec/ruby/core/math/sinh_spec.rb
index 027c2395a7..de0f06affa 100644
--- a/spec/ruby/core/math/sinh_spec.rb
+++ b/spec/ruby/core/math/sinh_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.sinh" do
it "returns a float" do
- Math.sinh(1.2).should be_kind_of(Float)
+ Math.sinh(1.2).should.is_a?(Float)
end
it "returns the hyperbolic sin of the argument" do
@@ -14,15 +14,15 @@ describe "Math.sinh" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.sinh("test") }.should raise_error(TypeError)
+ -> { Math.sinh("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.sinh(nan_value).nan?.should be_true
+ Math.sinh(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.sinh(nil) }.should raise_error(TypeError)
+ -> { Math.sinh(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/sqrt_spec.rb b/spec/ruby/core/math/sqrt_spec.rb
index 918e7c3a17..545fa4d1c2 100644
--- a/spec/ruby/core/math/sqrt_spec.rb
+++ b/spec/ruby/core/math/sqrt_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.sqrt" do
it "returns a float" do
- Math.sqrt(1).should be_kind_of(Float)
+ Math.sqrt(1).should.is_a?(Float)
end
it "returns the square root of the argument" do
@@ -13,15 +13,15 @@ describe "Math.sqrt" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.sqrt("test") }.should raise_error(TypeError)
+ -> { Math.sqrt("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.sqrt(nan_value).nan?.should be_true
+ Math.sqrt(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.sqrt(nil) }.should raise_error(TypeError)
+ -> { Math.sqrt(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
@@ -29,7 +29,7 @@ describe "Math.sqrt" do
end
it "raises a Math::DomainError when given a negative number" do
- -> { Math.sqrt(-1) }.should raise_error(Math::DomainError)
+ -> { Math.sqrt(-1) }.should.raise(Math::DomainError)
end
end
diff --git a/spec/ruby/core/math/tan_spec.rb b/spec/ruby/core/math/tan_spec.rb
index 67307f1e6e..c3e773f318 100644
--- a/spec/ruby/core/math/tan_spec.rb
+++ b/spec/ruby/core/math/tan_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.tan" do
it "returns a float" do
- Math.tan(1.35).should be_kind_of(Float)
+ Math.tan(1.35).should.is_a?(Float)
end
it "returns the tangent of the argument" do
@@ -19,15 +19,15 @@ describe "Math.tan" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.tan("test") }.should raise_error(TypeError)
+ -> { Math.tan("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.tan(nan_value).nan?.should be_true
+ Math.tan(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.tan(nil) }.should raise_error(TypeError)
+ -> { Math.tan(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/math/tanh_spec.rb b/spec/ruby/core/math/tanh_spec.rb
index 568f8dfa77..74a938ffd8 100644
--- a/spec/ruby/core/math/tanh_spec.rb
+++ b/spec/ruby/core/math/tanh_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Math.tanh" do
it "returns a float" do
- Math.tanh(0.5).should be_kind_of(Float)
+ Math.tanh(0.5).should.is_a?(Float)
end
it "returns the hyperbolic tangent of the argument" do
@@ -16,15 +16,15 @@ describe "Math.tanh" do
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
- -> { Math.tanh("test") }.should raise_error(TypeError)
+ -> { Math.tanh("test") }.should.raise(TypeError)
end
it "returns NaN given NaN" do
- Math.tanh(nan_value).nan?.should be_true
+ Math.tanh(nan_value).nan?.should == true
end
it "raises a TypeError if the argument is nil" do
- -> { Math.tanh(nil) }.should raise_error(TypeError)
+ -> { Math.tanh(nil) }.should.raise(TypeError)
end
it "accepts any argument that can be coerced with Float()" do
diff --git a/spec/ruby/core/method/clone_spec.rb b/spec/ruby/core/method/clone_spec.rb
index 3fe4000fb7..b0eb5751a9 100644
--- a/spec/ruby/core/method/clone_spec.rb
+++ b/spec/ruby/core/method/clone_spec.rb
@@ -1,14 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+require_relative 'shared/dup'
describe "Method#clone" do
- it "returns a copy of the method" do
- m1 = MethodSpecs::Methods.new.method(:foo)
- m2 = m1.clone
+ it_behaves_like :method_dup, :clone
- m1.should == m2
- m1.should_not equal(m2)
-
- m1.call.should == m2.call
+ it "preserves frozen status" do
+ method = Object.new.method(:method)
+ method.freeze
+ method.frozen?.should == true
+ method.clone.frozen?.should == true
end
end
diff --git a/spec/ruby/core/method/compose_spec.rb b/spec/ruby/core/method/compose_spec.rb
index 87cf61f7ad..7506e33ea8 100644
--- a/spec/ruby/core/method/compose_spec.rb
+++ b/spec/ruby/core/method/compose_spec.rb
@@ -38,8 +38,7 @@ describe "Method#<<" do
double = proc { |x| x + x }
(pow_2 << double).is_a?(Proc).should == true
- ruby_version_is(''...'3.0') { (pow_2 << double).should.lambda? }
- ruby_version_is('3.0') { (pow_2 << double).should_not.lambda? }
+ (pow_2 << double).should_not.lambda?
end
it "may accept multiple arguments" do
diff --git a/spec/ruby/core/method/curry_spec.rb b/spec/ruby/core/method/curry_spec.rb
index 219de0f6b5..79c5d7c662 100644
--- a/spec/ruby/core/method/curry_spec.rb
+++ b/spec/ruby/core/method/curry_spec.rb
@@ -7,7 +7,7 @@ describe "Method#curry" do
def x.foo(a,b,c); [a,b,c]; end
c = x.method(:foo).curry
- c.should be_kind_of(Proc)
+ c.should.is_a?(Proc)
c.call(1).call(2, 3).should == [1,2,3]
end
@@ -17,20 +17,20 @@ describe "Method#curry" do
end
it "returns a curried proc when given correct arity" do
- @obj.method(:one_req).curry(1).should be_kind_of(Proc)
- @obj.method(:zero_with_splat).curry(100).should be_kind_of(Proc)
- @obj.method(:two_req_with_splat).curry(2).should be_kind_of(Proc)
+ @obj.method(:one_req).curry(1).should.is_a?(Proc)
+ @obj.method(:zero_with_splat).curry(100).should.is_a?(Proc)
+ @obj.method(:two_req_with_splat).curry(2).should.is_a?(Proc)
end
it "raises ArgumentError when the method requires less arguments than the given arity" do
- -> { @obj.method(:zero).curry(1) }.should raise_error(ArgumentError)
- -> { @obj.method(:one_req_one_opt).curry(3) }.should raise_error(ArgumentError)
- -> { @obj.method(:two_req_one_opt_with_block).curry(4) }.should raise_error(ArgumentError)
+ -> { @obj.method(:zero).curry(1) }.should.raise(ArgumentError)
+ -> { @obj.method(:one_req_one_opt).curry(3) }.should.raise(ArgumentError)
+ -> { @obj.method(:two_req_one_opt_with_block).curry(4) }.should.raise(ArgumentError)
end
it "raises ArgumentError when the method requires more arguments than the given arity" do
- -> { @obj.method(:two_req_with_splat).curry(1) }.should raise_error(ArgumentError)
- -> { @obj.method(:one_req).curry(0) }.should raise_error(ArgumentError)
+ -> { @obj.method(:two_req_with_splat).curry(1) }.should.raise(ArgumentError)
+ -> { @obj.method(:one_req).curry(0) }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/method/dup_spec.rb b/spec/ruby/core/method/dup_spec.rb
new file mode 100644
index 0000000000..e3e29d8a68
--- /dev/null
+++ b/spec/ruby/core/method/dup_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+require_relative 'shared/dup'
+
+describe "Method#dup" do
+ ruby_version_is "3.4" do
+ it_behaves_like :method_dup, :dup
+
+ it "resets frozen status" do
+ method = Object.new.method(:method)
+ method.freeze
+ method.frozen?.should == true
+ method.dup.frozen?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/method/fixtures/classes.rb b/spec/ruby/core/method/fixtures/classes.rb
index be96f65e25..41904df1d1 100644
--- a/spec/ruby/core/method/fixtures/classes.rb
+++ b/spec/ruby/core/method/fixtures/classes.rb
@@ -27,6 +27,7 @@ module MethodSpecs
alias bar foo
alias baz bar
+ alias qux baz
def same_as_foo
true
@@ -84,6 +85,12 @@ module MethodSpecs
def two_req_one_opt_with_splat_and_block(a, b, c=nil, *d, &blk); end
def one_req_two_opt_with_splat_and_block(a, b=nil, c=nil, *d, &blk); end
+ def my_public_method; end
+ def my_protected_method; end
+ def my_private_method; end
+ protected :my_protected_method
+ private :my_private_method
+
define_method(:zero_defined_method, Proc.new {||})
define_method(:zero_with_splat_defined_method, Proc.new {|*x|})
define_method(:one_req_defined_method, Proc.new {|x|})
@@ -213,4 +220,28 @@ module MethodSpecs
n * m
end
end
+
+ module InheritedMethods
+ module A
+ private
+ def derp(message)
+ 'A'
+ end
+ end
+
+ module B
+ private
+ def derp
+ 'B' + super('superclass')
+ end
+ end
+
+ class C
+ include A
+ include B
+
+ public :derp
+ alias_method :meow, :derp
+ end
+ end
end
diff --git a/spec/ruby/core/method/inspect_spec.rb b/spec/ruby/core/method/inspect_spec.rb
index e0fe1afdd0..97ff2d8c11 100644
--- a/spec/ruby/core/method/inspect_spec.rb
+++ b/spec/ruby/core/method/inspect_spec.rb
@@ -1,6 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/to_s'
+require_relative 'shared/aliased_inspect'
describe "Method#inspect" do
it_behaves_like :method_to_s, :inspect
+ it_behaves_like :method_to_s_aliased, :inspect, -> meth { meth }
end
diff --git a/spec/ruby/core/method/original_name_spec.rb b/spec/ruby/core/method/original_name_spec.rb
index 676fdaedb4..b92cf35154 100644
--- a/spec/ruby/core/method/original_name_spec.rb
+++ b/spec/ruby/core/method/original_name_spec.rb
@@ -19,4 +19,41 @@ describe "Method#original_name" do
obj.method(:baz).original_name.should == :foo
obj.method(:baz).unbind.bind(obj).original_name.should == :foo
end
+
+ it "returns the original name even when aliased thrice" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:qux).original_name.should == :foo
+ obj.method(:qux).unbind.bind(obj).original_name.should == :foo
+ end
+
+ it "returns the source UnboundMethod's name (not the name given to define_method)" do
+ klass = Class.new { define_method(:my_inspect, ::Kernel.instance_method(:inspect)) }
+ klass.new.method(:my_inspect).original_name.should == :inspect
+ end
+
+ it "preserves the source method's name through define_method and alias" do
+ source = Class.new { def my_method; end }
+ klass = Class.new(source) do
+ define_method(:renamed, source.instance_method(:my_method))
+ alias aliased renamed
+ end
+ klass.new.method(:renamed).original_name.should == :my_method
+ klass.new.method(:aliased).original_name.should == :my_method
+ end
+
+ it "returns the source UnboundMethod's name for Kernel#is_a? and Kernel#kind_of?" do
+ klass = Class.new { define_method(:my_is_a?, ::Kernel.instance_method(:is_a?)) }
+ klass.new.method(:my_is_a?).original_name.should == :is_a?
+
+ klass = Class.new { define_method(:my_kind_of?, ::Kernel.instance_method(:kind_of?)) }
+ klass.new.method(:my_kind_of?).original_name.should == :kind_of?
+ end
+
+ it "preserves the source name when aliasing a define_method'd Kernel method" do
+ klass = Class.new do
+ define_method(:my_is_a?, ::Kernel.instance_method(:is_a?))
+ alias_method :renamed_is_a?, :my_is_a?
+ end
+ klass.new.method(:renamed_is_a?).original_name.should == :is_a?
+ end
end
diff --git a/spec/ruby/core/method/owner_spec.rb b/spec/ruby/core/method/owner_spec.rb
index ca5dff7295..1cdc4edfa7 100644
--- a/spec/ruby/core/method/owner_spec.rb
+++ b/spec/ruby/core/method/owner_spec.rb
@@ -23,4 +23,8 @@ describe "Method#owner" do
@m.method(:handled_via_method_missing).owner.should == MethodSpecs::Methods
end
end
+
+ it "returns the class on which public was called for a private method in ancestor" do
+ MethodSpecs::InheritedMethods::C.new.method(:derp).owner.should == MethodSpecs::InheritedMethods::C
+ end
end
diff --git a/spec/ruby/core/method/parameters_spec.rb b/spec/ruby/core/method/parameters_spec.rb
index e6d51d1b4d..fd88e8dcb8 100644
--- a/spec/ruby/core/method/parameters_spec.rb
+++ b/spec/ruby/core/method/parameters_spec.rb
@@ -7,6 +7,7 @@ describe "Method#parameters" do
def one_keyrest(**a); end
def one_keyreq(a:); end
+ def one_nokey(**nil); end
def one_splat_one_req(*a,b); end
def one_splat_two_req(*a,b,c); end
@@ -15,11 +16,22 @@ describe "Method#parameters" do
def one_opt_with_stabby(a=-> b { true }); end
def one_unnamed_splat(*); end
+ def one_unnamed_keyrest(**); end
def one_splat_one_block(*args, &block)
local_is_not_parameter = {}
end
+ ruby_version_is "4.1" do
+ eval <<-RUBY
+ def one_noblock(&nil); end
+ RUBY
+ end
+
+ def forward_parameters(...) end
+
+ def underscore_parameters(_, _, _ = 1, *_, _:, _: 2, **_, &_); end
+
define_method(:one_optional_defined_method) {|x = 1|}
end
@@ -176,6 +188,18 @@ describe "Method#parameters" do
m.parameters.should == [[:keyreq,:a]]
end
+ it "returns [[:nokey]] for a method with a single **nil parameter" do
+ m = MethodSpecs::Methods.instance_method(:one_nokey)
+ m.parameters.should == [[:nokey]]
+ end
+
+ ruby_version_is "4.1" do
+ it "returns [[:noblock]] for a method with a single &nil parameter" do
+ m = MethodSpecs::Methods.instance_method(:one_noblock)
+ m.parameters.should == [[:noblock]]
+ end
+ end
+
it "works with ->(){} as the value of an optional argument" do
m = MethodSpecs::Methods.instance_method(:one_opt_with_stabby)
m.parameters.should == [[:opt,:a]]
@@ -222,18 +246,27 @@ describe "Method#parameters" do
m.method(:handled_via_method_missing).parameters.should == [[:rest]]
end
- ruby_version_is '3.2' do
- it "adds * rest arg for \"star\" argument" do
- m = MethodSpecs::Methods.new
- m.method(:one_unnamed_splat).parameters.should == [[:rest, :*]]
- end
+ it "adds rest arg with name * for \"star\" argument" do
+ m = MethodSpecs::Methods.new
+ m.method(:one_unnamed_splat).parameters.should == [[:rest, :*]]
end
- ruby_version_is ''...'3.2' do
- it "adds nameless rest arg for \"star\" argument" do
- m = MethodSpecs::Methods.new
- m.method(:one_unnamed_splat).parameters.should == [[:rest]]
+ it "adds keyrest arg with ** as a name for \"double star\" argument" do
+ m = MethodSpecs::Methods.new
+ m.method(:one_unnamed_keyrest).parameters.should == [[:keyrest, :**]]
+ end
+
+ it "adds block arg with name & for anonymous block argument" do
+ object = Object.new
+ def object.foo(&)
end
+
+ object.method(:foo).parameters.should == [[:block, :&]]
+ end
+
+ it "returns [:rest, :*], [:keyrest, :**], [:block, :&] for forward parameters operator" do
+ m = MethodSpecs::Methods.new
+ m.method(:forward_parameters).parameters.should == [[:rest, :*], [:keyrest, :**], [:block, :&]]
end
it "returns the args and block for a splat and block argument" do
@@ -251,6 +284,20 @@ describe "Method#parameters" do
m.method(:writer=).parameters.should == [[:req]]
end
+ it "returns all parameters defined with the name _ as _" do
+ m = MethodSpecs::Methods.instance_method(:underscore_parameters)
+ m.parameters.should == [
+ [:req, :_],
+ [:req, :_],
+ [:opt, :_],
+ [:rest, :_],
+ [:keyreq, :_],
+ [:key, :_],
+ [:keyrest, :_],
+ [:block, :_]
+ ]
+ end
+
it "returns [[:rest]] for core methods with variable-length argument lists" do
# delete! takes rest args
"foo".method(:delete!).parameters.should == [[:rest]]
@@ -261,7 +308,7 @@ describe "Method#parameters" do
[
[[:rest]],
[[:opt]]
- ].should include([].method(:pop).parameters)
+ ].should.include?([].method(:pop).parameters)
end
it "returns [[:req]] for each parameter for core methods with fixed-length argument lists" do
diff --git a/spec/ruby/core/method/private_spec.rb b/spec/ruby/core/method/private_spec.rb
new file mode 100644
index 0000000000..e708542b2e
--- /dev/null
+++ b/spec/ruby/core/method/private_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Method#private?" do
+ it "has been removed" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_private_method).should_not.respond_to?(:private?)
+ end
+end
diff --git a/spec/ruby/core/method/protected_spec.rb b/spec/ruby/core/method/protected_spec.rb
new file mode 100644
index 0000000000..f9e422ae3d
--- /dev/null
+++ b/spec/ruby/core/method/protected_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Method#protected?" do
+ it "has been removed" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_protected_method).should_not.respond_to?(:protected?)
+ end
+end
diff --git a/spec/ruby/core/method/public_spec.rb b/spec/ruby/core/method/public_spec.rb
new file mode 100644
index 0000000000..4cb23f4cf1
--- /dev/null
+++ b/spec/ruby/core/method/public_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Method#public?" do
+ it "has been removed" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_public_method).should_not.respond_to?(:public?)
+ end
+end
diff --git a/spec/ruby/core/method/receiver_spec.rb b/spec/ruby/core/method/receiver_spec.rb
index 2b2e11dd2e..315a08d288 100644
--- a/spec/ruby/core/method/receiver_spec.rb
+++ b/spec/ruby/core/method/receiver_spec.rb
@@ -4,19 +4,19 @@ require_relative 'fixtures/classes'
describe "Method#receiver" do
it "returns the receiver of the method" do
s = "abc"
- s.method(:upcase).receiver.should equal(s)
+ s.method(:upcase).receiver.should.equal?(s)
end
it "returns the right receiver even when aliased" do
obj = MethodSpecs::Methods.new
- obj.method(:foo).receiver.should equal(obj)
- obj.method(:bar).receiver.should equal(obj)
+ obj.method(:foo).receiver.should.equal?(obj)
+ obj.method(:bar).receiver.should.equal?(obj)
end
describe "for a Method generated by respond_to_missing?" do
it "returns the receiver of the method" do
m = MethodSpecs::Methods.new
- m.method(:handled_via_method_missing).receiver.should equal(m)
+ m.method(:handled_via_method_missing).receiver.should.equal?(m)
end
end
end
diff --git a/spec/ruby/core/method/shared/aliased_inspect.rb b/spec/ruby/core/method/shared/aliased_inspect.rb
new file mode 100644
index 0000000000..2a622c2f97
--- /dev/null
+++ b/spec/ruby/core/method/shared/aliased_inspect.rb
@@ -0,0 +1,31 @@
+describe :method_to_s_aliased, shared: true do
+ # @object converts a bound Method to either a Method (identity) or an
+ # UnboundMethod (-> meth { meth.unbind }), so these expectations cover both
+ # Method#to_s/#inspect and UnboundMethod#to_s/#inspect.
+
+ it "shows the original name in parentheses for an aliased method" do
+ klass = Class.new do
+ def original_method; end
+ alias_method :renamed_method, :original_method
+ end
+ @object.call(klass.new.method(:renamed_method)).send(@method).should.include? '#renamed_method(original_method)'
+ end
+
+ it "shows the source UnboundMethod's name in parentheses for a define_method'd method" do
+ klass = Class.new { define_method(:renamed_is_a?, ::Kernel.instance_method(:is_a?)) }
+ @object.call(klass.new.method(:renamed_is_a?)).send(@method).should.include? '#renamed_is_a?(is_a?)'
+ end
+
+ it "does not annotate a directly looked-up Kernel method with a shared internal name" do
+ @object.call(Object.new.method(:is_a?)).send(@method).should_not.include? '(kind_of?)'
+ @object.call(Object.new.method(:kind_of?)).send(@method).should_not.include? '(is_a?)'
+ end
+
+ it "shows the source name when aliasing a define_method'd Kernel method" do
+ klass = Class.new do
+ define_method(:my_is_a?, ::Kernel.instance_method(:is_a?))
+ alias_method :renamed_is_a?, :my_is_a?
+ end
+ @object.call(klass.new.method(:renamed_is_a?)).send(@method).should.include? '#renamed_is_a?(is_a?)'
+ end
+end
diff --git a/spec/ruby/core/method/shared/call.rb b/spec/ruby/core/method/shared/call.rb
index f26e373695..41ee2b06cb 100644
--- a/spec/ruby/core/method/shared/call.rb
+++ b/spec/ruby/core/method/shared/call.rb
@@ -11,10 +11,10 @@ describe :method_call, shared: true do
it "raises an ArgumentError when given incorrect number of arguments" do
-> {
MethodSpecs::Methods.new.method(:two_req).send(@method, 1, 2, 3)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
MethodSpecs::Methods.new.method(:two_req).send(@method, 1)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
describe "for a Method generated by respond_to_missing?" do
diff --git a/spec/ruby/core/method/shared/dup.rb b/spec/ruby/core/method/shared/dup.rb
new file mode 100644
index 0000000000..eee790890a
--- /dev/null
+++ b/spec/ruby/core/method/shared/dup.rb
@@ -0,0 +1,32 @@
+describe :method_dup, shared: true do
+ it "returns a copy of self" do
+ a = Object.new.method(:method)
+ b = a.send(@method)
+
+ a.should == b
+ a.should_not.equal?(b)
+ end
+
+ ruby_version_is "3.4" do
+ it "copies instance variables" do
+ method = Object.new.method(:method)
+ method.instance_variable_set(:@ivar, 1)
+ cl = method.send(@method)
+ cl.instance_variables.should == [:@ivar]
+ end
+
+ it "copies the finalizer" do
+ code = <<-'RUBY'
+ obj = Object.new.method(:method)
+
+ ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
+
+ obj.clone
+
+ exit 0
+ RUBY
+
+ ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"]
+ end
+ end
+end
diff --git a/spec/ruby/core/method/shared/eql.rb b/spec/ruby/core/method/shared/eql.rb
index 5c720cbac1..3c340202b7 100644
--- a/spec/ruby/core/method/shared/eql.rb
+++ b/spec/ruby/core/method/shared/eql.rb
@@ -12,54 +12,54 @@ describe :method_equal, shared: true do
it "returns true if methods are the same" do
m2 = @m.method(:foo)
- @m_foo.send(@method, @m_foo).should be_true
- @m_foo.send(@method, m2).should be_true
+ @m_foo.send(@method, @m_foo).should == true
+ @m_foo.send(@method, m2).should == true
end
it "returns true on aliased methods" do
m_bar = @m.method(:bar)
- m_bar.send(@method, @m_foo).should be_true
+ m_bar.send(@method, @m_foo).should == true
end
it "returns true if the two core methods are aliases" do
s = "hello"
a = s.method(:size)
b = s.method(:length)
- a.send(@method, b).should be_true
+ a.send(@method, b).should == true
end
it "returns false on a method which is neither aliased nor the same method" do
m2 = @m.method(:zero)
- @m_foo.send(@method, m2).should be_false
+ @m_foo.send(@method, m2).should == false
end
it "returns false for a method which is not bound to the same object" do
m2_foo = @m2.method(:foo)
a_baz = @a.method(:baz)
- @m_foo.send(@method, m2_foo).should be_false
- @m_foo.send(@method, a_baz).should be_false
+ @m_foo.send(@method, m2_foo).should == false
+ @m_foo.send(@method, a_baz).should == false
end
it "returns false if the two methods are bound to the same object but were defined independently" do
m2 = @m.method(:same_as_foo)
- @m_foo.send(@method, m2).should be_false
+ @m_foo.send(@method, m2).should == false
end
it "returns true if a method was defined using the other one" do
MethodSpecs::Methods.send :define_method, :defined_foo, MethodSpecs::Methods.instance_method(:foo)
m2 = @m.method(:defined_foo)
- @m_foo.send(@method, m2).should be_true
+ @m_foo.send(@method, m2).should == true
end
it "returns false if comparing a method defined via define_method and def" do
defn = @m.method(:zero)
defined = @m.method(:zero_defined_method)
- defn.send(@method, defined).should be_false
- defined.send(@method, defn).should be_false
+ defn.send(@method, defined).should == false
+ defined.send(@method, defn).should == false
end
describe 'missing methods' do
@@ -68,8 +68,8 @@ describe :method_equal, shared: true do
miss1bis = @m.method(:handled_via_method_missing)
miss2 = @m.method(:also_handled)
- miss1.send(@method, miss1bis).should be_true
- miss1.send(@method, miss2).should be_false
+ miss1.send(@method, miss1bis).should == true
+ miss1.send(@method, miss2).should == false
end
it 'calls respond_to_missing? with true to include private methods' do
@@ -81,14 +81,14 @@ describe :method_equal, shared: true do
it "returns false if the two methods are bound to different objects, have the same names, and identical bodies" do
a = MethodSpecs::Eql.instance_method(:same_body)
b = MethodSpecs::Eql2.instance_method(:same_body)
- a.send(@method, b).should be_false
+ a.send(@method, b).should == false
end
it "returns false if the argument is not a Method object" do
- String.instance_method(:size).send(@method, 7).should be_false
+ String.instance_method(:size).send(@method, 7).should == false
end
it "returns false if the argument is an unbound version of self" do
- method(:load).send(@method, method(:load).unbind).should be_false
+ method(:load).send(@method, method(:load).unbind).should == false
end
end
diff --git a/spec/ruby/core/method/shared/to_s.rb b/spec/ruby/core/method/shared/to_s.rb
index 6fdeaaf99c..bfb58e6896 100644
--- a/spec/ruby/core/method/shared/to_s.rb
+++ b/spec/ruby/core/method/shared/to_s.rb
@@ -8,12 +8,12 @@ describe :method_to_s, shared: true do
end
it "returns a String" do
- @m.send(@method).should be_kind_of(String)
+ @m.send(@method).should.is_a?(String)
end
it "returns a String for methods defined with attr_accessor" do
m = MethodSpecs::Methods.new.method :attr
- m.send(@method).should be_kind_of(String)
+ m.send(@method).should.is_a?(String)
end
it "returns a String containing 'Method'" do
@@ -53,20 +53,18 @@ describe :method_to_s, shared: true do
MethodSpecs::A.new.method(:baz).send(@method).should.start_with? "#<Method: MethodSpecs::A#baz"
end
- ruby_version_is '3.0' do
- it "returns a String containing the Module containing the method if object has a singleton class but method is not defined in the singleton class" do
- obj = MethodSpecs::MySub.new
- obj.singleton_class
- @m = obj.method(:bar)
- @string = @m.send(@method)
- @string.should.start_with? "#<Method: MethodSpecs::MySub(MethodSpecs::MyMod)#bar"
+ it "returns a String containing the Module containing the method if object has a singleton class but method is not defined in the singleton class" do
+ obj = MethodSpecs::MySub.new
+ obj.singleton_class
+ @m = obj.method(:bar)
+ @string = @m.send(@method)
+ @string.should.start_with? "#<Method: MethodSpecs::MySub(MethodSpecs::MyMod)#bar"
- c = MethodSpecs::MySub.dup
- m = Module.new{def bar; end}
- c.extend(m)
- @string = c.method(:bar).send(@method)
- @string.should.start_with? "#<Method: #<Class:#{c.inspect}>(#{m.inspect})#bar"
- end
+ c = MethodSpecs::MySub.dup
+ m = Module.new{def bar; end}
+ c.extend(m)
+ @string = c.method(:bar).send(@method)
+ @string.should.start_with? "#<Method: #<Class:#{c.inspect}>(#{m.inspect})#bar"
end
it "returns a String containing the singleton class if method is defined in the singleton class" do
@@ -77,9 +75,7 @@ describe :method_to_s, shared: true do
@string.should.start_with? "#<Method: #<MethodSpecs::MySub:0xXXXXXX>.bar"
end
- ruby_bug '#17428', ''...'3.0' do
- it "shows the metaclass and the owner for a Module instance method retrieved from a class" do
- String.method(:include).inspect.should.start_with?("#<Method: #<Class:String>(Module)#include")
- end
+ it "shows the metaclass and the owner for a Module instance method retrieved from a class" do
+ String.method(:include).inspect.should.start_with?("#<Method: #<Class:String>(Module)#include")
end
end
diff --git a/spec/ruby/core/method/source_location_spec.rb b/spec/ruby/core/method/source_location_spec.rb
index 1f476aaa9b..22fcb98c74 100644
--- a/spec/ruby/core/method/source_location_spec.rb
+++ b/spec/ruby/core/method/source_location_spec.rb
@@ -7,18 +7,18 @@ describe "Method#source_location" do
end
it "returns an Array" do
- @method.source_location.should be_an_instance_of(Array)
+ @method.source_location.should.instance_of?(Array)
end
it "sets the first value to the path of the file in which the method was defined" do
file = @method.source_location.first
- file.should be_an_instance_of(String)
- file.should == File.realpath('../fixtures/classes.rb', __FILE__)
+ file.should.instance_of?(String)
+ file.should == File.realpath('fixtures/classes.rb', __dir__)
end
it "sets the last value to an Integer representing the line on which the method was defined" do
line = @method.source_location.last
- line.should be_an_instance_of(Integer)
+ line.should.instance_of?(Integer)
line.should == 5
end
@@ -92,7 +92,7 @@ describe "Method#source_location" do
loc.should == nil
else
loc[0].should.start_with?('<internal:')
- loc[1].should be_kind_of(Integer)
+ loc[1].should.is_a?(Integer)
end
loc = method(:tap).source_location
@@ -100,14 +100,21 @@ describe "Method#source_location" do
loc.should == nil
else
loc[0].should.start_with?('<internal:')
- loc[1].should be_kind_of(Integer)
+ loc[1].should.is_a?(Integer)
end
end
+ it "works for eval with a given line" do
+ c = Class.new do
+ eval('def self.m; end', nil, "foo", 100)
+ end
+ c.method(:m).source_location.should == ["foo", 100]
+ end
+
describe "for a Method generated by respond_to_missing?" do
it "returns nil" do
m = MethodSpecs::Methods.new
- m.method(:handled_via_method_missing).source_location.should be_nil
+ m.method(:handled_via_method_missing).source_location.should == nil
end
end
end
diff --git a/spec/ruby/core/method/super_method_spec.rb b/spec/ruby/core/method/super_method_spec.rb
index e5d8b87a06..c63a7aaa0f 100644
--- a/spec/ruby/core/method/super_method_spec.rb
+++ b/spec/ruby/core/method/super_method_spec.rb
@@ -42,4 +42,23 @@ describe "Method#super_method" do
method.super_method.should == nil
end
+
+ # https://github.com/jruby/jruby/issues/7240
+ context "after changing an inherited methods visibility" do
+ it "calls the proper super method" do
+ MethodSpecs::InheritedMethods::C.new.derp.should == 'BA'
+ end
+
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.new.method(:derp)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
+
+ context "after aliasing an inherited method" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.new.method(:meow)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
end
diff --git a/spec/ruby/core/method/to_proc_spec.rb b/spec/ruby/core/method/to_proc_spec.rb
index 29b7bec2b3..4993cce239 100644
--- a/spec/ruby/core/method/to_proc_spec.rb
+++ b/spec/ruby/core/method/to_proc_spec.rb
@@ -35,7 +35,7 @@ describe "Method#to_proc" do
end
it "returns a proc that can be used by define_method" do
- x = 'test'
+ x = +'test'
to_s = class << x
define_method :foo, method(:to_s).to_proc
to_s
diff --git a/spec/ruby/core/method/to_s_spec.rb b/spec/ruby/core/method/to_s_spec.rb
index 9f19011302..ba0b4fa3c6 100644
--- a/spec/ruby/core/method/to_s_spec.rb
+++ b/spec/ruby/core/method/to_s_spec.rb
@@ -1,6 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/to_s'
+require_relative 'shared/aliased_inspect'
describe "Method#to_s" do
it_behaves_like :method_to_s, :to_s
+ it_behaves_like :method_to_s_aliased, :to_s, -> meth { meth }
end
diff --git a/spec/ruby/core/method/unbind_spec.rb b/spec/ruby/core/method/unbind_spec.rb
index cdd3a808f2..994c3a8879 100644
--- a/spec/ruby/core/method/unbind_spec.rb
+++ b/spec/ruby/core/method/unbind_spec.rb
@@ -11,7 +11,7 @@ describe "Method#unbind" do
end
it "returns an UnboundMethod" do
- @normal_um.should be_kind_of(UnboundMethod)
+ @normal_um.should.is_a?(UnboundMethod)
end
describe "#inspect" do
@@ -28,7 +28,7 @@ describe "Method#unbind" do
end
it "returns a String containing the Module the method is referenced from" do
- @string.should =~ /MethodSpecs::MySub/
+ @string.should =~ /MethodSpecs::MyMod/
end
end
diff --git a/spec/ruby/core/module/alias_method_spec.rb b/spec/ruby/core/module/alias_method_spec.rb
index 5d3d0c23d9..852879cc8a 100644
--- a/spec/ruby/core/module/alias_method_spec.rb
+++ b/spec/ruby/core/module/alias_method_spec.rb
@@ -28,12 +28,12 @@ describe "Module#alias_method" do
it "retains method visibility" do
@class.make_alias :private_ichi, :private_one
- -> { @object.private_one }.should raise_error(NameError)
- -> { @object.private_ichi }.should raise_error(NameError)
+ -> { @object.private_one }.should.raise(NameError)
+ -> { @object.private_ichi }.should.raise(NameError)
@class.make_alias :public_ichi, :public_one
@object.public_ichi.should == @object.public_one
@class.make_alias :protected_ichi, :protected_one
- -> { @object.protected_ichi }.should raise_error(NameError)
+ -> { @object.protected_ichi }.should.raise(NameError)
end
it "handles aliasing a stub that changes visibility" do
@@ -55,7 +55,7 @@ describe "Module#alias_method" do
end
it "fails if origin method not found" do
- -> { @class.make_alias :ni, :san }.should raise_error(NameError) { |e|
+ -> { @class.make_alias :ni, :san }.should.raise(NameError) { |e|
# a NameError and not a NoMethodError
e.class.should == NameError
}
@@ -63,7 +63,7 @@ describe "Module#alias_method" do
it "raises FrozenError if frozen" do
@class.freeze
- -> { @class.make_alias :uno, :public_one }.should raise_error(FrozenError)
+ -> { @class.make_alias :uno, :public_one }.should.raise(FrozenError)
end
it "converts the names using #to_str" do
@@ -78,25 +78,23 @@ describe "Module#alias_method" do
end
it "raises a TypeError when the given name can't be converted using to_str" do
- -> { @class.make_alias mock('x'), :public_one }.should raise_error(TypeError)
+ -> { @class.make_alias mock('x'), :public_one }.should.raise(TypeError)
+ end
+
+ it "raises a NoMethodError if the given name raises a NoMethodError during type coercion using to_str" do
+ obj = mock("mock-name")
+ obj.should_receive(:to_str).and_raise(NoMethodError)
+ -> { @class.make_alias obj, :public_one }.should.raise(NoMethodError)
end
it "is a public method" do
- Module.should have_public_instance_method(:alias_method, false)
+ Module.public_instance_methods(false).should.include?(:alias_method)
end
describe "returned value" do
- ruby_version_is ""..."3.0" do
- it "returns self" do
- @class.send(:alias_method, :checking_return_value, :public_one).should equal(@class)
- end
- end
-
- ruby_version_is "3.0" do
- it "returns symbol of the defined method name" do
- @class.send(:alias_method, :checking_return_value, :public_one).should equal(:checking_return_value)
- @class.send(:alias_method, 'checking_return_value', :public_one).should equal(:checking_return_value)
- end
+ it "returns symbol of the defined method name" do
+ @class.send(:alias_method, :checking_return_value, :public_one).should.equal?(:checking_return_value)
+ @class.send(:alias_method, 'checking_return_value', :public_one).should.equal?(:checking_return_value)
end
end
@@ -106,14 +104,14 @@ describe "Module#alias_method" do
it "works on private module methods in a module that has been reopened" do
ModuleSpecs::ReopeningModule.foo.should == true
- -> { ModuleSpecs::ReopeningModule.foo2 }.should_not raise_error(NoMethodError)
+ -> { ModuleSpecs::ReopeningModule.foo2 }.should_not.raise(NoMethodError)
end
it "accesses a method defined on Object from Kernel" do
- Kernel.should_not have_public_instance_method(:module_specs_public_method_on_object)
+ Kernel.public_instance_methods(true).should_not.include?(:module_specs_public_method_on_object)
- Kernel.should have_public_instance_method(:module_specs_alias_on_kernel)
- Object.should have_public_instance_method(:module_specs_alias_on_kernel)
+ Kernel.public_instance_methods(false).should.include?(:module_specs_alias_on_kernel)
+ Object.public_instance_methods(true).should.include?(:module_specs_alias_on_kernel)
end
it "can call a method with super aliased twice" do
@@ -132,42 +130,42 @@ describe "Module#alias_method" do
it "keeps initialize private when aliasing" do
@class.make_alias(:initialize, :public_one)
- @class.private_instance_methods.include?(:initialize).should be_true
+ @class.private_instance_methods.include?(:initialize).should == true
@subclass.make_alias(:initialize, :public_one)
- @subclass.private_instance_methods.include?(:initialize).should be_true
+ @subclass.private_instance_methods.include?(:initialize).should == true
end
it "keeps initialize_copy private when aliasing" do
@class.make_alias(:initialize_copy, :public_one)
- @class.private_instance_methods.include?(:initialize_copy).should be_true
+ @class.private_instance_methods.include?(:initialize_copy).should == true
@subclass.make_alias(:initialize_copy, :public_one)
- @subclass.private_instance_methods.include?(:initialize_copy).should be_true
+ @subclass.private_instance_methods.include?(:initialize_copy).should == true
end
it "keeps initialize_clone private when aliasing" do
@class.make_alias(:initialize_clone, :public_one)
- @class.private_instance_methods.include?(:initialize_clone).should be_true
+ @class.private_instance_methods.include?(:initialize_clone).should == true
@subclass.make_alias(:initialize_clone, :public_one)
- @subclass.private_instance_methods.include?(:initialize_clone).should be_true
+ @subclass.private_instance_methods.include?(:initialize_clone).should == true
end
it "keeps initialize_dup private when aliasing" do
@class.make_alias(:initialize_dup, :public_one)
- @class.private_instance_methods.include?(:initialize_dup).should be_true
+ @class.private_instance_methods.include?(:initialize_dup).should == true
@subclass.make_alias(:initialize_dup, :public_one)
- @subclass.private_instance_methods.include?(:initialize_dup).should be_true
+ @subclass.private_instance_methods.include?(:initialize_dup).should == true
end
it "keeps respond_to_missing? private when aliasing" do
@class.make_alias(:respond_to_missing?, :public_one)
- @class.private_instance_methods.include?(:respond_to_missing?).should be_true
+ @class.private_instance_methods.include?(:respond_to_missing?).should == true
@subclass.make_alias(:respond_to_missing?, :public_one)
- @subclass.private_instance_methods.include?(:respond_to_missing?).should be_true
+ @subclass.private_instance_methods.include?(:respond_to_missing?).should == true
end
end
end
diff --git a/spec/ruby/core/module/ancestors_spec.rb b/spec/ruby/core/module/ancestors_spec.rb
index 5e4c196206..f85884a4f3 100644
--- a/spec/ruby/core/module/ancestors_spec.rb
+++ b/spec/ruby/core/module/ancestors_spec.rb
@@ -7,27 +7,45 @@ describe "Module#ancestors" do
ModuleSpecs.ancestors.should == [ModuleSpecs]
ModuleSpecs::Basic.ancestors.should == [ModuleSpecs::Basic]
ModuleSpecs::Super.ancestors.should == [ModuleSpecs::Super, ModuleSpecs::Basic]
- ModuleSpecs.without_test_modules(ModuleSpecs::Parent.ancestors).should ==
- [ModuleSpecs::Parent, Object, Kernel, BasicObject]
- ModuleSpecs.without_test_modules(ModuleSpecs::Child.ancestors).should ==
- [ModuleSpecs::Child, ModuleSpecs::Super, ModuleSpecs::Basic, ModuleSpecs::Parent, Object, Kernel, BasicObject]
+ if defined?(Ruby::Box) && Ruby::Box.enabled?
+ ModuleSpecs.without_test_modules(ModuleSpecs::Parent.ancestors).should ==
+ [ModuleSpecs::Parent, Object, Ruby::Box::Loader, Kernel, BasicObject]
+ ModuleSpecs.without_test_modules(ModuleSpecs::Child.ancestors).should ==
+ [ModuleSpecs::Child, ModuleSpecs::Super, ModuleSpecs::Basic, ModuleSpecs::Parent, Object, Ruby::Box::Loader, Kernel, BasicObject]
+ else
+ ModuleSpecs.without_test_modules(ModuleSpecs::Parent.ancestors).should ==
+ [ModuleSpecs::Parent, Object, Kernel, BasicObject]
+ ModuleSpecs.without_test_modules(ModuleSpecs::Child.ancestors).should ==
+ [ModuleSpecs::Child, ModuleSpecs::Super, ModuleSpecs::Basic, ModuleSpecs::Parent, Object, Kernel, BasicObject]
+ end
end
it "returns only modules and classes" do
- class << ModuleSpecs::Child; self; end.ancestors.should include(ModuleSpecs::Internal, Class, Module, Object, Kernel)
+ class << ModuleSpecs::Child; self; end.ancestors.to_set.should >= Set[ModuleSpecs::Internal, Class, Module, Object, Kernel]
end
it "has 1 entry per module or class" do
ModuleSpecs::Parent.ancestors.should == ModuleSpecs::Parent.ancestors.uniq
end
+ it "returns a module that is included later into a nested module as well" do
+ m1 = Module.new
+ m2 = Module.new
+ m3 = Module.new do
+ include m2
+ end
+ m2.include m1 # should be after m3 includes m2
+
+ m3.ancestors.should == [m3, m2, m1]
+ end
+
describe "when called on a singleton class" do
it "includes the singleton classes of ancestors" do
parent = Class.new
child = Class.new(parent)
schild = child.singleton_class
- schild.ancestors.should include(schild,
+ schild.ancestors.to_set.should >= Set[schild,
parent.singleton_class,
Object.singleton_class,
BasicObject.singleton_class,
@@ -35,14 +53,14 @@ describe "Module#ancestors" do
Module,
Object,
Kernel,
- BasicObject)
+ BasicObject]
end
describe 'for a standalone module' do
it 'does not include Class' do
s_mod = ModuleSpecs.singleton_class
- s_mod.ancestors.should_not include(Class)
+ s_mod.ancestors.should_not.include?(Class)
end
it 'does not include other singleton classes' do
@@ -51,19 +69,19 @@ describe "Module#ancestors" do
s_object = Object.singleton_class
s_basic_object = BasicObject.singleton_class
- s_standalone_mod.ancestors.should_not include(s_module, s_object, s_basic_object)
+ (s_standalone_mod.ancestors & [s_module, s_object, s_basic_object]).should.empty?
end
it 'includes its own singleton class' do
s_mod = ModuleSpecs.singleton_class
- s_mod.ancestors.should include(s_mod)
+ s_mod.ancestors.should.include?(s_mod)
end
it 'includes standard chain' do
s_mod = ModuleSpecs.singleton_class
- s_mod.ancestors.should include(Module, Object, Kernel, BasicObject)
+ s_mod.ancestors.to_set.should >= Set[Module, Object, Kernel, BasicObject]
end
end
end
diff --git a/spec/ruby/core/module/append_features_spec.rb b/spec/ruby/core/module/append_features_spec.rb
index 1724cde5d6..4d2207330d 100644
--- a/spec/ruby/core/module/append_features_spec.rb
+++ b/spec/ruby/core/module/append_features_spec.rb
@@ -3,18 +3,18 @@ require_relative 'fixtures/classes'
describe "Module#append_features" do
it "is a private method" do
- Module.should have_private_instance_method(:append_features)
+ Module.private_instance_methods(false).should.include?(:append_features)
end
describe "on Class" do
it "is undefined" do
- Class.should_not have_private_instance_method(:append_features, true)
+ Class.private_instance_methods(true).should_not.include?(:append_features)
end
it "raises a TypeError if calling after rebinded to Class" do
-> {
Module.instance_method(:append_features).bind(Class.new).call Module.new
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
@@ -39,11 +39,11 @@ describe "Module#append_features" do
it "raises an ArgumentError on a cyclic include" do
-> {
ModuleSpecs::CyclicAppendA.send(:append_features, ModuleSpecs::CyclicAppendA)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
ModuleSpecs::CyclicAppendB.send(:append_features, ModuleSpecs::CyclicAppendA)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
@@ -54,8 +54,8 @@ describe "Module#append_features" do
end
it "raises a FrozenError before appending self" do
- -> { @receiver.send(:append_features, @other) }.should raise_error(FrozenError)
- @other.ancestors.should_not include(@receiver)
+ -> { @receiver.send(:append_features, @other) }.should.raise(FrozenError)
+ @other.ancestors.should_not.include?(@receiver)
end
end
end
diff --git a/spec/ruby/core/module/attr_accessor_spec.rb b/spec/ruby/core/module/attr_accessor_spec.rb
index ba5289cbea..a608760cf2 100644
--- a/spec/ruby/core/module/attr_accessor_spec.rb
+++ b/spec/ruby/core/module/attr_accessor_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/attr_added'
describe "Module#attr_accessor" do
it "creates a getter and setter for each given attribute name" do
@@ -33,7 +34,7 @@ describe "Module#attr_accessor" do
attr_accessor :spec_attr_accessor
end
- -> { true.spec_attr_accessor = "a" }.should raise_error(FrozenError)
+ -> { true.spec_attr_accessor = "a" }.should.raise(FrozenError)
end
it "raises FrozenError if the receiver if frozen" do
@@ -45,7 +46,7 @@ describe "Module#attr_accessor" do
obj.foo.should == 1
obj.freeze
- -> { obj.foo = 42 }.should raise_error(FrozenError)
+ -> { obj.foo = 42 }.should.raise(FrozenError)
obj.foo.should == 1
end
@@ -61,9 +62,9 @@ describe "Module#attr_accessor" do
it "raises a TypeError when the given names can't be converted to strings using to_str" do
o = mock('o')
- -> { Class.new { attr_accessor o } }.should raise_error(TypeError)
+ -> { Class.new { attr_accessor o } }.should.raise(TypeError)
(o = mock('123')).should_receive(:to_str).and_return(123)
- -> { Class.new { attr_accessor o } }.should raise_error(TypeError)
+ -> { Class.new { attr_accessor o } }.should.raise(TypeError)
end
it "applies current visibility to methods created" do
@@ -72,27 +73,17 @@ describe "Module#attr_accessor" do
attr_accessor :foo
end
- -> { c.new.foo }.should raise_error(NoMethodError)
- -> { c.new.foo=1 }.should raise_error(NoMethodError)
+ -> { c.new.foo }.should.raise(NoMethodError)
+ -> { c.new.foo=1 }.should.raise(NoMethodError)
end
it "is a public method" do
- Module.should have_public_instance_method(:attr_accessor, false)
+ Module.public_instance_methods(false).should.include?(:attr_accessor)
end
- ruby_version_is ""..."3.0" do
- it "returns nil" do
- Class.new do
- (attr_accessor :foo, 'bar').should == nil
- end
- end
- end
-
- ruby_version_is "3.0" do
- it "returns an array of defined method names as symbols" do
- Class.new do
- (attr_accessor :foo, 'bar').should == [:foo, :foo=, :bar, :bar=]
- end
+ it "returns an array of defined method names as symbols" do
+ Class.new do
+ (attr_accessor :foo, 'bar').should == [:foo, :foo=, :bar, :bar=]
end
end
@@ -113,7 +104,9 @@ describe "Module#attr_accessor" do
end
it "can read through the accessor" do
- 1.foobar.should be_nil
+ 1.foobar.should == nil
end
end
+
+ it_behaves_like :module_attr_added, :attr_accessor
end
diff --git a/spec/ruby/core/module/attr_reader_spec.rb b/spec/ruby/core/module/attr_reader_spec.rb
index b0ae906ab5..2b4ca2100e 100644
--- a/spec/ruby/core/module/attr_reader_spec.rb
+++ b/spec/ruby/core/module/attr_reader_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/attr_added'
describe "Module#attr_reader" do
it "creates a getter for each given attribute name" do
@@ -29,7 +30,7 @@ describe "Module#attr_reader" do
attr_reader :spec_attr_reader
end
- -> { true.instance_variable_set("@spec_attr_reader", "a") }.should raise_error(RuntimeError)
+ -> { true.instance_variable_set("@spec_attr_reader", "a") }.should.raise(RuntimeError)
end
it "converts non string/symbol names to strings using to_str" do
@@ -44,9 +45,9 @@ describe "Module#attr_reader" do
it "raises a TypeError when the given names can't be converted to strings using to_str" do
o = mock('o')
- -> { Class.new { attr_reader o } }.should raise_error(TypeError)
+ -> { Class.new { attr_reader o } }.should.raise(TypeError)
(o = mock('123')).should_receive(:to_str).and_return(123)
- -> { Class.new { attr_reader o } }.should raise_error(TypeError)
+ -> { Class.new { attr_reader o } }.should.raise(TypeError)
end
it "applies current visibility to methods created" do
@@ -55,26 +56,18 @@ describe "Module#attr_reader" do
attr_reader :foo
end
- -> { c.new.foo }.should raise_error(NoMethodError)
+ -> { c.new.foo }.should.raise(NoMethodError)
end
it "is a public method" do
- Module.should have_public_instance_method(:attr_reader, false)
+ Module.public_instance_methods(false).should.include?(:attr_reader)
end
- ruby_version_is ""..."3.0" do
- it "returns nil" do
- Class.new do
- (attr_reader :foo, 'bar').should == nil
- end
+ it "returns an array of defined method names as symbols" do
+ Class.new do
+ (attr_reader :foo, 'bar').should == [:foo, :bar]
end
end
- ruby_version_is "3.0" do
- it "returns an array of defined method names as symbols" do
- Class.new do
- (attr_reader :foo, 'bar').should == [:foo, :bar]
- end
- end
- end
+ it_behaves_like :module_attr_added, :attr_reader
end
diff --git a/spec/ruby/core/module/attr_spec.rb b/spec/ruby/core/module/attr_spec.rb
index 33e0eb8628..d696864955 100644
--- a/spec/ruby/core/module/attr_spec.rb
+++ b/spec/ruby/core/module/attr_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/attr_added'
describe "Module#attr" do
before :each do
@@ -89,8 +90,8 @@ describe "Module#attr" do
attr :foo, true
end
- -> { c.new.foo }.should raise_error(NoMethodError)
- -> { c.new.foo=1 }.should raise_error(NoMethodError)
+ -> { c.new.foo }.should.raise(NoMethodError)
+ -> { c.new.foo=1 }.should.raise(NoMethodError)
end
it "creates a getter but no setter for all given attribute names" do
@@ -120,8 +121,8 @@ describe "Module#attr" do
attr :foo, :bar
end
- -> { c.new.foo }.should raise_error(NoMethodError)
- -> { c.new.bar }.should raise_error(NoMethodError)
+ -> { c.new.foo }.should.raise(NoMethodError)
+ -> { c.new.bar }.should.raise(NoMethodError)
end
it "converts non string/symbol names to strings using to_str" do
@@ -131,9 +132,9 @@ describe "Module#attr" do
it "raises a TypeError when the given names can't be converted to strings using to_str" do
o = mock('o')
- -> { Class.new { attr o } }.should raise_error(TypeError)
+ -> { Class.new { attr o } }.should.raise(TypeError)
(o = mock('123')).should_receive(:to_str).and_return(123)
- -> { Class.new { attr o } }.should raise_error(TypeError)
+ -> { Class.new { attr o } }.should.raise(TypeError)
end
it "with a boolean argument emits a warning when $VERBOSE is true" do
@@ -143,26 +144,16 @@ describe "Module#attr" do
end
it "is a public method" do
- Module.should have_public_instance_method(:attr, false)
+ Module.public_instance_methods(false).should.include?(:attr)
end
- ruby_version_is ""..."3.0" do
- it "returns nil" do
- Class.new do
- (attr :foo, 'bar').should == nil
- (attr :baz, false).should == nil
- (attr :qux, true).should == nil
- end
+ it "returns an array of defined method names as symbols" do
+ Class.new do
+ (attr :foo, 'bar').should == [:foo, :bar]
+ (attr :baz, false).should == [:baz]
+ (attr :qux, true).should == [:qux, :qux=]
end
end
- ruby_version_is "3.0" do
- it "returns an array of defined method names as symbols" do
- Class.new do
- (attr :foo, 'bar').should == [:foo, :bar]
- (attr :baz, false).should == [:baz]
- (attr :qux, true).should == [:qux, :qux=]
- end
- end
- end
+ it_behaves_like :module_attr_added, :attr
end
diff --git a/spec/ruby/core/module/attr_writer_spec.rb b/spec/ruby/core/module/attr_writer_spec.rb
index 0e9d201317..6089b52495 100644
--- a/spec/ruby/core/module/attr_writer_spec.rb
+++ b/spec/ruby/core/module/attr_writer_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/attr_added'
describe "Module#attr_writer" do
it "creates a setter for each given attribute name" do
@@ -29,7 +30,7 @@ describe "Module#attr_writer" do
attr_writer :spec_attr_writer
end
- -> { true.spec_attr_writer = "a" }.should raise_error(FrozenError)
+ -> { true.spec_attr_writer = "a" }.should.raise(FrozenError)
end
it "raises FrozenError if the receiver if frozen" do
@@ -39,7 +40,7 @@ describe "Module#attr_writer" do
obj = c.new
obj.freeze
- -> { obj.foo = 42 }.should raise_error(FrozenError)
+ -> { obj.foo = 42 }.should.raise(FrozenError)
end
it "converts non string/symbol names to strings using to_str" do
@@ -54,9 +55,9 @@ describe "Module#attr_writer" do
it "raises a TypeError when the given names can't be converted to strings using to_str" do
o = mock('test1')
- -> { Class.new { attr_writer o } }.should raise_error(TypeError)
+ -> { Class.new { attr_writer o } }.should.raise(TypeError)
(o = mock('123')).should_receive(:to_str).and_return(123)
- -> { Class.new { attr_writer o } }.should raise_error(TypeError)
+ -> { Class.new { attr_writer o } }.should.raise(TypeError)
end
it "applies current visibility to methods created" do
@@ -65,26 +66,18 @@ describe "Module#attr_writer" do
attr_writer :foo
end
- -> { c.new.foo=1 }.should raise_error(NoMethodError)
+ -> { c.new.foo=1 }.should.raise(NoMethodError)
end
it "is a public method" do
- Module.should have_public_instance_method(:attr_writer, false)
+ Module.public_instance_methods(false).should.include?(:attr_writer)
end
- ruby_version_is ""..."3.0" do
- it "returns nil" do
- Class.new do
- (attr_writer :foo, 'bar').should == nil
- end
+ it "returns an array of defined method names as symbols" do
+ Class.new do
+ (attr_writer :foo, 'bar').should == [:foo=, :bar=]
end
end
- ruby_version_is "3.0" do
- it "returns an array of defined method names as symbols" do
- Class.new do
- (attr_writer :foo, 'bar').should == [:foo=, :bar=]
- end
- end
- end
+ it_behaves_like :module_attr_added, :attr_writer
end
diff --git a/spec/ruby/core/module/autoload_relative_spec.rb b/spec/ruby/core/module/autoload_relative_spec.rb
new file mode 100644
index 0000000000..2e7d85496b
--- /dev/null
+++ b/spec/ruby/core/module/autoload_relative_spec.rb
@@ -0,0 +1,128 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+# Specs for Module#autoload_relative
+module ModuleSpecs
+ module AutoloadRelative
+ # Will be used for testing
+ end
+end
+
+ruby_version_is "4.1" do
+ describe "Module#autoload_relative" do
+ before :each do
+ @loaded_features = $".dup
+ end
+
+ after :each do
+ $".replace @loaded_features
+ end
+
+ it "is a public method" do
+ Module.public_instance_methods(false).should.include?(:autoload_relative)
+ end
+
+ it "registers a file to load relative to the current file the first time the named constant is accessed" do
+ ModuleSpecs::Autoload.autoload_relative :AutoloadRelativeA, "fixtures/autoload_relative_a.rb"
+ path = ModuleSpecs::Autoload.autoload?(:AutoloadRelativeA)
+ path.should_not == nil
+ path.should.end_with?("autoload_relative_a.rb")
+ File.exist?(path).should == true
+ end
+
+ it "loads the registered file when the constant is accessed" do
+ ModuleSpecs::Autoload.autoload_relative :AutoloadRelativeB, "fixtures/autoload_relative_a.rb"
+ ModuleSpecs::Autoload::AutoloadRelativeB.should.is_a?(Module)
+ end
+
+ it "returns nil" do
+ ModuleSpecs::Autoload.autoload_relative(:AutoloadRelativeC, "fixtures/autoload_relative_a.rb").should == nil
+ end
+
+ it "registers a file to load the first time the named constant is accessed" do
+ module ModuleSpecs::Autoload::AutoloadRelativeTest
+ autoload_relative :D, "fixtures/autoload_relative_a.rb"
+ end
+ path = ModuleSpecs::Autoload::AutoloadRelativeTest.autoload?(:D)
+ path.should_not == nil
+ path.should.end_with?("autoload_relative_a.rb")
+ end
+
+ it "sets the autoload constant in the constants table" do
+ ModuleSpecs::Autoload.autoload_relative :AutoloadRelativeTableTest, "fixtures/autoload_relative_a.rb"
+ ModuleSpecs::Autoload.should.const_defined?(:AutoloadRelativeTableTest, false)
+ end
+
+ it "calls #to_path on non-String filenames" do
+ name = mock("autoload_relative mock")
+ name.should_receive(:to_path).and_return("fixtures/autoload_relative_a.rb")
+ ModuleSpecs::Autoload.autoload_relative :AutoloadRelativeToPath, name
+ ModuleSpecs::Autoload.autoload?(:AutoloadRelativeToPath).should_not == nil
+ end
+
+ it "calls #to_str on non-String filenames" do
+ name = mock("autoload_relative mock")
+ name.should_receive(:to_str).and_return("fixtures/autoload_relative_a.rb")
+ ModuleSpecs::Autoload.autoload_relative :AutoloadRelativeToStr, name
+ ModuleSpecs::Autoload.autoload?(:AutoloadRelativeToStr).should_not == nil
+ end
+
+ it "raises a TypeError if the filename argument is not a String or pathname" do
+ -> {
+ ModuleSpecs::Autoload.autoload_relative :AutoloadRelativeTypError, nil
+ }.should.raise(TypeError)
+ end
+
+ it "raises a NameError if the constant name is not valid" do
+ -> {
+ ModuleSpecs::Autoload.autoload_relative :invalid_name, "fixtures/autoload_relative_a.rb"
+ }.should.raise(NameError)
+ end
+
+ it "raises an ArgumentError if the constant name starts with a lowercase letter" do
+ -> {
+ ModuleSpecs::Autoload.autoload_relative :autoload, "fixtures/autoload_relative_a.rb"
+ }.should.raise(NameError)
+ end
+
+ it "raises LoadError if called from eval without file context" do
+ -> {
+ ModuleSpecs::Autoload.module_eval('autoload_relative :EvalTest, "fixtures/autoload_relative_a.rb"')
+ }.should.raise(LoadError, /autoload_relative called without file context/)
+ end
+
+ it "can autoload in instance_eval with a file context" do
+ path = nil
+ ModuleSpecs::Autoload.instance_eval(<<-CODE, __FILE__, __LINE__)
+ autoload_relative :InstanceEvalTest, "fixtures/autoload_relative_a.rb"
+ path = autoload?(:InstanceEvalTest)
+ CODE
+ path.should_not == nil
+ path.should.end_with?("autoload_relative_a.rb")
+ end
+
+ it "resolves paths relative to the file where it's called" do
+ # Using fixtures/autoload_relative_a.rb which exists
+ ModuleSpecs::Autoload.autoload_relative :RelativePathTest, "fixtures/autoload_relative_a.rb"
+ path = ModuleSpecs::Autoload.autoload?(:RelativePathTest)
+ path.should.include?("fixtures")
+ path.should.end_with?("autoload_relative_a.rb")
+ end
+
+ it "can load nested directory paths" do
+ ModuleSpecs::Autoload.autoload_relative :NestedPath, "fixtures/autoload_relative_a.rb"
+ path = ModuleSpecs::Autoload.autoload?(:NestedPath)
+ path.should_not == nil
+ File.exist?(path).should == true
+ end
+
+ describe "interoperability with autoload?" do
+ it "returns the absolute path with autoload?" do
+ ModuleSpecs::Autoload.autoload_relative :QueryTest, "fixtures/autoload_relative_a.rb"
+ path = ModuleSpecs::Autoload.autoload?(:QueryTest)
+ # Should be an absolute path
+ Pathname.new(path).absolute?.should == true
+ end
+ end
+end
+end
diff --git a/spec/ruby/core/module/autoload_spec.rb b/spec/ruby/core/module/autoload_spec.rb
index af04ab26c8..057237a92f 100644
--- a/spec/ruby/core/module/autoload_spec.rb
+++ b/spec/ruby/core/module/autoload_spec.rb
@@ -1,7 +1,6 @@
require_relative '../../spec_helper'
require_relative '../../fixtures/code_loading'
require_relative 'fixtures/classes'
-require 'thread'
describe "Module#autoload?" do
it "returns the name of the file that will be autoloaded" do
@@ -10,7 +9,7 @@ describe "Module#autoload?" do
end
it "returns nil if no file has been registered for a constant" do
- ModuleSpecs::Autoload.autoload?(:Manualload).should be_nil
+ ModuleSpecs::Autoload.autoload?(:Manualload).should == nil
end
it "returns the name of the file that will be autoloaded if an ancestor defined that autoload" do
@@ -20,7 +19,7 @@ describe "Module#autoload?" do
it "returns nil if an ancestor defined that autoload but recursion is disabled" do
ModuleSpecs::Autoload::Parent.autoload :InheritedAutoload, "inherited_autoload.rb"
- ModuleSpecs::Autoload::Child.autoload?(:InheritedAutoload, false).should be_nil
+ ModuleSpecs::Autoload::Child.autoload?(:InheritedAutoload, false).should == nil
end
it "returns the name of the file that will be loaded if recursion is disabled but the autoload is defined on the class itself" do
@@ -56,7 +55,7 @@ describe "Module#autoload" do
it "sets the autoload constant in the constants table" do
ModuleSpecs::Autoload.autoload :B, @non_existent
- ModuleSpecs::Autoload.should have_constant(:B)
+ ModuleSpecs::Autoload.should.const_defined?(:B, false)
end
it "can be overridden with a second autoload on the same constant" do
@@ -72,7 +71,7 @@ describe "Module#autoload" do
end
it "loads the registered constant when it is accessed" do
- ModuleSpecs::Autoload.should_not have_constant(:X)
+ ModuleSpecs::Autoload.should_not.const_defined?(:X)
ModuleSpecs::Autoload.autoload :X, fixture(__FILE__, "autoload_x.rb")
@remove << :X
ModuleSpecs::Autoload::X.should == :x
@@ -83,7 +82,7 @@ describe "Module#autoload" do
ModuleSpecs::Autoload::DynClass = cls
@remove << :DynClass
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
ModuleSpecs::Autoload::DynClass::C.new.loaded.should == :dynclass_c
ScratchPad.recorded.should == :loaded
end
@@ -93,7 +92,7 @@ describe "Module#autoload" do
ModuleSpecs::Autoload::DynModule = mod
@remove << :DynModule
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
ModuleSpecs::Autoload::DynModule::D.new.loaded.should == :dynmodule_d
ScratchPad.recorded.should == :loaded
end
@@ -132,7 +131,7 @@ describe "Module#autoload" do
@remove << :I
ModuleSpecs::Autoload.const_set :I, 3
ModuleSpecs::Autoload::I.should == 3
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
it "loads a file with .rb extension when passed the name without the extension" do
@@ -145,7 +144,7 @@ describe "Module#autoload" do
main = TOPLEVEL_BINDING.eval("self")
main.should_receive(:require).with("module_autoload_not_exist.rb")
# The constant won't be defined since require is mocked to do nothing
- -> { ModuleSpecs::Autoload::ModuleAutoloadCallsRequire }.should raise_error(NameError)
+ -> { ModuleSpecs::Autoload::ModuleAutoloadCallsRequire }.should.raise(NameError)
end
it "does not load the file if the file is manually required" do
@@ -157,9 +156,9 @@ describe "Module#autoload" do
ScratchPad.recorded.should == :loaded
ScratchPad.clear
- ModuleSpecs::Autoload::KHash.should be_kind_of(Class)
+ ModuleSpecs::Autoload::KHash.should.is_a?(Class)
ModuleSpecs::Autoload::KHash::K.should == :autoload_k
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
it "ignores the autoload request if the file is already loaded" do
@@ -172,7 +171,7 @@ describe "Module#autoload" do
ModuleSpecs::Autoload.autoload :S, filename
@remove << :S
- ModuleSpecs::Autoload.autoload?(:S).should be_nil
+ ModuleSpecs::Autoload.autoload?(:S).should == nil
end
it "retains the autoload even if the request to require fails" do
@@ -183,7 +182,7 @@ describe "Module#autoload" do
-> {
require filename
- }.should raise_error(LoadError)
+ }.should.raise(LoadError)
ModuleSpecs::Autoload.autoload?(:NotThere).should == filename
end
@@ -206,7 +205,7 @@ describe "Module#autoload" do
filename = fixture(__FILE__, "autoload_during_require_current_file.rb")
require filename
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
describe "interacting with defined?" do
@@ -216,9 +215,9 @@ describe "Module#autoload" do
end
defined?(ModuleSpecs::Autoload::Dog::R).should == "constant"
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
- ModuleSpecs::Autoload::Dog.should have_constant(:R)
+ ModuleSpecs::Autoload::Dog.should.const_defined?(:R, false)
end
it "loads an autoloaded parent when referencing a nested constant" do
@@ -236,7 +235,7 @@ describe "Module#autoload" do
autoload :BadParent, fixture(__FILE__, "autoload_exception.rb")
end
- defined?(ModuleSpecs::Autoload::BadParent::Nested).should be_nil
+ defined?(ModuleSpecs::Autoload::BadParent::Nested).should == nil
ScratchPad.recorded.should == :exception
end
end
@@ -343,6 +342,29 @@ describe "Module#autoload" do
end
end
+ def check_before_during_thread_after(const, &check)
+ before = check.call
+ to_autoload_thread, from_autoload_thread = Queue.new, Queue.new
+ ScratchPad.record -> {
+ from_autoload_thread.push check.call
+ to_autoload_thread.pop
+ }
+ t = Thread.new {
+ in_loading_thread = from_autoload_thread.pop
+ in_other_thread = check.call
+ to_autoload_thread.push :done
+ [in_loading_thread, in_other_thread]
+ }
+ in_loading_thread, in_other_thread = nil
+ begin
+ ModuleSpecs::Autoload.const_get(const)
+ ensure
+ in_loading_thread, in_other_thread = t.value
+ end
+ after = check.call
+ [before, in_loading_thread, in_other_thread, after]
+ end
+
describe "during the autoload before the constant is assigned" do
before :each do
@path = fixture(__FILE__, "autoload_during_autoload.rb")
@@ -351,72 +373,97 @@ describe "Module#autoload" do
raise unless ModuleSpecs::Autoload.autoload?(:DuringAutoload) == @path
end
- def check_before_during_thread_after(&check)
- before = check.call
- to_autoload_thread, from_autoload_thread = Queue.new, Queue.new
- ScratchPad.record -> {
- from_autoload_thread.push check.call
- to_autoload_thread.pop
- }
- t = Thread.new {
- in_loading_thread = from_autoload_thread.pop
- in_other_thread = check.call
- to_autoload_thread.push :done
- [in_loading_thread, in_other_thread]
- }
- in_loading_thread, in_other_thread = nil
- begin
- ModuleSpecs::Autoload::DuringAutoload
- ensure
- in_loading_thread, in_other_thread = t.value
- end
- after = check.call
- [before, in_loading_thread, in_other_thread, after]
- end
-
it "returns nil in autoload thread and 'constant' otherwise for defined?" do
- results = check_before_during_thread_after {
+ results = check_before_during_thread_after(:DuringAutoload) {
defined?(ModuleSpecs::Autoload::DuringAutoload)
}
results.should == ['constant', nil, 'constant', 'constant']
end
it "keeps the constant in Module#constants" do
- results = check_before_during_thread_after {
+ results = check_before_during_thread_after(:DuringAutoload) {
ModuleSpecs::Autoload.constants(false).include?(:DuringAutoload)
}
results.should == [true, true, true, true]
end
it "returns false in autoload thread and true otherwise for Module#const_defined?" do
- results = check_before_during_thread_after {
+ results = check_before_during_thread_after(:DuringAutoload) {
ModuleSpecs::Autoload.const_defined?(:DuringAutoload, false)
}
results.should == [true, false, true, true]
end
it "returns nil in autoload thread and returns the path in other threads for Module#autoload?" do
- results = check_before_during_thread_after {
+ results = check_before_during_thread_after(:DuringAutoload) {
ModuleSpecs::Autoload.autoload?(:DuringAutoload)
}
results.should == [@path, nil, @path, nil]
end
end
+ describe "during the autoload after the constant is assigned" do
+ before :each do
+ @path = fixture(__FILE__, "autoload_during_autoload_after_define.rb")
+ ModuleSpecs::Autoload.autoload :DuringAutoloadAfterDefine, @path
+ @autoload_location = [__FILE__, __LINE__ - 1]
+ @const_location = [@path, 2]
+ @remove << :DuringAutoloadAfterDefine
+ raise unless ModuleSpecs::Autoload.autoload?(:DuringAutoloadAfterDefine) == @path
+ end
+
+ it "returns 'constant' in both threads" do
+ results = check_before_during_thread_after(:DuringAutoloadAfterDefine) {
+ defined?(ModuleSpecs::Autoload::DuringAutoloadAfterDefine)
+ }
+ results.should == ['constant', 'constant', 'constant', 'constant']
+ end
+
+ it "Module#constants include the autoloaded in both threads" do
+ results = check_before_during_thread_after(:DuringAutoloadAfterDefine) {
+ ModuleSpecs::Autoload.constants(false).include?(:DuringAutoloadAfterDefine)
+ }
+ results.should == [true, true, true, true]
+ end
+
+ it "Module#const_defined? returns true in both threads" do
+ results = check_before_during_thread_after(:DuringAutoloadAfterDefine) {
+ ModuleSpecs::Autoload.const_defined?(:DuringAutoloadAfterDefine, false)
+ }
+ results.should == [true, true, true, true]
+ end
+
+ it "returns nil in autoload thread and returns the path in other threads for Module#autoload?" do
+ results = check_before_during_thread_after(:DuringAutoloadAfterDefine) {
+ ModuleSpecs::Autoload.autoload?(:DuringAutoloadAfterDefine)
+ }
+ results.should == [@path, nil, @path, nil]
+ end
+
+ ruby_bug("#20188", ""..."3.4") do
+ it "returns the real constant location in autoload thread and returns the autoload location in other threads for Module#const_source_location" do
+ results = check_before_during_thread_after(:DuringAutoloadAfterDefine) {
+ ModuleSpecs::Autoload.const_source_location(:DuringAutoloadAfterDefine)
+ }
+ results.should == [@autoload_location, @const_location, @autoload_location, @const_location]
+ end
+ end
+ end
+
it "does not remove the constant from Module#constants if load fails and keeps it as an autoload" do
ModuleSpecs::Autoload.autoload :Fail, @non_existent
ModuleSpecs::Autoload.const_defined?(:Fail).should == true
- ModuleSpecs::Autoload.should have_constant(:Fail)
+ ModuleSpecs::Autoload.should.const_defined?(:Fail, false)
ModuleSpecs::Autoload.autoload?(:Fail).should == @non_existent
- -> { ModuleSpecs::Autoload::Fail }.should raise_error(LoadError)
+ -> { ModuleSpecs::Autoload::Fail }.should.raise(LoadError)
- ModuleSpecs::Autoload.should have_constant(:Fail)
+ ModuleSpecs::Autoload.should.const_defined?(:Fail, false)
ModuleSpecs::Autoload.const_defined?(:Fail).should == true
ModuleSpecs::Autoload.autoload?(:Fail).should == @non_existent
- -> { ModuleSpecs::Autoload::Fail }.should raise_error(LoadError)
+ -> { ModuleSpecs::Autoload::Fail }.should.raise(LoadError)
end
it "does not remove the constant from Module#constants if load raises a RuntimeError and keeps it as an autoload" do
@@ -425,56 +472,35 @@ describe "Module#autoload" do
ModuleSpecs::Autoload.autoload :Raise, path
ModuleSpecs::Autoload.const_defined?(:Raise).should == true
- ModuleSpecs::Autoload.should have_constant(:Raise)
+ ModuleSpecs::Autoload.should.const_defined?(:Raise, false)
ModuleSpecs::Autoload.autoload?(:Raise).should == path
- -> { ModuleSpecs::Autoload::Raise }.should raise_error(RuntimeError)
+ -> { ModuleSpecs::Autoload::Raise }.should.raise(RuntimeError)
ScratchPad.recorded.should == [:raise]
- ModuleSpecs::Autoload.should have_constant(:Raise)
+ ModuleSpecs::Autoload.should.const_defined?(:Raise, false)
ModuleSpecs::Autoload.const_defined?(:Raise).should == true
ModuleSpecs::Autoload.autoload?(:Raise).should == path
- -> { ModuleSpecs::Autoload::Raise }.should raise_error(RuntimeError)
+ -> { ModuleSpecs::Autoload::Raise }.should.raise(RuntimeError)
ScratchPad.recorded.should == [:raise, :raise]
end
- ruby_version_is "3.1" do
- it "removes the constant from Module#constants if the loaded file does not define it" do
- path = fixture(__FILE__, "autoload_o.rb")
- ScratchPad.record []
- ModuleSpecs::Autoload.autoload :O, path
-
- ModuleSpecs::Autoload.const_defined?(:O).should == true
- ModuleSpecs::Autoload.should have_constant(:O)
- ModuleSpecs::Autoload.autoload?(:O).should == path
-
- -> { ModuleSpecs::Autoload::O }.should raise_error(NameError)
-
- ModuleSpecs::Autoload.const_defined?(:O).should == false
- ModuleSpecs::Autoload.should_not have_constant(:O)
- ModuleSpecs::Autoload.autoload?(:O).should == nil
- -> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError)
- end
- end
-
- ruby_version_is ""..."3.1" do
- it "does not remove the constant from Module#constants if the loaded file does not define it, but leaves it as 'undefined'" do
- path = fixture(__FILE__, "autoload_o.rb")
- ScratchPad.record []
- ModuleSpecs::Autoload.autoload :O, path
+ it "removes the constant from Module#constants if the loaded file does not define it" do
+ path = fixture(__FILE__, "autoload_o.rb")
+ ScratchPad.record []
+ ModuleSpecs::Autoload.autoload :O, path
- ModuleSpecs::Autoload.const_defined?(:O).should == true
- ModuleSpecs::Autoload.should have_constant(:O)
- ModuleSpecs::Autoload.autoload?(:O).should == path
+ ModuleSpecs::Autoload.const_defined?(:O).should == true
+ ModuleSpecs::Autoload.should.const_defined?(:O, false)
+ ModuleSpecs::Autoload.autoload?(:O).should == path
- -> { ModuleSpecs::Autoload::O }.should raise_error(NameError)
+ -> { ModuleSpecs::Autoload::O }.should.raise(NameError)
- ModuleSpecs::Autoload.const_defined?(:O).should == false
- ModuleSpecs::Autoload.should have_constant(:O)
- ModuleSpecs::Autoload.autoload?(:O).should == nil
- -> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError)
- end
+ ModuleSpecs::Autoload.const_defined?(:O).should == false
+ ModuleSpecs::Autoload.should_not.const_defined?(:O)
+ ModuleSpecs::Autoload.autoload?(:O).should == nil
+ -> { ModuleSpecs::Autoload.const_get(:O) }.should.raise(NameError)
end
it "does not try to load the file again if the loaded file did not define the constant" do
@@ -482,13 +508,13 @@ describe "Module#autoload" do
ScratchPad.record []
ModuleSpecs::Autoload.autoload :NotDefinedByFile, path
- -> { ModuleSpecs::Autoload::NotDefinedByFile }.should raise_error(NameError)
+ -> { ModuleSpecs::Autoload::NotDefinedByFile }.should.raise(NameError)
ScratchPad.recorded.should == [:loaded]
- -> { ModuleSpecs::Autoload::NotDefinedByFile }.should raise_error(NameError)
+ -> { ModuleSpecs::Autoload::NotDefinedByFile }.should.raise(NameError)
ScratchPad.recorded.should == [:loaded]
Thread.new {
- -> { ModuleSpecs::Autoload::NotDefinedByFile }.should raise_error(NameError)
+ -> { ModuleSpecs::Autoload::NotDefinedByFile }.should.raise(NameError)
}.join
ScratchPad.recorded.should == [:loaded]
end
@@ -498,7 +524,7 @@ describe "Module#autoload" do
autoload :R, fixture(__FILE__, "autoload.rb")
defined?(R).should == 'constant'
end
- ModuleSpecs::Autoload::Q.should have_constant(:R)
+ ModuleSpecs::Autoload::Q.should.const_defined?(:R, false)
end
it "does not load the file when removing an autoload constant" do
@@ -506,13 +532,13 @@ describe "Module#autoload" do
autoload :R, fixture(__FILE__, "autoload.rb")
remove_const :R
end
- ModuleSpecs::Autoload::Q.should_not have_constant(:R)
+ ModuleSpecs::Autoload::Q.should_not.const_defined?(:R)
end
it "does not load the file when accessing the constants table of the module" do
ModuleSpecs::Autoload.autoload :P, @non_existent
- ModuleSpecs::Autoload.const_defined?(:P).should be_true
- ModuleSpecs::Autoload.const_defined?("P").should be_true
+ ModuleSpecs::Autoload.const_defined?(:P).should == true
+ ModuleSpecs::Autoload.const_defined?("P").should == true
end
it "loads the file when opening a module that is the autoloaded constant" do
@@ -547,8 +573,8 @@ describe "Module#autoload" do
DeclaredAndDefinedInParent.should == :declared_and_defined_in_parent
# The constant is really in Autoload, not Autoload::LexicalScope
- self.should_not have_constant(:DeclaredAndDefinedInParent)
- -> { const_get(:DeclaredAndDefinedInParent) }.should raise_error(NameError)
+ self.should_not.const_defined?(:DeclaredAndDefinedInParent)
+ -> { const_get(:DeclaredAndDefinedInParent) }.should.raise(NameError)
end
DeclaredAndDefinedInParent.should == :declared_and_defined_in_parent
end
@@ -571,84 +597,57 @@ describe "Module#autoload" do
# Basically, the parent autoload constant remains in a "undefined" state
self.autoload?(:DeclaredInParentDefinedInCurrent).should == nil
const_defined?(:DeclaredInParentDefinedInCurrent).should == false
- -> { DeclaredInParentDefinedInCurrent }.should raise_error(NameError)
+ -> { DeclaredInParentDefinedInCurrent }.should.raise(NameError)
ModuleSpecs::Autoload::LexicalScope.send(:remove_const, :DeclaredInParentDefinedInCurrent)
end
end
- ruby_version_is "3.2" do
- it "warns once in verbose mode if the constant was defined in a parent scope" do
- ScratchPad.record -> {
- ModuleSpecs::DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
- }
+ it "warns once in verbose mode if the constant was defined in a parent scope" do
+ ScratchPad.record -> {
+ ModuleSpecs::DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
+ }
- module ModuleSpecs
- module Autoload
- autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
- self.autoload?(:DeclaredInCurrentDefinedInParent).should == fixture(__FILE__, "autoload_callback.rb")
- const_defined?(:DeclaredInCurrentDefinedInParent).should == true
-
- -> {
- DeclaredInCurrentDefinedInParent
- }.should complain(
- /Expected .*autoload_callback.rb to define ModuleSpecs::Autoload::DeclaredInCurrentDefinedInParent but it didn't/,
- verbose: true,
- )
-
- -> {
- DeclaredInCurrentDefinedInParent
- }.should_not complain(/.*/, verbose: true)
- self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
- const_defined?(:DeclaredInCurrentDefinedInParent).should == false
- ModuleSpecs.const_defined?(:DeclaredInCurrentDefinedInParent).should == true
- end
+ module ModuleSpecs
+ module Autoload
+ autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
+ self.autoload?(:DeclaredInCurrentDefinedInParent).should == fixture(__FILE__, "autoload_callback.rb")
+ const_defined?(:DeclaredInCurrentDefinedInParent).should == true
+
+ -> {
+ DeclaredInCurrentDefinedInParent
+ }.should complain(
+ /Expected .*autoload_callback.rb to define ModuleSpecs::Autoload::DeclaredInCurrentDefinedInParent but it didn't/,
+ verbose: true,
+ )
+
+ -> {
+ DeclaredInCurrentDefinedInParent
+ }.should_not complain(/.*/, verbose: true)
+ self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
+ const_defined?(:DeclaredInCurrentDefinedInParent).should == false
+ ModuleSpecs.const_defined?(:DeclaredInCurrentDefinedInParent).should == true
end
end
end
- ruby_version_is "3.1" do
- it "looks up in parent scope after failed autoload" do
- @remove << :DeclaredInCurrentDefinedInParent
- module ModuleSpecs::Autoload
- ScratchPad.record -> {
- DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
- }
-
- class LexicalScope
- autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
- -> { DeclaredInCurrentDefinedInParent }.should_not raise_error(NameError)
- # Basically, the autoload constant remains in a "undefined" state
- self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
- const_defined?(:DeclaredInCurrentDefinedInParent).should == false
- -> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError)
- end
+ it "looks up in parent scope after failed autoload" do
+ @remove << :DeclaredInCurrentDefinedInParent
+ module ModuleSpecs::Autoload
+ ScratchPad.record -> {
+ DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
+ }
- DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
+ class LexicalScope
+ autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
+ -> { DeclaredInCurrentDefinedInParent }.should_not.raise(NameError)
+ # Basically, the autoload constant remains in a "undefined" state
+ self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
+ const_defined?(:DeclaredInCurrentDefinedInParent).should == false
+ -> { const_get(:DeclaredInCurrentDefinedInParent) }.should.raise(NameError)
end
- end
- end
-
- ruby_version_is ""..."3.1" do
- it "and fails when finding the undefined autoload constant in the current scope when declared in current and defined in parent" do
- @remove << :DeclaredInCurrentDefinedInParent
- module ModuleSpecs::Autoload
- ScratchPad.record -> {
- DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
- }
- class LexicalScope
- autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
- -> { DeclaredInCurrentDefinedInParent }.should raise_error(NameError)
- # Basically, the autoload constant remains in a "undefined" state
- self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
- const_defined?(:DeclaredInCurrentDefinedInParent).should == false
- self.should have_constant(:DeclaredInCurrentDefinedInParent)
- -> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError)
- end
-
- DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
- end
+ DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
end
end
@@ -715,10 +714,25 @@ describe "Module#autoload" do
end
end
end
- ModuleSpecs::Autoload.r.should be_kind_of(ModuleSpecs::Autoload::MetaScope)
+ ModuleSpecs::Autoload.r.should.is_a?(ModuleSpecs::Autoload::MetaScope)
end
end
+ it "should trigger the autoload when using `private_constant`" do
+ @remove << :DynClass
+ module ModuleSpecs::Autoload
+ autoload :DynClass, fixture(__FILE__, "autoload_c.rb")
+ private_constant :DynClass
+
+ ScratchPad.recorded.should == nil
+
+ DynClass::C.new.loaded.should == :dynclass_c
+ ScratchPad.recorded.should == :loaded
+ end
+
+ -> { ModuleSpecs::Autoload::DynClass }.should.raise(NameError, /private constant/)
+ end
+
# [ruby-core:19127] [ruby-core:29941]
it "does NOT raise a NameError when the autoload file did not define the constant and a module is opened with the same name" do
module ModuleSpecs::Autoload
@@ -731,7 +745,7 @@ describe "Module#autoload" do
end
@remove << :W
- ModuleSpecs::Autoload::W::Y.should be_kind_of(Class)
+ ModuleSpecs::Autoload::W::Y.should.is_a?(Class)
ScratchPad.recorded.should == :loaded
end
@@ -746,7 +760,7 @@ describe "Module#autoload" do
-> {
Kernel.require fixture(__FILE__, "autoload_during_require.rb")
}.should_not complain(verbose: true)
- ModuleSpecs::Autoload::AutoloadDuringRequire.should be_kind_of(Class)
+ ModuleSpecs::Autoload::AutoloadDuringRequire.should.is_a?(Class)
end
it "does not call #require a second time and does not warn if feature sets and trigger autoload on itself" do
@@ -756,15 +770,15 @@ describe "Module#autoload" do
-> {
Kernel.require fixture(__FILE__, "autoload_self_during_require.rb")
}.should_not complain(verbose: true)
- ModuleSpecs::Autoload::AutoloadSelfDuringRequire.should be_kind_of(Class)
+ ModuleSpecs::Autoload::AutoloadSelfDuringRequire.should.is_a?(Class)
end
it "handles multiple autoloads in the same file" do
$LOAD_PATH.unshift(File.expand_path('../fixtures/multi', __FILE__))
begin
require 'foo/bar_baz'
- ModuleSpecs::Autoload::Foo::Bar.should be_kind_of(Class)
- ModuleSpecs::Autoload::Foo::Baz.should be_kind_of(Class)
+ ModuleSpecs::Autoload::Foo::Bar.should.is_a?(Class)
+ ModuleSpecs::Autoload::Foo::Baz.should.is_a?(Class)
ensure
$LOAD_PATH.shift
end
@@ -777,19 +791,19 @@ describe "Module#autoload" do
end
it "raises an ArgumentError when an empty filename is given" do
- -> { ModuleSpecs.autoload :A, "" }.should raise_error(ArgumentError)
+ -> { ModuleSpecs.autoload :A, "" }.should.raise(ArgumentError)
end
it "raises a NameError when the constant name starts with a lower case letter" do
- -> { ModuleSpecs.autoload "a", @non_existent }.should raise_error(NameError)
+ -> { ModuleSpecs.autoload "a", @non_existent }.should.raise(NameError)
end
it "raises a NameError when the constant name starts with a number" do
- -> { ModuleSpecs.autoload "1two", @non_existent }.should raise_error(NameError)
+ -> { ModuleSpecs.autoload "1two", @non_existent }.should.raise(NameError)
end
it "raises a NameError when the constant name has a space in it" do
- -> { ModuleSpecs.autoload "a name", @non_existent }.should raise_error(NameError)
+ -> { ModuleSpecs.autoload "a name", @non_existent }.should.raise(NameError)
end
it "shares the autoload request across dup'ed copies of modules" do
@@ -806,7 +820,7 @@ describe "Module#autoload" do
mod2.autoload?(:T).should == filename
mod1::T.should == :autoload_t
- -> { mod2::T }.should raise_error(NameError)
+ -> { mod2::T }.should.raise(NameError)
end
it "raises a TypeError if opening a class with a different superclass than the class defined in the autoload file" do
@@ -817,27 +831,27 @@ describe "Module#autoload" do
-> do
class ModuleSpecs::Autoload::Z < ModuleSpecs::Autoload::ZZ
end
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if not passed a String or object responding to #to_path for the filename" do
name = mock("autoload_name.rb")
- -> { ModuleSpecs::Autoload.autoload :Str, name }.should raise_error(TypeError)
+ -> { ModuleSpecs::Autoload.autoload :Str, name }.should.raise(TypeError)
end
it "calls #to_path on non-String filename arguments" do
name = mock("autoload_name.rb")
name.should_receive(:to_path).and_return("autoload_name.rb")
- -> { ModuleSpecs::Autoload.autoload :Str, name }.should_not raise_error
+ -> { ModuleSpecs::Autoload.autoload :Str, name }.should_not.raise
end
describe "on a frozen module" do
it "raises a FrozenError before setting the name" do
frozen_module = Module.new.freeze
- -> { frozen_module.autoload :Foo, @non_existent }.should raise_error(FrozenError)
- frozen_module.should_not have_constant(:Foo)
+ -> { frozen_module.autoload :Foo, @non_existent }.should.raise(FrozenError)
+ frozen_module.should_not.const_defined?(:Foo)
end
end
@@ -902,7 +916,7 @@ describe "Module#autoload" do
t1_val.should == 1
t2_val.should == t1_val
- t2_exc.should be_nil
+ t2_exc.should == nil
end
# https://bugs.ruby-lang.org/issues/10892
@@ -934,7 +948,7 @@ describe "Module#autoload" do
begin
Object.const_get(mod_name).foo
- rescue NoMethodError
+ rescue NameError, NoMethodError # rubocop:disable Lint/ShadowedException
barrier.disable!
break false
end
@@ -942,8 +956,8 @@ describe "Module#autoload" do
end
end
- # check that no thread got a NoMethodError because of partially loaded module
- threads.all? {|t| t.value}.should be_true
+ # check that no thread got a NameError or NoMethodError because of partially loaded module
+ threads.all? {|t| t.value}.should == true
# check that the autoloaded file was evaled exactly once
ScratchPad.recorded.get.should == mod_count
@@ -951,6 +965,8 @@ describe "Module#autoload" do
mod_names.each do |mod_name|
Object.send(:remove_const, mod_name)
end
+ ensure
+ threads.each(&:join) if threads
end
it "raises a NameError in each thread if the constant is not set" do
@@ -974,7 +990,7 @@ describe "Module#autoload" do
start = true
threads.each { |t|
- t.value.should be_an_instance_of(NameError)
+ t.value.should.instance_of?(NameError)
}
end
@@ -999,7 +1015,7 @@ describe "Module#autoload" do
start = true
threads.each { |t|
- t.value.should be_an_instance_of(LoadError)
+ t.value.should.instance_of?(LoadError)
}
end
end
diff --git a/spec/ruby/core/module/class_variable_defined_spec.rb b/spec/ruby/core/module/class_variable_defined_spec.rb
index c0f2072a37..dedce9589a 100644
--- a/spec/ruby/core/module/class_variable_defined_spec.rb
+++ b/spec/ruby/core/module/class_variable_defined_spec.rb
@@ -19,13 +19,13 @@ describe "Module#class_variable_defined?" do
obj = mock("metaclass class variable")
meta = obj.singleton_class
meta.send :class_variable_set, :@@var, 1
- meta.send(:class_variable_defined?, :@@var).should be_true
+ meta.send(:class_variable_defined?, :@@var).should == true
end
it "returns false if the class variable is not defined in a metaclass" do
obj = mock("metaclass class variable")
meta = obj.singleton_class
- meta.class_variable_defined?(:@@var).should be_false
+ meta.class_variable_defined?(:@@var).should == false
end
it "returns true if a class variables with the given name is defined in an included module" do
@@ -44,11 +44,11 @@ describe "Module#class_variable_defined?" do
-> {
c.class_variable_defined?(:invalid_name)
- }.should raise_error(NameError)
+ }.should.raise(NameError)
-> {
c.class_variable_defined?("@invalid_name")
- }.should raise_error(NameError)
+ }.should.raise(NameError)
end
it "converts a non string/symbol name to string using to_str" do
@@ -62,11 +62,11 @@ describe "Module#class_variable_defined?" do
o = mock('123')
-> {
c.class_variable_defined?(o)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
o.should_receive(:to_str).and_return(123)
-> {
c.class_variable_defined?(o)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/module/class_variable_get_spec.rb b/spec/ruby/core/module/class_variable_get_spec.rb
index e5d06731ec..13f06cb94a 100644
--- a/spec/ruby/core/module/class_variable_get_spec.rb
+++ b/spec/ruby/core/module/class_variable_get_spec.rb
@@ -15,8 +15,8 @@ describe "Module#class_variable_get" do
it "raises a NameError for a class variable named '@@'" do
c = Class.new
- -> { c.send(:class_variable_get, "@@") }.should raise_error(NameError)
- -> { c.send(:class_variable_get, :"@@") }.should raise_error(NameError)
+ -> { c.send(:class_variable_get, "@@") }.should.raise(NameError)
+ -> { c.send(:class_variable_get, :"@@") }.should.raise(NameError)
end
it "raises a NameError for a class variables with the given name defined in an extended module" do
@@ -24,7 +24,7 @@ describe "Module#class_variable_get" do
c.extend ModuleSpecs::MVars
-> {
c.send(:class_variable_get, "@@mvar")
- }.should raise_error(NameError)
+ }.should.raise(NameError)
end
it "returns class variables defined in the class body and accessed in the metaclass" do
@@ -49,15 +49,15 @@ describe "Module#class_variable_get" do
it "raises a NameError when an uninitialized class variable is accessed" do
c = Class.new
[:@@no_class_var, "@@no_class_var"].each do |cvar|
- -> { c.send(:class_variable_get, cvar) }.should raise_error(NameError)
+ -> { c.send(:class_variable_get, cvar) }.should.raise(NameError)
end
end
it "raises a NameError when the given name is not allowed" do
c = Class.new
- -> { c.send(:class_variable_get, :invalid_name) }.should raise_error(NameError)
- -> { c.send(:class_variable_get, "@invalid_name") }.should raise_error(NameError)
+ -> { c.send(:class_variable_get, :invalid_name) }.should.raise(NameError)
+ -> { c.send(:class_variable_get, "@invalid_name") }.should.raise(NameError)
end
it "converts a non string/symbol name to string using to_str" do
@@ -69,8 +69,8 @@ describe "Module#class_variable_get" do
it "raises a TypeError when the given names can't be converted to strings using to_str" do
c = Class.new { class_variable_set :@@class_var, "test" }
o = mock('123')
- -> { c.send(:class_variable_get, o) }.should raise_error(TypeError)
+ -> { c.send(:class_variable_get, o) }.should.raise(TypeError)
o.should_receive(:to_str).and_return(123)
- -> { c.send(:class_variable_get, o) }.should raise_error(TypeError)
+ -> { c.send(:class_variable_get, o) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/module/class_variable_set_spec.rb b/spec/ruby/core/module/class_variable_set_spec.rb
index 63f32f5389..a3d759767b 100644
--- a/spec/ruby/core/module/class_variable_set_spec.rb
+++ b/spec/ruby/core/module/class_variable_set_spec.rb
@@ -28,10 +28,10 @@ describe "Module#class_variable_set" do
it "raises a FrozenError when self is frozen" do
-> {
Class.new.freeze.send(:class_variable_set, :@@test, "test")
- }.should raise_error(FrozenError)
+ }.should.raise(FrozenError)
-> {
Module.new.freeze.send(:class_variable_set, :@@test, "test")
- }.should raise_error(FrozenError)
+ }.should.raise(FrozenError)
end
it "raises a NameError when the given name is not allowed" do
@@ -39,10 +39,10 @@ describe "Module#class_variable_set" do
-> {
c.send(:class_variable_set, :invalid_name, "test")
- }.should raise_error(NameError)
+ }.should.raise(NameError)
-> {
c.send(:class_variable_set, "@invalid_name", "test")
- }.should raise_error(NameError)
+ }.should.raise(NameError)
end
it "converts a non string/symbol name to string using to_str" do
@@ -55,8 +55,8 @@ describe "Module#class_variable_set" do
it "raises a TypeError when the given names can't be converted to strings using to_str" do
c = Class.new { class_variable_set :@@class_var, "test" }
o = mock('123')
- -> { c.send(:class_variable_set, o, "test") }.should raise_error(TypeError)
+ -> { c.send(:class_variable_set, o, "test") }.should.raise(TypeError)
o.should_receive(:to_str).and_return(123)
- -> { c.send(:class_variable_set, o, "test") }.should raise_error(TypeError)
+ -> { c.send(:class_variable_set, o, "test") }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/module/class_variables_spec.rb b/spec/ruby/core/module/class_variables_spec.rb
index e155f1deac..9529df48ae 100644
--- a/spec/ruby/core/module/class_variables_spec.rb
+++ b/spec/ruby/core/module/class_variables_spec.rb
@@ -3,8 +3,8 @@ require_relative 'fixtures/classes'
describe "Module#class_variables" do
it "returns an Array with the names of class variables of self" do
- ModuleSpecs::ClassVars::A.class_variables.should include(:@@a_cvar)
- ModuleSpecs::ClassVars::M.class_variables.should include(:@@m_cvar)
+ ModuleSpecs::ClassVars::A.class_variables.should.include?(:@@a_cvar)
+ ModuleSpecs::ClassVars::M.class_variables.should.include?(:@@m_cvar)
end
it "returns an Array of Symbols of class variable names defined in a metaclass" do
@@ -15,13 +15,13 @@ describe "Module#class_variables" do
end
it "returns an Array with names of class variables defined in metaclasses" do
- ModuleSpecs::CVars.class_variables.should include(:@@cls, :@@meta)
+ ModuleSpecs::CVars.class_variables.to_set.should >= Set[:@@cls, :@@meta]
end
it "does not return class variables defined in extended modules" do
c = Class.new
c.extend ModuleSpecs::MVars
- c.class_variables.should_not include(:@@mvar)
+ c.class_variables.should_not.include?(:@@mvar)
end
it "returns the correct class variables when inherit is given" do
diff --git a/spec/ruby/core/module/const_added_spec.rb b/spec/ruby/core/module/const_added_spec.rb
index 31ac6eb105..b60af7a2e8 100644
--- a/spec/ruby/core/module/const_added_spec.rb
+++ b/spec/ruby/core/module/const_added_spec.rb
@@ -1,125 +1,238 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'fixtures/const_added'
describe "Module#const_added" do
- ruby_version_is "3.2" do
- it "is a private instance method" do
- Module.should have_private_instance_method(:const_added)
+ it "is a private instance method" do
+ Module.private_instance_methods(false).should.include?(:const_added)
+ end
+
+ it "returns nil in the default implementation" do
+ Module.new do
+ const_added(:TEST).should == nil
+ end
+ end
+
+ it "for a class defined with the `class` keyword, const_added runs before inherited" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(_)
+ ScratchPad << :const_added
+ end
end
- it "returns nil in the default implementation" do
- Module.new do
- const_added(:TEST).should == nil
+ parent = Class.new do
+ def self.inherited(_)
+ ScratchPad << :inherited
end
end
- it "is called when a new constant is assigned on self" do
- ScratchPad.record []
+ class mod::C < parent; end
- mod = Module.new do
- def self.const_added(name)
- ScratchPad << name
- end
+ ScratchPad.recorded.should == [:const_added, :inherited]
+ end
+
+ it "the superclass of a class assigned to a constant is set before const_added is called" do
+ ScratchPad.record []
+
+ parent = Class.new do
+ def self.const_added(name)
+ ScratchPad << name
+ ScratchPad << const_get(name).superclass
end
+ end
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- TEST = 1
- RUBY
+ class parent::C < parent; end
+
+ ScratchPad.recorded.should == [:C, parent]
+ end
- ScratchPad.recorded.should == [:TEST]
+ it "is called when a new constant is assigned on self" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
end
- it "is called when a new constant is assigned on self through const_set" do
- ScratchPad.record []
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 1
+ RUBY
- mod = Module.new do
- def self.const_added(name)
- ScratchPad << name
- end
+ ScratchPad.recorded.should == [:TEST]
+ end
+
+ it "is called when a new constant is assigned on self through const_set" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
end
+ end
+
+ mod.const_set(:TEST, 1)
+
+ ScratchPad.recorded.should == [:TEST]
+ end
- mod.const_set(:TEST, 1)
+ it "is called when a new module is defined under self" do
+ ScratchPad.record []
- ScratchPad.recorded.should == [:TEST]
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
end
- it "is called when a new module is defined under self" do
- ScratchPad.record []
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ module SubModule
+ end
+
+ module SubModule
+ end
+ RUBY
- mod = Module.new do
+ ScratchPad.recorded.should == [:SubModule]
+ end
+
+ it "is called when a new module is defined under a named module (assigned to a constant)" do
+ ScratchPad.record []
+
+ ModuleSpecs::ConstAddedSpecs::NamedModule = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
+
+ module self::A
def self.const_added(name)
ScratchPad << name
end
- end
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- module SubModule
+ module self::B
end
+ end
+ end
- module SubModule
- end
- RUBY
+ ScratchPad.recorded.should == [:A, :B]
+ ModuleSpecs::ConstAddedSpecs.send :remove_const, :NamedModule
+ end
- ScratchPad.recorded.should == [:SubModule]
+ it "is called when a new class is defined under self" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
end
- it "is called when a new class is defined under self" do
- ScratchPad.record []
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ class SubClass
+ end
+
+ class SubClass
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [:SubClass]
+ end
+
+ it "is called when a new class is defined under a named module (assigned to a constant)" do
+ ScratchPad.record []
+
+ ModuleSpecs::ConstAddedSpecs::NamedModuleB = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
- mod = Module.new do
+ class self::A
def self.const_added(name)
ScratchPad << name
end
- end
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- class SubClass
+ class self::B
end
+ end
+ end
- class SubClass
- end
- RUBY
+ ScratchPad.recorded.should == [:A, :B]
+ ModuleSpecs::ConstAddedSpecs.send :remove_const, :NamedModuleB
+ end
+
+ it "is called when an autoload is defined" do
+ ScratchPad.record []
- ScratchPad.recorded.should == [:SubClass]
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
end
- it "is called when an autoload is defined" do
- ScratchPad.record []
+ mod.autoload :Autoload, "foo"
+ ScratchPad.recorded.should == [:Autoload]
+ end
- mod = Module.new do
- def self.const_added(name)
- ScratchPad << name
- end
- end
+ it "is called with a precise caller location with the line of definition" do
+ ScratchPad.record []
- mod.autoload :Autoload, "foo"
- ScratchPad.recorded.should == [:Autoload]
+ mod = Module.new do
+ def self.const_added(name)
+ location = caller_locations(1, 1)[0]
+ ScratchPad << location.lineno
+ end
end
- it "is called with a precise caller location with the line of definition" do
- ScratchPad.record []
+ line = __LINE__
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 1
- mod = Module.new do
- def self.const_added(name)
- location = caller_locations(1, 1)[0]
- ScratchPad << location.lineno
- end
+ module SubModule
end
- line = __LINE__
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- TEST = 1
+ class SubClass
+ end
+ RUBY
- module SubModule
- end
+ mod.const_set(:CONST_SET, 1)
- class SubClass
- end
- RUBY
+ ScratchPad.recorded.should == [line + 2, line + 4, line + 7, line + 11]
+ end
+
+ it "is called when the constant is already assigned a value" do
+ ScratchPad.record []
- mod.const_set(:CONST_SET, 1)
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad.record const_get(name)
+ end
+ end
+
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 123
+ RUBY
+
+ ScratchPad.recorded.should == 123
+ end
+
+ it "records re-definition of existing constants" do
+ ScratchPad.record []
- ScratchPad.recorded.should == [line + 2, line + 4, line + 7, line + 11]
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << const_get(name)
+ end
end
+
+ -> {
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 123
+ TEST = 456
+ RUBY
+ }.should complain(/warning: already initialized constant .+::TEST/)
+
+ ScratchPad.recorded.should == [123, 456]
end
end
diff --git a/spec/ruby/core/module/const_defined_spec.rb b/spec/ruby/core/module/const_defined_spec.rb
index 75730395e8..9d973c2b2b 100644
--- a/spec/ruby/core/module/const_defined_spec.rb
+++ b/spec/ruby/core/module/const_defined_spec.rb
@@ -14,35 +14,40 @@ describe "Module#const_defined?" do
it "returns true if the constant is defined in the receiver's superclass" do
# CS_CONST4 is defined in the superclass of ChildA
- ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4).should be_true
+ ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4).should == true
end
- it "returns true if the constant is defined in a mixed-in module of the receiver" do
+ it "returns true if the constant is defined in a mixed-in module of the receiver's parent" do
# CS_CONST10 is defined in a module included by ChildA
- ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST10).should be_true
+ ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST10).should == true
+ end
+
+ it "returns true if the constant is defined in a mixed-in module (with prepends) of the receiver" do
+ # CS_CONST11 is defined in the module included by ContainerPrepend
+ ConstantSpecs::ContainerPrepend.const_defined?(:CS_CONST11).should == true
end
it "returns true if the constant is defined in Object and the receiver is a module" do
# CS_CONST1 is defined in Object
- ConstantSpecs::ModuleA.const_defined?(:CS_CONST1).should be_true
+ ConstantSpecs::ModuleA.const_defined?(:CS_CONST1).should == true
end
it "returns true if the constant is defined in Object and the receiver is a class that has Object among its ancestors" do
# CS_CONST1 is defined in Object
- ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST1).should be_true
+ ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST1).should == true
end
it "returns false if the constant is defined in the receiver's superclass and the inherit flag is false" do
- ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, false).should be_false
+ ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, false).should == false
end
it "returns true if the constant is defined in the receiver's superclass and the inherit flag is true" do
- ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, true).should be_true
+ ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, true).should == true
end
it "coerces the inherit flag to a boolean" do
- ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, nil).should be_false
- ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, :true).should be_true
+ ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, nil).should == false
+ ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4, :true).should == true
end
it "returns true if the given String names a constant defined in the receiver" do
@@ -53,21 +58,23 @@ describe "Module#const_defined?" do
end
it "returns true when passed a constant name with unicode characters" do
- ConstantUnicodeSpecs.const_defined?("CS_CONSTλ").should be_true
+ ConstantUnicodeSpecs.const_defined?("CS_CONSTλ").should == true
end
it "returns true when passed a constant name with EUC-JP characters" do
str = "CS_CONSTλ".encode("euc-jp")
ConstantSpecs.const_set str, 1
- ConstantSpecs.const_defined?(str).should be_true
+ ConstantSpecs.const_defined?(str).should == true
+ ensure
+ ConstantSpecs.send(:remove_const, str)
end
it "returns false if the constant is not defined in the receiver, its superclass, or any included modules" do
# The following constant isn't defined at all.
- ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4726).should be_false
+ ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4726).should == false
# DETACHED_CONSTANT is defined in ConstantSpecs::Detached, which isn't
# included by or inherited from ParentA
- ConstantSpecs::ParentA.const_defined?(:DETACHED_CONSTANT).should be_false
+ ConstantSpecs::ParentA.const_defined?(:DETACHED_CONSTANT).should == false
end
it "does not call #const_missing if the constant is not defined in the receiver" do
@@ -75,54 +82,67 @@ describe "Module#const_defined?" do
ConstantSpecs::ClassA.const_defined?(:CS_CONSTX).should == false
end
- it "calls #to_str to convert the given name to a String" do
- name = mock("ClassA")
- name.should_receive(:to_str).and_return("ClassA")
- ConstantSpecs.const_defined?(name).should == true
+ describe "converts the given name to a String using #to_str" do
+ it "calls #to_str to convert the given name to a String" do
+ name = mock("ClassA")
+ name.should_receive(:to_str).and_return("ClassA")
+ ConstantSpecs.const_defined?(name).should == true
+ end
+
+ it "raises a TypeError if the given name can't be converted to a String" do
+ -> { ConstantSpecs.const_defined?(nil) }.should.raise(TypeError)
+ -> { ConstantSpecs.const_defined?([]) }.should.raise(TypeError)
+ end
+
+ it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to a String" do
+ name = mock("classA")
+ name.should_receive(:to_str).and_raise(NoMethodError)
+ -> { ConstantSpecs.const_defined?(name) }.should.raise(NoMethodError)
+ end
end
it "special cases Object and checks it's included Modules" do
- Object.const_defined?(:CS_CONST10).should be_true
+ Object.const_defined?(:CS_CONST10).should == true
end
it "returns true for toplevel constant when the name begins with '::'" do
- ConstantSpecs.const_defined?("::Array").should be_true
+ ConstantSpecs.const_defined?("::Array").should == true
end
it "returns true when passed a scoped constant name" do
- ConstantSpecs.const_defined?("ClassC::CS_CONST1").should be_true
+ ConstantSpecs.const_defined?("ClassC::CS_CONST1").should == true
end
it "returns true when passed a scoped constant name for a constant in the inheritance hierarchy and the inherited flag is default" do
- ConstantSpecs::ClassD.const_defined?("ClassE::CS_CONST2").should be_true
+ ConstantSpecs::ClassD.const_defined?("ClassE::CS_CONST2").should == true
end
it "returns true when passed a scoped constant name for a constant in the inheritance hierarchy and the inherited flag is true" do
- ConstantSpecs::ClassD.const_defined?("ClassE::CS_CONST2", true).should be_true
+ ConstantSpecs::ClassD.const_defined?("ClassE::CS_CONST2", true).should == true
end
it "returns false when passed a scoped constant name for a constant in the inheritance hierarchy and the inherited flag is false" do
- ConstantSpecs::ClassD.const_defined?("ClassE::CS_CONST2", false).should be_false
+ ConstantSpecs::ClassD.const_defined?("ClassE::CS_CONST2", false).should == false
end
it "returns false when the name begins with '::' and the toplevel constant does not exist" do
- ConstantSpecs.const_defined?("::Name").should be_false
+ ConstantSpecs.const_defined?("::Name").should == false
end
it "raises a NameError if the name does not start with a capital letter" do
- -> { ConstantSpecs.const_defined? "name" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_defined? "name" }.should.raise(NameError)
end
it "raises a NameError if the name starts with '_'" do
- -> { ConstantSpecs.const_defined? "__CONSTX__" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_defined? "__CONSTX__" }.should.raise(NameError)
end
it "raises a NameError if the name starts with '@'" do
- -> { ConstantSpecs.const_defined? "@Name" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_defined? "@Name" }.should.raise(NameError)
end
it "raises a NameError if the name starts with '!'" do
- -> { ConstantSpecs.const_defined? "!Name" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_defined? "!Name" }.should.raise(NameError)
end
it "returns true or false for the nested name" do
@@ -135,15 +155,15 @@ describe "Module#const_defined?" do
it "raises a NameError if the name contains non-alphabetic characters except '_'" do
ConstantSpecs.const_defined?("CS_CONSTX").should == false
- -> { ConstantSpecs.const_defined? "Name=" }.should raise_error(NameError)
- -> { ConstantSpecs.const_defined? "Name?" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_defined? "Name=" }.should.raise(NameError)
+ -> { ConstantSpecs.const_defined? "Name?" }.should.raise(NameError)
end
it "raises a TypeError if conversion to a String by calling #to_str fails" do
name = mock('123')
- -> { ConstantSpecs.const_defined? name }.should raise_error(TypeError)
+ -> { ConstantSpecs.const_defined? name }.should.raise(TypeError)
name.should_receive(:to_str).and_return(123)
- -> { ConstantSpecs.const_defined? name }.should raise_error(TypeError)
+ -> { ConstantSpecs.const_defined? name }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/module/const_get_spec.rb b/spec/ruby/core/module/const_get_spec.rb
index 69f181cf51..68b5594faa 100644
--- a/spec/ruby/core/module/const_get_spec.rb
+++ b/spec/ruby/core/module/const_get_spec.rb
@@ -9,28 +9,28 @@ describe "Module#const_get" do
end
it "raises a NameError if no constant is defined in the search path" do
- -> { ConstantSpecs.const_get :CS_CONSTX }.should raise_error(NameError)
+ -> { ConstantSpecs.const_get :CS_CONSTX }.should.raise(NameError)
end
it "raises a NameError with the not found constant symbol" do
error_inspection = -> e { e.name.should == :CS_CONSTX }
- -> { ConstantSpecs.const_get :CS_CONSTX }.should raise_error(NameError, &error_inspection)
+ -> { ConstantSpecs.const_get :CS_CONSTX }.should.raise(NameError, &error_inspection)
end
it "raises a NameError if the name does not start with a capital letter" do
- -> { ConstantSpecs.const_get "name" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_get "name" }.should.raise(NameError)
end
it "raises a NameError if the name starts with a non-alphabetic character" do
- -> { ConstantSpecs.const_get "__CONSTX__" }.should raise_error(NameError)
- -> { ConstantSpecs.const_get "@CS_CONST1" }.should raise_error(NameError)
- -> { ConstantSpecs.const_get "!CS_CONST1" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_get "__CONSTX__" }.should.raise(NameError)
+ -> { ConstantSpecs.const_get "@CS_CONST1" }.should.raise(NameError)
+ -> { ConstantSpecs.const_get "!CS_CONST1" }.should.raise(NameError)
end
it "raises a NameError if the name contains non-alphabetic characters except '_'" do
Object.const_get("CS_CONST1").should == :const1
- -> { ConstantSpecs.const_get "CS_CONST1=" }.should raise_error(NameError)
- -> { ConstantSpecs.const_get "CS_CONST1?" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_get "CS_CONST1=" }.should.raise(NameError)
+ -> { ConstantSpecs.const_get "CS_CONST1?" }.should.raise(NameError)
end
it "calls #to_str to convert the given name to a String" do
@@ -41,10 +41,10 @@ describe "Module#const_get" do
it "raises a TypeError if conversion to a String by calling #to_str fails" do
name = mock('123')
- -> { ConstantSpecs.const_get(name) }.should raise_error(TypeError)
+ -> { ConstantSpecs.const_get(name) }.should.raise(TypeError)
name.should_receive(:to_str).and_return(123)
- -> { ConstantSpecs.const_get(name) }.should raise_error(TypeError)
+ -> { ConstantSpecs.const_get(name) }.should.raise(TypeError)
end
it "calls #const_missing on the receiver if unable to locate the constant" do
@@ -55,21 +55,21 @@ describe "Module#const_get" do
it "does not search the singleton class of a Class or Module" do
-> do
ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST14)
- end.should raise_error(NameError)
- -> { ConstantSpecs.const_get(:CS_CONST14) }.should raise_error(NameError)
+ end.should.raise(NameError)
+ -> { ConstantSpecs.const_get(:CS_CONST14) }.should.raise(NameError)
end
it "does not search the containing scope" do
ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST20).should == :const20_2
-> do
ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST5)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError if the constant is defined in the receiver's superclass and the inherit flag is false" do
-> do
ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST4, false)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "searches into the receiver superclasses if the inherit flag is true" do
@@ -79,13 +79,13 @@ describe "Module#const_get" do
it "raises a NameError when the receiver is a Module, the constant is defined at toplevel and the inherit flag is false" do
-> do
ConstantSpecs::ModuleA.const_get(:CS_CONST1, false)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError when the receiver is a Class, the constant is defined at toplevel and the inherit flag is false" do
-> do
ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST1, false)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "coerces the inherit flag to a boolean" do
@@ -93,7 +93,7 @@ describe "Module#const_get" do
-> do
ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST1, nil)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "accepts a toplevel scope qualifier" do
@@ -102,10 +102,10 @@ describe "Module#const_get" do
it "accepts a toplevel scope qualifier when inherit is false" do
ConstantSpecs.const_get("::CS_CONST1", false).should == :const1
- -> { ConstantSpecs.const_get("CS_CONST1", false) }.should raise_error(NameError)
+ -> { ConstantSpecs.const_get("CS_CONST1", false) }.should.raise(NameError)
end
- it "returns a constant whose module is defined the the toplevel" do
+ it "returns a constant whose module is defined the toplevel" do
ConstantSpecs.const_get("ConstantSpecsTwo::Foo").should == :cs_two_foo
ConstantSpecsThree.const_get("ConstantSpecsTwo::Foo").should == :cs_three_foo
end
@@ -115,23 +115,23 @@ describe "Module#const_get" do
end
it "raises a NameError if the name includes two successive scope separators" do
- -> { ConstantSpecs.const_get("ClassA::::CS_CONST10") }.should raise_error(NameError)
+ -> { ConstantSpecs.const_get("ClassA::::CS_CONST10") }.should.raise(NameError)
end
it "raises a NameError if only '::' is passed" do
- -> { ConstantSpecs.const_get("::") }.should raise_error(NameError)
+ -> { ConstantSpecs.const_get("::") }.should.raise(NameError)
end
it "raises a NameError if a Symbol has a toplevel scope qualifier" do
- -> { ConstantSpecs.const_get(:'::CS_CONST1') }.should raise_error(NameError)
+ -> { ConstantSpecs.const_get(:'::CS_CONST1') }.should.raise(NameError)
end
it "raises a NameError if a Symbol is a scoped constant name" do
- -> { ConstantSpecs.const_get(:'ClassA::CS_CONST10') }.should raise_error(NameError)
+ -> { ConstantSpecs.const_get(:'ClassA::CS_CONST10') }.should.raise(NameError)
end
it "does read private constants" do
- ConstantSpecs.const_get(:CS_PRIVATE).should == :cs_private
+ ConstantSpecs.const_get(:CS_PRIVATE).should == :cs_private
end
it 'does autoload a constant' do
@@ -151,7 +151,7 @@ describe "Module#const_get" do
end
it "raises a NameError when the nested constant does not exist on the module but exists in Object" do
- -> { Object.const_get('ConstantSpecs::CS_CONST1') }.should raise_error(NameError)
+ -> { Object.const_get('ConstantSpecs::CS_CONST1') }.should.raise(NameError)
end
describe "with statically assigned constants" do
@@ -202,40 +202,60 @@ describe "Module#const_get" do
ConstantSpecs::ContainerA::ChildA::CS_CONST301 = :const301_5
ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST301).should == :const301_5
+ ensure
+ ConstantSpecs::ClassA.send(:remove_const, :CS_CONST301)
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST301)
+ ConstantSpecs::ParentA.send(:remove_const, :CS_CONST301)
+ ConstantSpecs::ContainerA::ChildA.send(:remove_const, :CS_CONST301)
end
it "searches a module included in the immediate class before the superclass" do
ConstantSpecs::ParentB::CS_CONST302 = :const302_1
ConstantSpecs::ModuleF::CS_CONST302 = :const302_2
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST302).should == :const302_2
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST302)
+ ConstantSpecs::ModuleF.send(:remove_const, :CS_CONST302)
end
it "searches the superclass before a module included in the superclass" do
ConstantSpecs::ModuleE::CS_CONST303 = :const303_1
ConstantSpecs::ParentB::CS_CONST303 = :const303_2
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST303).should == :const303_2
+ ensure
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST303)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST303)
end
it "searches a module included in the superclass" do
ConstantSpecs::ModuleA::CS_CONST304 = :const304_1
ConstantSpecs::ModuleE::CS_CONST304 = :const304_2
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST304).should == :const304_2
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST304)
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST304)
end
it "searches the superclass chain" do
ConstantSpecs::ModuleA::CS_CONST305 = :const305
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST305).should == :const305
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST305)
end
it "returns a toplevel constant when the receiver is a Class" do
Object::CS_CONST306 = :const306
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST306).should == :const306
+ ensure
+ Object.send(:remove_const, :CS_CONST306)
end
it "returns a toplevel constant when the receiver is a Module" do
Object::CS_CONST308 = :const308
ConstantSpecs.const_get(:CS_CONST308).should == :const308
ConstantSpecs::ModuleA.const_get(:CS_CONST308).should == :const308
+ ensure
+ Object.send(:remove_const, :CS_CONST308)
end
it "returns the updated value of a constant" do
@@ -246,6 +266,8 @@ describe "Module#const_get" do
ConstantSpecs::ClassB::CS_CONST309 = :const309_2
}.should complain(/already initialized constant/)
ConstantSpecs::ClassB.const_get(:CS_CONST309).should == :const309_2
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST309)
end
end
end
diff --git a/spec/ruby/core/module/const_missing_spec.rb b/spec/ruby/core/module/const_missing_spec.rb
index 742218281c..80a2caccab 100644
--- a/spec/ruby/core/module/const_missing_spec.rb
+++ b/spec/ruby/core/module/const_missing_spec.rb
@@ -13,7 +13,7 @@ describe "Module#const_missing" do
it "raises NameError and includes the name of the value that wasn't found" do
-> {
ConstantSpecs.const_missing("HelloMissing")
- }.should raise_error(NameError, /ConstantSpecs::HelloMissing/)
+ }.should.raise(NameError, /ConstantSpecs::HelloMissing/)
end
it "raises NameError and does not include toplevel Object" do
diff --git a/spec/ruby/core/module/const_set_spec.rb b/spec/ruby/core/module/const_set_spec.rb
index ba7810d17b..aa3c6bbcfc 100644
--- a/spec/ruby/core/module/const_set_spec.rb
+++ b/spec/ruby/core/module/const_set_spec.rb
@@ -8,32 +8,29 @@ describe "Module#const_set" do
ConstantSpecs.const_set "CS_CONST402", :const402
ConstantSpecs.const_get(:CS_CONST402).should == :const402
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST401)
+ ConstantSpecs.send(:remove_const, :CS_CONST402)
end
it "returns the value set" do
ConstantSpecs.const_set(:CS_CONST403, :const403).should == :const403
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST403)
end
it "sets the name of an anonymous module" do
m = Module.new
ConstantSpecs.const_set(:CS_CONST1000, m)
m.name.should == "ConstantSpecs::CS_CONST1000"
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST1000)
end
- ruby_version_is ""..."3.0" do
- it "does not set the name of a module scoped by an anonymous module" do
- a, b = Module.new, Module.new
- a.const_set :B, b
- b.name.should be_nil
- end
- end
-
- ruby_version_is "3.0" do
- it "sets the name of a module scoped by an anonymous module" do
- a, b = Module.new, Module.new
- a.const_set :B, b
- b.name.should.end_with? '::B'
- end
+ it "sets the name of a module scoped by an anonymous module" do
+ a, b = Module.new, Module.new
+ a.const_set :B, b
+ b.name.should.end_with? '::B'
end
it "sets the name of contained modules when assigning a toplevel anonymous module" do
@@ -48,23 +45,27 @@ describe "Module#const_set" do
b.name.should == "ModuleSpecs_CS3::B"
c.name.should == "ModuleSpecs_CS3::B::C"
d.name.should == "ModuleSpecs_CS3::D"
+ ensure
+ Object.send(:remove_const, :ModuleSpecs_CS3)
end
it "raises a NameError if the name does not start with a capital letter" do
- -> { ConstantSpecs.const_set "name", 1 }.should raise_error(NameError)
+ -> { ConstantSpecs.const_set "name", 1 }.should.raise(NameError)
end
it "raises a NameError if the name starts with a non-alphabetic character" do
- -> { ConstantSpecs.const_set "__CONSTX__", 1 }.should raise_error(NameError)
- -> { ConstantSpecs.const_set "@Name", 1 }.should raise_error(NameError)
- -> { ConstantSpecs.const_set "!Name", 1 }.should raise_error(NameError)
- -> { ConstantSpecs.const_set "::Name", 1 }.should raise_error(NameError)
+ -> { ConstantSpecs.const_set "__CONSTX__", 1 }.should.raise(NameError)
+ -> { ConstantSpecs.const_set "@Name", 1 }.should.raise(NameError)
+ -> { ConstantSpecs.const_set "!Name", 1 }.should.raise(NameError)
+ -> { ConstantSpecs.const_set "::Name", 1 }.should.raise(NameError)
end
it "raises a NameError if the name contains non-alphabetic characters except '_'" do
ConstantSpecs.const_set("CS_CONST404", :const404).should == :const404
- -> { ConstantSpecs.const_set "Name=", 1 }.should raise_error(NameError)
- -> { ConstantSpecs.const_set "Name?", 1 }.should raise_error(NameError)
+ -> { ConstantSpecs.const_set "Name=", 1 }.should.raise(NameError)
+ -> { ConstantSpecs.const_set "Name?", 1 }.should.raise(NameError)
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST404)
end
it "calls #to_str to convert the given name to a String" do
@@ -72,14 +73,16 @@ describe "Module#const_set" do
name.should_receive(:to_str).and_return("CS_CONST405")
ConstantSpecs.const_set(name, :const405).should == :const405
ConstantSpecs::CS_CONST405.should == :const405
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST405)
end
it "raises a TypeError if conversion to a String by calling #to_str fails" do
name = mock('123')
- -> { ConstantSpecs.const_set name, 1 }.should raise_error(TypeError)
+ -> { ConstantSpecs.const_set name, 1 }.should.raise(TypeError)
name.should_receive(:to_str).and_return(123)
- -> { ConstantSpecs.const_set name, 1 }.should raise_error(TypeError)
+ -> { ConstantSpecs.const_set name, 1 }.should.raise(TypeError)
end
describe "when overwriting an existing constant" do
@@ -107,7 +110,7 @@ describe "Module#const_set" do
mod = Module.new
mod.autoload :Foo, path
- -> { mod::Foo }.should raise_error(NameError)
+ -> { mod::Foo }.should.raise(NameError)
mod.const_defined?(:Foo).should == false
mod.autoload?(:Foo).should == nil
@@ -135,8 +138,8 @@ describe "Module#const_set" do
end
it "raises a FrozenError before setting the name" do
- -> { @frozen.const_set @name, nil }.should raise_error(FrozenError)
- @frozen.should_not have_constant(@name)
+ -> { @frozen.const_set @name, nil }.should.raise(FrozenError)
+ @frozen.should_not.const_defined?(@name)
end
end
end
diff --git a/spec/ruby/core/module/const_source_location_spec.rb b/spec/ruby/core/module/const_source_location_spec.rb
index 11a2e74756..e6cef727e2 100644
--- a/spec/ruby/core/module/const_source_location_spec.rb
+++ b/spec/ruby/core/module/const_source_location_spec.rb
@@ -19,40 +19,60 @@ describe "Module#const_source_location" do
ConstantSpecs::ContainerA::ChildA::CSL_CONST301 = :const301_5
ConstantSpecs::ContainerA::ChildA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+ ensure
+ ConstantSpecs::ClassA.send(:remove_const, :CSL_CONST301)
+ ConstantSpecs::ModuleA.send(:remove_const, :CSL_CONST301)
+ ConstantSpecs::ParentA.send(:remove_const, :CSL_CONST301)
+ ConstantSpecs::ContainerA::ChildA.send(:remove_const, :CSL_CONST301)
end
it "searches a path in a module included in the immediate class before the superclass" do
ConstantSpecs::ParentB::CSL_CONST302 = :const302_1
ConstantSpecs::ModuleF::CSL_CONST302 = :const302_2
ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST302).should == [__FILE__, __LINE__ - 1]
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CSL_CONST302)
+ ConstantSpecs::ModuleF.send(:remove_const, :CSL_CONST302)
end
it "searches a path in the superclass before a module included in the superclass" do
ConstantSpecs::ModuleE::CSL_CONST303 = :const303_1
ConstantSpecs::ParentB::CSL_CONST303 = :const303_2
ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST303).should == [__FILE__, __LINE__ - 1]
+ ensure
+ ConstantSpecs::ModuleE.send(:remove_const, :CSL_CONST303)
+ ConstantSpecs::ParentB.send(:remove_const, :CSL_CONST303)
end
it "searches a path in a module included in the superclass" do
ConstantSpecs::ModuleA::CSL_CONST304 = :const304_1
ConstantSpecs::ModuleE::CSL_CONST304 = :const304_2
ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST304).should == [__FILE__, __LINE__ - 1]
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CSL_CONST304)
+ ConstantSpecs::ModuleE.send(:remove_const, :CSL_CONST304)
end
it "searches a path in the superclass chain" do
ConstantSpecs::ModuleA::CSL_CONST305 = :const305
ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST305).should == [__FILE__, __LINE__ - 1]
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CSL_CONST305)
end
it "returns path to a toplevel constant when the receiver is a Class" do
Object::CSL_CONST306 = :const306
ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST306).should == [__FILE__, __LINE__ - 1]
+ ensure
+ Object.send(:remove_const, :CSL_CONST306)
end
it "returns path to a toplevel constant when the receiver is a Module" do
Object::CSL_CONST308 = :const308
ConstantSpecs.const_source_location(:CSL_CONST308).should == [__FILE__, __LINE__ - 1]
ConstantSpecs::ModuleA.const_source_location(:CSL_CONST308).should == [__FILE__, __LINE__ - 2]
+ ensure
+ Object.send(:remove_const, :CSL_CONST308)
end
it "returns path to the updated value of a constant" do
@@ -63,10 +83,17 @@ describe "Module#const_source_location" do
ConstantSpecs::ClassB::CSL_CONST309 = :const309_2
}.should complain(/already initialized constant/)
ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 2]
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CSL_CONST309)
end
end
describe "with statically assigned constants" do
+ it "works for the module and class keywords" do
+ ConstantSpecs.const_source_location(:ModuleB).should == [@constants_fixture_path, ConstantSpecs::ModuleB::LINE]
+ ConstantSpecs.const_source_location(:ClassA).should == [@constants_fixture_path, ConstantSpecs::ClassA::LINE]
+ end
+
it "searches location path the immediate class or module first" do
ConstantSpecs::ClassA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CONST10_LINE]
ConstantSpecs::ModuleA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ModuleA::CS_CONST10_LINE]
@@ -115,33 +142,33 @@ describe "Module#const_source_location" do
end
it "raises a NameError if the name does not start with a capital letter" do
- -> { ConstantSpecs.const_source_location "name" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location "name" }.should.raise(NameError)
end
it "raises a NameError if the name starts with a non-alphabetic character" do
- -> { ConstantSpecs.const_source_location "__CONSTX__" }.should raise_error(NameError)
- -> { ConstantSpecs.const_source_location "@CS_CONST1" }.should raise_error(NameError)
- -> { ConstantSpecs.const_source_location "!CS_CONST1" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location "__CONSTX__" }.should.raise(NameError)
+ -> { ConstantSpecs.const_source_location "@CS_CONST1" }.should.raise(NameError)
+ -> { ConstantSpecs.const_source_location "!CS_CONST1" }.should.raise(NameError)
end
it "raises a NameError if the name contains non-alphabetic characters except '_'" do
Object.const_source_location("CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE]
- -> { ConstantSpecs.const_source_location "CS_CONST1=" }.should raise_error(NameError)
- -> { ConstantSpecs.const_source_location "CS_CONST1?" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location "CS_CONST1=" }.should.raise(NameError)
+ -> { ConstantSpecs.const_source_location "CS_CONST1?" }.should.raise(NameError)
end
it "calls #to_str to convert the given name to a String" do
name = mock("ClassA")
name.should_receive(:to_str).and_return("ClassA")
- ConstantSpecs.const_source_location(name).should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CLASS_A_LINE]
+ ConstantSpecs.const_source_location(name).should == [@constants_fixture_path, ConstantSpecs::ClassA::LINE]
end
it "raises a TypeError if conversion to a String by calling #to_str fails" do
name = mock('123')
- -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError)
+ -> { ConstantSpecs.const_source_location(name) }.should.raise(TypeError)
name.should_receive(:to_str).and_return(123)
- -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError)
+ -> { ConstantSpecs.const_source_location(name) }.should.raise(TypeError)
end
it "does not search the singleton class of a Class or Module" do
@@ -186,23 +213,30 @@ describe "Module#const_source_location" do
end
it "raises a NameError if the name includes two successive scope separators" do
- -> { ConstantSpecs.const_source_location("ClassA::::CS_CONST10") }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location("ClassA::::CS_CONST10") }.should.raise(NameError)
end
it "raises a NameError if only '::' is passed" do
- -> { ConstantSpecs.const_source_location("::") }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location("::") }.should.raise(NameError)
end
it "raises a NameError if a Symbol has a toplevel scope qualifier" do
- -> { ConstantSpecs.const_source_location(:'::CS_CONST1') }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location(:'::CS_CONST1') }.should.raise(NameError)
end
it "raises a NameError if a Symbol is a scoped constant name" do
- -> { ConstantSpecs.const_source_location(:'ClassA::CS_CONST10') }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location(:'ClassA::CS_CONST10') }.should.raise(NameError)
end
it "does search private constants path" do
- ConstantSpecs.const_source_location(:CS_PRIVATE).should == [@constants_fixture_path, ConstantSpecs::CS_PRIVATE_LINE]
+ ConstantSpecs.const_source_location(:CS_PRIVATE).should == [@constants_fixture_path, ConstantSpecs::CS_PRIVATE_LINE]
+ end
+
+ it "works for eval with a given line" do
+ c = Class.new do
+ eval('self::C = 1', nil, "foo", 100)
+ end
+ c.const_source_location(:C).should == ["foo", 100]
end
context 'autoload' do
@@ -211,6 +245,14 @@ describe "Module#const_source_location" do
@line = __LINE__ - 1
end
+ before :each do
+ @loaded_features = $".dup
+ end
+
+ after :each do
+ $".replace @loaded_features
+ end
+
it 'returns the autoload location while not resolved' do
ConstantSpecs.const_source_location('CSL_CONST1').should == [__FILE__, @line]
end
@@ -221,5 +263,19 @@ describe "Module#const_source_location" do
line = ConstantSpecs::CONST_LOCATION
ConstantSpecs.const_source_location('CONST_LOCATION').should == [file, line]
end
+
+ ruby_bug("#20188", ""..."3.4") do
+ it 'returns the real constant location as soon as it is defined' do
+ file = fixture(__FILE__, 'autoload_const_source_location.rb')
+ ConstantSpecs.autoload :ConstSource, file
+ autoload_location = [__FILE__, __LINE__ - 1]
+
+ ConstantSpecs.const_source_location(:ConstSource).should == autoload_location
+ ConstantSpecs::ConstSource::LOCATION.should == ConstantSpecs.const_source_location(:ConstSource)
+ ConstantSpecs::BEFORE_DEFINE_LOCATION.should == autoload_location
+ ConstantSpecs.send :remove_const, :ConstSource
+ ConstantSpecs.send :remove_const, :BEFORE_DEFINE_LOCATION
+ end
+ end
end
end
diff --git a/spec/ruby/core/module/constants_spec.rb b/spec/ruby/core/module/constants_spec.rb
index 330da1cc88..f2f12761e3 100644
--- a/spec/ruby/core/module/constants_spec.rb
+++ b/spec/ruby/core/module/constants_spec.rb
@@ -13,12 +13,13 @@ describe "Module.constants" do
it "returns an array of Symbol names" do
# This in NOT an exhaustive list
- Module.constants.should include(:Array, :Class, :Comparable, :Dir,
+ Module.constants.to_set.should >= Set[
+ :Array, :Class, :Comparable, :Dir,
:Enumerable, :ENV, :Exception, :FalseClass,
:File, :Float, :Hash, :Integer, :IO,
:Kernel, :Math, :Method, :Module, :NilClass,
:Numeric, :Object, :Range, :Regexp, :String,
- :Symbol, :Thread, :Time, :TrueClass)
+ :Symbol, :Thread, :Time, :TrueClass]
end
it "returns Module's constants when given a parameter" do
@@ -92,6 +93,6 @@ describe "Module#constants" do
end
it "includes names of constants defined after a module is included" do
- ConstantSpecs::ContainerA.constants.should include(:CS_CONST251)
+ ConstantSpecs::ContainerA.constants.should.include?(:CS_CONST251)
end
end
diff --git a/spec/ruby/core/module/define_method_spec.rb b/spec/ruby/core/module/define_method_spec.rb
index c65b30de24..f838e2b85f 100644
--- a/spec/ruby/core/module/define_method_spec.rb
+++ b/spec/ruby/core/module/define_method_spec.rb
@@ -12,7 +12,7 @@ describe "passed { |a, b = 1| } creates a method that" do
end
it "raises an ArgumentError when passed zero arguments" do
- -> { @klass.new.m }.should raise_error(ArgumentError)
+ -> { @klass.new.m }.should.raise(ArgumentError)
end
it "has a default value for b when passed one argument" do
@@ -24,7 +24,7 @@ describe "passed { |a, b = 1| } creates a method that" do
end
it "raises an ArgumentError when passed three arguments" do
- -> { @klass.new.m(1, 2, 3) }.should raise_error(ArgumentError)
+ -> { @klass.new.m(1, 2, 3) }.should.raise(ArgumentError)
end
end
@@ -47,7 +47,7 @@ describe "Module#define_method when given an UnboundMethod" do
end
define_method(:another_test_method, instance_method(:test_method))
end
- klass.new.should have_method(:another_test_method)
+ klass.new.should.respond_to?(:another_test_method)
end
describe "defining a method on a singleton class" do
@@ -83,7 +83,7 @@ describe "Module#define_method when given an UnboundMethod" do
define_method :piggy, instance_method(:ziggy)
end
- -> { foo.new.ziggy }.should raise_error(NoMethodError)
+ -> { foo.new.ziggy }.should.raise(NoMethodError)
foo.new.piggy.should == 'piggy'
end
end
@@ -115,8 +115,8 @@ describe "Module#define_method when name is not a special private name" do
define_method(:baz, ModuleSpecs::EmptyFooMethod)
end
- klass.should have_public_instance_method(:bar)
- klass.should have_private_instance_method(:baz)
+ klass.public_instance_methods(false).should.include?(:bar)
+ klass.private_instance_methods(false).should.include?(:baz)
end
end
@@ -129,10 +129,21 @@ describe "Module#define_method when name is not a special private name" do
klass.send(:define_method, :baz, ModuleSpecs::EmptyFooMethod)
end
- klass.should have_public_instance_method(:bar)
- klass.should have_public_instance_method(:baz)
+ klass.public_instance_methods(false).should.include?(:bar)
+ klass.public_instance_methods(false).should.include?(:baz)
end
end
+
+ it "sets the method owner for a dynamically added method with a different original owner" do
+ mixin_module = Module.new do
+ def bar; end
+ end
+
+ foo = Object.new
+ foo.singleton_class.define_method(:bar, mixin_module.instance_method(:bar))
+
+ foo.method(:bar).owner.should == foo.singleton_class
+ end
end
describe "passed a block" do
@@ -144,8 +155,8 @@ describe "Module#define_method when name is not a special private name" do
define_method(:baz) {}
end
- klass.should have_public_instance_method(:bar)
- klass.should have_private_instance_method(:baz)
+ klass.public_instance_methods(false).should.include?(:bar)
+ klass.private_instance_methods(false).should.include?(:baz)
end
end
@@ -158,8 +169,8 @@ describe "Module#define_method when name is not a special private name" do
klass.send(:define_method, :baz) {}
end
- klass.should have_public_instance_method(:bar)
- klass.should have_public_instance_method(:baz)
+ klass.public_instance_methods(false).should.include?(:bar)
+ klass.public_instance_methods(false).should.include?(:baz)
end
end
end
@@ -171,7 +182,7 @@ describe "Module#define_method when name is :initialize" do
klass = Class.new do
define_method(:initialize) { }
end
- klass.should have_private_instance_method(:initialize)
+ klass.private_instance_methods(false).should.include?(:initialize)
end
end
@@ -182,7 +193,7 @@ describe "Module#define_method when name is :initialize" do
end
define_method(:initialize, instance_method(:test_method))
end
- klass.should have_private_instance_method(:initialize)
+ klass.private_instance_methods(false).should.include?(:initialize)
end
end
end
@@ -219,24 +230,61 @@ describe "Module#define_method" do
o.block_test2.should == o
end
+ it "raises TypeError if name cannot converted to String" do
+ -> {
+ Class.new { define_method(1001, -> {}) }
+ }.should.raise(TypeError, /is not a symbol nor a string/)
+
+ -> {
+ Class.new { define_method([], -> {}) }
+ }.should.raise(TypeError, /is not a symbol nor a string/)
+ end
+
+ it "converts non-String name to String with #to_str" do
+ obj = Object.new
+ def obj.to_str() "foo" end
+
+ new_class = Class.new { define_method(obj, -> { :called }) }
+ new_class.new.foo.should == :called
+ end
+
+ it "raises TypeError when #to_str called on non-String name returns non-String value" do
+ obj = Object.new
+ def obj.to_str() [] end
+
+ -> {
+ Class.new { define_method(obj, -> {}) }
+ }.should raise_consistent_error(TypeError, /can't convert Object into String/)
+ end
+
it "raises a TypeError when the given method is no Method/Proc" do
-> {
Class.new { define_method(:test, "self") }
- }.should raise_error(TypeError)
+ }.should.raise(TypeError, "wrong argument type String (expected Proc/Method/UnboundMethod)")
-> {
Class.new { define_method(:test, 1234) }
- }.should raise_error(TypeError)
+ }.should.raise(TypeError, "wrong argument type Integer (expected Proc/Method/UnboundMethod)")
-> {
Class.new { define_method(:test, nil) }
- }.should raise_error(TypeError)
+ }.should.raise(TypeError, "wrong argument type NilClass (expected Proc/Method/UnboundMethod)")
+ end
+
+ it "uses provided Method/Proc even if block is specified" do
+ new_class = Class.new do
+ define_method(:test, -> { :method_is_called }) do
+ :block_is_called
+ end
+ end
+
+ new_class.new.test.should == :method_is_called
end
it "raises an ArgumentError when no block is given" do
-> {
Class.new { define_method(:test) }
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "does not use the caller block when no block is given" do
@@ -249,7 +297,7 @@ describe "Module#define_method" do
-> {
o.define(:foo) { raise "not used" }
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "does not change the arity check style of the original proc" do
@@ -259,13 +307,13 @@ describe "Module#define_method" do
end
obj = DefineMethodSpecClass.new
- -> { obj.proc_style_test :arg }.should raise_error(ArgumentError)
+ -> { obj.proc_style_test :arg }.should.raise(ArgumentError)
end
it "raises a FrozenError if frozen" do
-> {
Class.new { freeze; define_method(:foo) {} }
- }.should raise_error(FrozenError)
+ }.should.raise(FrozenError)
end
it "accepts a Method (still bound)" do
@@ -278,13 +326,13 @@ describe "Module#define_method" do
o = DefineMethodSpecClass.new
o.data = :foo
m = o.method(:inspect_data)
- m.should be_an_instance_of(Method)
+ m.should.instance_of?(Method)
klass = Class.new(DefineMethodSpecClass)
klass.send(:define_method,:other_inspect, m)
c = klass.new
c.data = :bar
c.other_inspect.should == "data is bar"
- ->{o.other_inspect}.should raise_error(NoMethodError)
+ ->{o.other_inspect}.should.raise(NoMethodError)
end
it "raises a TypeError when a Method from a singleton class is defined on another class" do
@@ -298,7 +346,7 @@ describe "Module#define_method" do
-> {
Class.new { define_method :bar, m }
- }.should raise_error(TypeError, /can't bind singleton method to a different class/)
+ }.should.raise(TypeError, /can't bind singleton method to a different class/)
end
it "raises a TypeError when a Method from one class is defined on an unrelated class" do
@@ -310,7 +358,7 @@ describe "Module#define_method" do
-> {
Class.new { define_method :bar, m }
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "accepts an UnboundMethod from an attr_accessor method" do
@@ -322,7 +370,7 @@ describe "Module#define_method" do
o = DefineMethodSpecClass.new
DefineMethodSpecClass.send(:undef_method, :accessor_method)
- -> { o.accessor_method }.should raise_error(NoMethodError)
+ -> { o.accessor_method }.should.raise(NoMethodError)
DefineMethodSpecClass.send(:define_method, :accessor_method, m)
@@ -367,7 +415,7 @@ describe "Module#define_method" do
end
o = DefineMethodByProcClass.new
- o.proc_test.should be_true
+ o.proc_test.should == true
end
it "accepts a String method name" do
@@ -381,7 +429,7 @@ describe "Module#define_method" do
end
it "is a public method" do
- Module.should have_public_instance_method(:define_method)
+ Module.public_instance_methods(false).should.include?(:define_method)
end
it "returns its symbol" do
@@ -395,7 +443,7 @@ describe "Module#define_method" do
klass = Class.new {
define_method :bar, ModuleSpecs::UnboundMethodTest.instance_method(:foo)
}
- klass.new.should respond_to(:bar)
+ klass.new.should.respond_to?(:bar)
end
it "allows an UnboundMethod from a parent class to be defined on a child class" do
@@ -403,7 +451,7 @@ describe "Module#define_method" do
child = Class.new(parent) {
define_method :baz, parent.instance_method(:foo)
}
- child.new.should respond_to(:baz)
+ child.new.should.respond_to?(:baz)
end
it "allows an UnboundMethod from a module to be defined on another unrelated module" do
@@ -411,7 +459,7 @@ describe "Module#define_method" do
define_method :bar, ModuleSpecs::UnboundMethodTest.instance_method(:foo)
}
klass = Class.new { include mod }
- klass.new.should respond_to(:bar)
+ klass.new.should.respond_to?(:bar)
end
@@ -427,7 +475,10 @@ describe "Module#define_method" do
ParentClass = Class.new { define_method(:foo) { :bar } }
ChildClass = Class.new(ParentClass) { define_method(:foo) { :baz } }
ParentClass.send :define_method, :foo, ChildClass.instance_method(:foo)
- }.should raise_error(TypeError, /bind argument must be a subclass of ChildClass/)
+ }.should.raise(TypeError, /bind argument must be a subclass of ChildClass/)
+ ensure
+ Object.send(:remove_const, :ParentClass)
+ Object.send(:remove_const, :ChildClass)
end
it "raises a TypeError when an UnboundMethod from one class is defined on an unrelated class" do
@@ -435,7 +486,7 @@ describe "Module#define_method" do
DestinationClass = Class.new {
define_method :bar, ModuleSpecs::InstanceMeth.instance_method(:foo)
}
- }.should raise_error(TypeError, /bind argument must be a subclass of ModuleSpecs::InstanceMeth/)
+ }.should.raise(TypeError, /bind argument must be a subclass of ModuleSpecs::InstanceMeth/)
end
it "raises a TypeError when an UnboundMethod from a singleton class is defined on another class" do
@@ -449,7 +500,34 @@ describe "Module#define_method" do
-> {
Class.new { define_method :bar, m }
- }.should raise_error(TypeError, /can't bind singleton method to a different class/)
+ }.should.raise(TypeError, /can't bind singleton method to a different class/)
+ end
+
+ it "defines a new method with public visibility when a Method passed and the class/module of the context isn't equal to the receiver of #define_method" do
+ c = Class.new do
+ private def foo
+ "public"
+ end
+ end
+
+ object = c.new
+ object.singleton_class.define_method(:bar, object.method(:foo))
+
+ object.bar.should == "public"
+ end
+
+ it "defines the new method according to the scope visibility when a Method passed and the class/module of the context is equal to the receiver of #define_method" do
+ c = Class.new do
+ def foo; end
+ end
+
+ object = c.new
+ object.singleton_class.class_eval do
+ private
+ define_method(:bar, c.new.method(:foo))
+ end
+
+ -> { object.bar }.should.raise(NoMethodError)
end
end
@@ -466,11 +544,11 @@ describe "Module#define_method" do
end
it "raises an ArgumentError when passed one argument" do
- -> { @klass.new.m 1 }.should raise_error(ArgumentError)
+ -> { @klass.new.m 1 }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed two arguments" do
- -> { @klass.new.m 1, 2 }.should raise_error(ArgumentError)
+ -> { @klass.new.m 1, 2 }.should.raise(ArgumentError)
end
end
@@ -486,11 +564,11 @@ describe "Module#define_method" do
end
it "raises an ArgumentError when passed one argument" do
- -> { @klass.new.m 1 }.should raise_error(ArgumentError)
+ -> { @klass.new.m 1 }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed two arguments" do
- -> { @klass.new.m 1, 2 }.should raise_error(ArgumentError)
+ -> { @klass.new.m 1, 2 }.should.raise(ArgumentError)
end
end
@@ -502,15 +580,15 @@ describe "Module#define_method" do
end
it "raises an ArgumentError when passed zero arguments" do
- -> { @klass.new.m }.should raise_error(ArgumentError)
+ -> { @klass.new.m }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed zero arguments and a block" do
- -> { @klass.new.m { :computed } }.should raise_error(ArgumentError)
+ -> { @klass.new.m { :computed } }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed two arguments" do
- -> { @klass.new.m 1, 2 }.should raise_error(ArgumentError)
+ -> { @klass.new.m 1, 2 }.should.raise(ArgumentError)
end
it "receives the value passed as the argument when passed one argument" do
@@ -526,15 +604,15 @@ describe "Module#define_method" do
end
it "raises an ArgumentError when passed zero arguments" do
- -> { @klass.new.m }.should raise_error(ArgumentError)
+ -> { @klass.new.m }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed zero arguments and a block" do
- -> { @klass.new.m { :computed } }.should raise_error(ArgumentError)
+ -> { @klass.new.m { :computed } }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed two arguments" do
- -> { @klass.new.m 1, 2 }.should raise_error(ArgumentError)
+ -> { @klass.new.m 1, 2 }.should.raise(ArgumentError)
end
it "receives the value passed as the argument when passed one argument" do
@@ -576,7 +654,7 @@ describe "Module#define_method" do
end
it "raises an ArgumentError when passed zero arguments" do
- -> { @klass.new.m }.should raise_error(ArgumentError)
+ -> { @klass.new.m }.should.raise(ArgumentError)
end
it "returns the value computed by the block when passed one argument" do
@@ -604,19 +682,19 @@ describe "Module#define_method" do
end
it "raises an ArgumentError when passed zero arguments" do
- -> { @klass.new.m }.should raise_error(ArgumentError)
+ -> { @klass.new.m }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed one argument" do
- -> { @klass.new.m 1 }.should raise_error(ArgumentError)
+ -> { @klass.new.m 1 }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed one argument and a block" do
- -> { @klass.new.m(1) { } }.should raise_error(ArgumentError)
+ -> { @klass.new.m(1) { } }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed three arguments" do
- -> { @klass.new.m 1, 2, 3 }.should raise_error(ArgumentError)
+ -> { @klass.new.m 1, 2, 3 }.should.raise(ArgumentError)
end
end
@@ -628,15 +706,15 @@ describe "Module#define_method" do
end
it "raises an ArgumentError when passed zero arguments" do
- -> { @klass.new.m }.should raise_error(ArgumentError)
+ -> { @klass.new.m }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed one argument" do
- -> { @klass.new.m 1 }.should raise_error(ArgumentError)
+ -> { @klass.new.m 1 }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed one argument and a block" do
- -> { @klass.new.m(1) { } }.should raise_error(ArgumentError)
+ -> { @klass.new.m(1) { } }.should.raise(ArgumentError)
end
it "receives an empty array as the third argument when passed two arguments" do
@@ -649,7 +727,7 @@ describe "Module#define_method" do
end
end
-describe "Method#define_method when passed a Method object" do
+describe "Module#define_method when passed a Method object" do
before :each do
@klass = Class.new do
def m(a, b, *c)
@@ -674,7 +752,7 @@ describe "Method#define_method when passed a Method object" do
end
end
-describe "Method#define_method when passed an UnboundMethod object" do
+describe "Module#define_method when passed an UnboundMethod object" do
before :each do
@klass = Class.new do
def m(a, b, *c)
@@ -699,7 +777,7 @@ describe "Method#define_method when passed an UnboundMethod object" do
end
end
-describe "Method#define_method when passed a Proc object" do
+describe "Module#define_method when passed a Proc object" do
describe "and a method is defined inside" do
it "defines the nested method in the default definee where the Proc was created" do
prc = nil
@@ -717,14 +795,14 @@ describe "Method#define_method when passed a Proc object" do
o = c.new
o.test
- o.should_not have_method :nested_method_in_proc_for_define_method
+ o.should_not.respond_to? :nested_method_in_proc_for_define_method
t.new.nested_method_in_proc_for_define_method.should == 42
end
end
end
-describe "Method#define_method when passed a block" do
+describe "Module#define_method when passed a block" do
describe "behaves exactly like a lambda" do
it "for return" do
Class.new do
diff --git a/spec/ruby/core/module/deprecate_constant_spec.rb b/spec/ruby/core/module/deprecate_constant_spec.rb
index aabef934c4..597379eb87 100644
--- a/spec/ruby/core/module/deprecate_constant_spec.rb
+++ b/spec/ruby/core/module/deprecate_constant_spec.rb
@@ -19,9 +19,9 @@ describe "Module#deprecate_constant" do
-> {
value = @module::PUBLIC1
}.should complain(/warning: constant .+::PUBLIC1 is deprecated/)
- value.should equal(@value)
+ value.should.equal?(@value)
- -> { @module::PRIVATE }.should raise_error(NameError)
+ -> { @module::PRIVATE }.should.raise(NameError)
end
it "warns with a message" do
@@ -44,6 +44,15 @@ describe "Module#deprecate_constant" do
end
end
+ ruby_bug '#20900', ''...'3.4' do
+ describe "when removing the deprecated module" do
+ it "warns with a message" do
+ @module.deprecate_constant :PUBLIC1
+ -> { @module.module_eval {remove_const :PUBLIC1} }.should complain(/warning: constant .+::PUBLIC1 is deprecated/)
+ end
+ end
+ end
+
it "accepts multiple symbols and strings as constant names" do
@module.deprecate_constant "PUBLIC1", :PUBLIC2
@@ -52,10 +61,10 @@ describe "Module#deprecate_constant" do
end
it "returns self" do
- @module.deprecate_constant(:PUBLIC1).should equal(@module)
+ @module.deprecate_constant(:PUBLIC1).should.equal?(@module)
end
it "raises a NameError when given an undefined name" do
- -> { @module.deprecate_constant :UNDEFINED }.should raise_error(NameError)
+ -> { @module.deprecate_constant :UNDEFINED }.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/module/extend_object_spec.rb b/spec/ruby/core/module/extend_object_spec.rb
index 1fd1abc0b5..b428eb7924 100644
--- a/spec/ruby/core/module/extend_object_spec.rb
+++ b/spec/ruby/core/module/extend_object_spec.rb
@@ -7,18 +7,18 @@ describe "Module#extend_object" do
end
it "is a private method" do
- Module.should have_private_instance_method(:extend_object)
+ Module.private_instance_methods(false).should.include?(:extend_object)
end
describe "on Class" do
it "is undefined" do
- Class.should_not have_private_instance_method(:extend_object, true)
+ Class.private_instance_methods(true).should_not.include?(:extend_object)
end
it "raises a TypeError if calling after rebinded to Class" do
-> {
Module.instance_method(:extend_object).bind(Class.new).call Object.new
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
@@ -49,8 +49,8 @@ describe "Module#extend_object" do
end
it "raises a RuntimeError before extending the object" do
- -> { @receiver.send(:extend_object, @object) }.should raise_error(RuntimeError)
- @object.should_not be_kind_of(@receiver)
+ -> { @receiver.send(:extend_object, @object) }.should.raise(RuntimeError)
+ @object.should_not.is_a?(@receiver)
end
end
end
diff --git a/spec/ruby/core/module/extended_spec.rb b/spec/ruby/core/module/extended_spec.rb
index c6300ffa0b..a4ec5a4ba7 100644
--- a/spec/ruby/core/module/extended_spec.rb
+++ b/spec/ruby/core/module/extended_spec.rb
@@ -39,6 +39,6 @@ describe "Module#extended" do
end
it "is private in its default implementation" do
- Module.new.private_methods.should include(:extended)
+ Module.new.private_methods.should.include?(:extended)
end
end
diff --git a/spec/ruby/core/module/fixtures/autoload_const_source_location.rb b/spec/ruby/core/module/fixtures/autoload_const_source_location.rb
new file mode 100644
index 0000000000..ee0e5a689f
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_const_source_location.rb
@@ -0,0 +1,6 @@
+module ConstantSpecs
+ BEFORE_DEFINE_LOCATION = const_source_location(:ConstSource)
+ module ConstSource
+ LOCATION = Object.const_source_location(name)
+ end
+end
diff --git a/spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb b/spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb
new file mode 100644
index 0000000000..a9d886dfd6
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb
@@ -0,0 +1,6 @@
+module ModuleSpecs::Autoload
+ class DuringAutoloadAfterDefine
+ block = ScratchPad.recorded
+ ScratchPad.record(block.call)
+ end
+end
diff --git a/spec/ruby/core/module/fixtures/autoload_relative_a.rb b/spec/ruby/core/module/fixtures/autoload_relative_a.rb
new file mode 100644
index 0000000000..494181adc2
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_relative_a.rb
@@ -0,0 +1,9 @@
+module ModuleSpecs
+ module Autoload
+ class AutoloadRelativeA
+ end
+
+ class AutoloadRelativeB
+ end
+ end
+end
diff --git a/spec/ruby/core/module/fixtures/classes.rb b/spec/ruby/core/module/fixtures/classes.rb
index a64f672b2f..964f64c593 100644
--- a/spec/ruby/core/module/fixtures/classes.rb
+++ b/spec/ruby/core/module/fixtures/classes.rb
@@ -1,6 +1,6 @@
module ModuleSpecs
def self.without_test_modules(modules)
- ignore = %w[MSpecRSpecAdapter PP::ObjectMixin ModuleSpecs::IncludedInObject MainSpecs::Module ConstantSpecs::ModuleA]
+ ignore = %w[MSpecRSpecAdapter PP::ObjectMixin MainSpecs::Module ConstantSpecs::ModuleA]
modules.reject { |k| ignore.include?(k.name) }
end
@@ -42,6 +42,14 @@ module ModuleSpecs
class LookupChild < Lookup
end
+ module ModuleWithPrepend
+ prepend LookupMod
+ end
+
+ class WithPrependedModule
+ include ModuleWithPrepend
+ end
+
class Parent
# For private_class_method spec
def self.private_method; end
@@ -380,6 +388,7 @@ module ModuleSpecs
# empty modules
module M1; end
module M2; end
+ module M3; end
module Autoload
def self.use_ex1
@@ -587,6 +596,32 @@ module ModuleSpecs
private :foo
end
EmptyFooMethod = m.instance_method(:foo)
+
+ # for undefined_instance_methods spec
+ module UndefinedInstanceMethods
+ module Super
+ def super_included_method; end
+ end
+
+ class Parent
+ def undefed_method; end
+ undef_method :undefed_method
+
+ def parent_method; end
+ def another_parent_method; end
+ end
+
+ class Child < Parent
+ include Super
+
+ undef_method :parent_method
+ undef_method :another_parent_method
+ end
+
+ class Grandchild < Child
+ undef_method :super_included_method
+ end
+ end
end
class Object
diff --git a/spec/ruby/core/module/fixtures/const_added.rb b/spec/ruby/core/module/fixtures/const_added.rb
new file mode 100644
index 0000000000..0f5baad65d
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/const_added.rb
@@ -0,0 +1,4 @@
+module ModuleSpecs
+ module ConstAddedSpecs
+ end
+end
diff --git a/spec/ruby/core/module/fixtures/module.rb b/spec/ruby/core/module/fixtures/module.rb
index 9050a272ec..34543ca2b4 100644
--- a/spec/ruby/core/module/fixtures/module.rb
+++ b/spec/ruby/core/module/fixtures/module.rb
@@ -1,4 +1,8 @@
module ModuleSpecs
module Anonymous
+ module Child
+ end
+
+ SameChild = Child
end
end
diff --git a/spec/ruby/core/module/fixtures/name.rb b/spec/ruby/core/module/fixtures/name.rb
index fb9e66c309..25c74d3944 100644
--- a/spec/ruby/core/module/fixtures/name.rb
+++ b/spec/ruby/core/module/fixtures/name.rb
@@ -7,4 +7,7 @@ module ModuleSpecs
Cß.name
end
end
+
+ module NameSpecs
+ end
end
diff --git a/spec/ruby/core/module/fixtures/set_temporary_name.rb b/spec/ruby/core/module/fixtures/set_temporary_name.rb
new file mode 100644
index 0000000000..901b3b94d1
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/set_temporary_name.rb
@@ -0,0 +1,4 @@
+module ModuleSpecs
+ module SetTemporaryNameSpec
+ end
+end
diff --git a/spec/ruby/core/module/gt_spec.rb b/spec/ruby/core/module/gt_spec.rb
index b8a73c9ff9..04cdd90efb 100644
--- a/spec/ruby/core/module/gt_spec.rb
+++ b/spec/ruby/core/module/gt_spec.rb
@@ -3,10 +3,10 @@ require_relative 'fixtures/classes'
describe "Module#>" do
it "returns false if self is a subclass of or includes the given module" do
- (ModuleSpecs::Child > ModuleSpecs::Parent).should be_false
- (ModuleSpecs::Child > ModuleSpecs::Basic).should be_false
- (ModuleSpecs::Child > ModuleSpecs::Super).should be_false
- (ModuleSpecs::Super > ModuleSpecs::Basic).should be_false
+ (ModuleSpecs::Child > ModuleSpecs::Parent).should == false
+ (ModuleSpecs::Child > ModuleSpecs::Basic).should == false
+ (ModuleSpecs::Child > ModuleSpecs::Super).should == false
+ (ModuleSpecs::Super > ModuleSpecs::Basic).should == false
end
it "returns true if self is a superclass of or included by the given module" do
@@ -31,6 +31,6 @@ describe "Module#>" do
end
it "raises a TypeError if the argument is not a class/module" do
- -> { ModuleSpecs::Parent > mock('x') }.should raise_error(TypeError)
+ -> { ModuleSpecs::Parent > mock('x') }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/module/gte_spec.rb b/spec/ruby/core/module/gte_spec.rb
index 18c60ba586..b19fc9fac3 100644
--- a/spec/ruby/core/module/gte_spec.rb
+++ b/spec/ruby/core/module/gte_spec.rb
@@ -28,6 +28,6 @@ describe "Module#>=" do
end
it "raises a TypeError if the argument is not a class/module" do
- -> { ModuleSpecs::Parent >= mock('x') }.should raise_error(TypeError)
+ -> { ModuleSpecs::Parent >= mock('x') }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/module/include_spec.rb b/spec/ruby/core/module/include_spec.rb
index c47e052d22..b6201550e4 100644
--- a/spec/ruby/core/module/include_spec.rb
+++ b/spec/ruby/core/module/include_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Module#include" do
it "is a public method" do
- Module.should have_public_instance_method(:include, false)
+ Module.public_instance_methods(false).should.include?(:include)
end
it "calls #append_features(self) in reversed order on each module" do
@@ -33,24 +33,40 @@ describe "Module#include" do
end
it "adds all ancestor modules when a previously included module is included again" do
- ModuleSpecs::MultipleIncludes.ancestors.should include(ModuleSpecs::MA, ModuleSpecs::MB)
+ ModuleSpecs::MultipleIncludes.ancestors.to_set.should >= Set[ModuleSpecs::MA, ModuleSpecs::MB]
ModuleSpecs::MB.include(ModuleSpecs::MC)
ModuleSpecs::MultipleIncludes.include(ModuleSpecs::MB)
- ModuleSpecs::MultipleIncludes.ancestors.should include(ModuleSpecs::MA, ModuleSpecs::MB, ModuleSpecs::MC)
+ ModuleSpecs::MultipleIncludes.ancestors.to_set.should >= Set[ModuleSpecs::MA, ModuleSpecs::MB, ModuleSpecs::MC]
end
it "raises a TypeError when the argument is not a Module" do
- -> { ModuleSpecs::Basic.include(Class.new) }.should raise_error(TypeError)
+ -> { ModuleSpecs::Basic.include(Class.new) }.should.raise(TypeError)
end
it "does not raise a TypeError when the argument is an instance of a subclass of Module" do
- -> { ModuleSpecs::SubclassSpec.include(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
+ class ModuleSpecs::SubclassSpec::AClass
+ end
+ -> { ModuleSpecs::SubclassSpec::AClass.include(ModuleSpecs::Subclass.new) }.should_not.raise(TypeError)
+ ensure
+ ModuleSpecs::SubclassSpec.send(:remove_const, :AClass)
+ end
+
+ it "raises a TypeError when the argument is a refinement" do
+ refinement = nil
+
+ Module.new do
+ refine String do
+ refinement = self
+ end
+ end
+
+ -> { ModuleSpecs::Basic.include(refinement) }.should.raise(TypeError, "Cannot include refinement")
end
it "imports constants to modules and classes" do
- ModuleSpecs::A.constants.should include(:CONSTANT_A)
- ModuleSpecs::B.constants.should include(:CONSTANT_A, :CONSTANT_B)
- ModuleSpecs::C.constants.should include(:CONSTANT_A, :CONSTANT_B)
+ ModuleSpecs::A.constants.should.include?(:CONSTANT_A)
+ ModuleSpecs::B.constants.to_set.should >= Set[:CONSTANT_A, :CONSTANT_B]
+ ModuleSpecs::C.constants.to_set.should >= Set[:CONSTANT_A, :CONSTANT_B]
end
it "shadows constants from ancestors" do
@@ -68,9 +84,9 @@ describe "Module#include" do
end
it "imports instance methods to modules and classes" do
- ModuleSpecs::A.instance_methods.should include(:ma)
- ModuleSpecs::B.instance_methods.should include(:ma,:mb)
- ModuleSpecs::C.instance_methods.should include(:ma,:mb)
+ ModuleSpecs::A.instance_methods.should.include?(:ma)
+ ModuleSpecs::B.instance_methods.to_set.should >= Set[:ma,:mb]
+ ModuleSpecs::C.instance_methods.to_set.should >= Set[:ma,:mb]
end
it "does not import methods to modules and classes" do
@@ -104,9 +120,9 @@ describe "Module#include" do
class A; include M; end
class B < A; include M; end
- all = [A,B,M]
+ all = [A, B, M]
- (B.ancestors & all).should == [B, A, M]
+ (B.ancestors.filter { |a| all.include?(a) }).should == [B, A, M]
end
end
@@ -130,7 +146,7 @@ describe "Module#include" do
anc = B.ancestors
[B, U, V, W, A, X].each do |i|
- anc.include?(i).should be_true
+ anc.include?(i).should == true
end
class B; include V; end
@@ -138,7 +154,7 @@ describe "Module#include" do
# the only new module is Y, it is added after U since it follows U in V mixin list:
anc = B.ancestors
[B, U, Y, V, W, A, X].each do |i|
- anc.include?(i).should be_true
+ anc.include?(i).should == true
end
end
end
@@ -162,7 +178,7 @@ describe "Module#include" do
module ModuleSpecs::M
include ModuleSpecs::M
end
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "doesn't accept no-arguments" do
@@ -170,7 +186,7 @@ describe "Module#include" do
Module.new do
include
end
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "returns the class it's included into" do
@@ -399,6 +415,8 @@ describe "Module#include" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdated)
end
it "updates the constant when a module included after a call is later updated" do
@@ -425,6 +443,8 @@ describe "Module#include" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstLaterUpdated)
end
it "updates the constant when a module included in another module after a call is later updated" do
@@ -451,6 +471,8 @@ describe "Module#include" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstModuleLaterUpdated)
end
it "updates the constant when a nested included module is updated" do
@@ -479,6 +501,8 @@ describe "Module#include" do
N.const_set(:FOO, 'n')
B.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNestedIncludeUpdated)
end
it "updates the constant when a new module is included" do
@@ -503,6 +527,8 @@ describe "Module#include" do
B.include(M)
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNewInclude)
end
it "updates the constant when a new module with nested module is included" do
@@ -531,6 +557,8 @@ describe "Module#include" do
B.include M
B.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNestedIncluded)
end
it "overrides a previous super method call" do
@@ -553,6 +581,29 @@ describe "Module#include" do
c2.include(m)
c2.new.foo.should == [:c2, :m1]
end
+
+ it "update a module when a nested module is updated and includes a module on its own" do
+ m1 = Module.new
+ m2 = Module.new do
+ def m2; [:m2]; end
+ end
+ m3 = Module.new do
+ def m3; [:m3]; end
+ end
+ m4 = Module.new do
+ def m4; [:m4]; end
+ end
+ c = Class.new
+
+ c.include(m1)
+ m1.include(m2)
+ m2.include(m3)
+ m3.include(m4)
+
+ c.new.m2.should == [:m2]
+ c.new.m3.should == [:m3]
+ c.new.m4.should == [:m4]
+ end
end
describe "Module#include?" do
@@ -571,7 +622,7 @@ describe "Module#include?" do
end
it "raises a TypeError when no module was given" do
- -> { ModuleSpecs::Child.include?("Test") }.should raise_error(TypeError)
- -> { ModuleSpecs::Child.include?(ModuleSpecs::Parent) }.should raise_error(TypeError)
+ -> { ModuleSpecs::Child.include?("Test") }.should.raise(TypeError)
+ -> { ModuleSpecs::Child.include?(ModuleSpecs::Parent) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/module/included_modules_spec.rb b/spec/ruby/core/module/included_modules_spec.rb
index 40e20953f4..e22ee5e6cf 100644
--- a/spec/ruby/core/module/included_modules_spec.rb
+++ b/spec/ruby/core/module/included_modules_spec.rb
@@ -4,9 +4,11 @@ require_relative 'fixtures/classes'
describe "Module#included_modules" do
it "returns a list of modules included in self" do
ModuleSpecs.included_modules.should == []
- ModuleSpecs::Child.included_modules.should include(ModuleSpecs::Super, ModuleSpecs::Basic, Kernel)
- ModuleSpecs::Parent.included_modules.should include(Kernel)
+
+ ModuleSpecs::Child.included_modules.to_set.should >= Set[ModuleSpecs::Super, ModuleSpecs::Basic, Kernel]
+ ModuleSpecs::Parent.included_modules.should.include?(Kernel)
ModuleSpecs::Basic.included_modules.should == []
- ModuleSpecs::Super.included_modules.should include(ModuleSpecs::Basic)
+ ModuleSpecs::Super.included_modules.should.include?(ModuleSpecs::Basic)
+ ModuleSpecs::WithPrependedModule.included_modules.should.include?(ModuleSpecs::ModuleWithPrepend)
end
end
diff --git a/spec/ruby/core/module/included_spec.rb b/spec/ruby/core/module/included_spec.rb
index 2fdd4325f2..d8a6c3f839 100644
--- a/spec/ruby/core/module/included_spec.rb
+++ b/spec/ruby/core/module/included_spec.rb
@@ -34,7 +34,7 @@ describe "Module#included" do
end
it "is private in its default implementation" do
- Module.should have_private_instance_method(:included)
+ Module.private_instance_methods(false).should.include?(:included)
end
it "works with super using a singleton class" do
diff --git a/spec/ruby/core/module/instance_method_spec.rb b/spec/ruby/core/module/instance_method_spec.rb
index b4d6a0d8c8..8615e352f6 100644
--- a/spec/ruby/core/module/instance_method_spec.rb
+++ b/spec/ruby/core/module/instance_method_spec.rb
@@ -9,7 +9,7 @@ describe "Module#instance_method" do
end
it "is a public method" do
- Module.should have_public_instance_method(:instance_method, false)
+ Module.public_instance_methods(false).should.include?(:instance_method)
end
it "requires an argument" do
@@ -17,26 +17,26 @@ describe "Module#instance_method" do
end
it "returns an UnboundMethod corresponding to the given name" do
- @parent_um.should be_kind_of(UnboundMethod)
+ @parent_um.should.is_a?(UnboundMethod)
@parent_um.bind(ModuleSpecs::InstanceMeth.new).call.should == :foo
end
it "returns an UnboundMethod corresponding to the given name from a superclass" do
- @child_um.should be_kind_of(UnboundMethod)
+ @child_um.should.is_a?(UnboundMethod)
@child_um.bind(ModuleSpecs::InstanceMethChild.new).call.should == :foo
end
it "returns an UnboundMethod corresponding to the given name from an included Module" do
- @mod_um.should be_kind_of(UnboundMethod)
+ @mod_um.should.is_a?(UnboundMethod)
@mod_um.bind(ModuleSpecs::InstanceMethChild.new).call.should == :bar
end
it "returns an UnboundMethod when given a protected method name" do
- ModuleSpecs::Basic.instance_method(:protected_module).should be_an_instance_of(UnboundMethod)
+ ModuleSpecs::Basic.instance_method(:protected_module).should.instance_of?(UnboundMethod)
end
it "returns an UnboundMethod when given a private method name" do
- ModuleSpecs::Basic.instance_method(:private_module).should be_an_instance_of(UnboundMethod)
+ ModuleSpecs::Basic.instance_method(:private_module).should.instance_of?(UnboundMethod)
end
it "gives UnboundMethod method name, Module defined in and Module extracted from" do
@@ -45,20 +45,41 @@ describe "Module#instance_method" do
@parent_um.inspect.should =~ /\bModuleSpecs::InstanceMeth\b/
@child_um.inspect.should =~ /\bfoo\b/
@child_um.inspect.should =~ /\bModuleSpecs::InstanceMeth\b/
- @child_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/
+
@mod_um.inspect.should =~ /\bbar\b/
@mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethMod\b/
- @mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/
end
- it "raises a TypeError if not passed a symbol" do
- -> { Object.instance_method([]) }.should raise_error(TypeError)
- -> { Object.instance_method(0) }.should raise_error(TypeError)
+ it "raises a TypeError if the given name is not a String/Symbol" do
+ -> { Object.instance_method([]) }.should.raise(TypeError, /is not a symbol nor a string/)
+ -> { Object.instance_method(0) }.should.raise(TypeError, /is not a symbol nor a string/)
+ -> { Object.instance_method(nil) }.should.raise(TypeError, /is not a symbol nor a string/)
+ -> { Object.instance_method(mock('x')) }.should.raise(TypeError, /is not a symbol nor a string/)
+ end
+
+ it "accepts String name argument" do
+ method = ModuleSpecs::InstanceMeth.instance_method(:foo)
+ method.should.is_a?(UnboundMethod)
+ end
+
+ it "accepts Symbol name argument" do
+ method = ModuleSpecs::InstanceMeth.instance_method("foo")
+ method.should.is_a?(UnboundMethod)
end
- it "raises a TypeError if the given name is not a string/symbol" do
- -> { Object.instance_method(nil) }.should raise_error(TypeError)
- -> { Object.instance_method(mock('x')) }.should raise_error(TypeError)
+ it "converts non-String name by calling #to_str method" do
+ obj = Object.new
+ def obj.to_str() "foo" end
+
+ method = ModuleSpecs::InstanceMeth.instance_method(obj)
+ method.should.is_a?(UnboundMethod)
+ end
+
+ it "raises TypeError when passed non-String name and #to_str returns non-String value" do
+ obj = Object.new
+ def obj.to_str() [] end
+
+ -> { ModuleSpecs::InstanceMeth.instance_method(obj) }.should raise_consistent_error(TypeError, /can't convert Object into String/)
end
it "raises a NameError if the method has been undefined" do
@@ -68,11 +89,11 @@ describe "Module#instance_method" do
um.should == @parent_um
-> do
child.instance_method(:foo)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError if the method does not exist" do
- -> { Object.instance_method(:missing) }.should raise_error(NameError)
+ -> { Object.instance_method(:missing) }.should.raise(NameError)
end
it "sets the NameError#name attribute to the name of the missing method" do
diff --git a/spec/ruby/core/module/instance_methods_spec.rb b/spec/ruby/core/module/instance_methods_spec.rb
index d2d38cdda2..dbb6df8c34 100644
--- a/spec/ruby/core/module/instance_methods_spec.rb
+++ b/spec/ruby/core/module/instance_methods_spec.rb
@@ -4,21 +4,22 @@ require_relative 'fixtures/classes'
describe "Module#instance_methods" do
it "does not return methods undefined in a superclass" do
methods = ModuleSpecs::Parent.instance_methods(false)
- methods.should_not include(:undefed_method)
+ methods.should_not.include?(:undefed_method)
end
it "only includes module methods on an included module" do
methods = ModuleSpecs::Basic.instance_methods(false)
- methods.should include(:public_module)
+ methods.should.include?(:public_module)
# Child is an including class
methods = ModuleSpecs::Child.instance_methods(false)
- methods.should include(:public_child)
- methods.should_not include(:public_module)
+ methods.should.include?(:public_child)
+ methods.should_not.include?(:public_module)
end
it "does not return methods undefined in a subclass" do
methods = ModuleSpecs::Grandchild.instance_methods
- methods.should_not include(:parent_method, :another_parent_method)
+ methods.should_not.include?(:parent_method)
+ methods.should_not.include?(:another_parent_method)
end
it "does not return methods undefined in the current class" do
@@ -28,34 +29,35 @@ describe "Module#instance_methods" do
end
ModuleSpecs::Child.send(:undef_method, :undefed_child)
methods = ModuleSpecs::Child.instance_methods
- methods.should_not include(:undefed_method, :undefed_child)
+ methods.should_not.include?(:undefed_method)
+ methods.should_not.include?(:undefed_child)
end
it "does not return methods from an included module that are undefined in the class" do
- ModuleSpecs::Grandchild.instance_methods.should_not include(:super_included_method)
+ ModuleSpecs::Grandchild.instance_methods.should_not.include?(:super_included_method)
end
it "returns the public and protected methods of self if include_super is false" do
methods = ModuleSpecs::Parent.instance_methods(false)
- methods.should include(:protected_parent, :public_parent)
+ methods.to_set.should >= Set[:protected_parent, :public_parent]
methods = ModuleSpecs::Child.instance_methods(false)
- methods.should include(:protected_child, :public_child)
+ methods.to_set.should >= Set[:protected_child, :public_child]
end
it "returns the public and protected methods of self and it's ancestors" do
methods = ModuleSpecs::Basic.instance_methods
- methods.should include(:protected_module, :public_module)
+ methods.to_set.should >= Set[:protected_module, :public_module]
methods = ModuleSpecs::Super.instance_methods
- methods.should include(:protected_module, :protected_super_module,
- :public_module, :public_super_module)
+ methods.to_set.should >= Set[:protected_module, :protected_super_module,
+ :public_module, :public_super_module]
end
it "makes a private Object instance method public in Kernel" do
methods = Kernel.instance_methods
- methods.should include(:module_specs_private_method_on_object_for_kernel_public)
+ methods.should.include?(:module_specs_private_method_on_object_for_kernel_public)
methods = Object.instance_methods
- methods.should_not include(:module_specs_private_method_on_object_for_kernel_public)
+ methods.should_not.include?(:module_specs_private_method_on_object_for_kernel_public)
end
end
diff --git a/spec/ruby/core/module/lt_spec.rb b/spec/ruby/core/module/lt_spec.rb
index d7771e07a8..8567a24993 100644
--- a/spec/ruby/core/module/lt_spec.rb
+++ b/spec/ruby/core/module/lt_spec.rb
@@ -10,10 +10,10 @@ describe "Module#<" do
end
it "returns false if self is a superclass of or included by the given module" do
- (ModuleSpecs::Parent < ModuleSpecs::Child).should be_false
- (ModuleSpecs::Basic < ModuleSpecs::Child).should be_false
- (ModuleSpecs::Super < ModuleSpecs::Child).should be_false
- (ModuleSpecs::Basic < ModuleSpecs::Super).should be_false
+ (ModuleSpecs::Parent < ModuleSpecs::Child).should == false
+ (ModuleSpecs::Basic < ModuleSpecs::Child).should == false
+ (ModuleSpecs::Super < ModuleSpecs::Child).should == false
+ (ModuleSpecs::Basic < ModuleSpecs::Super).should == false
end
it "returns false if self is the same as the given module" do
@@ -31,6 +31,6 @@ describe "Module#<" do
end
it "raises a TypeError if the argument is not a class/module" do
- -> { ModuleSpecs::Parent < mock('x') }.should raise_error(TypeError)
+ -> { ModuleSpecs::Parent < mock('x') }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/module/lte_spec.rb b/spec/ruby/core/module/lte_spec.rb
index 7a0e8496b8..c6aab94e9f 100644
--- a/spec/ruby/core/module/lte_spec.rb
+++ b/spec/ruby/core/module/lte_spec.rb
@@ -28,6 +28,6 @@ describe "Module#<=" do
end
it "raises a TypeError if the argument is not a class/module" do
- -> { ModuleSpecs::Parent <= mock('x') }.should raise_error(TypeError)
+ -> { ModuleSpecs::Parent <= mock('x') }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/module/method_added_spec.rb b/spec/ruby/core/module/method_added_spec.rb
index b983c8da76..996a14eb86 100644
--- a/spec/ruby/core/module/method_added_spec.rb
+++ b/spec/ruby/core/module/method_added_spec.rb
@@ -2,8 +2,12 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Module#method_added" do
+ before :each do
+ ScratchPad.record []
+ end
+
it "is a private instance method" do
- Module.should have_private_instance_method(:method_added)
+ Module.private_instance_methods(false).should.include?(:method_added)
end
it "returns nil in the default implementation" do
@@ -13,8 +17,6 @@ describe "Module#method_added" do
end
it "is called when a new instance method is defined in self" do
- ScratchPad.record []
-
Module.new do
def self.method_added(name)
ScratchPad << name
@@ -32,8 +34,6 @@ describe "Module#method_added" do
it "is not called when a singleton method is added" do
# obj.singleton_method_added is called instead
- ScratchPad.record []
-
klass = Class.new
def klass.method_added(name)
ScratchPad << name
@@ -57,11 +57,74 @@ describe "Module#method_added" do
undef_method :method_to_undef
end
- m.should_not have_method(:method_to_undef)
+ m.should_not.respond_to?(:method_to_undef)
+ end
+
+ it "is not called when a method changes visibility" do
+ Module.new do
+ def public_method
+ end
+
+ def private_method
+ end
+
+ def self.method_added(name)
+ ScratchPad << name
+ end
+
+ public :public_method
+ private :public_method
+
+ private :private_method
+ public :private_method
+ end
+
+ ScratchPad.recorded.should == []
+ end
+
+ it "is called when using #private in a subclass" do
+ parent = Class.new do
+ def foo
+ end
+ end
+
+ Class.new(parent) do
+ def self.method_added(name)
+ ScratchPad << name
+ end
+
+ # Create an instance as that might initialize some method lookup caches, which is interesting to test
+ self.new.foo
+
+ private :foo
+ public :foo
+ end
+
+ ScratchPad.recorded.should == [:foo]
+ end
+
+ it "is not called when a method is copied via module_function, rather #singleton_method_added is called" do
+ Module.new do
+ def mod_function
+ end
+
+ def self.method_added(name)
+ ScratchPad << [:method_added, name]
+ end
+
+ def self.singleton_method_added(name)
+ ScratchPad << [:singleton_method_added, name]
+ end
+
+ ScratchPad.record []
+
+ module_function :mod_function
+ end
+
+ ScratchPad.recorded.should == [[:singleton_method_added, :mod_function]]
end
it "is called with a precise caller location with the line of the 'def'" do
- ScratchPad.record []
line = nil
Module.new do
diff --git a/spec/ruby/core/module/method_defined_spec.rb b/spec/ruby/core/module/method_defined_spec.rb
index bc5b420e11..e6b4c7b817 100644
--- a/spec/ruby/core/module/method_defined_spec.rb
+++ b/spec/ruby/core/module/method_defined_spec.rb
@@ -27,17 +27,17 @@ describe "Module#method_defined?" do
it "does not search Object or Kernel when called on a module" do
m = Module.new
- m.method_defined?(:module_specs_public_method_on_kernel).should be_false
+ m.method_defined?(:module_specs_public_method_on_kernel).should == false
end
it "raises a TypeError when the given object is not a string/symbol" do
c = Class.new
o = mock('123')
- -> { c.method_defined?(o) }.should raise_error(TypeError)
+ -> { c.method_defined?(o) }.should.raise(TypeError)
o.should_receive(:to_str).and_return(123)
- -> { c.method_defined?(o) }.should raise_error(TypeError)
+ -> { c.method_defined?(o) }.should.raise(TypeError)
end
it "converts the given name to a string using to_str" do
diff --git a/spec/ruby/core/module/method_removed_spec.rb b/spec/ruby/core/module/method_removed_spec.rb
index 9b39eb77a6..80e546406c 100644
--- a/spec/ruby/core/module/method_removed_spec.rb
+++ b/spec/ruby/core/module/method_removed_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Module#method_removed" do
it "is a private instance method" do
- Module.should have_private_instance_method(:method_removed)
+ Module.private_instance_methods(false).should.include?(:method_removed)
end
it "returns nil in the default implementation" do
diff --git a/spec/ruby/core/module/method_undefined_spec.rb b/spec/ruby/core/module/method_undefined_spec.rb
index a94388fe0a..596c5c50e2 100644
--- a/spec/ruby/core/module/method_undefined_spec.rb
+++ b/spec/ruby/core/module/method_undefined_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Module#method_undefined" do
it "is a private instance method" do
- Module.should have_private_instance_method(:method_undefined)
+ Module.private_instance_methods(false).should.include?(:method_undefined)
end
it "returns nil in the default implementation" do
diff --git a/spec/ruby/core/module/module_function_spec.rb b/spec/ruby/core/module/module_function_spec.rb
index 0602e95ca9..41bd152608 100644
--- a/spec/ruby/core/module/module_function_spec.rb
+++ b/spec/ruby/core/module/module_function_spec.rb
@@ -3,22 +3,22 @@ require_relative 'fixtures/classes'
describe "Module#module_function" do
it "is a private method" do
- Module.should have_private_instance_method(:module_function)
+ Module.private_instance_methods(false).should.include?(:module_function)
end
describe "on Class" do
it "is undefined" do
- Class.should_not have_private_instance_method(:module_function, true)
+ Class.private_instance_methods(true).should_not.include?(:module_function)
end
it "raises a TypeError if calling after rebinded to Class" do
-> {
Module.instance_method(:module_function).bind(Class.new).call
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
-> {
Module.instance_method(:module_function).bind(Class.new).call :foo
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
end
@@ -38,22 +38,11 @@ describe "Module#module_function with specific method names" do
m.respond_to?(:test3).should == false
end
- ruby_version_is ""..."3.1" do
- it "returns self" do
- Module.new do
- def foo; end
- module_function(:foo).should equal(self)
- end
- end
- end
-
- ruby_version_is "3.1" do
- it "returns argument or arguments if given" do
- Module.new do
- def foo; end
- module_function(:foo).should equal(:foo)
- module_function(:foo, :foo).should == [:foo, :foo]
- end
+ it "returns argument or arguments if given" do
+ Module.new do
+ def foo; end
+ module_function(:foo).should.equal?(:foo)
+ module_function(:foo, :foo).should == [:foo, :foo]
end
end
@@ -94,9 +83,9 @@ describe "Module#module_function with specific method names" do
(o = mock('x')).extend(m)
o.respond_to?(:test).should == false
- m.should have_private_instance_method(:test)
+ m.private_instance_methods(false).should.include?(:test)
o.send(:test).should == "hello"
- -> { o.test }.should raise_error(NoMethodError)
+ -> { o.test }.should.raise(NoMethodError)
end
it "makes the new Module methods public" do
@@ -125,17 +114,17 @@ describe "Module#module_function with specific method names" do
it "raises a TypeError when the given names can't be converted to string using to_str" do
o = mock('123')
- -> { Module.new { module_function(o) } }.should raise_error(TypeError)
+ -> { Module.new { module_function(o) } }.should.raise(TypeError)
o.should_receive(:to_str).and_return(123)
- -> { Module.new { module_function(o) } }.should raise_error(TypeError)
+ -> { Module.new { module_function(o) } }.should.raise(TypeError)
end
it "can make accessible private methods" do # JRUBY-4214
m = Module.new do
module_function :require
end
- m.respond_to?(:require).should be_true
+ m.respond_to?(:require).should == true
end
it "creates Module methods that super up the singleton class of the module" do
@@ -155,45 +144,82 @@ describe "Module#module_function with specific method names" do
m.foo.should == ["m", "super_m"]
end
+
+ context "methods created with define_method" do
+ context "passed a block" do
+ it "creates duplicates of the given instance methods" do
+ m = Module.new do
+ define_method :test1 do; end
+ module_function :test1
+ end
+
+ m.respond_to?(:test1).should == true
+ end
+ end
+
+ context "passed a method" do
+ it "creates duplicates of the given instance methods" do
+ module_with_method = Module.new do
+ def test1; end
+ end
+
+ c = Class.new do
+ extend module_with_method
+ end
+
+ m = Module.new do
+ define_method :test2, c.method(:test1)
+ module_function :test2
+ end
+
+ m.respond_to?(:test2).should == true
+ end
+ end
+
+ context "passed an unbound method" do
+ it "creates duplicates of the given instance methods" do
+ module_with_method = Module.new do
+ def test1; end
+ end
+
+ m = Module.new do
+ define_method :test2, module_with_method.instance_method(:test1)
+ module_function :test2
+ end
+
+ m.respond_to?(:test2).should == true
+ end
+ end
+ end
end
describe "Module#module_function as a toggle (no arguments) in a Module body" do
it "makes any subsequently defined methods module functions with the normal semantics" do
- m = Module.new {
+ m = Module.new do
module_function
def test1() end
def test2() end
- }
+ end
m.respond_to?(:test1).should == true
m.respond_to?(:test2).should == true
end
- ruby_version_is ""..."3.1" do
- it "returns self" do
- Module.new do
- module_function.should equal(self)
- end
- end
- end
-
- ruby_version_is "3.1" do
- it "returns nil" do
- Module.new do
- module_function.should equal(nil)
- end
+ it "returns nil" do
+ Module.new do
+ module_function.should.equal?(nil)
end
end
it "stops creating module functions if the body encounters another toggle " \
"like public/protected/private without arguments" do
- m = Module.new {
+ m = Module.new do
module_function
def test1() end
def test2() end
public
def test3() end
- }
+ end
m.respond_to?(:test1).should == true
m.respond_to?(:test2).should == true
@@ -202,14 +228,14 @@ describe "Module#module_function as a toggle (no arguments) in a Module body" do
it "does not stop creating module functions if the body encounters " \
"public/protected/private WITH arguments" do
- m = Module.new {
+ m = Module.new do
def foo() end
module_function
def test1() end
def test2() end
public :foo
def test3() end
- }
+ end
m.respond_to?(:test1).should == true
m.respond_to?(:test2).should == true
@@ -217,69 +243,116 @@ describe "Module#module_function as a toggle (no arguments) in a Module body" do
end
it "does not affect module_evaled method definitions also if outside the eval itself" do
- m = Module.new {
+ m = Module.new do
module_function
module_eval { def test1() end }
module_eval " def test2() end "
- }
+ end
m.respond_to?(:test1).should == false
m.respond_to?(:test2).should == false
end
it "has no effect if inside a module_eval if the definitions are outside of it" do
- m = Module.new {
+ m = Module.new do
module_eval { module_function }
def test1() end
def test2() end
- }
+ end
m.respond_to?(:test1).should == false
m.respond_to?(:test2).should == false
end
it "functions normally if both toggle and definitions inside a module_eval" do
- m = Module.new {
- module_eval {
+ m = Module.new do
+ module_eval do
module_function
def test1() end
def test2() end
- }
- }
+ end
+ end
m.respond_to?(:test1).should == true
m.respond_to?(:test2).should == true
end
- it "affects evaled method definitions also even when outside the eval itself" do
- m = Module.new {
+ it "affects eval'ed method definitions also even when outside the eval itself" do
+ m = Module.new do
module_function
eval "def test1() end"
- }
+ end
m.respond_to?(:test1).should == true
end
it "doesn't affect definitions when inside an eval even if the definitions are outside of it" do
- m = Module.new {
+ m = Module.new do
eval "module_function"
def test1() end
- }
+ end
m.respond_to?(:test1).should == false
end
it "functions normally if both toggle and definitions inside a eval" do
- m = Module.new {
+ m = Module.new do
eval <<-CODE
module_function
def test1() end
def test2() end
CODE
- }
+ end
m.respond_to?(:test1).should == true
m.respond_to?(:test2).should == true
end
+
+ context "methods are defined with define_method" do
+ context "passed a block" do
+ it "makes any subsequently defined methods module functions with the normal semantics" do
+ m = Module.new do
+ module_function
+ define_method :test1 do; end
+ end
+
+ m.respond_to?(:test1).should == true
+ end
+ end
+
+ context "passed a method" do
+ it "makes any subsequently defined methods module functions with the normal semantics" do
+ module_with_method = Module.new do
+ def test1; end
+ end
+
+ c = Class.new do
+ extend module_with_method
+ end
+
+ m = Module.new do
+ module_function
+ define_method :test2, c.method(:test1)
+ end
+
+ m.respond_to?(:test2).should == true
+ end
+ end
+
+ context "passed an unbound method" do
+ it "makes any subsequently defined methods module functions with the normal semantics" do
+ module_with_method = Module.new do
+ def test1; end
+ end
+
+ m = Module.new do
+ module_function
+ define_method :test2, module_with_method.instance_method(:test1)
+ end
+
+ m.respond_to?(:test2).should == true
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/module/name_spec.rb b/spec/ruby/core/module/name_spec.rb
index b78bbfcc80..332c08d782 100644
--- a/spec/ruby/core/module/name_spec.rb
+++ b/spec/ruby/core/module/name_spec.rb
@@ -3,23 +3,13 @@ require_relative 'fixtures/module'
describe "Module#name" do
it "is nil for an anonymous module" do
- Module.new.name.should be_nil
+ Module.new.name.should == nil
end
- ruby_version_is ""..."3.0" do
- it "is nil when assigned to a constant in an anonymous module" do
- m = Module.new
- m::N = Module.new
- m::N.name.should be_nil
- end
- end
-
- ruby_version_is "3.0" do
- it "is not nil when assigned to a constant in an anonymous module" do
- m = Module.new
- m::N = Module.new
- m::N.name.should.end_with? '::N'
- end
+ it "is not nil when assigned to a constant in an anonymous module" do
+ m = Module.new
+ m::N = Module.new
+ m::N.name.should.end_with? '::N'
end
it "is not nil for a nested module created with the module keyword" do
@@ -29,9 +19,9 @@ describe "Module#name" do
end
it "returns nil for a singleton class" do
- Module.new.singleton_class.name.should be_nil
- String.singleton_class.name.should be_nil
- Object.new.singleton_class.name.should be_nil
+ Module.new.singleton_class.name.should == nil
+ String.singleton_class.name.should == nil
+ Object.new.singleton_class.name.should == nil
end
it "changes when the module is reachable through a constant path" do
@@ -40,6 +30,21 @@ describe "Module#name" do
m::N.name.should =~ /\A#<Module:0x\h+>::N\z/
ModuleSpecs::Anonymous::WasAnnon = m::N
m::N.name.should == "ModuleSpecs::Anonymous::WasAnnon"
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :WasAnnon)
+ end
+
+ it "may be the repeated in different module objects" do
+ m = Module.new
+ n = Module.new
+
+ suppress_warning do
+ ModuleSpecs::Anonymous::SameName = m
+ ModuleSpecs::Anonymous::SameName = n
+ end
+
+ m.name.should == "ModuleSpecs::Anonymous::SameName"
+ n.name.should == "ModuleSpecs::Anonymous::SameName"
end
it "is set after it is removed from a constant" do
@@ -69,10 +74,20 @@ describe "Module#name" do
ModuleSpecs::Anonymous.name.should == "ModuleSpecs::Anonymous"
end
- it "is set when assigning to a constant" do
+ it "is set when assigning to a constant (constant path matches outer module name)" do
m = Module.new
ModuleSpecs::Anonymous::A = m
m.name.should == "ModuleSpecs::Anonymous::A"
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :A)
+ end
+
+ it "is set when assigning to a constant (constant path does not match outer module name)" do
+ m = Module.new
+ ModuleSpecs::Anonymous::SameChild::A = m
+ m.name.should == "ModuleSpecs::Anonymous::Child::A"
+ ensure
+ ModuleSpecs::Anonymous::SameChild.send(:remove_const, :A)
end
it "is not modified when assigning to a new constant after it has been accessed" do
@@ -81,6 +96,9 @@ describe "Module#name" do
m.name.should == "ModuleSpecs::Anonymous::B"
ModuleSpecs::Anonymous::C = m
m.name.should == "ModuleSpecs::Anonymous::B"
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :B)
+ ModuleSpecs::Anonymous.send(:remove_const, :C)
end
it "is not modified when assigned to a different anonymous module" do
@@ -111,11 +129,68 @@ describe "Module#name" do
ModuleSpecs::NameEncoding.new.name.encoding.should == Encoding::UTF_8
end
- it "is set when the anonymous outer module name is set" do
+ it "is set when the anonymous outer module name is set (module in one single constant)" do
m = Module.new
m::N = Module.new
ModuleSpecs::Anonymous::E = m
m::N.name.should == "ModuleSpecs::Anonymous::E::N"
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :E)
+ end
+
+ # https://bugs.ruby-lang.org/issues/19681
+ it "is set when the anonymous outer module name is set (module in several constants)" do
+ m = Module.new
+ m::N = Module.new
+ m::O = m::N
+ ModuleSpecs::Anonymous::StoredInMultiplePlaces = m
+ valid_names = [
+ "ModuleSpecs::Anonymous::StoredInMultiplePlaces::N",
+ "ModuleSpecs::Anonymous::StoredInMultiplePlaces::O"
+ ]
+ valid_names.should.include?(m::N.name) # You get one of the two, but you don't know which one.
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :StoredInMultiplePlaces)
+ end
+
+ it "is set in #const_added callback when a module defined in the top-level scope" do
+ ruby_exe(<<~RUBY, args: "2>&1").chomp.should == "TEST1\nTEST2"
+ class Module
+ def const_added(name)
+ puts const_get(name).name
+ end
+ end
+
+ # module with name
+ module TEST1
+ end
+
+ # anonymous module
+ TEST2 = Module.new
+ RUBY
+ end
+
+ it "is set in #const_added callback for a nested module when an outer module defined in the top-level scope" do
+ ScratchPad.record []
+
+ ModuleSpecs::NameSpecs::NamedModule = Module.new do
+ def self.const_added(name)
+ ScratchPad << const_get(name).name
+ end
+
+ module self::A
+ def self.const_added(name)
+ ScratchPad << const_get(name).name
+ end
+
+ module self::B
+ end
+ end
+ end
+
+ ScratchPad.recorded.should.one?(/#<Module.+>::A$/)
+ ScratchPad.recorded.should.one?(/#<Module.+>::A::B$/)
+ ModuleSpecs::NameSpecs.send :remove_const, :NamedModule
end
it "returns a frozen String" do
@@ -125,6 +200,6 @@ describe "Module#name" do
it "always returns the same String for a given Module" do
s1 = ModuleSpecs.name
s2 = ModuleSpecs.name
- s1.should equal(s2)
+ s1.should.equal?(s2)
end
end
diff --git a/spec/ruby/core/module/new_spec.rb b/spec/ruby/core/module/new_spec.rb
index da7f3b8720..ec7a0cfa77 100644
--- a/spec/ruby/core/module/new_spec.rb
+++ b/spec/ruby/core/module/new_spec.rb
@@ -6,6 +6,10 @@ describe "Module.new" do
Module.new.is_a?(Module).should == true
end
+ it "creates a module without a name" do
+ Module.new.name.should == nil
+ end
+
it "creates a new Module and passes it to the provided block" do
test_mod = nil
m = Module.new do |mod|
diff --git a/spec/ruby/core/module/prepend_features_spec.rb b/spec/ruby/core/module/prepend_features_spec.rb
index 09c15c5c15..3a50f2c2a4 100644
--- a/spec/ruby/core/module/prepend_features_spec.rb
+++ b/spec/ruby/core/module/prepend_features_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Module#prepend_features" do
it "is a private method" do
- Module.should have_private_instance_method(:prepend_features, true)
+ Module.private_instance_methods(false).should.include?(:prepend_features)
end
it "gets called when self is included in another module/class" do
@@ -25,7 +25,7 @@ describe "Module#prepend_features" do
it "raises an ArgumentError on a cyclic prepend" do
-> {
ModuleSpecs::CyclicPrepend.send(:prepend_features, ModuleSpecs::CyclicPrepend)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "clears caches of the given module" do
@@ -52,13 +52,13 @@ describe "Module#prepend_features" do
describe "on Class" do
it "is undefined" do
- Class.should_not have_private_instance_method(:prepend_features, true)
+ Class.private_instance_methods(true).should_not.include?(:prepend_features)
end
it "raises a TypeError if calling after rebinded to Class" do
-> {
Module.instance_method(:prepend_features).bind(Class.new).call Module.new
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/module/prepend_spec.rb b/spec/ruby/core/module/prepend_spec.rb
index d636e023ed..f7887e6d6a 100644
--- a/spec/ruby/core/module/prepend_spec.rb
+++ b/spec/ruby/core/module/prepend_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Module#prepend" do
it "is a public method" do
- Module.should have_public_instance_method(:prepend, false)
+ Module.public_instance_methods(false).should.include?(:prepend)
end
it "does not affect the superclass" do
@@ -75,6 +75,26 @@ describe "Module#prepend" do
foo.call.should == 'm'
end
+ it "updates the optimized method when a prepended module is updated" do
+ out = ruby_exe(<<~RUBY)
+ module M; end
+ class Integer
+ prepend M
+ end
+ l = -> { 1 + 2 }
+ p l.call
+ M.module_eval do
+ def +(o)
+ $called = true
+ super(o)
+ end
+ end
+ p l.call
+ p $called
+ RUBY
+ out.should == "3\n3\ntrue\n"
+ end
+
it "updates the method when there is a base included method and the prepended module overrides it" do
base_module = Module.new do
def foo
@@ -241,6 +261,8 @@ describe "Module#prepend" do
B.prepend M
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatePrepended)
end
it "updates the constant when a prepended module is updated" do
@@ -261,6 +283,8 @@ describe "Module#prepend" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstPrependedUpdated)
end
it "updates the constant when there is a base included constant and the prepended module overrides it" do
@@ -282,6 +306,8 @@ describe "Module#prepend" do
A.prepend M
A.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstIncludedPrependedOverride)
end
it "updates the constant when there is a base included constant and the prepended module is later updated" do
@@ -305,6 +331,8 @@ describe "Module#prepend" do
M.const_set(:FOO, 'm')
A.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstIncludedPrependedLaterUpdated)
end
it "updates the constant when a module prepended after a constant is later updated" do
@@ -328,6 +356,8 @@ describe "Module#prepend" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedPrependedAfterLaterUpdated)
end
it "updates the constant when a module is prepended after another and the constant is defined later on that module" do
@@ -352,6 +382,8 @@ describe "Module#prepend" do
N.const_set(:FOO, 'n')
A.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedPrependedAfterConstDefined)
end
it "updates the constant when a module is included in a prepended module and the constant is defined later" do
@@ -379,6 +411,8 @@ describe "Module#prepend" do
N.const_set(:FOO, 'n')
A.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedIncludedInPrependedConstDefinedLater)
end
it "updates the constant when a new module with an included module is prepended" do
@@ -405,29 +439,47 @@ describe "Module#prepend" do
B.prepend M
B.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNewModuleIncludedPrepended)
end
it "raises a TypeError when the argument is not a Module" do
- -> { ModuleSpecs::Basic.prepend(Class.new) }.should raise_error(TypeError)
+ -> { ModuleSpecs::Basic.prepend(Class.new) }.should.raise(TypeError)
end
it "does not raise a TypeError when the argument is an instance of a subclass of Module" do
- -> { ModuleSpecs::SubclassSpec.prepend(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
+ class ModuleSpecs::SubclassSpec::AClass
+ end
+ -> { ModuleSpecs::SubclassSpec::AClass.prepend(ModuleSpecs::Subclass.new) }.should_not.raise(TypeError)
+ ensure
+ ModuleSpecs::SubclassSpec.send(:remove_const, :AClass)
+ end
+
+ it "raises a TypeError when the argument is a refinement" do
+ refinement = nil
+
+ Module.new do
+ refine String do
+ refinement = self
+ end
+ end
+
+ -> { ModuleSpecs::Basic.prepend(refinement) }.should.raise(TypeError, "Cannot prepend refinement")
end
it "imports constants" do
m1 = Module.new
m1::MY_CONSTANT = 1
m2 = Module.new { prepend(m1) }
- m2.constants.should include(:MY_CONSTANT)
+ m2.constants.should.include?(:MY_CONSTANT)
end
it "imports instance methods" do
- Module.new { prepend ModuleSpecs::A }.instance_methods.should include(:ma)
+ Module.new { prepend ModuleSpecs::A }.instance_methods.should.include?(:ma)
end
it "does not import methods to modules and classes" do
- Module.new { prepend ModuleSpecs::A }.methods.should_not include(:ma)
+ Module.new { prepend ModuleSpecs::A }.methods.should_not.include?(:ma)
end
it "allows wrapping methods" do
@@ -453,7 +505,7 @@ describe "Module#prepend" do
it "includes prepended modules in ancestors" do
m = Module.new
- Class.new { prepend(m) }.ancestors.should include(m)
+ Class.new { prepend(m) }.ancestors.should.include?(m)
end
it "reports the prepended module as the method owner" do
@@ -490,48 +542,31 @@ describe "Module#prepend" do
it "sees an instance of a prepended class as kind of the prepended module" do
m = Module.new
c = Class.new { prepend(m) }
- c.new.should be_kind_of(m)
+ c.new.should.is_a?(m)
end
it "keeps the module in the chain when dupping the class" do
m = Module.new
c = Class.new { prepend(m) }
- c.dup.new.should be_kind_of(m)
+ c.dup.new.should.is_a?(m)
end
- ruby_version_is ''...'3.0' do
- it "keeps the module in the chain when dupping an intermediate module" do
- m1 = Module.new { def calc(x) x end }
- m2 = Module.new { prepend(m1) }
- c1 = Class.new { prepend(m2) }
- m2dup = m2.dup
- m2dup.ancestors.should == [m2dup,m1,m2]
- c2 = Class.new { prepend(m2dup) }
- c1.ancestors[0,3].should == [m1,m2,c1]
- c1.new.should be_kind_of(m1)
- c2.ancestors[0,4].should == [m2dup,m1,m2,c2]
- c2.new.should be_kind_of(m1)
- end
- end
-
- ruby_version_is '3.0' do
- it "uses only new module when dupping the module" do
- m1 = Module.new { def calc(x) x end }
- m2 = Module.new { prepend(m1) }
- c1 = Class.new { prepend(m2) }
- m2dup = m2.dup
- m2dup.ancestors.should == [m1,m2dup]
- c2 = Class.new { prepend(m2dup) }
- c1.ancestors[0,3].should == [m1,m2,c1]
- c1.new.should be_kind_of(m1)
- c2.ancestors[0,3].should == [m1,m2dup,c2]
- c2.new.should be_kind_of(m1)
- end
+ it "uses only new module when dupping the module" do
+ m1 = Module.new { def calc(x) x end }
+ m2 = Module.new { prepend(m1) }
+ c1 = Class.new { prepend(m2) }
+ m2dup = m2.dup
+ m2dup.ancestors.should == [m1,m2dup]
+ c2 = Class.new { prepend(m2dup) }
+ c1.ancestors[0,3].should == [m1,m2,c1]
+ c1.new.should.is_a?(m1)
+ c2.ancestors[0,3].should == [m1,m2dup,c2]
+ c2.new.should.is_a?(m1)
end
it "depends on prepend_features to add the module" do
m = Module.new { def self.prepend_features(mod) end }
- Class.new { prepend(m) }.ancestors.should_not include(m)
+ Class.new { prepend(m) }.ancestors.should_not.include?(m)
end
it "adds the module in the subclass chains" do
@@ -592,7 +627,7 @@ describe "Module#prepend" do
super << :class
end
end
- -> { c.new.chain }.should raise_error(NoMethodError)
+ -> { c.new.chain }.should.raise(NoMethodError)
end
it "calls prepended after prepend_features" do
@@ -611,12 +646,24 @@ describe "Module#prepend" do
ScratchPad.recorded.should == [[:prepend_features, c], [:prepended, c]]
end
+ it "prepends a module if it is included in a super class" do
+ module ModuleSpecs::M3
+ module M; end
+ class A; include M; end
+ class B < A; prepend M; end
+
+ all = [A, B, M]
+
+ (B.ancestors.filter { |a| all.include?(a) }).should == [M, B, A, M]
+ end
+ end
+
it "detects cyclic prepends" do
-> {
module ModuleSpecs::P
prepend ModuleSpecs::P
end
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "doesn't accept no-arguments" do
@@ -624,7 +671,7 @@ describe "Module#prepend" do
Module.new do
prepend
end
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "returns the class it's included into" do
@@ -731,6 +778,33 @@ describe "Module#prepend" do
ary.should == [3, 2, 1]
end
+ it "does not prepend a second copy if the module already indirectly exists in the hierarchy" do
+ mod = Module.new do; end
+ submod = Module.new do; end
+ klass = Class.new do; end
+ klass.include(mod)
+ mod.prepend(submod)
+ klass.include(mod)
+
+ klass.ancestors.take(4).should == [klass, submod, mod, Object]
+ end
+
+ # https://bugs.ruby-lang.org/issues/17423
+ describe "when module already exists in ancestor chain" do
+ it "modifies the ancestor chain" do
+ m = Module.new do; end
+ a = Module.new do; end
+ b = Class.new do; end
+
+ b.include(a)
+ a.prepend(m)
+ b.ancestors.take(4).should == [b, m, a, Object]
+
+ b.prepend(m)
+ b.ancestors.take(5).should == [m, b, m, a, Object]
+ end
+ end
+
describe "called on a module" do
describe "included into a class"
it "does not obscure the module's methods from reflective access" do
@@ -743,7 +817,7 @@ describe "Module#prepend" do
pre = Module.new
mod.prepend pre
- cls.instance_methods.should include(:foo)
+ cls.instance_methods.should.include?(:foo)
end
end
end
diff --git a/spec/ruby/core/module/prepended_spec.rb b/spec/ruby/core/module/prepended_spec.rb
index bd95d8fd05..ccd450d668 100644
--- a/spec/ruby/core/module/prepended_spec.rb
+++ b/spec/ruby/core/module/prepended_spec.rb
@@ -8,7 +8,7 @@ describe "Module#prepended" do
end
it "is a private method" do
- Module.should have_private_instance_method(:prepended, true)
+ Module.private_instance_methods(false).should.include?(:prepended)
end
it "is invoked when self is prepended to another module or class" do
diff --git a/spec/ruby/core/module/private_class_method_spec.rb b/spec/ruby/core/module/private_class_method_spec.rb
index 407779cccc..7ce07f1600 100644
--- a/spec/ruby/core/module/private_class_method_spec.rb
+++ b/spec/ruby/core/module/private_class_method_spec.rb
@@ -22,11 +22,11 @@ describe "Module#private_class_method" do
it "makes an existing class method private" do
ModuleSpecs::Parent.private_method_1.should == nil
ModuleSpecs::Parent.private_class_method :private_method_1
- -> { ModuleSpecs::Parent.private_method_1 }.should raise_error(NoMethodError)
+ -> { ModuleSpecs::Parent.private_method_1 }.should.raise(NoMethodError)
# Technically above we're testing the Singleton classes, class method(right?).
# Try a "real" class method set private.
- -> { ModuleSpecs::Parent.private_method }.should raise_error(NoMethodError)
+ -> { ModuleSpecs::Parent.private_method }.should.raise(NoMethodError)
end
it "makes an existing class method private up the inheritance tree" do
@@ -34,8 +34,8 @@ describe "Module#private_class_method" do
ModuleSpecs::Child.private_method_1.should == nil
ModuleSpecs::Child.private_class_method :private_method_1
- -> { ModuleSpecs::Child.private_method_1 }.should raise_error(NoMethodError)
- -> { ModuleSpecs::Child.private_method }.should raise_error(NoMethodError)
+ -> { ModuleSpecs::Child.private_method_1 }.should.raise(NoMethodError)
+ -> { ModuleSpecs::Child.private_method }.should.raise(NoMethodError)
end
it "accepts more than one method at a time" do
@@ -44,14 +44,14 @@ describe "Module#private_class_method" do
ModuleSpecs::Child.private_class_method :private_method_1, :private_method_2
- -> { ModuleSpecs::Child.private_method_1 }.should raise_error(NoMethodError)
- -> { ModuleSpecs::Child.private_method_2 }.should raise_error(NoMethodError)
+ -> { ModuleSpecs::Child.private_method_1 }.should.raise(NoMethodError)
+ -> { ModuleSpecs::Child.private_method_2 }.should.raise(NoMethodError)
end
it "raises a NameError if class method doesn't exist" do
-> do
ModuleSpecs.private_class_method :no_method_here
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "makes a class method private" do
@@ -59,7 +59,7 @@ describe "Module#private_class_method" do
def self.foo() "foo" end
private_class_method :foo
end
- -> { c.foo }.should raise_error(NoMethodError)
+ -> { c.foo }.should.raise(NoMethodError)
end
it "raises a NameError when the given name is not a method" do
@@ -67,7 +67,7 @@ describe "Module#private_class_method" do
Class.new do
private_class_method :foo
end
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError when the given name is an instance method" do
@@ -76,18 +76,16 @@ describe "Module#private_class_method" do
def foo() "foo" end
private_class_method :foo
end
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
- ruby_version_is "3.0" do
- context "when single argument is passed and is an array" do
- it "sets the visibility of the given methods to private" do
- c = Class.new do
- def self.foo() "foo" end
- private_class_method [:foo]
- end
- -> { c.foo }.should raise_error(NoMethodError)
+ context "when single argument is passed and is an array" do
+ it "sets the visibility of the given methods to private" do
+ c = Class.new do
+ def self.foo() "foo" end
+ private_class_method [:foo]
end
+ -> { c.foo }.should.raise(NoMethodError)
end
end
end
diff --git a/spec/ruby/core/module/private_constant_spec.rb b/spec/ruby/core/module/private_constant_spec.rb
index 3a91b3c3cd..ca0df48c0b 100644
--- a/spec/ruby/core/module/private_constant_spec.rb
+++ b/spec/ruby/core/module/private_constant_spec.rb
@@ -8,7 +8,7 @@ describe "Module#private_constant" do
-> do
cls2.send :private_constant, :Foo
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "accepts strings as constant names" do
@@ -16,7 +16,7 @@ describe "Module#private_constant" do
cls.const_set :Foo, true
cls.send :private_constant, "Foo"
- -> { cls::Foo }.should raise_error(NameError)
+ -> { cls::Foo }.should.raise(NameError)
end
it "accepts multiple names" do
@@ -26,7 +26,7 @@ describe "Module#private_constant" do
mod.send :private_constant, :Foo, :Bar
- -> {mod::Foo}.should raise_error(NameError)
- -> {mod::Bar}.should raise_error(NameError)
+ -> {mod::Foo}.should.raise(NameError)
+ -> {mod::Bar}.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/module/private_instance_methods_spec.rb b/spec/ruby/core/module/private_instance_methods_spec.rb
index cce0f001bf..ae0f21d1dd 100644
--- a/spec/ruby/core/module/private_instance_methods_spec.rb
+++ b/spec/ruby/core/module/private_instance_methods_spec.rb
@@ -5,20 +5,20 @@ require_relative '../../fixtures/reflection'
# TODO: rewrite
describe "Module#private_instance_methods" do
it "returns a list of private methods in module and its ancestors" do
- ModuleSpecs::CountsMixin.should have_private_instance_method(:private_3)
+ ModuleSpecs::CountsMixin.private_instance_methods(false).should.include?(:private_3)
- ModuleSpecs::CountsParent.should have_private_instance_method(:private_2)
- ModuleSpecs::CountsParent.should have_private_instance_method(:private_3)
+ ModuleSpecs::CountsParent.private_instance_methods(false).should.include?(:private_2)
+ ModuleSpecs::CountsParent.private_instance_methods(true).should.include?(:private_3)
- ModuleSpecs::CountsChild.should have_private_instance_method(:private_1)
- ModuleSpecs::CountsChild.should have_private_instance_method(:private_2)
- ModuleSpecs::CountsChild.should have_private_instance_method(:private_3)
+ ModuleSpecs::CountsChild.private_instance_methods(false).should.include?(:private_1)
+ ModuleSpecs::CountsChild.private_instance_methods(true).should.include?(:private_2)
+ ModuleSpecs::CountsChild.private_instance_methods(true).should.include?(:private_3)
end
it "when passed false as a parameter, should return only methods defined in that module" do
- ModuleSpecs::CountsMixin.should have_private_instance_method(:private_3, false)
- ModuleSpecs::CountsParent.should have_private_instance_method(:private_2, false)
- ModuleSpecs::CountsChild.should have_private_instance_method(:private_1, false)
+ ModuleSpecs::CountsMixin.private_instance_methods(false).should.include?(:private_3)
+ ModuleSpecs::CountsParent.private_instance_methods(false).should.include?(:private_2)
+ ModuleSpecs::CountsChild.private_instance_methods(false).should.include?(:private_1)
end
it "default list should be the same as passing true as an argument" do
diff --git a/spec/ruby/core/module/private_method_defined_spec.rb b/spec/ruby/core/module/private_method_defined_spec.rb
index 01fc8f8fb9..f730decc0a 100644
--- a/spec/ruby/core/module/private_method_defined_spec.rb
+++ b/spec/ruby/core/module/private_method_defined_spec.rb
@@ -34,25 +34,25 @@ describe "Module#private_method_defined?" do
it "raises a TypeError if passed an Integer" do
-> do
ModuleSpecs::CountsMixin.private_method_defined?(1)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed nil" do
-> do
ModuleSpecs::CountsMixin.private_method_defined?(nil)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed false" do
-> do
ModuleSpecs::CountsMixin.private_method_defined?(false)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed an object that does not defined #to_str" do
-> do
ModuleSpecs::CountsMixin.private_method_defined?(mock('x'))
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed an object that defines #to_sym" do
@@ -61,7 +61,7 @@ describe "Module#private_method_defined?" do
-> do
ModuleSpecs::CountsMixin.private_method_defined?(sym)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "calls #to_str to convert an Object" do
diff --git a/spec/ruby/core/module/private_spec.rb b/spec/ruby/core/module/private_spec.rb
index ead806637c..e60fdb24cc 100644
--- a/spec/ruby/core/module/private_spec.rb
+++ b/spec/ruby/core/module/private_spec.rb
@@ -17,7 +17,7 @@ describe "Module#private" do
private :foo
end
- -> { obj.foo }.should raise_error(NoMethodError)
+ -> { obj.foo }.should.raise(NoMethodError)
end
it "makes a public Object instance method private in a new module" do
@@ -25,45 +25,33 @@ describe "Module#private" do
private :module_specs_public_method_on_object
end
- m.should have_private_instance_method(:module_specs_public_method_on_object)
+ m.private_instance_methods(false).should.include?(:module_specs_public_method_on_object)
# Ensure we did not change Object's method
- Object.should_not have_private_instance_method(:module_specs_public_method_on_object)
+ Object.private_instance_methods(true).should_not.include?(:module_specs_public_method_on_object)
end
it "makes a public Object instance method private in Kernel" do
- Kernel.should have_private_instance_method(
+ Kernel.private_instance_methods(false).should.include?(
:module_specs_public_method_on_object_for_kernel_private)
- Object.should_not have_private_instance_method(
+ Object.private_instance_methods(true).should_not.include?(
:module_specs_public_method_on_object_for_kernel_private)
end
- ruby_version_is ""..."3.1" do
- it "returns self" do
- (class << Object.new; self; end).class_eval do
- def foo; end
- private(:foo).should equal(self)
- private.should equal(self)
- end
- end
- end
-
- ruby_version_is "3.1" do
- it "returns argument or arguments if given" do
- (class << Object.new; self; end).class_eval do
- def foo; end
- private(:foo).should equal(:foo)
- private([:foo, :foo]).should == [:foo, :foo]
- private(:foo, :foo).should == [:foo, :foo]
- private.should equal(nil)
- end
+ it "returns argument or arguments if given" do
+ (class << Object.new; self; end).class_eval do
+ def foo; end
+ private(:foo).should.equal?(:foo)
+ private([:foo, :foo]).should == [:foo, :foo]
+ private(:foo, :foo).should == [:foo, :foo]
+ private.should.equal?(nil)
end
end
it "raises a NameError when given an undefined name" do
-> do
Module.new.send(:private, :undefined)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "only makes the method private in the class it is called on" do
@@ -83,7 +71,7 @@ describe "Module#private" do
base.new.wrapped.should == 1
-> do
klass.new.wrapped
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "continues to allow a prepended module method to call super" do
diff --git a/spec/ruby/core/module/protected_instance_methods_spec.rb b/spec/ruby/core/module/protected_instance_methods_spec.rb
index 78ce7e788f..ea7ded030e 100644
--- a/spec/ruby/core/module/protected_instance_methods_spec.rb
+++ b/spec/ruby/core/module/protected_instance_methods_spec.rb
@@ -6,16 +6,16 @@ require_relative '../../fixtures/reflection'
describe "Module#protected_instance_methods" do
it "returns a list of protected methods in module and its ancestors" do
methods = ModuleSpecs::CountsMixin.protected_instance_methods
- methods.should include(:protected_3)
+ methods.should.include?(:protected_3)
methods = ModuleSpecs::CountsParent.protected_instance_methods
- methods.should include(:protected_3)
- methods.should include(:protected_2)
+ methods.should.include?(:protected_3)
+ methods.should.include?(:protected_2)
methods = ModuleSpecs::CountsChild.protected_instance_methods
- methods.should include(:protected_3)
- methods.should include(:protected_2)
- methods.should include(:protected_1)
+ methods.should.include?(:protected_3)
+ methods.should.include?(:protected_2)
+ methods.should.include?(:protected_1)
end
it "when passed false as a parameter, should return only methods defined in that module" do
diff --git a/spec/ruby/core/module/protected_method_defined_spec.rb b/spec/ruby/core/module/protected_method_defined_spec.rb
index 31e24a16c1..78ba120c2f 100644
--- a/spec/ruby/core/module/protected_method_defined_spec.rb
+++ b/spec/ruby/core/module/protected_method_defined_spec.rb
@@ -34,25 +34,25 @@ describe "Module#protected_method_defined?" do
it "raises a TypeError if passed an Integer" do
-> do
ModuleSpecs::CountsMixin.protected_method_defined?(1)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed nil" do
-> do
ModuleSpecs::CountsMixin.protected_method_defined?(nil)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed false" do
-> do
ModuleSpecs::CountsMixin.protected_method_defined?(false)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed an object that does not defined #to_str" do
-> do
ModuleSpecs::CountsMixin.protected_method_defined?(mock('x'))
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed an object that defines #to_sym" do
@@ -61,7 +61,7 @@ describe "Module#protected_method_defined?" do
-> do
ModuleSpecs::CountsMixin.protected_method_defined?(sym)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "calls #to_str to convert an Object" do
diff --git a/spec/ruby/core/module/protected_spec.rb b/spec/ruby/core/module/protected_spec.rb
index 058d49d751..3ef6c76fae 100644
--- a/spec/ruby/core/module/protected_spec.rb
+++ b/spec/ruby/core/module/protected_spec.rb
@@ -18,7 +18,7 @@ describe "Module#protected" do
protected :protected_method_1
end
- -> { ModuleSpecs::Parent.protected_method_1 }.should raise_error(NoMethodError)
+ -> { ModuleSpecs::Parent.protected_method_1 }.should.raise(NoMethodError)
end
it "makes a public Object instance method protected in a new module" do
@@ -26,44 +26,32 @@ describe "Module#protected" do
protected :module_specs_public_method_on_object
end
- m.should have_protected_instance_method(:module_specs_public_method_on_object)
+ m.protected_instance_methods(false).should.include?(:module_specs_public_method_on_object)
# Ensure we did not change Object's method
- Object.should_not have_protected_instance_method(:module_specs_public_method_on_object)
+ Object.protected_instance_methods(true).should_not.include?(:module_specs_public_method_on_object)
end
it "makes a public Object instance method protected in Kernel" do
- Kernel.should have_protected_instance_method(
+ Kernel.protected_instance_methods(false).should.include?(
:module_specs_public_method_on_object_for_kernel_protected)
- Object.should_not have_protected_instance_method(
+ Object.protected_instance_methods(true).should_not.include?(
:module_specs_public_method_on_object_for_kernel_protected)
end
- ruby_version_is ""..."3.1" do
- it "returns self" do
- (class << Object.new; self; end).class_eval do
- def foo; end
- protected(:foo).should equal(self)
- protected.should equal(self)
- end
- end
- end
-
- ruby_version_is "3.1" do
- it "returns argument or arguments if given" do
- (class << Object.new; self; end).class_eval do
- def foo; end
- protected(:foo).should equal(:foo)
- protected([:foo, :foo]).should == [:foo, :foo]
- protected(:foo, :foo).should == [:foo, :foo]
- protected.should equal(nil)
- end
+ it "returns argument or arguments if given" do
+ (class << Object.new; self; end).class_eval do
+ def foo; end
+ protected(:foo).should.equal?(:foo)
+ protected([:foo, :foo]).should == [:foo, :foo]
+ protected(:foo, :foo).should == [:foo, :foo]
+ protected.should.equal?(nil)
end
end
it "raises a NameError when given an undefined name" do
-> do
Module.new.send(:protected, :undefined)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/module/public_class_method_spec.rb b/spec/ruby/core/module/public_class_method_spec.rb
index b5d76e7b7a..4aca4d4311 100644
--- a/spec/ruby/core/module/public_class_method_spec.rb
+++ b/spec/ruby/core/module/public_class_method_spec.rb
@@ -18,7 +18,7 @@ describe "Module#public_class_method" do
end
it "makes an existing class method public" do
- -> { ModuleSpecs::Parent.public_method_1 }.should raise_error(NoMethodError)
+ -> { ModuleSpecs::Parent.public_method_1 }.should.raise(NoMethodError)
ModuleSpecs::Parent.public_class_method :public_method_1
ModuleSpecs::Parent.public_method_1.should == nil
@@ -29,7 +29,7 @@ describe "Module#public_class_method" do
it "makes an existing class method public up the inheritance tree" do
ModuleSpecs::Child.private_class_method :public_method_1
- -> { ModuleSpecs::Child.public_method_1 }.should raise_error(NoMethodError)
+ -> { ModuleSpecs::Child.public_method_1 }.should.raise(NoMethodError)
ModuleSpecs::Child.public_class_method :public_method_1
ModuleSpecs::Child.public_method_1.should == nil
@@ -37,8 +37,8 @@ describe "Module#public_class_method" do
end
it "accepts more than one method at a time" do
- -> { ModuleSpecs::Parent.public_method_1 }.should raise_error(NameError)
- -> { ModuleSpecs::Parent.public_method_2 }.should raise_error(NameError)
+ -> { ModuleSpecs::Parent.public_method_1 }.should.raise(NameError)
+ -> { ModuleSpecs::Parent.public_method_2 }.should.raise(NameError)
ModuleSpecs::Child.public_class_method :public_method_1, :public_method_2
@@ -49,7 +49,7 @@ describe "Module#public_class_method" do
it "raises a NameError if class method doesn't exist" do
-> do
ModuleSpecs.public_class_method :no_method_here
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "makes a class method public" do
@@ -66,7 +66,7 @@ describe "Module#public_class_method" do
Class.new do
public_class_method :foo
end
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError when the given name is an instance method" do
@@ -75,22 +75,20 @@ describe "Module#public_class_method" do
def foo() "foo" end
public_class_method :foo
end
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
- ruby_version_is "3.0" do
- context "when single argument is passed and is an array" do
- it "makes a class method public" do
- c = Class.new do
- class << self
- private
- def foo() "foo" end
- end
- public_class_method [:foo]
+ context "when single argument is passed and is an array" do
+ it "makes a class method public" do
+ c = Class.new do
+ class << self
+ private
+ def foo() "foo" end
end
-
- c.foo.should == "foo"
+ public_class_method [:foo]
end
+
+ c.foo.should == "foo"
end
end
end
diff --git a/spec/ruby/core/module/public_constant_spec.rb b/spec/ruby/core/module/public_constant_spec.rb
index e624d45fd2..87a051f125 100644
--- a/spec/ruby/core/module/public_constant_spec.rb
+++ b/spec/ruby/core/module/public_constant_spec.rb
@@ -8,7 +8,7 @@ describe "Module#public_constant" do
-> do
cls2.send :public_constant, :Foo
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "accepts strings as constant names" do
diff --git a/spec/ruby/core/module/public_instance_method_spec.rb b/spec/ruby/core/module/public_instance_method_spec.rb
index ba19ad0404..87c1bae599 100644
--- a/spec/ruby/core/module/public_instance_method_spec.rb
+++ b/spec/ruby/core/module/public_instance_method_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Module#public_instance_method" do
it "is a public method" do
- Module.should have_public_instance_method(:public_instance_method, false)
+ Module.public_instance_methods(false).should.include?(:public_instance_method)
end
it "requires an argument" do
@@ -13,12 +13,12 @@ describe "Module#public_instance_method" do
describe "when given a public method name" do
it "returns an UnboundMethod corresponding to the defined Module" do
ret = ModuleSpecs::Super.public_instance_method(:public_module)
- ret.should be_an_instance_of(UnboundMethod)
- ret.owner.should equal(ModuleSpecs::Basic)
+ ret.should.instance_of?(UnboundMethod)
+ ret.owner.should.equal?(ModuleSpecs::Basic)
ret = ModuleSpecs::Super.public_instance_method(:public_super_module)
- ret.should be_an_instance_of(UnboundMethod)
- ret.owner.should equal(ModuleSpecs::Super)
+ ret.should.instance_of?(UnboundMethod)
+ ret.owner.should.equal?(ModuleSpecs::Super)
end
it "accepts if the name is a Symbol or String" do
@@ -28,31 +28,31 @@ describe "Module#public_instance_method" do
end
it "raises a TypeError when given a name is not Symbol or String" do
- -> { Module.new.public_instance_method(nil) }.should raise_error(TypeError)
+ -> { Module.new.public_instance_method(nil) }.should.raise(TypeError)
end
it "raises a NameError when given a protected method name" do
-> do
ModuleSpecs::Basic.public_instance_method(:protected_module)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError if the method is private" do
-> do
ModuleSpecs::Basic.public_instance_method(:private_module)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError if the method has been undefined" do
-> do
ModuleSpecs::Parent.public_instance_method(:undefed_method)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "raises a NameError if the method does not exist" do
-> do
Module.new.public_instance_method(:missing)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "sets the NameError#name attribute to the name of the missing method" do
diff --git a/spec/ruby/core/module/public_instance_methods_spec.rb b/spec/ruby/core/module/public_instance_methods_spec.rb
index ae7d9b5ffb..edea00d927 100644
--- a/spec/ruby/core/module/public_instance_methods_spec.rb
+++ b/spec/ruby/core/module/public_instance_methods_spec.rb
@@ -7,19 +7,19 @@ require_relative '../../fixtures/reflection'
describe "Module#public_instance_methods" do
it "returns a list of public methods in module and its ancestors" do
methods = ModuleSpecs::CountsMixin.public_instance_methods
- methods.should include(:public_3)
+ methods.should.include?(:public_3)
methods = ModuleSpecs::CountsParent.public_instance_methods
- methods.should include(:public_3)
- methods.should include(:public_2)
+ methods.should.include?(:public_3)
+ methods.should.include?(:public_2)
methods = ModuleSpecs::CountsChild.public_instance_methods
- methods.should include(:public_3)
- methods.should include(:public_2)
- methods.should include(:public_1)
+ methods.should.include?(:public_3)
+ methods.should.include?(:public_2)
+ methods.should.include?(:public_1)
methods = ModuleSpecs::Child2.public_instance_methods
- methods.should include(:foo)
+ methods.should.include?(:foo)
end
it "when passed false as a parameter, should return only methods defined in that module" do
diff --git a/spec/ruby/core/module/public_method_defined_spec.rb b/spec/ruby/core/module/public_method_defined_spec.rb
index 5c9bdf1ccc..70cd992358 100644
--- a/spec/ruby/core/module/public_method_defined_spec.rb
+++ b/spec/ruby/core/module/public_method_defined_spec.rb
@@ -34,25 +34,25 @@ describe "Module#public_method_defined?" do
it "raises a TypeError if passed an Integer" do
-> do
ModuleSpecs::CountsMixin.public_method_defined?(1)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed nil" do
-> do
ModuleSpecs::CountsMixin.public_method_defined?(nil)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed false" do
-> do
ModuleSpecs::CountsMixin.public_method_defined?(false)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed an object that does not defined #to_str" do
-> do
ModuleSpecs::CountsMixin.public_method_defined?(mock('x'))
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "raises a TypeError if passed an object that defines #to_sym" do
@@ -61,7 +61,7 @@ describe "Module#public_method_defined?" do
-> do
ModuleSpecs::CountsMixin.public_method_defined?(sym)
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "calls #to_str to convert an Object" do
diff --git a/spec/ruby/core/module/public_spec.rb b/spec/ruby/core/module/public_spec.rb
index e3b183f228..f35c64143b 100644
--- a/spec/ruby/core/module/public_spec.rb
+++ b/spec/ruby/core/module/public_spec.rb
@@ -14,44 +14,32 @@ describe "Module#public" do
public :module_specs_private_method_on_object
end
- m.should have_public_instance_method(:module_specs_private_method_on_object)
+ m.public_instance_methods(false).should.include?(:module_specs_private_method_on_object)
# Ensure we did not change Object's method
- Object.should_not have_public_instance_method(:module_specs_private_method_on_object)
+ Object.public_instance_methods(true).should_not.include?(:module_specs_private_method_on_object)
end
it "makes a private Object instance method public in Kernel" do
- Kernel.should have_public_instance_method(
+ Kernel.public_instance_methods(false).should.include?(
:module_specs_private_method_on_object_for_kernel_public)
- Object.should_not have_public_instance_method(
+ Object.public_instance_methods(true).should_not.include?(
:module_specs_private_method_on_object_for_kernel_public)
end
- ruby_version_is ""..."3.1" do
- it "returns self" do
- (class << Object.new; self; end).class_eval do
- def foo; end
- public(:foo).should equal(self)
- public.should equal(self)
- end
- end
- end
-
- ruby_version_is "3.1" do
- it "returns argument or arguments if given" do
- (class << Object.new; self; end).class_eval do
- def foo; end
- public(:foo).should equal(:foo)
- public([:foo, :foo]).should == [:foo, :foo]
- public(:foo, :foo).should == [:foo, :foo]
- public.should equal(nil)
- end
+ it "returns argument or arguments if given" do
+ (class << Object.new; self; end).class_eval do
+ def foo; end
+ public(:foo).should.equal?(:foo)
+ public([:foo, :foo]).should == [:foo, :foo]
+ public(:foo, :foo).should == [:foo, :foo]
+ public.should.equal?(nil)
end
end
it "raises a NameError when given an undefined name" do
-> do
Module.new.send(:public, :undefined)
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb
index 841900cf87..d0fc7015f8 100644
--- a/spec/ruby/core/module/refine_spec.rb
+++ b/spec/ruby/core/module/refine_spec.rb
@@ -11,7 +11,7 @@ describe "Module#refine" do
end
mod.should_not == inner_self
- inner_self.should be_kind_of(Module)
+ inner_self.should.is_a?(Module)
inner_self.name.should == nil
end
@@ -43,7 +43,7 @@ describe "Module#refine" do
end
end
- inner_self.public_instance_methods.should include(:blah)
+ inner_self.public_instance_methods.should.include?(:blah)
end
it "returns created anonymous module" do
@@ -63,7 +63,7 @@ describe "Module#refine" do
Module.new do
refine {}
end
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "raises TypeError if not passed a class" do
@@ -71,7 +71,7 @@ describe "Module#refine" do
Module.new do
refine("foo") {}
end
- end.should raise_error(TypeError)
+ end.should.raise(TypeError, "wrong argument type String (expected Class or Module)")
end
it "accepts a module as argument" do
@@ -84,7 +84,7 @@ describe "Module#refine" do
end
end
- inner_self.public_instance_methods.should include(:blah)
+ inner_self.public_instance_methods.should.include?(:blah)
end
it "applies refinements to the module" do
@@ -117,7 +117,7 @@ describe "Module#refine" do
Module.new do
refine String
end
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "applies refinements to calls in the refine block" do
@@ -136,7 +136,7 @@ describe "Module#refine" do
refine(String) {def foo; "foo"; end}
-> {
"hello".foo
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
end
@@ -145,7 +145,7 @@ describe "Module#refine" do
refine(String) {def foo; 'foo'; end}
end
- -> {"hello".foo}.should raise_error(NoMethodError)
+ -> {"hello".foo}.should.raise(NoMethodError)
end
# When defining multiple refinements in the same module,
@@ -209,7 +209,7 @@ describe "Module#refine" do
[1, 2].to_json_format
end
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
# method lookup:
@@ -243,36 +243,10 @@ describe "Module#refine" do
result.should == "foo from singleton class"
end
- ruby_version_is ""..."3.2" do
- it "looks in the included modules for builtin methods" do
- result = ruby_exe(<<-RUBY)
- a = Module.new do
- def /(other) quo(other) end
- end
-
- refinement = Module.new do
- refine Integer do
- include a
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = 1 / 2
- end
-
- print result.class
- RUBY
-
- result.should == 'Rational'
- end
- end
-
it "looks in later included modules of the refined module first" do
a = Module.new do
def foo
- "foo from A"
+ "foo from A"
end
end
@@ -300,67 +274,6 @@ describe "Module#refine" do
result.should == "foo from IncludeMeLater"
end
- ruby_version_is ""..."3.1" do
- it "looks in prepended modules from the refinement first" do
- refined_class = ModuleSpecs.build_refined_class
-
- refinement = Module.new do
- refine refined_class do
- include ModuleSpecs::IncludedModule
- prepend ModuleSpecs::PrependedModule
-
- def foo; "foo from refinement"; end
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
- end
-
- result.should == "foo from prepended module"
- end
-
- it "looks in refinement then" do
- refined_class = ModuleSpecs.build_refined_class
-
- refinement = Module.new do
- refine(refined_class) do
- include ModuleSpecs::IncludedModule
-
- def foo; "foo from refinement"; end
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
- end
-
- result.should == "foo from refinement"
- end
-
- it "looks in included modules from the refinement then" do
- refined_class = ModuleSpecs.build_refined_class
-
- refinement = Module.new do
- refine refined_class do
- include ModuleSpecs::IncludedModule
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
- end
-
- result.should == "foo from included module"
- end
- end
-
it "looks in the class then" do
refined_class = ModuleSpecs.build_refined_class
@@ -606,30 +519,6 @@ describe "Module#refine" do
end
context "when super is called in a refinement" do
- ruby_version_is ""..."3.1" do
- it "looks in the included to refinery module" do
- refined_class = ModuleSpecs.build_refined_class
-
- refinement = Module.new do
- refine refined_class do
- include ModuleSpecs::IncludedModule
-
- def foo
- super
- end
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
- end
-
- result.should == "foo from included module"
- end
- end
-
it "looks in the refined class" do
refined_class = ModuleSpecs.build_refined_class
@@ -650,59 +539,6 @@ describe "Module#refine" do
result.should == "foo"
end
- ruby_version_is ""..."3.1" do
- it "looks in the refined class from included module" do
- refined_class = ModuleSpecs.build_refined_class(for_super: true)
-
- a = Module.new do
- def foo
- [:A] + super
- end
- end
-
- refinement = Module.new do
- refine refined_class do
- include a
- end
- end
-
- result = nil
- Module.new do
- using refinement
-
- result = refined_class.new.foo
- end
-
- result.should == [:A, :C]
- end
-
- it "looks in the refined ancestors from included module" do
- refined_class = ModuleSpecs.build_refined_class(for_super: true)
- subclass = Class.new(refined_class)
-
- a = Module.new do
- def foo
- [:A] + super
- end
- end
-
- refinement = Module.new do
- refine refined_class do
- include a
- end
- end
-
- result = nil
- Module.new do
- using refinement
-
- result = subclass.new.foo
- end
-
- result.should == [:A, :C]
- end
- 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.
@@ -760,180 +596,7 @@ describe "Module#refine" do
using refinement_with_super
-> {
refined_class.new.bar
- }.should raise_error(NoMethodError)
- end
- end
-
- ruby_version_is ""..."3.1" do
- it "does't have access to active refinements for C from included module" do
- refined_class = ModuleSpecs.build_refined_class
-
- a = Module.new do
- def foo
- super + bar
- end
- end
-
- refinement = Module.new do
- refine refined_class do
- include a
-
- def bar
- "bar is not seen from A methods"
- end
- end
- end
-
- Module.new do
- using refinement
- -> {
- refined_class.new.foo
- }.should raise_error(NameError) { |e| e.name.should == :bar }
- end
- end
-
- it "does't have access to other active refinements from included module" do
- refined_class = ModuleSpecs.build_refined_class
-
- refinement_integer = Module.new do
- refine Integer do
- def bar
- "bar is not seen from A methods"
- end
- end
- end
-
- a = Module.new do
- def foo
- super + 1.bar
- end
- end
-
- refinement = Module.new do
- refine refined_class do
- include a
- end
- end
-
- Module.new do
- using refinement
- using refinement_integer
- -> {
- refined_class.new.foo
- }.should raise_error(NameError) { |e| e.name.should == :bar }
- end
- end
-
- # https://bugs.ruby-lang.org/issues/16977
- it "looks in the another active refinement if super called from included modules" do
- refined_class = ModuleSpecs.build_refined_class(for_super: true)
-
- a = Module.new do
- def foo
- [:A] + super
- end
- end
-
- b = Module.new do
- def foo
- [:B] + super
- end
- end
-
- refinement_a = Module.new do
- refine refined_class do
- include a
- end
- end
-
- refinement_b = Module.new do
- refine refined_class do
- include b
- end
- end
-
- result = nil
- Module.new do
- using refinement_a
- using refinement_b
- result = refined_class.new.foo
- end
-
- result.should == [:B, :A, :C]
- end
-
- it "looks in the current active refinement from included modules" do
- refined_class = ModuleSpecs.build_refined_class(for_super: true)
-
- a = Module.new do
- def foo
- [:A] + super
- end
- end
-
- b = Module.new do
- def foo
- [:B] + super
- end
- end
-
- refinement = Module.new do
- refine refined_class do
- def foo
- [:LAST] + super
- end
- end
- end
-
- refinement_a_b = Module.new do
- refine refined_class do
- include a
- include b
- end
- end
-
- result = nil
- Module.new do
- using refinement
- using refinement_a_b
- result = refined_class.new.foo
- end
-
- result.should == [:B, :A, :LAST, :C]
- end
-
- it "looks in the lexical scope refinements before other active refinements" do
- refined_class = ModuleSpecs.build_refined_class(for_super: true)
-
- refinement_local = Module.new do
- refine refined_class do
- def foo
- [:LOCAL] + super
- end
- end
- end
-
- a = Module.new do
- using refinement_local
-
- def foo
- [:A] + super
- end
- end
-
- refinement = Module.new do
- refine refined_class do
- include a
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
- end
-
- result.should == [:A, :LOCAL, :C]
+ }.should.raise(NoMethodError)
end
end
end
@@ -947,7 +610,7 @@ describe "Module#refine" do
}
[1,2].orig_count.should == 2
end
- -> { [1,2].orig_count }.should raise_error(NoMethodError)
+ -> { [1,2].orig_count }.should.raise(NoMethodError)
end
it 'and alias_method aliases a method within a refinement module, but not outside it' do
@@ -959,7 +622,7 @@ describe "Module#refine" do
}
[1,2].orig_count.should == 2
end
- -> { [1,2].orig_count }.should raise_error(NoMethodError)
+ -> { [1,2].orig_count }.should.raise(NoMethodError)
end
it "and instance_methods returns a list of methods including those of the refined module" do
@@ -1041,11 +704,10 @@ describe "Module#refine" do
end
end
end
- spec = self
- klass = Class.new { instance_methods.should_not spec.send(:include, :refinement_only_method) }
+ klass = Class.new { instance_methods.should_not.include?(:refinement_only_method) }
instance = klass.new
- instance.methods.should_not include :refinement_only_method
+ instance.methods.should_not.include? :refinement_only_method
instance.respond_to?(:refinement_only_method).should == false
- -> { instance.method :refinement_only_method }.should raise_error(NameError)
+ -> { instance.method :refinement_only_method }.should.raise(NameError)
end
end
diff --git a/spec/ruby/core/module/refinements_spec.rb b/spec/ruby/core/module/refinements_spec.rb
new file mode 100644
index 0000000000..05658a8b0e
--- /dev/null
+++ b/spec/ruby/core/module/refinements_spec.rb
@@ -0,0 +1,43 @@
+require_relative '../../spec_helper'
+
+describe "Module#refinements" do
+ it "returns refinements defined in a module" do
+ ScratchPad.record []
+
+ m = Module.new do
+ refine String do
+ ScratchPad << self
+ end
+
+ refine Array do
+ ScratchPad << self
+ end
+ end
+
+ m.refinements.sort_by(&:object_id).should == ScratchPad.recorded.sort_by(&:object_id)
+ end
+
+ it "does not return refinements defined in the included module" do
+ ScratchPad.record []
+
+ m1 = Module.new do
+ refine Integer do
+ nil
+ end
+ end
+
+ m2 = Module.new do
+ include m1
+
+ refine String do
+ ScratchPad << self
+ end
+ end
+
+ m2.refinements.should == ScratchPad.recorded
+ end
+
+ it "returns an empty array if no refinements defined in a module" do
+ Module.new.refinements.should == []
+ end
+end
diff --git a/spec/ruby/core/module/remove_class_variable_spec.rb b/spec/ruby/core/module/remove_class_variable_spec.rb
index ab9514adf6..fccb29f52d 100644
--- a/spec/ruby/core/module/remove_class_variable_spec.rb
+++ b/spec/ruby/core/module/remove_class_variable_spec.rb
@@ -18,27 +18,27 @@ describe "Module#remove_class_variable" do
meta = obj.singleton_class
meta.send :class_variable_set, :@@var, 1
meta.send(:remove_class_variable, :@@var).should == 1
- meta.class_variable_defined?(:@@var).should be_false
+ meta.class_variable_defined?(:@@var).should == false
end
it "raises a NameError when removing class variable declared in included module" do
c = ModuleSpecs::RemoveClassVariable.new { include ModuleSpecs::MVars.dup }
- -> { c.send(:remove_class_variable, :@@mvar) }.should raise_error(NameError)
+ -> { c.send(:remove_class_variable, :@@mvar) }.should.raise(NameError)
end
it "raises a NameError when passed a symbol with one leading @" do
- -> { ModuleSpecs::MVars.send(:remove_class_variable, :@mvar) }.should raise_error(NameError)
+ -> { ModuleSpecs::MVars.send(:remove_class_variable, :@mvar) }.should.raise(NameError)
end
it "raises a NameError when passed a symbol with no leading @" do
- -> { ModuleSpecs::MVars.send(:remove_class_variable, :mvar) }.should raise_error(NameError)
+ -> { ModuleSpecs::MVars.send(:remove_class_variable, :mvar) }.should.raise(NameError)
end
it "raises a NameError when an uninitialized class variable is given" do
- -> { ModuleSpecs::MVars.send(:remove_class_variable, :@@nonexisting_class_variable) }.should raise_error(NameError)
+ -> { ModuleSpecs::MVars.send(:remove_class_variable, :@@nonexisting_class_variable) }.should.raise(NameError)
end
it "is public" do
- Module.should_not have_private_instance_method(:remove_class_variable)
+ Module.private_instance_methods(true).should_not.include?(:remove_class_variable)
end
end
diff --git a/spec/ruby/core/module/remove_const_spec.rb b/spec/ruby/core/module/remove_const_spec.rb
index 0ac23f05a5..4e4b9fcb45 100644
--- a/spec/ruby/core/module/remove_const_spec.rb
+++ b/spec/ruby/core/module/remove_const_spec.rb
@@ -7,13 +7,13 @@ describe "Module#remove_const" do
ConstantSpecs::ModuleM::CS_CONST252.should == :const252
ConstantSpecs::ModuleM.send :remove_const, :CS_CONST252
- -> { ConstantSpecs::ModuleM::CS_CONST252 }.should raise_error(NameError)
+ -> { ConstantSpecs::ModuleM::CS_CONST252 }.should.raise(NameError)
ConstantSpecs::ModuleM::CS_CONST253 = :const253
ConstantSpecs::ModuleM::CS_CONST253.should == :const253
ConstantSpecs::ModuleM.send :remove_const, "CS_CONST253"
- -> { ConstantSpecs::ModuleM::CS_CONST253 }.should raise_error(NameError)
+ -> { ConstantSpecs::ModuleM::CS_CONST253 }.should.raise(NameError)
end
it "returns the value of the removed constant" do
@@ -23,7 +23,7 @@ describe "Module#remove_const" do
it "raises a NameError and does not call #const_missing if the constant is not defined" do
ConstantSpecs.should_not_receive(:const_missing)
- -> { ConstantSpecs.send(:remove_const, :Nonexistent) }.should raise_error(NameError)
+ -> { ConstantSpecs.send(:remove_const, :Nonexistent) }.should.raise(NameError)
end
it "raises a NameError and does not call #const_missing if the constant is not defined directly in the module" do
@@ -34,28 +34,28 @@ describe "Module#remove_const" do
-> do
ConstantSpecs::ContainerA.send :remove_const, :CS_CONST255
- end.should raise_error(NameError)
+ end.should.raise(NameError)
ensure
ConstantSpecs::ModuleM.send :remove_const, "CS_CONST255"
end
end
it "raises a NameError if the name does not start with a capital letter" do
- -> { ConstantSpecs.send :remove_const, "name" }.should raise_error(NameError)
+ -> { ConstantSpecs.send :remove_const, "name" }.should.raise(NameError)
end
it "raises a NameError if the name starts with a non-alphabetic character" do
- -> { ConstantSpecs.send :remove_const, "__CONSTX__" }.should raise_error(NameError)
- -> { ConstantSpecs.send :remove_const, "@Name" }.should raise_error(NameError)
- -> { ConstantSpecs.send :remove_const, "!Name" }.should raise_error(NameError)
- -> { ConstantSpecs.send :remove_const, "::Name" }.should raise_error(NameError)
+ -> { ConstantSpecs.send :remove_const, "__CONSTX__" }.should.raise(NameError)
+ -> { ConstantSpecs.send :remove_const, "@Name" }.should.raise(NameError)
+ -> { ConstantSpecs.send :remove_const, "!Name" }.should.raise(NameError)
+ -> { ConstantSpecs.send :remove_const, "::Name" }.should.raise(NameError)
end
it "raises a NameError if the name contains non-alphabetic characters except '_'" do
ConstantSpecs::ModuleM::CS_CONST256 = :const256
ConstantSpecs::ModuleM.send :remove_const, "CS_CONST256"
- -> { ConstantSpecs.send :remove_const, "Name=" }.should raise_error(NameError)
- -> { ConstantSpecs.send :remove_const, "Name?" }.should raise_error(NameError)
+ -> { ConstantSpecs.send :remove_const, "Name=" }.should.raise(NameError)
+ -> { ConstantSpecs.send :remove_const, "Name?" }.should.raise(NameError)
end
it "calls #to_str to convert the given name to a String" do
@@ -67,19 +67,19 @@ describe "Module#remove_const" do
it "raises a TypeError if conversion to a String by calling #to_str fails" do
name = mock('123')
- -> { ConstantSpecs.send :remove_const, name }.should raise_error(TypeError)
+ -> { ConstantSpecs.send :remove_const, name }.should.raise(TypeError)
name.should_receive(:to_str).and_return(123)
- -> { ConstantSpecs.send :remove_const, name }.should raise_error(TypeError)
+ -> { ConstantSpecs.send :remove_const, name }.should.raise(TypeError)
end
it "is a private method" do
- Module.private_methods.should include(:remove_const)
+ Module.private_methods.should.include?(:remove_const)
end
it "returns nil when removing autoloaded constant" do
ConstantSpecs.autoload :AutoloadedConstant, 'a_file'
- ConstantSpecs.send(:remove_const, :AutoloadedConstant).should be_nil
+ ConstantSpecs.send(:remove_const, :AutoloadedConstant).should == nil
end
it "updates the constant value" do
@@ -101,5 +101,7 @@ describe "Module#remove_const" do
A.send(:remove_const,:FOO)
A.foo.should == 'm'
end
+ ensure
+ ConstantSpecs.send(:remove_const, :RemovedConstantUpdate)
end
end
diff --git a/spec/ruby/core/module/remove_method_spec.rb b/spec/ruby/core/module/remove_method_spec.rb
index 94b255df62..39add01e36 100644
--- a/spec/ruby/core/module/remove_method_spec.rb
+++ b/spec/ruby/core/module/remove_method_spec.rb
@@ -21,7 +21,7 @@ describe "Module#remove_method" do
end
it "is a public method" do
- Module.should have_public_instance_method(:remove_method, false)
+ Module.public_instance_methods(false).should.include?(:remove_method)
end
it "removes the method from a class" do
@@ -88,14 +88,14 @@ describe "Module#remove_method" do
end
it "returns self" do
- @module.send(:remove_method, :method_to_remove).should equal(@module)
+ @module.send(:remove_method, :method_to_remove).should.equal?(@module)
end
it "raises a NameError when attempting to remove method further up the inheritance tree" do
Class.new(ModuleSpecs::Second) do
-> {
remove_method :method_to_remove
- }.should raise_error(NameError)
+ }.should.raise(NameError)
end
end
@@ -103,7 +103,7 @@ describe "Module#remove_method" do
Class.new(ModuleSpecs::Second) do
-> {
remove_method :blah
- }.should raise_error(NameError)
+ }.should.raise(NameError)
end
end
@@ -113,19 +113,19 @@ describe "Module#remove_method" do
end
it "raises a FrozenError when passed a name" do
- -> { @frozen.send :remove_method, :method_to_remove }.should raise_error(FrozenError)
+ -> { @frozen.send :remove_method, :method_to_remove }.should.raise(FrozenError)
end
it "raises a FrozenError when passed a missing name" do
- -> { @frozen.send :remove_method, :not_exist }.should raise_error(FrozenError)
+ -> { @frozen.send :remove_method, :not_exist }.should.raise(FrozenError)
end
it "raises a TypeError when passed a not name" do
- -> { @frozen.send :remove_method, Object.new }.should raise_error(TypeError)
+ -> { @frozen.send :remove_method, Object.new }.should.raise(TypeError)
end
it "does not raise exceptions when no arguments given" do
- @frozen.send(:remove_method).should equal(@frozen)
+ @frozen.send(:remove_method).should.equal?(@frozen)
end
end
end
diff --git a/spec/ruby/core/module/ruby2_keywords_spec.rb b/spec/ruby/core/module/ruby2_keywords_spec.rb
index 80a99e2624..e392642978 100644
--- a/spec/ruby/core/module/ruby2_keywords_spec.rb
+++ b/spec/ruby/core/module/ruby2_keywords_spec.rb
@@ -22,9 +22,6 @@ describe "Module#ruby2_keywords" do
end
h = {a: 1}
- ruby_version_is "3.0" do
- obj.regular(**h).should.equal?(h)
- end
last = mark(**h).last
Hash.ruby2_keywords_hash?(last).should == true
@@ -79,122 +76,60 @@ describe "Module#ruby2_keywords" do
Hash.ruby2_keywords_hash?(marked).should == true
end
- ruby_version_is "3.2" do
- it "makes a copy and unmark the Hash when calling a method taking (*args)" do
- obj = Object.new
- obj.singleton_class.class_exec do
- def splat(*args)
- args.last
- end
-
- def splat1(arg, *args)
- args.last
- end
+ it "makes a copy and unmark the Hash when calling a method taking (*args)" do
+ obj = Object.new
+ obj.singleton_class.class_exec do
+ def splat(*args)
+ args.last
+ end
- def proc_call(*args)
- -> *a { a.last }.call(*args)
- end
+ def splat1(arg, *args)
+ args.last
end
- h = { a: 1 }
- args = mark(**h)
- marked = args.last
- Hash.ruby2_keywords_hash?(marked).should == true
-
- after_usage = obj.splat(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should_not.equal?(marked)
- Hash.ruby2_keywords_hash?(after_usage).should == false
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(1, **h)
- marked = args.last
- after_usage = obj.splat1(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should_not.equal?(marked)
- Hash.ruby2_keywords_hash?(after_usage).should == false
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(**h)
- marked = args.last
- after_usage = obj.proc_call(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should_not.equal?(marked)
- Hash.ruby2_keywords_hash?(after_usage).should == false
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(**h)
- marked = args.last
- after_usage = obj.send(:splat, *args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should_not.equal?(marked)
- Hash.ruby2_keywords_hash?(after_usage).should == false
- Hash.ruby2_keywords_hash?(marked).should == true
+ def proc_call(*args)
+ -> *a { a.last }.call(*args)
+ end
end
- end
- ruby_version_is ""..."3.2" do
- # https://bugs.ruby-lang.org/issues/18625
- it "does NOT copy the Hash when calling a method taking (*args)" do
- obj = Object.new
- obj.singleton_class.class_exec do
- def splat(*args)
- args.last
- end
+ h = { a: 1 }
+ args = mark(**h)
+ marked = args.last
+ Hash.ruby2_keywords_hash?(marked).should == true
- def splat1(arg, *args)
- args.last
- end
+ after_usage = obj.splat(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
- def proc_call(*args)
- -> *a { a.last }.call(*args)
- end
- end
+ args = mark(1, **h)
+ marked = args.last
+ after_usage = obj.splat1(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
- h = { a: 1 }
- args = mark(**h)
- marked = args.last
- Hash.ruby2_keywords_hash?(marked).should == true
-
- after_usage = obj.splat(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(1, **h)
- marked = args.last
- after_usage = obj.splat1(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(**h)
- marked = args.last
- after_usage = obj.proc_call(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(**h)
- marked = args.last
- after_usage = obj.send(:splat, *args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- send_copies = RUBY_ENGINE == "ruby" # inconsistent with Proc#call above for CRuby
- after_usage.equal?(marked).should == !send_copies
- Hash.ruby2_keywords_hash?(after_usage).should == !send_copies
- Hash.ruby2_keywords_hash?(marked).should == true
- end
+ args = mark(**h)
+ marked = args.last
+ after_usage = obj.proc_call(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ args = mark(**h)
+ marked = args.last
+ after_usage = obj.send(:splat, *args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
end
it "applies to the underlying method and applies across aliasing" do
@@ -223,25 +158,6 @@ describe "Module#ruby2_keywords" do
Hash.ruby2_keywords_hash?(last).should == true
end
- ruby_version_is ""..."3.0" do
- it "fixes delegation warnings when calling a method accepting keywords" do
- obj = Object.new
-
- obj.singleton_class.class_exec do
- def foo(*a) bar(*a) end
- def bar(*a, **b) end
- end
-
- -> { obj.foo(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/)
-
- obj.singleton_class.class_exec do
- ruby2_keywords :foo
- end
-
- -> { obj.foo(1, 2, {a: "a"}) }.should_not complain
- end
- end
-
it "returns nil" do
obj = Object.new
@@ -259,7 +175,7 @@ describe "Module#ruby2_keywords" do
obj.singleton_class.class_exec do
ruby2_keywords :not_existing
end
- }.should raise_error(NameError, /undefined method `not_existing'/)
+ }.should.raise(NameError, /undefined method [`']not_existing'/)
end
it "accepts String as well" do
@@ -281,7 +197,7 @@ describe "Module#ruby2_keywords" do
obj.singleton_class.class_exec do
ruby2_keywords Object.new
end
- }.should raise_error(TypeError, /is not a symbol nor a string/)
+ }.should.raise(TypeError, /is not a symbol nor a string/)
end
it "prints warning when a method does not accept argument splat" do
@@ -297,7 +213,7 @@ describe "Module#ruby2_keywords" do
it "prints warning when a method accepts keywords" do
obj = Object.new
- def obj.foo(a:, b:) end
+ def obj.foo(*a, b:) end
-> {
obj.singleton_class.class_exec do
@@ -308,7 +224,7 @@ describe "Module#ruby2_keywords" do
it "prints warning when a method accepts keyword splat" do
obj = Object.new
- def obj.foo(**a) end
+ def obj.foo(*a, **b) end
-> {
obj.singleton_class.class_exec do
@@ -316,4 +232,17 @@ describe "Module#ruby2_keywords" do
end
}.should complain(/Skipping set of ruby2_keywords flag for/)
end
+
+ ruby_version_is "4.0" do
+ it "prints warning when a method accepts post arguments" do
+ obj = Object.new
+ def obj.foo(*a, b) end
+
+ -> {
+ obj.singleton_class.class_exec do
+ ruby2_keywords :foo
+ end
+ }.should complain(/Skipping set of ruby2_keywords flag for/)
+ end
+ end
end
diff --git a/spec/ruby/core/module/set_temporary_name_spec.rb b/spec/ruby/core/module/set_temporary_name_spec.rb
new file mode 100644
index 0000000000..7c159121fa
--- /dev/null
+++ b/spec/ruby/core/module/set_temporary_name_spec.rb
@@ -0,0 +1,145 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_temporary_name'
+
+describe "Module#set_temporary_name" do
+ it "can assign a temporary name" do
+ m = Module.new
+ m.name.should == nil
+
+ m.set_temporary_name("fake_name")
+ m.name.should == "fake_name"
+
+ m.set_temporary_name(nil)
+ m.name.should == nil
+ end
+
+ it "returns self" do
+ m = Module.new
+ m.set_temporary_name("fake_name").should.equal? m
+ end
+
+ it "can assign a temporary name which is not a valid constant path" do
+ m = Module.new
+
+ m.set_temporary_name("name")
+ m.name.should == "name"
+
+ m.set_temporary_name("Template['foo.rb']")
+ m.name.should == "Template['foo.rb']"
+
+ m.set_temporary_name("a::B")
+ m.name.should == "a::B"
+
+ m.set_temporary_name("A::b")
+ m.name.should == "A::b"
+
+ m.set_temporary_name("A::B::")
+ m.name.should == "A::B::"
+
+ m.set_temporary_name("A::::B")
+ m.name.should == "A::::B"
+
+ m.set_temporary_name("A=")
+ m.name.should == "A="
+ end
+
+ it "can't assign empty string as name" do
+ m = Module.new
+ -> { m.set_temporary_name("") }.should.raise(ArgumentError, "empty class/module name")
+ end
+
+ it "can't assign a constant name as a temporary name" do
+ m = Module.new
+ -> { m.set_temporary_name("Object") }.should.raise(ArgumentError, "the temporary name must not be a constant path to avoid confusion")
+ end
+
+ it "can't assign a constant path as a temporary name" do
+ m = Module.new
+ -> { m.set_temporary_name("A::B") }.should.raise(ArgumentError, "the temporary name must not be a constant path to avoid confusion")
+ -> { m.set_temporary_name("::A") }.should.raise(ArgumentError, "the temporary name must not be a constant path to avoid confusion")
+ -> { m.set_temporary_name("::A::B") }.should.raise(ArgumentError, "the temporary name must not be a constant path to avoid confusion")
+ end
+
+ it "can't assign name to permanent module" do
+ -> { Object.set_temporary_name("fake_name") }.should.raise(RuntimeError, "can't change permanent name")
+ end
+
+ it "can assign a temporary name to a module nested into an anonymous module" do
+ m = Module.new
+ module m::N; end
+ m::N.name.should =~ /\A#<Module:0x\h+>::N\z/
+
+ m::N.set_temporary_name("fake_name")
+ m::N.name.should == "fake_name"
+
+ m::N.set_temporary_name(nil)
+ m::N.name.should == nil
+ end
+
+ it "discards a temporary name when an outer anonymous module gets a permanent name" do
+ m = Module.new
+ module m::N; end
+
+ m::N.set_temporary_name("fake_name")
+ m::N.name.should == "fake_name"
+
+ ModuleSpecs::SetTemporaryNameSpec::M = m
+ m::N.name.should == "ModuleSpecs::SetTemporaryNameSpec::M::N"
+ ModuleSpecs::SetTemporaryNameSpec.send :remove_const, :M
+ end
+
+ it "can update the name when assigned to a constant" do
+ m = Module.new
+ m::N = Module.new
+ m::N.name.should =~ /\A#<Module:0x\h+>::N\z/
+ m::N.set_temporary_name(nil)
+
+ m::M = m::N
+ m::M.name.should =~ /\A#<Module:0x\h+>::M\z/m
+ end
+
+ it "can reassign a temporary name repeatedly" do
+ m = Module.new
+
+ m.set_temporary_name("fake_name")
+ m.name.should == "fake_name"
+
+ m.set_temporary_name("fake_name_2")
+ m.name.should == "fake_name_2"
+ end
+
+ ruby_bug "#21094", ""..."4.0" do
+ it "also updates a name of a nested module" do
+ m = Module.new
+ m::N = Module.new
+ m::N.name.should =~ /\A#<Module:0x\h+>::N\z/
+
+ m.set_temporary_name "m"
+ m::N.name.should == "m::N"
+
+ m.set_temporary_name nil
+ m::N.name.should == nil
+ end
+ end
+
+ it "keeps temporary name when assigned in an anonymous module" do
+ outer = Module.new
+ m = Module.new
+ m.set_temporary_name "m"
+ m.name.should == "m"
+ outer::M = m
+ m.name.should == "m"
+ m.inspect.should == "m"
+ end
+
+ it "keeps temporary name when assigned in an anonymous module and nested before" do
+ outer = Module.new
+ m = Module.new
+ outer::A = m
+ m.set_temporary_name "m"
+ m.name.should == "m"
+ outer::M = m
+ m.name.should == "m"
+ m.inspect.should == "m"
+ end
+end
diff --git a/spec/ruby/core/module/shared/attr_added.rb b/spec/ruby/core/module/shared/attr_added.rb
new file mode 100644
index 0000000000..ce832cdcff
--- /dev/null
+++ b/spec/ruby/core/module/shared/attr_added.rb
@@ -0,0 +1,34 @@
+describe :module_attr_added, shared: true do
+ it "calls method_added for normal classes" do
+ ScratchPad.record []
+
+ cls = Class.new do
+ class << self
+ def method_added(name)
+ ScratchPad.recorded << name
+ end
+ end
+ end
+
+ cls.send(@method, :foo)
+
+ ScratchPad.recorded.each {|name| name.to_s.should =~ /foo[=]?/}
+ end
+
+ it "calls singleton_method_added for singleton classes" do
+ ScratchPad.record []
+ cls = Class.new do
+ class << self
+ def singleton_method_added(name)
+ # called for this def so ignore it
+ return if name == :singleton_method_added
+ ScratchPad.recorded << name
+ end
+ end
+ end
+
+ cls.singleton_class.send(@method, :foo)
+
+ ScratchPad.recorded.each {|name| name.to_s.should =~ /foo[=]?/}
+ end
+end
diff --git a/spec/ruby/core/module/shared/class_eval.rb b/spec/ruby/core/module/shared/class_eval.rb
index 224078ae54..ee2860449a 100644
--- a/spec/ruby/core/module/shared/class_eval.rb
+++ b/spec/ruby/core/module/shared/class_eval.rb
@@ -14,7 +14,7 @@ describe :module_class_eval, shared: true do
'foo'
end
end
- -> {42.foo}.should raise_error(NoMethodError)
+ -> {42.foo}.should.raise(NoMethodError)
end
it "resolves constants in the caller scope" do
@@ -45,50 +45,63 @@ describe :module_class_eval, shared: true do
ModuleSpecs.send(@method) do |block_parameter|
given = block_parameter
end
- given.should equal ModuleSpecs
+ given.should.equal? ModuleSpecs
end
it "uses the optional filename and lineno parameters for error messages" do
ModuleSpecs.send(@method, "[__FILE__, __LINE__]", "test", 102).should == ["test", 102]
end
+ it "uses the caller location as default filename" do
+ ModuleSpecs.send(@method, "[__FILE__, __LINE__]").should == ["(eval at #{__FILE__}:#{__LINE__})", 1]
+ end
+
it "converts a non-string filename to a string using to_str" do
(file = mock(__FILE__)).should_receive(:to_str).and_return(__FILE__)
ModuleSpecs.send(@method, "1+1", file)
+
+ (file = mock(__FILE__)).should_receive(:to_str).and_return(__FILE__)
+ ModuleSpecs.send(@method, "1+1", file, 15)
end
it "raises a TypeError when the given filename can't be converted to string using to_str" do
(file = mock('123')).should_receive(:to_str).and_return(123)
- -> { ModuleSpecs.send(@method, "1+1", file) }.should raise_error(TypeError)
+ -> { ModuleSpecs.send(@method, "1+1", file) }.should raise_consistent_error(TypeError, /can't convert MockObject into String/)
end
it "converts non string eval-string to string using to_str" do
(o = mock('1 + 1')).should_receive(:to_str).and_return("1 + 1")
ModuleSpecs.send(@method, o).should == 2
+
+ (o = mock('1 + 1')).should_receive(:to_str).and_return("1 + 1")
+ ModuleSpecs.send(@method, o, "file.rb").should == 2
+
+ (o = mock('1 + 1')).should_receive(:to_str).and_return("1 + 1")
+ ModuleSpecs.send(@method, o, "file.rb", 15).should == 2
end
it "raises a TypeError when the given eval-string can't be converted to string using to_str" do
o = mock('x')
- -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError)
+ -> { ModuleSpecs.send(@method, o) }.should.raise(TypeError, "no implicit conversion of MockObject into String")
(o = mock('123')).should_receive(:to_str).and_return(123)
- -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError)
+ -> { ModuleSpecs.send(@method, o) }.should raise_consistent_error(TypeError, /can't convert MockObject into String/)
end
it "raises an ArgumentError when no arguments and no block are given" do
- -> { ModuleSpecs.send(@method) }.should raise_error(ArgumentError)
+ -> { ModuleSpecs.send(@method) }.should.raise(ArgumentError, "wrong number of arguments (given 0, expected 1..3)")
end
it "raises an ArgumentError when more than 3 arguments are given" do
-> {
ModuleSpecs.send(@method, "1 + 1", "some file", 0, "bogus")
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
it "raises an ArgumentError when a block and normal arguments are given" do
-> {
ModuleSpecs.send(@method, "1 + 1") { 1 + 1 }
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, "wrong number of arguments (given 1, expected 0)")
end
# This case was found because Rubinius was caching the compiled
diff --git a/spec/ruby/core/module/shared/class_exec.rb b/spec/ruby/core/module/shared/class_exec.rb
index c7a9e5297f..e51af1966d 100644
--- a/spec/ruby/core/module/shared/class_exec.rb
+++ b/spec/ruby/core/module/shared/class_exec.rb
@@ -5,7 +5,7 @@ describe :module_class_exec, shared: true do
'foo'
end
end
- -> {42.foo}.should raise_error(NoMethodError)
+ -> {42.foo}.should.raise(NoMethodError)
end
it "defines method in the receiver's scope" do
@@ -19,11 +19,17 @@ describe :module_class_exec, shared: true do
end
it "raises a LocalJumpError when no block is given" do
- -> { ModuleSpecs::Subclass.send(@method) }.should raise_error(LocalJumpError)
+ -> { ModuleSpecs::Subclass.send(@method) }.should.raise(LocalJumpError)
end
it "passes arguments to the block" do
a = ModuleSpecs::Subclass
- a.send(@method, 1) { |b| b }.should equal(1)
+ a.send(@method, 1) { |b| b }.should.equal?(1)
+ end
+
+ describe "with optional argument" do
+ it "does not destructure a single array argument" do
+ ModuleSpecs::Subclass.send(@method, [1, 2, 3]) { |a = 99| a }.should == [1, 2, 3]
+ end
end
end
diff --git a/spec/ruby/core/module/shared/set_visibility.rb b/spec/ruby/core/module/shared/set_visibility.rb
index 9f31e230ca..38cc2ad260 100644
--- a/spec/ruby/core/module/shared/set_visibility.rb
+++ b/spec/ruby/core/module/shared/set_visibility.rb
@@ -2,7 +2,7 @@
describe :set_visibility, shared: true do
it "is a private method" do
- Module.should have_private_instance_method(@method, false)
+ Module.private_instance_methods(false).should.include?(@method)
end
describe "with argument" do
@@ -17,26 +17,24 @@ describe :set_visibility, shared: true do
def test2() end
send visibility, :test1, :test2
}
- mod.should send(:"have_#{visibility}_instance_method", :test1, false)
- mod.should send(:"have_#{visibility}_instance_method", :test2, false)
+ mod.send(:"#{visibility}_instance_methods", false).should.include?(:test1)
+ mod.send(:"#{visibility}_instance_methods", false).should.include?(:test2)
end
end
- ruby_version_is "3.0" do
- describe "array as a single argument" do
- it "sets visibility of given method names" do
- visibility = @method
- old_visibility = [:protected, :private].find {|vis| vis != visibility }
-
- mod = Module.new {
- send old_visibility
- def test1() end
- def test2() end
- send visibility, [:test1, :test2]
- }
- mod.should send(:"have_#{visibility}_instance_method", :test1, false)
- mod.should send(:"have_#{visibility}_instance_method", :test2, false)
- end
+ describe "array as a single argument" do
+ it "sets visibility of given method names" do
+ visibility = @method
+ old_visibility = [:protected, :private].find {|vis| vis != visibility }
+
+ mod = Module.new {
+ send old_visibility
+ def test1() end
+ def test2() end
+ send visibility, [:test1, :test2]
+ }
+ mod.send(:"#{visibility}_instance_methods", false).should.include?(:test1)
+ mod.send(:"#{visibility}_instance_methods", false).should.include?(:test2)
end
end
@@ -52,7 +50,7 @@ describe :set_visibility, shared: true do
send(visibility, :test_method)
}
- child.should_not send(:"have_#{visibility}_instance_method", :test_method, false)
+ child.send(:"#{visibility}_instance_methods", false).should_not.include?(:test_method)
end
end
@@ -66,8 +64,8 @@ describe :set_visibility, shared: true do
def test2() end
}
- mod.should send(:"have_#{@method}_instance_method", :test1, false)
- mod.should send(:"have_#{@method}_instance_method", :test2, false)
+ mod.send(:"#{@method}_instance_methods", false).should.include?(:test1)
+ mod.send(:"#{@method}_instance_methods", false).should.include?(:test2)
end
it "stops setting visibility if the body encounters other visibility setters without arguments" do
@@ -80,7 +78,7 @@ describe :set_visibility, shared: true do
def test1() end
}
- mod.should send(:"have_#{new_visibility}_instance_method", :test1, false)
+ mod.send(:"#{new_visibility}_instance_methods", false).should.include?(:test1)
end
it "continues setting visibility if the body encounters other visibility setters with arguments" do
@@ -92,7 +90,7 @@ describe :set_visibility, shared: true do
def test2() end
}
- mod.should send(:"have_#{@method}_instance_method", :test2, false)
+ mod.send(:"#{@method}_instance_methods", false).should.include?(:test2)
end
it "does not affect module_evaled method definitions when itself is outside the eval" do
@@ -104,8 +102,8 @@ describe :set_visibility, shared: true do
module_eval " def test2() end "
}
- mod.should have_public_instance_method(:test1, false)
- mod.should have_public_instance_method(:test2, false)
+ mod.public_instance_methods(false).should.include?(:test1)
+ mod.public_instance_methods(false).should.include?(:test2)
end
it "does not affect outside method definitions when itself is inside a module_eval" do
@@ -116,7 +114,7 @@ describe :set_visibility, shared: true do
def test1() end
}
- mod.should have_public_instance_method(:test1, false)
+ mod.public_instance_methods(false).should.include?(:test1)
end
it "affects normally if itself and method definitions are inside a module_eval" do
@@ -129,7 +127,7 @@ describe :set_visibility, shared: true do
}
}
- mod.should send(:"have_#{@method}_instance_method", :test1, false)
+ mod.send(:"#{@method}_instance_methods", false).should.include?(:test1)
end
it "does not affect method definitions when itself is inside an eval and method definitions are outside" do
@@ -142,7 +140,7 @@ describe :set_visibility, shared: true do
def test1() end
}
- mod.should send(:"have_#{initialized_visibility}_instance_method", :test1, false)
+ mod.send(:"#{initialized_visibility}_instance_methods", false).should.include?(:test1)
end
it "affects evaled method definitions when itself is outside the eval" do
@@ -153,7 +151,7 @@ describe :set_visibility, shared: true do
eval "def test1() end"
}
- mod.should send(:"have_#{@method}_instance_method", :test1, false)
+ mod.send(:"#{@method}_instance_methods", false).should.include?(:test1)
end
it "affects normally if itself and following method definitions are inside a eval" do
@@ -166,7 +164,7 @@ describe :set_visibility, shared: true do
CODE
}
- mod.should send(:"have_#{@method}_instance_method", :test1, false)
+ mod.send(:"#{@method}_instance_methods", false).should.include?(:test1)
end
describe "within a closure" do
@@ -179,7 +177,7 @@ describe :set_visibility, shared: true do
def test1() end
}
- mod.should send(:"have_#{@method}_instance_method", :test1, false)
+ mod.send(:"#{@method}_instance_methods", false).should.include?(:test1)
end
end
end
diff --git a/spec/ruby/core/module/to_s_spec.rb b/spec/ruby/core/module/to_s_spec.rb
index 6b1a615ef9..83c0ae0825 100644
--- a/spec/ruby/core/module/to_s_spec.rb
+++ b/spec/ruby/core/module/to_s_spec.rb
@@ -51,6 +51,8 @@ describe "Module#to_s" do
ModuleSpecs::RefinementInspect::R.name.should == 'ModuleSpecs::RefinementInspect::R'
ModuleSpecs::RefinementInspect::R.to_s.should == '#<refinement:String@ModuleSpecs::RefinementInspect>'
+ ensure
+ ModuleSpecs.send(:remove_const, :RefinementInspect)
end
it 'does not call #inspect or #to_s for singleton classes' do
diff --git a/spec/ruby/core/module/undef_method_spec.rb b/spec/ruby/core/module/undef_method_spec.rb
index c2ad200536..d77640cb7e 100644
--- a/spec/ruby/core/module/undef_method_spec.rb
+++ b/spec/ruby/core/module/undef_method_spec.rb
@@ -19,7 +19,7 @@ describe "Module#undef_method" do
end
it "is a public method" do
- Module.should have_public_instance_method(:undef_method, false)
+ Module.public_instance_methods(false).should.include?(:undef_method)
end
it "requires multiple arguments" do
@@ -34,8 +34,8 @@ describe "Module#undef_method" do
x = klass.new
klass.send(:undef_method, :method_to_undef, :another_method_to_undef)
- -> { x.method_to_undef }.should raise_error(NoMethodError)
- -> { x.another_method_to_undef }.should raise_error(NoMethodError)
+ -> { x.method_to_undef }.should.raise(NoMethodError)
+ -> { x.another_method_to_undef }.should.raise(NoMethodError)
end
it "does not undef any instance methods when argument not given" do
@@ -46,11 +46,11 @@ describe "Module#undef_method" do
end
it "returns self" do
- @module.send(:undef_method, :method_to_undef).should equal(@module)
+ @module.send(:undef_method, :method_to_undef).should.equal?(@module)
end
it "raises a NameError when passed a missing name for a module" do
- -> { @module.send :undef_method, :not_exist }.should raise_error(NameError, /undefined method `not_exist' for module `#{@module}'/) { |e|
+ -> { @module.send :undef_method, :not_exist }.should.raise(NameError, /undefined method [`']not_exist' for module [`']#{@module}'/) { |e|
# a NameError and not a NoMethodError
e.class.should == NameError
}
@@ -58,7 +58,7 @@ describe "Module#undef_method" do
it "raises a NameError when passed a missing name for a class" do
klass = Class.new
- -> { klass.send :undef_method, :not_exist }.should raise_error(NameError, /undefined method `not_exist' for class `#{klass}'/) { |e|
+ -> { klass.send :undef_method, :not_exist }.should.raise(NameError, /undefined method [`']not_exist' for class [`']#{klass}'/) { |e|
# a NameError and not a NoMethodError
e.class.should == NameError
}
@@ -69,8 +69,8 @@ describe "Module#undef_method" do
obj = klass.new
sclass = obj.singleton_class
- -> { sclass.send :undef_method, :not_exist }.should raise_error(NameError, /undefined method `not_exist' for class `#{sclass}'/) { |e|
- e.message.should include('`#<Class:#<#<Class:')
+ -> { sclass.send :undef_method, :not_exist }.should.raise(NameError, /undefined method [`']not_exist' for class [`']#{sclass}'/) { |e|
+ e.message.should =~ /[`']#<Class:#<#<Class:/
# a NameError and not a NoMethodError
e.class.should == NameError
@@ -79,7 +79,7 @@ describe "Module#undef_method" do
it "raises a NameError when passed a missing name for a metaclass" do
klass = String.singleton_class
- -> { klass.send :undef_method, :not_exist }.should raise_error(NameError, /undefined method `not_exist' for class `String'/) { |e|
+ -> { klass.send :undef_method, :not_exist }.should.raise(NameError, /undefined method [`']not_exist' for class [`']String'/) { |e|
# a NameError and not a NoMethodError
e.class.should == NameError
}
@@ -91,19 +91,19 @@ describe "Module#undef_method" do
end
it "raises a FrozenError when passed a name" do
- -> { @frozen.send :undef_method, :method_to_undef }.should raise_error(FrozenError)
+ -> { @frozen.send :undef_method, :method_to_undef }.should.raise(FrozenError)
end
it "raises a FrozenError when passed a missing name" do
- -> { @frozen.send :undef_method, :not_exist }.should raise_error(FrozenError)
+ -> { @frozen.send :undef_method, :not_exist }.should.raise(FrozenError)
end
it "raises a TypeError when passed a not name" do
- -> { @frozen.send :undef_method, Object.new }.should raise_error(TypeError)
+ -> { @frozen.send :undef_method, Object.new }.should.raise(TypeError)
end
it "does not raise exceptions when no arguments given" do
- @frozen.send(:undef_method).should equal(@frozen)
+ @frozen.send(:undef_method).should.equal?(@frozen)
end
end
end
@@ -120,7 +120,7 @@ describe "Module#undef_method with symbol" do
klass.send :undef_method, :method_to_undef
- -> { x.method_to_undef }.should raise_error(NoMethodError)
+ -> { x.method_to_undef }.should.raise(NoMethodError)
end
it "removes a method defined in a super class" do
@@ -130,7 +130,7 @@ describe "Module#undef_method with symbol" do
child_class.send :undef_method, :method_to_undef
- -> { child.method_to_undef }.should raise_error(NoMethodError)
+ -> { child.method_to_undef }.should.raise(NoMethodError)
end
it "does not remove a method defined in a super class when removed from a subclass" do
@@ -156,7 +156,7 @@ describe "Module#undef_method with string" do
klass.send :undef_method, 'another_method_to_undef'
- -> { x.another_method_to_undef }.should raise_error(NoMethodError)
+ -> { x.another_method_to_undef }.should.raise(NoMethodError)
end
it "removes a method defined in a super class" do
@@ -166,7 +166,7 @@ describe "Module#undef_method with string" do
child_class.send :undef_method, 'another_method_to_undef'
- -> { child.another_method_to_undef }.should raise_error(NoMethodError)
+ -> { child.another_method_to_undef }.should.raise(NoMethodError)
end
it "does not remove a method defined in a super class when removed from a subclass" do
diff --git a/spec/ruby/core/module/undefined_instance_methods_spec.rb b/spec/ruby/core/module/undefined_instance_methods_spec.rb
new file mode 100644
index 0000000000..9f731c6adf
--- /dev/null
+++ b/spec/ruby/core/module/undefined_instance_methods_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Module#undefined_instance_methods" do
+ it "returns methods undefined in the class" do
+ methods = ModuleSpecs::UndefinedInstanceMethods::Parent.undefined_instance_methods
+ methods.should == [:undefed_method]
+ end
+
+ it "returns inherited methods undefined in the class" do
+ methods = ModuleSpecs::UndefinedInstanceMethods::Child.undefined_instance_methods
+ methods.to_set.should >= Set[:parent_method, :another_parent_method]
+ end
+
+ it "returns methods from an included module that are undefined in the class" do
+ methods = ModuleSpecs::UndefinedInstanceMethods::Grandchild.undefined_instance_methods
+ methods.should.include?(:super_included_method)
+ end
+
+ it "does not returns ancestors undefined methods" do
+ methods = ModuleSpecs::UndefinedInstanceMethods::Grandchild.undefined_instance_methods
+ methods.should_not.include?(:parent_method)
+ methods.should_not.include?(:another_parent_method)
+ end
+end
diff --git a/spec/ruby/core/module/used_refinements_spec.rb b/spec/ruby/core/module/used_refinements_spec.rb
new file mode 100644
index 0000000000..40dd4a444e
--- /dev/null
+++ b/spec/ruby/core/module/used_refinements_spec.rb
@@ -0,0 +1,85 @@
+require_relative '../../spec_helper'
+
+describe "Module.used_refinements" do
+ it "returns list of all refinements imported in the current scope" do
+ refinement_int = nil
+ refinement_str = nil
+ ScratchPad.record []
+
+ m1 = Module.new do
+ refine Integer do
+ refinement_int = self
+ end
+ end
+
+ m2 = Module.new do
+ refine String do
+ refinement_str = self
+ end
+ end
+
+ Module.new do
+ using m1
+ using m2
+
+ Module.used_refinements.each { |r| ScratchPad << r }
+ end
+
+ ScratchPad.recorded.sort_by(&:object_id).should == [refinement_int, refinement_str].sort_by(&:object_id)
+ end
+
+ it "returns empty array if does not have any refinements imported" do
+ used_refinements = nil
+
+ Module.new do
+ used_refinements = Module.used_refinements
+ end
+
+ used_refinements.should == []
+ end
+
+ it "ignores refinements imported in a module that is included into the current one" do
+ used_refinements = nil
+
+ m1 = Module.new do
+ refine Integer do
+ nil
+ end
+ end
+
+ m2 = Module.new do
+ using m1
+ end
+
+ Module.new do
+ include m2
+
+ used_refinements = Module.used_refinements
+ end
+
+ used_refinements.should == []
+ end
+
+ it "returns refinements even not defined directly in a module refinements are imported from" do
+ used_refinements = nil
+ ScratchPad.record []
+
+ m1 = Module.new do
+ refine Integer do
+ ScratchPad << self
+ end
+ end
+
+ m2 = Module.new do
+ include m1
+ end
+
+ Module.new do
+ using m2
+
+ used_refinements = Module.used_refinements
+ end
+
+ used_refinements.should == ScratchPad.recorded
+ end
+end
diff --git a/spec/ruby/core/module/using_spec.rb b/spec/ruby/core/module/using_spec.rb
index 4781b99bb7..cff0edef28 100644
--- a/spec/ruby/core/module/using_spec.rb
+++ b/spec/ruby/core/module/using_spec.rb
@@ -28,7 +28,7 @@ describe "Module#using" do
Module.new do
using refinement
end
- }.should_not raise_error
+ }.should_not.raise
end
it "accepts module without refinements" do
@@ -38,7 +38,7 @@ describe "Module#using" do
Module.new do
using mod
end
- }.should_not raise_error
+ }.should_not.raise
end
it "does not accept class" do
@@ -48,7 +48,7 @@ describe "Module#using" do
Module.new do
using klass
end
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises TypeError if passed something other than module" do
@@ -56,7 +56,7 @@ describe "Module#using" do
Module.new do
using "foo"
end
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "returns self" do
@@ -67,7 +67,7 @@ describe "Module#using" do
result = using refinement
end
- result.should equal(mod)
+ result.should.equal?(mod)
end
it "works in classes too" do
@@ -95,7 +95,7 @@ describe "Module#using" do
-> {
mod.foo
- }.should raise_error(RuntimeError, /Module#using is not permitted in methods/)
+ }.should.raise(RuntimeError, /Module#using is not permitted in methods/)
end
it "activates refinement even for existed objects" do
@@ -316,7 +316,7 @@ describe "Module#using" do
using refinement
def initialize
- @a = "1703"
+ @a = +"1703"
@a.instance_eval do
def abc
diff --git a/spec/ruby/core/mutex/lock_spec.rb b/spec/ruby/core/mutex/lock_spec.rb
index 7a39817b11..4fee29091a 100644
--- a/spec/ruby/core/mutex/lock_spec.rb
+++ b/spec/ruby/core/mutex/lock_spec.rb
@@ -1,10 +1,6 @@
require_relative '../../spec_helper'
describe "Mutex#lock" do
- before :each do
- ScratchPad.clear
- end
-
it "returns self" do
m = Mutex.new
m.lock.should == m
@@ -24,11 +20,73 @@ describe "Mutex#lock" do
# Unable to find a specific ticket but behavior change may be
# related to this ML thread.
- it "raises a ThreadError when used recursively" do
+ it "raises a deadlock ThreadError when used recursively" do
m = Mutex.new
m.lock
-> {
m.lock
- }.should raise_error(ThreadError)
+ }.should.raise(ThreadError, /deadlock/)
+ end
+
+ it "raises a deadlock ThreadError when multiple fibers from the same thread try to lock" do
+ m = Mutex.new
+
+ m.lock
+ f0 = Fiber.new do
+ m.lock
+ end
+ -> { f0.resume }.should.raise(ThreadError, /deadlock/)
+
+ m.unlock
+ f1 = Fiber.new do
+ m.lock
+ Fiber.yield
+ end
+ f2 = Fiber.new do
+ m.lock
+ end
+ f1.resume
+ -> { f2.resume }.should.raise(ThreadError, /deadlock/)
+ end
+
+ it "does not raise deadlock if a fiber's attempt to lock was interrupted" do
+ lock = Mutex.new
+ main = Thread.current
+
+ t2 = nil
+ t1 = Thread.new do
+ loop do
+ # interrupt fiber below looping on synchronize
+ sleep 0.01
+ t2.raise if t2
+ end
+ end
+
+ # loop ten times to try to handle the interrupt during synchronize
+ t2 = Thread.new do
+ 10.times do
+ Fiber.new do
+ begin
+ loop { lock.synchronize {} }
+ rescue RuntimeError
+ end
+ end.resume
+
+ Fiber.new do
+ -> do
+ lock.synchronize {}
+ end.should_not.raise(ThreadError)
+ end.resume
+ rescue RuntimeError
+ retry
+ end
+ end
+ t2.join
+ ensure
+ t1.kill rescue nil
+ t2.kill rescue nil
+
+ t1.join
+ t2.join
end
end
diff --git a/spec/ruby/core/mutex/locked_spec.rb b/spec/ruby/core/mutex/locked_spec.rb
index 1bf3ed6394..1818cdb4f3 100644
--- a/spec/ruby/core/mutex/locked_spec.rb
+++ b/spec/ruby/core/mutex/locked_spec.rb
@@ -4,12 +4,12 @@ describe "Mutex#locked?" do
it "returns true if locked" do
m = Mutex.new
m.lock
- m.locked?.should be_true
+ m.locked?.should == true
end
it "returns false if unlocked" do
m = Mutex.new
- m.locked?.should be_false
+ m.locked?.should == false
end
it "returns the status of the lock" do
@@ -27,10 +27,10 @@ describe "Mutex#locked?" do
Thread.pass until m1_locked
- m1.locked?.should be_true
+ m1.locked?.should == true
m2.unlock # release th
th.join
# A Thread releases its locks upon termination
- m1.locked?.should be_false
+ m1.locked?.should == false
end
end
diff --git a/spec/ruby/core/mutex/owned_spec.rb b/spec/ruby/core/mutex/owned_spec.rb
index 1f843cd576..ea7d5faf1c 100644
--- a/spec/ruby/core/mutex/owned_spec.rb
+++ b/spec/ruby/core/mutex/owned_spec.rb
@@ -4,7 +4,7 @@ describe "Mutex#owned?" do
describe "when unlocked" do
it "returns false" do
m = Mutex.new
- m.owned?.should be_false
+ m.owned?.should == false
end
end
@@ -12,7 +12,7 @@ describe "Mutex#owned?" do
it "returns true" do
m = Mutex.new
m.lock
- m.owned?.should be_true
+ m.owned?.should == true
end
end
@@ -37,19 +37,17 @@ describe "Mutex#owned?" do
end
Thread.pass until locked
- m.owned?.should be_false
+ m.owned?.should == false
end
end
- ruby_version_is "3.0" do
- it "is held per Fiber" do
- m = Mutex.new
- m.lock
+ it "is held per Fiber" do
+ m = Mutex.new
+ m.lock
- Fiber.new do
- m.locked?.should == true
- m.owned?.should == false
- end.resume
- end
+ Fiber.new do
+ m.locked?.should == true
+ m.owned?.should == false
+ end.resume
end
end
diff --git a/spec/ruby/core/mutex/sleep_spec.rb b/spec/ruby/core/mutex/sleep_spec.rb
index 9832e3125e..71b089d251 100644
--- a/spec/ruby/core/mutex/sleep_spec.rb
+++ b/spec/ruby/core/mutex/sleep_spec.rb
@@ -4,21 +4,21 @@ describe "Mutex#sleep" do
describe "when not locked by the current thread" do
it "raises a ThreadError" do
m = Mutex.new
- -> { m.sleep }.should raise_error(ThreadError)
+ -> { m.sleep }.should.raise(ThreadError)
end
it "raises an ArgumentError if passed a negative duration" do
m = Mutex.new
- -> { m.sleep(-0.1) }.should raise_error(ArgumentError)
- -> { m.sleep(-1) }.should raise_error(ArgumentError)
+ -> { m.sleep(-0.1) }.should.raise(ArgumentError)
+ -> { m.sleep(-1) }.should.raise(ArgumentError)
end
end
it "raises an ArgumentError if passed a negative duration" do
m = Mutex.new
m.lock
- -> { m.sleep(-0.1) }.should raise_error(ArgumentError)
- -> { m.sleep(-1) }.should raise_error(ArgumentError)
+ -> { m.sleep(-0.1) }.should.raise(ArgumentError)
+ -> { m.sleep(-1) }.should.raise(ArgumentError)
end
it "pauses execution for approximately the duration requested" do
@@ -38,7 +38,7 @@ describe "Mutex#sleep" do
th = Thread.new { m.lock; locked = true; m.sleep }
Thread.pass until locked
Thread.pass until th.stop?
- m.locked?.should be_false
+ m.locked?.should == false
th.run
th.join
end
@@ -47,7 +47,7 @@ describe "Mutex#sleep" do
m = Mutex.new
m.lock
m.sleep(0.001)
- m.locked?.should be_true
+ m.locked?.should == true
end
it "relocks the mutex when woken by an exception being raised" do
@@ -65,7 +65,7 @@ describe "Mutex#sleep" do
Thread.pass until locked
Thread.pass until th.stop?
th.raise(Exception)
- th.value.should be_true
+ th.value.should == true
end
it "returns the rounded number of seconds asleep" do
@@ -79,7 +79,15 @@ describe "Mutex#sleep" do
Thread.pass until locked
Thread.pass until th.stop?
th.wakeup
- th.value.should be_kind_of(Integer)
+ th.value.should.is_a?(Integer)
+ end
+
+ it "accepts nil as a sleep duration" do
+ m = Mutex.new
+ -> {
+ m.lock
+ m.sleep(nil)
+ }.should block_caller
end
it "wakes up when requesting sleep times near or equal to zero" do
@@ -97,7 +105,7 @@ describe "Mutex#sleep" do
m.lock
times.each do |time|
# just testing that sleep completes
- -> {m.sleep(time)}.should_not raise_error
+ -> {m.sleep(time)}.should_not.raise
end
end
end
diff --git a/spec/ruby/core/mutex/synchronize_spec.rb b/spec/ruby/core/mutex/synchronize_spec.rb
index 7942885197..823f29a634 100644
--- a/spec/ruby/core/mutex/synchronize_spec.rb
+++ b/spec/ruby/core/mutex/synchronize_spec.rb
@@ -14,15 +14,15 @@ describe "Mutex#synchronize" do
m2.lock
raise Exception
end
- end.should raise_error(Exception)
+ end.should.raise(Exception)
end
Thread.pass until synchronized
- m1.locked?.should be_true
+ m1.locked?.should == true
m2.unlock
th.join
- m1.locked?.should be_false
+ m1.locked?.should == false
end
it "blocks the caller if already locked" do
@@ -60,7 +60,7 @@ describe "Mutex#synchronize" do
m = Mutex.new
m.synchronize do
- -> { m.synchronize { } }.should raise_error(ThreadError)
+ -> { m.synchronize { } }.should.raise(ThreadError)
end
end
end
diff --git a/spec/ruby/core/mutex/try_lock_spec.rb b/spec/ruby/core/mutex/try_lock_spec.rb
index 8d521f4c6b..1da0735d6a 100644
--- a/spec/ruby/core/mutex/try_lock_spec.rb
+++ b/spec/ruby/core/mutex/try_lock_spec.rb
@@ -4,13 +4,13 @@ describe "Mutex#try_lock" do
describe "when unlocked" do
it "returns true" do
m = Mutex.new
- m.try_lock.should be_true
+ m.try_lock.should == true
end
it "locks the mutex" do
m = Mutex.new
m.try_lock
- m.locked?.should be_true
+ m.locked?.should == true
end
end
@@ -18,7 +18,7 @@ describe "Mutex#try_lock" do
it "returns false" do
m = Mutex.new
m.lock
- m.try_lock.should be_false
+ m.try_lock.should == false
end
end
@@ -26,7 +26,7 @@ describe "Mutex#try_lock" do
it "returns false" do
m = Mutex.new
m.lock
- Thread.new { m.try_lock }.value.should be_false
+ Thread.new { m.try_lock }.value.should == false
end
end
end
diff --git a/spec/ruby/core/mutex/unlock_spec.rb b/spec/ruby/core/mutex/unlock_spec.rb
index d999e66842..ed493cf84a 100644
--- a/spec/ruby/core/mutex/unlock_spec.rb
+++ b/spec/ruby/core/mutex/unlock_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Mutex#unlock" do
it "raises ThreadError unless Mutex is locked" do
mutex = Mutex.new
- -> { mutex.unlock }.should raise_error(ThreadError)
+ -> { mutex.unlock }.should.raise(ThreadError)
end
it "raises ThreadError unless thread owns Mutex" do
@@ -19,7 +19,7 @@ describe "Mutex#unlock" do
Thread.pass until mutex.locked?
Thread.pass until th.stop?
- -> { mutex.unlock }.should raise_error(ThreadError)
+ -> { mutex.unlock }.should.raise(ThreadError)
wait.unlock
th.join
@@ -33,6 +33,6 @@ describe "Mutex#unlock" do
th.join
- -> { mutex.unlock }.should raise_error(ThreadError)
+ -> { mutex.unlock }.should.raise(ThreadError)
end
end
diff --git a/spec/ruby/core/nil/dup_spec.rb b/spec/ruby/core/nil/dup_spec.rb
index 0324b3f1f4..e0be9540a6 100644
--- a/spec/ruby/core/nil/dup_spec.rb
+++ b/spec/ruby/core/nil/dup_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../spec_helper'
describe "NilClass#dup" do
it "returns self" do
- nil.dup.should equal(nil)
+ nil.dup.should.equal?(nil)
end
end
diff --git a/spec/ruby/core/nil/match_spec.rb b/spec/ruby/core/nil/match_spec.rb
index bc1c591793..27ebc53c3d 100644
--- a/spec/ruby/core/nil/match_spec.rb
+++ b/spec/ruby/core/nil/match_spec.rb
@@ -5,13 +5,13 @@ describe "NilClass#=~" do
o = nil
suppress_warning do
- (o =~ /Object/).should be_nil
- (o =~ 'Object').should be_nil
- (o =~ Object).should be_nil
- (o =~ Object.new).should be_nil
- (o =~ nil).should be_nil
- (o =~ false).should be_nil
- (o =~ true).should be_nil
+ (o =~ /Object/).should == nil
+ (o =~ 'Object').should == nil
+ (o =~ Object).should == nil
+ (o =~ Object.new).should == nil
+ (o =~ nil).should == nil
+ (o =~ false).should == nil
+ (o =~ true).should == nil
end
end
diff --git a/spec/ruby/core/nil/nilclass_spec.rb b/spec/ruby/core/nil/nilclass_spec.rb
index 7f6d8af25d..55c5d0eba7 100644
--- a/spec/ruby/core/nil/nilclass_spec.rb
+++ b/spec/ruby/core/nil/nilclass_spec.rb
@@ -4,12 +4,12 @@ describe "NilClass" do
it ".allocate raises a TypeError" do
-> do
NilClass.allocate
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it ".new is undefined" do
-> do
NilClass.new
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
end
diff --git a/spec/ruby/core/nil/rationalize_spec.rb b/spec/ruby/core/nil/rationalize_spec.rb
index 84d6e6f056..69fb257a7f 100644
--- a/spec/ruby/core/nil/rationalize_spec.rb
+++ b/spec/ruby/core/nil/rationalize_spec.rb
@@ -10,7 +10,7 @@ describe "NilClass#rationalize" do
end
it "raises ArgumentError when passed more than one argument" do
- -> { nil.rationalize(0.1, 0.1) }.should raise_error(ArgumentError)
- -> { nil.rationalize(0.1, 0.1, 2) }.should raise_error(ArgumentError)
+ -> { nil.rationalize(0.1, 0.1) }.should.raise(ArgumentError)
+ -> { nil.rationalize(0.1, 0.1, 2) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/nil/singleton_method_spec.rb b/spec/ruby/core/nil/singleton_method_spec.rb
new file mode 100644
index 0000000000..f121b42f81
--- /dev/null
+++ b/spec/ruby/core/nil/singleton_method_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+
+describe "NilClass#singleton_method" do
+ it "raises regardless of whether NilClass defines the method" do
+ -> { nil.singleton_method(:foo) }.should.raise(NameError)
+ begin
+ def (nil).foo; end
+ -> { nil.singleton_method(:foo) }.should.raise(NameError)
+ ensure
+ NilClass.send(:remove_method, :foo)
+ end
+ end
+end
diff --git a/spec/ruby/core/nil/to_c_spec.rb b/spec/ruby/core/nil/to_c_spec.rb
index e0052be5bd..f449ddb6a3 100644
--- a/spec/ruby/core/nil/to_c_spec.rb
+++ b/spec/ruby/core/nil/to_c_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../spec_helper'
describe "NilClass#to_c" do
it "returns Complex(0, 0)" do
- nil.to_c.should eql(Complex(0, 0))
+ nil.to_c.should.eql?(Complex(0, 0))
end
end
diff --git a/spec/ruby/core/nil/to_s_spec.rb b/spec/ruby/core/nil/to_s_spec.rb
index fa0b929677..016ba4165a 100644
--- a/spec/ruby/core/nil/to_s_spec.rb
+++ b/spec/ruby/core/nil/to_s_spec.rb
@@ -10,6 +10,6 @@ describe "NilClass#to_s" do
end
it "always returns the same string" do
- nil.to_s.should equal(nil.to_s)
+ nil.to_s.should.equal?(nil.to_s)
end
end
diff --git a/spec/ruby/core/numeric/abs2_spec.rb b/spec/ruby/core/numeric/abs2_spec.rb
index 0e60cd0ae7..12866f9c47 100644
--- a/spec/ruby/core/numeric/abs2_spec.rb
+++ b/spec/ruby/core/numeric/abs2_spec.rb
@@ -18,7 +18,7 @@ describe "Numeric#abs2" do
it "returns the square of the absolute value of self" do
@numbers.each do |number|
- number.abs2.should eql(number.abs ** 2)
+ number.abs2.should.eql?(number.abs ** 2)
end
end
@@ -29,6 +29,6 @@ describe "Numeric#abs2" do
end
it "returns NaN when self is NaN" do
- nan_value.abs2.nan?.should be_true
+ nan_value.abs2.nan?.should == true
end
end
diff --git a/spec/ruby/core/numeric/clone_spec.rb b/spec/ruby/core/numeric/clone_spec.rb
index c3b06ca0c9..1d06fdb050 100644
--- a/spec/ruby/core/numeric/clone_spec.rb
+++ b/spec/ruby/core/numeric/clone_spec.rb
@@ -3,30 +3,28 @@ require_relative '../../spec_helper'
describe "Numeric#clone" do
it "returns self" do
value = 1
- value.clone.should equal(value)
+ value.clone.should.equal?(value)
subclass = Class.new(Numeric)
value = subclass.new
- value.clone.should equal(value)
+ value.clone.should.equal?(value)
end
it "does not change frozen status" do
1.clone.frozen?.should == true
end
- it "accepts optonal keyword argument :freeze" do
+ it "accepts optional keyword argument :freeze" do
value = 1
- value.clone(freeze: true).should equal(value)
+ value.clone(freeze: true).should.equal?(value)
end
it "raises ArgumentError if passed freeze: false" do
- -> { 1.clone(freeze: false) }.should raise_error(ArgumentError, /can't unfreeze/)
+ -> { 1.clone(freeze: false) }.should.raise(ArgumentError, /can't unfreeze/)
end
- ruby_version_is "3.0" do
- it "does not change frozen status if passed freeze: nil" do
- value = 1
- value.clone(freeze: nil).should equal(value)
- end
+ it "does not change frozen status if passed freeze: nil" do
+ value = 1
+ value.clone(freeze: nil).should.equal?(value)
end
end
diff --git a/spec/ruby/core/numeric/coerce_spec.rb b/spec/ruby/core/numeric/coerce_spec.rb
index 4c4416d30b..9344d99ee6 100644
--- a/spec/ruby/core/numeric/coerce_spec.rb
+++ b/spec/ruby/core/numeric/coerce_spec.rb
@@ -25,7 +25,7 @@ describe "Numeric#coerce" do
class << a; true; end
# watch it explode
- -> { a.coerce(b) }.should raise_error(TypeError)
+ -> { a.coerce(b) }.should.raise(TypeError)
end
end
@@ -38,22 +38,22 @@ describe "Numeric#coerce" do
it "raise TypeError if they are instances of different classes and other does not respond to #to_f" do
other = mock("numeric")
- -> { @obj.coerce(other) }.should raise_error(TypeError)
+ -> { @obj.coerce(other) }.should.raise(TypeError)
end
it "raises a TypeError when passed nil" do
- -> { @obj.coerce(nil) }.should raise_error(TypeError)
+ -> { @obj.coerce(nil) }.should.raise(TypeError)
end
it "raises a TypeError when passed a boolean" do
- -> { @obj.coerce(false) }.should raise_error(TypeError)
+ -> { @obj.coerce(false) }.should.raise(TypeError)
end
it "raises a TypeError when passed a Symbol" do
- -> { @obj.coerce(:symbol) }.should raise_error(TypeError)
+ -> { @obj.coerce(:symbol) }.should.raise(TypeError)
end
it "raises an ArgumentError when passed a non-numeric String" do
- -> { @obj.coerce("test") }.should raise_error(ArgumentError)
+ -> { @obj.coerce("test") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/numeric/comparison_spec.rb b/spec/ruby/core/numeric/comparison_spec.rb
index 4b4d52501a..b0a9390cc0 100644
--- a/spec/ruby/core/numeric/comparison_spec.rb
+++ b/spec/ruby/core/numeric/comparison_spec.rb
@@ -26,22 +26,22 @@ describe "Numeric#<=>" do
end
it "is called when instances are compared with #<" do
- (@a < @b).should be_false
+ (@a < @b).should == false
ScratchPad.recorded.should == :numeric_comparison
end
it "is called when instances are compared with #<=" do
- (@a <= @b).should be_false
+ (@a <= @b).should == false
ScratchPad.recorded.should == :numeric_comparison
end
it "is called when instances are compared with #>" do
- (@a > @b).should be_true
+ (@a > @b).should == true
ScratchPad.recorded.should == :numeric_comparison
end
it "is called when instances are compared with #>=" do
- (@a >= @b).should be_true
+ (@a >= @b).should == true
ScratchPad.recorded.should == :numeric_comparison
end
end
diff --git a/spec/ruby/core/numeric/div_spec.rb b/spec/ruby/core/numeric/div_spec.rb
index 53917b84c9..a17961850c 100644
--- a/spec/ruby/core/numeric/div_spec.rb
+++ b/spec/ruby/core/numeric/div_spec.rb
@@ -15,8 +15,8 @@ describe "Numeric#div" do
end
it "raises ZeroDivisionError for 0" do
- -> { @obj.div(0) }.should raise_error(ZeroDivisionError)
- -> { @obj.div(0.0) }.should raise_error(ZeroDivisionError)
- -> { @obj.div(Complex(0,0)) }.should raise_error(ZeroDivisionError)
+ -> { @obj.div(0) }.should.raise(ZeroDivisionError)
+ -> { @obj.div(0.0) }.should.raise(ZeroDivisionError)
+ -> { @obj.div(Complex(0,0)) }.should.raise(ZeroDivisionError)
end
end
diff --git a/spec/ruby/core/numeric/dup_spec.rb b/spec/ruby/core/numeric/dup_spec.rb
index 189a7ef44d..c158c618de 100644
--- a/spec/ruby/core/numeric/dup_spec.rb
+++ b/spec/ruby/core/numeric/dup_spec.rb
@@ -3,11 +3,11 @@ require_relative '../../spec_helper'
describe "Numeric#dup" do
it "returns self" do
value = 1
- value.dup.should equal(value)
+ value.dup.should.equal?(value)
subclass = Class.new(Numeric)
value = subclass.new
- value.dup.should equal(value)
+ value.dup.should.equal?(value)
end
it "does not change frozen status" do
diff --git a/spec/ruby/core/numeric/eql_spec.rb b/spec/ruby/core/numeric/eql_spec.rb
index b33e00e51f..80c58caef4 100644
--- a/spec/ruby/core/numeric/eql_spec.rb
+++ b/spec/ruby/core/numeric/eql_spec.rb
@@ -7,16 +7,16 @@ describe "Numeric#eql?" do
end
it "returns false if self's and other's types don't match" do
- @obj.should_not eql(1)
- @obj.should_not eql(-1.5)
- @obj.should_not eql(bignum_value)
- @obj.should_not eql(:sym)
+ @obj.should_not.eql?(1)
+ @obj.should_not.eql?(-1.5)
+ @obj.should_not.eql?(bignum_value)
+ @obj.should_not.eql?(:sym)
end
it "returns the result of calling self#== with other when self's and other's types match" do
other = NumericSpecs::Subclass.new
@obj.should_receive(:==).with(other).and_return("result", nil)
- @obj.should eql(other)
- @obj.should_not eql(other)
+ @obj.should.eql?(other)
+ @obj.should_not.eql?(other)
end
end
diff --git a/spec/ruby/core/numeric/fdiv_spec.rb b/spec/ruby/core/numeric/fdiv_spec.rb
index 907e5d343c..2c22c6a86a 100644
--- a/spec/ruby/core/numeric/fdiv_spec.rb
+++ b/spec/ruby/core/numeric/fdiv_spec.rb
@@ -1,5 +1,4 @@
require_relative '../../spec_helper'
-require_relative 'shared/quo'
describe "Numeric#fdiv" do
it "coerces self with #to_f" do
@@ -19,7 +18,7 @@ describe "Numeric#fdiv" do
end
it "returns a Float" do
- bignum_value.fdiv(Float::MAX).should be_an_instance_of(Float)
+ bignum_value.fdiv(Float::MAX).should.instance_of?(Float)
end
it "returns Infinity if other is 0" do
@@ -27,6 +26,6 @@ describe "Numeric#fdiv" do
end
it "returns NaN if other is NaN" do
- 3334.fdiv(nan_value).nan?.should be_true
+ 3334.fdiv(nan_value).nan?.should == true
end
end
diff --git a/spec/ruby/core/numeric/finite_spec.rb b/spec/ruby/core/numeric/finite_spec.rb
index 05b5eebbd6..2c18c89466 100644
--- a/spec/ruby/core/numeric/finite_spec.rb
+++ b/spec/ruby/core/numeric/finite_spec.rb
@@ -3,6 +3,6 @@ require_relative '../../spec_helper'
describe "Numeric#finite?" do
it "returns true by default" do
o = mock_numeric("finite")
- o.finite?.should be_true
+ o.finite?.should == true
end
end
diff --git a/spec/ruby/core/numeric/i_spec.rb b/spec/ruby/core/numeric/i_spec.rb
index 621ecc09ec..f5fb99dfd3 100644
--- a/spec/ruby/core/numeric/i_spec.rb
+++ b/spec/ruby/core/numeric/i_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Numeric#i" do
it "returns a Complex object" do
- 34.i.should be_an_instance_of(Complex)
+ 34.i.should.instance_of?(Complex)
end
it "sets the real part to 0" do
diff --git a/spec/ruby/core/numeric/magnitude_spec.rb b/spec/ruby/core/numeric/magnitude_spec.rb
index 7a3290b036..1371dff21f 100644
--- a/spec/ruby/core/numeric/magnitude_spec.rb
+++ b/spec/ruby/core/numeric/magnitude_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../spec_helper"
require_relative 'shared/abs'
describe "Numeric#magnitude" do
diff --git a/spec/ruby/core/numeric/negative_spec.rb b/spec/ruby/core/numeric/negative_spec.rb
index 9c6f95fd87..f2d8a847da 100644
--- a/spec/ruby/core/numeric/negative_spec.rb
+++ b/spec/ruby/core/numeric/negative_spec.rb
@@ -4,22 +4,22 @@ require_relative 'fixtures/classes'
describe "Numeric#negative?" do
describe "on positive numbers" do
it "returns false" do
- 1.negative?.should be_false
- 0.1.negative?.should be_false
+ 1.negative?.should == false
+ 0.1.negative?.should == false
end
end
describe "on zero" do
it "returns false" do
- 0.negative?.should be_false
- 0.0.negative?.should be_false
+ 0.negative?.should == false
+ 0.0.negative?.should == false
end
end
describe "on negative numbers" do
it "returns true" do
- -1.negative?.should be_true
- -0.1.negative?.should be_true
+ -1.negative?.should == true
+ -0.1.negative?.should == true
end
end
end
diff --git a/spec/ruby/core/numeric/polar_spec.rb b/spec/ruby/core/numeric/polar_spec.rb
index b594e408b2..0695d7afb2 100644
--- a/spec/ruby/core/numeric/polar_spec.rb
+++ b/spec/ruby/core/numeric/polar_spec.rb
@@ -17,7 +17,7 @@ describe "Numeric#polar" do
it "returns a two-element Array" do
@numbers.each do |number|
- number.polar.should be_an_instance_of(Array)
+ number.polar.should.instance_of?(Array)
number.polar.size.should == 2
end
end
@@ -44,7 +44,7 @@ describe "Numeric#polar" do
it "returns [NaN, NaN] if self is NaN" do
nan_value.polar.size.should == 2
- nan_value.polar.first.nan?.should be_true
- nan_value.polar.last.nan?.should be_true
+ nan_value.polar.first.nan?.should == true
+ nan_value.polar.last.nan?.should == true
end
end
diff --git a/spec/ruby/core/numeric/positive_spec.rb b/spec/ruby/core/numeric/positive_spec.rb
index 3b831b4d34..7c8d15cd9f 100644
--- a/spec/ruby/core/numeric/positive_spec.rb
+++ b/spec/ruby/core/numeric/positive_spec.rb
@@ -4,22 +4,22 @@ require_relative 'fixtures/classes'
describe "Numeric#positive?" do
describe "on positive numbers" do
it "returns true" do
- 1.positive?.should be_true
- 0.1.positive?.should be_true
+ 1.positive?.should == true
+ 0.1.positive?.should == true
end
end
describe "on zero" do
it "returns false" do
- 0.positive?.should be_false
- 0.0.positive?.should be_false
+ 0.positive?.should == false
+ 0.0.positive?.should == false
end
end
describe "on negative numbers" do
it "returns false" do
- -1.positive?.should be_false
- -0.1.positive?.should be_false
+ -1.positive?.should == false
+ -0.1.positive?.should == false
end
end
end
diff --git a/spec/ruby/core/numeric/quo_spec.rb b/spec/ruby/core/numeric/quo_spec.rb
index 67bacee9b5..66ff019231 100644
--- a/spec/ruby/core/numeric/quo_spec.rb
+++ b/spec/ruby/core/numeric/quo_spec.rb
@@ -1,14 +1,13 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/quo'
describe "Numeric#quo" do
it "returns the result of self divided by the given Integer as a Rational" do
- 5.quo(2).should eql(Rational(5,2))
+ 5.quo(2).should.eql?(Rational(5,2))
end
it "returns the result of self divided by the given Float as a Float" do
- 2.quo(2.5).should eql(0.8)
+ 2.quo(2.5).should.eql?(0.8)
end
it "returns the result of self divided by the given Bignum as a Float" do
@@ -16,11 +15,11 @@ describe "Numeric#quo" do
end
it "raises a ZeroDivisionError when the given Integer is 0" do
- -> { 0.quo(0) }.should raise_error(ZeroDivisionError)
- -> { 10.quo(0) }.should raise_error(ZeroDivisionError)
- -> { -10.quo(0) }.should raise_error(ZeroDivisionError)
- -> { bignum_value.quo(0) }.should raise_error(ZeroDivisionError)
- -> { (-bignum_value).quo(0) }.should raise_error(ZeroDivisionError)
+ -> { 0.quo(0) }.should.raise(ZeroDivisionError)
+ -> { 10.quo(0) }.should.raise(ZeroDivisionError)
+ -> { -10.quo(0) }.should.raise(ZeroDivisionError)
+ -> { bignum_value.quo(0) }.should.raise(ZeroDivisionError)
+ -> { (-bignum_value).quo(0) }.should.raise(ZeroDivisionError)
end
it "calls #to_r to convert the object to a Rational" do
@@ -34,16 +33,16 @@ describe "Numeric#quo" do
obj = NumericSpecs::Subclass.new
obj.should_receive(:to_r).and_return(1)
- -> { obj.quo(19) }.should raise_error(TypeError)
+ -> { obj.quo(19) }.should.raise(TypeError)
end
it "raises a TypeError when given a non-Integer" do
-> {
(obj = mock('x')).should_not_receive(:to_int)
13.quo(obj)
- }.should raise_error(TypeError)
- -> { 13.quo("10") }.should raise_error(TypeError)
- -> { 13.quo(:symbol) }.should raise_error(TypeError)
+ }.should.raise(TypeError)
+ -> { 13.quo("10") }.should.raise(TypeError)
+ -> { 13.quo(:symbol) }.should.raise(TypeError)
end
it "returns the result of calling self#/ with other" do
@@ -54,7 +53,7 @@ describe "Numeric#quo" do
end
it "raises a ZeroDivisionError if the given argument is zero and not a Float" do
- -> { 1.quo(0) }.should raise_error(ZeroDivisionError)
+ -> { 1.quo(0) }.should.raise(ZeroDivisionError)
end
it "returns infinity if the given argument is zero and is a Float" do
diff --git a/spec/ruby/core/numeric/real_spec.rb b/spec/ruby/core/numeric/real_spec.rb
index 2d2499bcce..09d482a691 100644
--- a/spec/ruby/core/numeric/real_spec.rb
+++ b/spec/ruby/core/numeric/real_spec.rb
@@ -16,7 +16,7 @@ describe "Numeric#real" do
it "returns self" do
@numbers.each do |number|
if number.to_f.nan?
- number.real.nan?.should be_true
+ number.real.nan?.should == true
else
number.real.should == number
end
@@ -25,7 +25,7 @@ describe "Numeric#real" do
it "raises an ArgumentError if given any arguments" do
@numbers.each do |number|
- -> { number.real(number) }.should raise_error(ArgumentError)
+ -> { number.real(number) }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/numeric/remainder_spec.rb b/spec/ruby/core/numeric/remainder_spec.rb
index 1e2f5f3a96..bdf7358b21 100644
--- a/spec/ruby/core/numeric/remainder_spec.rb
+++ b/spec/ruby/core/numeric/remainder_spec.rb
@@ -6,13 +6,14 @@ describe "Numeric#remainder" do
@obj = NumericSpecs::Subclass.new
@result = mock("Numeric#% result")
@other = mock("Passed Object")
+ @other.should_receive(:coerce).with(@obj).and_return([@obj, @other])
end
it "returns the result of calling self#% with other if self is 0" do
@obj.should_receive(:%).with(@other).and_return(@result)
@result.should_receive(:==).with(0).and_return(true)
- @obj.remainder(@other).should equal(@result)
+ @obj.remainder(@other).should.equal?(@result)
end
it "returns the result of calling self#% with other if self and other are greater than 0" do
@@ -24,7 +25,7 @@ describe "Numeric#remainder" do
@obj.should_receive(:>).with(0).and_return(true)
@other.should_receive(:<).with(0).and_return(false)
- @obj.remainder(@other).should equal(@result)
+ @obj.remainder(@other).should.equal?(@result)
end
it "returns the result of calling self#% with other if self and other are less than 0" do
@@ -36,7 +37,7 @@ describe "Numeric#remainder" do
@obj.should_receive(:>).with(0).and_return(false)
- @obj.remainder(@other).should equal(@result)
+ @obj.remainder(@other).should.equal?(@result)
end
it "returns the result of calling self#% with other - other if self is greater than 0 and other is less than 0" do
diff --git a/spec/ruby/core/numeric/shared/conj.rb b/spec/ruby/core/numeric/shared/conj.rb
index 6d5197ecab..1a661fbbe8 100644
--- a/spec/ruby/core/numeric/shared/conj.rb
+++ b/spec/ruby/core/numeric/shared/conj.rb
@@ -14,7 +14,7 @@ describe :numeric_conj, shared: true do
it "returns self" do
@numbers.each do |number|
- number.send(@method).should equal(number)
+ number.send(@method).should.equal?(number)
end
end
end
diff --git a/spec/ruby/core/numeric/shared/imag.rb b/spec/ruby/core/numeric/shared/imag.rb
index ac2da40a3b..605a23d8c6 100644
--- a/spec/ruby/core/numeric/shared/imag.rb
+++ b/spec/ruby/core/numeric/shared/imag.rb
@@ -19,8 +19,8 @@ describe :numeric_imag, shared: true do
end
it "raises an ArgumentError if given any arguments" do
- @numbers.each do |number|
- -> { number.send(@method, number) }.should raise_error(ArgumentError)
- end
+ @numbers.each do |number|
+ -> { number.send(@method, number) }.should.raise(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/numeric/shared/quo.rb b/spec/ruby/core/numeric/shared/quo.rb
deleted file mode 100644
index 2392636fe7..0000000000
--- a/spec/ruby/core/numeric/shared/quo.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-describe :numeric_quo_18, shared: true do
- it "returns the result of calling self#/ with other" do
- obj = mock_numeric('numeric')
- obj.should_receive(:/).with(19).and_return(:result)
- obj.send(@method, 19).should == :result
- end
-end
diff --git a/spec/ruby/core/numeric/shared/rect.rb b/spec/ruby/core/numeric/shared/rect.rb
index 9cde19a398..32d03e45d2 100644
--- a/spec/ruby/core/numeric/shared/rect.rb
+++ b/spec/ruby/core/numeric/shared/rect.rb
@@ -14,7 +14,7 @@ describe :numeric_rect, shared: true do
it "returns an Array" do
@numbers.each do |number|
- number.send(@method).should be_an_instance_of(Array)
+ number.send(@method).should.instance_of?(Array)
end
end
@@ -25,24 +25,24 @@ describe :numeric_rect, shared: true do
end
it "returns self as the first element" do
- @numbers.each do |number|
- if Float === number and number.nan?
- number.send(@method).first.nan?.should be_true
- else
- number.send(@method).first.should == number
- end
- end
+ @numbers.each do |number|
+ if Float === number and number.nan?
+ number.send(@method).first.nan?.should == true
+ else
+ number.send(@method).first.should == number
+ end
+ end
end
it "returns 0 as the last element" do
- @numbers.each do |number|
- number.send(@method).last.should == 0
- end
+ @numbers.each do |number|
+ number.send(@method).last.should == 0
+ end
end
it "raises an ArgumentError if given any arguments" do
- @numbers.each do |number|
- -> { number.send(@method, number) }.should raise_error(ArgumentError)
- end
+ @numbers.each do |number|
+ -> { number.send(@method, number) }.should.raise(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/numeric/shared/step.rb b/spec/ruby/core/numeric/shared/step.rb
index 8b1a7bf307..66b8c1af0d 100644
--- a/spec/ruby/core/numeric/shared/step.rb
+++ b/spec/ruby/core/numeric/shared/step.rb
@@ -5,7 +5,7 @@ require_relative '../fixtures/classes'
# To be able to do it, the @step ivar must contain a Proc that transforms
# the step call arguments passed as positional arguments to the style of
# arguments pretended to test.
-describe :numeric_step, :shared => true do
+describe :numeric_step, shared: true do
before :each do
ScratchPad.record []
@prc = -> x { ScratchPad << x }
@@ -13,7 +13,7 @@ describe :numeric_step, :shared => true do
it "defaults to step = 1" do
@step.call(1, 5, &@prc)
- ScratchPad.recorded.should eql [1, 2, 3, 4, 5]
+ ScratchPad.recorded.should.eql? [1, 2, 3, 4, 5]
end
it "defaults to an infinite limit with a step size of 1 for Integers" do
@@ -26,35 +26,35 @@ describe :numeric_step, :shared => true do
describe "when self, stop and step are Integers" do
it "yields only Integers" do
- @step.call(1, 5, 1) { |x| x.should be_an_instance_of(Integer) }
+ @step.call(1, 5, 1) { |x| x.should.instance_of?(Integer) }
end
describe "with a positive step" do
it "yields while increasing self by step until stop is reached" do
@step.call(1, 5, 1, &@prc)
- ScratchPad.recorded.should eql [1, 2, 3, 4, 5]
+ ScratchPad.recorded.should.eql? [1, 2, 3, 4, 5]
end
it "yields once when self equals stop" do
@step.call(1, 1, 1, &@prc)
- ScratchPad.recorded.should eql [1]
+ ScratchPad.recorded.should.eql? [1]
end
it "does not yield when self is greater than stop" do
@step.call(2, 1, 1, &@prc)
- ScratchPad.recorded.should eql []
+ ScratchPad.recorded.should.eql? []
end
end
describe "with a negative step" do
it "yields while decreasing self by step until stop is reached" do
@step.call(5, 1, -1, &@prc)
- ScratchPad.recorded.should eql [5, 4, 3, 2, 1]
+ ScratchPad.recorded.should.eql? [5, 4, 3, 2, 1]
end
it "yields once when self equals stop" do
@step.call(5, 5, -1, &@prc)
- ScratchPad.recorded.should eql [5]
+ ScratchPad.recorded.should.eql? [5]
end
it "does not yield when self is less than stop" do
@@ -66,26 +66,26 @@ describe :numeric_step, :shared => true do
describe "when at least one of self, stop or step is a Float" do
it "yields Floats even if only self is a Float" do
- @step.call(1.5, 5, 1) { |x| x.should be_an_instance_of(Float) }
+ @step.call(1.5, 5, 1) { |x| x.should.instance_of?(Float) }
end
it "yields Floats even if only stop is a Float" do
- @step.call(1, 5.0, 1) { |x| x.should be_an_instance_of(Float) }
+ @step.call(1, 5.0, 1) { |x| x.should.instance_of?(Float) }
end
it "yields Floats even if only step is a Float" do
- @step.call(1, 5, 1.0) { |x| x.should be_an_instance_of(Float) }
+ @step.call(1, 5, 1.0) { |x| x.should.instance_of?(Float) }
end
describe "with a positive step" do
it "yields while increasing self by step while < stop" do
@step.call(1.5, 5, 1, &@prc)
- ScratchPad.recorded.should eql [1.5, 2.5, 3.5, 4.5]
+ ScratchPad.recorded.should.eql? [1.5, 2.5, 3.5, 4.5]
end
it "yields once when self equals stop" do
@step.call(1.5, 1.5, 1, &@prc)
- ScratchPad.recorded.should eql [1.5]
+ ScratchPad.recorded.should.eql? [1.5]
end
it "does not yield when self is greater than stop" do
@@ -96,19 +96,19 @@ describe :numeric_step, :shared => true do
it "is careful about not yielding a value greater than limit" do
# As 9*1.3+1.0 == 12.700000000000001 > 12.7, we test:
@step.call(1.0, 12.7, 1.3, &@prc)
- ScratchPad.recorded.should eql [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.7]
+ ScratchPad.recorded.should.eql? [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.7]
end
end
describe "with a negative step" do
it "yields while decreasing self by step while self > stop" do
@step.call(5, 1.5, -1, &@prc)
- ScratchPad.recorded.should eql [5.0, 4.0, 3.0, 2.0]
+ ScratchPad.recorded.should.eql? [5.0, 4.0, 3.0, 2.0]
end
it "yields once when self equals stop" do
@step.call(1.5, 1.5, -1, &@prc)
- ScratchPad.recorded.should eql [1.5]
+ ScratchPad.recorded.should.eql? [1.5]
end
it "does not yield when self is less than stop" do
@@ -119,24 +119,24 @@ describe :numeric_step, :shared => true do
it "is careful about not yielding a value smaller than limit" do
# As -9*1.3-1.0 == -12.700000000000001 < -12.7, we test:
@step.call(-1.0, -12.7, -1.3, &@prc)
- ScratchPad.recorded.should eql [-1.0, -2.3, -3.6, -4.9, -6.2, -7.5, -8.8, -10.1, -11.4, -12.7]
+ ScratchPad.recorded.should.eql? [-1.0, -2.3, -3.6, -4.9, -6.2, -7.5, -8.8, -10.1, -11.4, -12.7]
end
end
describe "with a positive Infinity step" do
it "yields once if self < stop" do
@step.call(42, 100, infinity_value, &@prc)
- ScratchPad.recorded.should eql [42.0]
+ ScratchPad.recorded.should.eql? [42.0]
end
it "yields once when stop is Infinity" do
@step.call(42, infinity_value, infinity_value, &@prc)
- ScratchPad.recorded.should eql [42.0]
+ ScratchPad.recorded.should.eql? [42.0]
end
it "yields once when self equals stop" do
@step.call(42, 42, infinity_value, &@prc)
- ScratchPad.recorded.should eql [42.0]
+ ScratchPad.recorded.should.eql? [42.0]
end
it "yields once when self and stop are Infinity" do
@@ -159,17 +159,17 @@ describe :numeric_step, :shared => true do
describe "with a negative Infinity step" do
it "yields once if self > stop" do
@step.call(42, 6, -infinity_value, &@prc)
- ScratchPad.recorded.should eql [42.0]
+ ScratchPad.recorded.should.eql? [42.0]
end
it "yields once if stop is -Infinity" do
@step.call(42, -infinity_value, -infinity_value, &@prc)
- ScratchPad.recorded.should eql [42.0]
+ ScratchPad.recorded.should.eql? [42.0]
end
it "yields once when self equals stop" do
@step.call(42, 42, -infinity_value, &@prc)
- ScratchPad.recorded.should eql [42.0]
+ ScratchPad.recorded.should.eql? [42.0]
end
it "yields once when self and stop are Infinity" do
@@ -226,66 +226,60 @@ describe :numeric_step, :shared => true do
describe "when step is a String" do
describe "with self and stop as Integers" do
it "raises an ArgumentError when step is a numeric representation" do
- -> { @step.call(1, 5, "1") {} }.should raise_error(ArgumentError)
- -> { @step.call(1, 5, "0.1") {} }.should raise_error(ArgumentError)
- -> { @step.call(1, 5, "1/3") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "1") {} }.should.raise(ArgumentError)
+ -> { @step.call(1, 5, "0.1") {} }.should.raise(ArgumentError)
+ -> { @step.call(1, 5, "1/3") {} }.should.raise(ArgumentError)
end
it "raises an ArgumentError with step as an alphanumeric string" do
- -> { @step.call(1, 5, "foo") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "foo") {} }.should.raise(ArgumentError)
end
end
describe "with self and stop as Floats" do
it "raises an ArgumentError when step is a numeric representation" do
- -> { @step.call(1.1, 5.1, "1") {} }.should raise_error(ArgumentError)
- -> { @step.call(1.1, 5.1, "0.1") {} }.should raise_error(ArgumentError)
- -> { @step.call(1.1, 5.1, "1/3") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "1") {} }.should.raise(ArgumentError)
+ -> { @step.call(1.1, 5.1, "0.1") {} }.should.raise(ArgumentError)
+ -> { @step.call(1.1, 5.1, "1/3") {} }.should.raise(ArgumentError)
end
it "raises an ArgumentError with step as an alphanumeric string" do
- -> { @step.call(1.1, 5.1, "foo") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "foo") {} }.should.raise(ArgumentError)
end
end
end
it "does not rescue ArgumentError exceptions" do
- -> { @step.call(1, 2) { raise ArgumentError, "" }}.should raise_error(ArgumentError)
+ -> { @step.call(1, 2) { raise ArgumentError, "" }}.should.raise(ArgumentError)
end
it "does not rescue TypeError exceptions" do
- -> { @step.call(1, 2) { raise TypeError, "" } }.should raise_error(TypeError)
+ -> { @step.call(1, 2) { raise TypeError, "" } }.should.raise(TypeError)
end
describe "when no block is given" do
step_enum_class = Enumerator::ArithmeticSequence
- ruby_version_is ""..."3.0" do
- it "returns an #{step_enum_class} when step is 0" do
- @step.call(1, 2, 0).should be_an_instance_of(step_enum_class)
- end
- end
-
it "returns an #{step_enum_class} when not passed a block and self > stop" do
- @step.call(1, 0, 2).should be_an_instance_of(step_enum_class)
+ @step.call(1, 0, 2).should.instance_of?(step_enum_class)
end
it "returns an #{step_enum_class} when not passed a block and self < stop" do
- @step.call(1, 2, 3).should be_an_instance_of(step_enum_class)
+ @step.call(1, 2, 3).should.instance_of?(step_enum_class)
end
it "returns an #{step_enum_class} that uses the given step" do
- @step.call(0, 5, 2).to_a.should eql [0, 2, 4]
+ @step.call(0, 5, 2).to_a.should.eql? [0, 2, 4]
end
describe "when step is a String" do
describe "with self and stop as Integers" do
it "returns an Enumerator" do
- @step.call(1, 5, "foo").should be_an_instance_of(Enumerator)
+ @step.call(1, 5, "foo").should.instance_of?(Enumerator)
end
end
describe "with self and stop as Floats" do
it "returns an Enumerator" do
- @step.call(1.1, 5.1, "foo").should be_an_instance_of(Enumerator)
+ @step.call(1.1, 5.1, "foo").should.instance_of?(Enumerator)
end
end
end
@@ -295,23 +289,23 @@ describe :numeric_step, :shared => true do
describe "when step is a String" do
describe "with self and stop as Integers" do
it "raises an ArgumentError when step is a numeric representation" do
- -> { @step.call(1, 5, "1").size }.should raise_error(ArgumentError)
- -> { @step.call(1, 5, "0.1").size }.should raise_error(ArgumentError)
- -> { @step.call(1, 5, "1/3").size }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "1").size }.should.raise(ArgumentError)
+ -> { @step.call(1, 5, "0.1").size }.should.raise(ArgumentError)
+ -> { @step.call(1, 5, "1/3").size }.should.raise(ArgumentError)
end
it "raises an ArgumentError with step as an alphanumeric string" do
- -> { @step.call(1, 5, "foo").size }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "foo").size }.should.raise(ArgumentError)
end
end
describe "with self and stop as Floats" do
it "raises an ArgumentError when step is a numeric representation" do
- -> { @step.call(1.1, 5.1, "1").size }.should raise_error(ArgumentError)
- -> { @step.call(1.1, 5.1, "0.1").size }.should raise_error(ArgumentError)
- -> { @step.call(1.1, 5.1, "1/3").size }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "1").size }.should.raise(ArgumentError)
+ -> { @step.call(1.1, 5.1, "0.1").size }.should.raise(ArgumentError)
+ -> { @step.call(1.1, 5.1, "1/3").size }.should.raise(ArgumentError)
end
it "raises an ArgumentError with step as an alphanumeric string" do
- -> { @step.call(1.1, 5.1, "foo").size }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "foo").size }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/numeric/singleton_method_added_spec.rb b/spec/ruby/core/numeric/singleton_method_added_spec.rb
index 2091398e5d..327bb5662a 100644
--- a/spec/ruby/core/numeric/singleton_method_added_spec.rb
+++ b/spec/ruby/core/numeric/singleton_method_added_spec.rb
@@ -21,21 +21,21 @@ describe "Numeric#singleton_method_added" do
-> do
a = NumericSpecs::Subclass.new
def a.test; end
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
-> do
a = 1
def a.test; end
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
-> do
a = 1.5
def a.test; end
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
-> do
a = bignum_value
def a.test; end
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/numeric/step_spec.rb b/spec/ruby/core/numeric/step_spec.rb
index 095c474fec..6896009eb6 100644
--- a/spec/ruby/core/numeric/step_spec.rb
+++ b/spec/ruby/core/numeric/step_spec.rb
@@ -6,11 +6,11 @@ describe "Numeric#step" do
describe 'with positional args' do
it "raises an ArgumentError when step is 0" do
- -> { 1.step(5, 0) {} }.should raise_error(ArgumentError)
+ -> { 1.step(5, 0) {} }.should.raise(ArgumentError)
end
it "raises an ArgumentError when step is 0.0" do
- -> { 1.step(2, 0.0) {} }.should raise_error(ArgumentError)
+ -> { 1.step(2, 0.0) {} }.should.raise(ArgumentError)
end
before :all do
@@ -23,30 +23,8 @@ describe "Numeric#step" do
describe "when no block is given" do
step_enum_class = Enumerator::ArithmeticSequence
- ruby_version_is ""..."3.0" do
- it "returns an #{step_enum_class} when step is 0" do
- 1.step(5, 0).should be_an_instance_of(step_enum_class)
- end
-
- it "returns an #{step_enum_class} when step is 0.0" do
- 1.step(2, 0.0).should be_an_instance_of(step_enum_class)
- end
- end
-
describe "returned #{step_enum_class}" do
describe "size" do
- ruby_version_is ""..."3.0" do
- it "is infinity when step is 0" do
- enum = 1.step(5, 0)
- enum.size.should == Float::INFINITY
- end
-
- it "is infinity when step is 0.0" do
- enum = 1.step(2, 0.0)
- enum.size.should == Float::INFINITY
- end
- end
-
it "defaults to an infinite size" do
enum = 1.step
enum.size.should == Float::INFINITY
@@ -63,22 +41,6 @@ describe "Numeric#step" do
end
describe 'with keyword arguments' do
- ruby_version_is ""..."3.0" do
- it "doesn't raise an error when step is 0" do
- -> { 1.step(to: 5, by: 0) { break } }.should_not raise_error
- end
-
- it "doesn't raise an error when step is 0.0" do
- -> { 1.step(to: 2, by: 0.0) { break } }.should_not raise_error
- end
-
- it "should loop over self when step is 0 or 0.0" do
- 1.step(to: 2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0]
- 1.step(to: 2, by: 0).take(5).should eql [1, 1, 1, 1, 1]
- 1.1.step(to: 2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1]
- end
- end
-
describe "when no block is given" do
describe "returned Enumerator" do
describe "size" do
@@ -86,16 +48,6 @@ describe "Numeric#step" do
1.step(by: 42).size.should == infinity_value
end
- ruby_version_is ""..."3.0" do
- it "should return infinity_value when step is 0" do
- 1.step(to: 5, by: 0).size.should == infinity_value
- end
-
- it "should return infinity_value when step is 0.0" do
- 1.step(to: 2, by: 0.0).size.should == infinity_value
- end
- end
-
it "should return infinity_value when ascending towards a limit of Float::INFINITY" do
1.step(to: Float::INFINITY, by: 42).size.should == infinity_value
end
@@ -128,54 +80,25 @@ describe "Numeric#step" do
end
describe 'with mixed arguments' do
- ruby_version_is ""..."3.0" do
- it "doesn't raise an error when step is 0" do
- -> { 1.step(5, by: 0) { break } }.should_not raise_error
- end
-
- it "doesn't raise an error when step is 0.0" do
- -> { 1.step(2, by: 0.0) { break } }.should_not raise_error
- end
+ it " raises an ArgumentError when step is 0" do
+ -> { 1.step(5, by: 0) { break } }.should.raise(ArgumentError)
end
- ruby_version_is "3.0" do
- it " raises an ArgumentError when step is 0" do
- -> { 1.step(5, by: 0) { break } }.should raise_error(ArgumentError)
- end
-
- it "raises an ArgumentError when step is 0.0" do
- -> { 1.step(2, by: 0.0) { break } }.should raise_error(ArgumentError)
- end
+ it "raises an ArgumentError when step is 0.0" do
+ -> { 1.step(2, by: 0.0) { break } }.should.raise(ArgumentError)
end
it "raises a ArgumentError when limit and to are defined" do
- -> { 1.step(5, 1, to: 5) { break } }.should raise_error(ArgumentError)
+ -> { 1.step(5, 1, to: 5) { break } }.should.raise(ArgumentError)
end
it "raises a ArgumentError when step and by are defined" do
- -> { 1.step(5, 1, by: 5) { break } }.should raise_error(ArgumentError)
- end
-
- ruby_version_is ""..."3.0" do
- it "should loop over self when step is 0 or 0.0" do
- 1.step(2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0]
- 1.step(2, by: 0).take(5).should eql [1, 1, 1, 1, 1]
- 1.1.step(2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1]
- end
+ -> { 1.step(5, 1, by: 5) { break } }.should.raise(ArgumentError)
end
describe "when no block is given" do
describe "returned Enumerator" do
describe "size" do
- ruby_version_is ""..."3.0" do
- it "should return infinity_value when step is 0" do
- 1.step(5, by: 0).size.should == infinity_value
- end
-
- it "should return infinity_value when step is 0.0" do
- 1.step(2, by: 0.0).size.should == infinity_value
- end
- end
end
end
end
diff --git a/spec/ruby/core/numeric/to_c_spec.rb b/spec/ruby/core/numeric/to_c_spec.rb
index 75245a612e..70b7a9dd0c 100644
--- a/spec/ruby/core/numeric/to_c_spec.rb
+++ b/spec/ruby/core/numeric/to_c_spec.rb
@@ -22,7 +22,7 @@ describe "Numeric#to_c" do
it "returns a Complex object" do
@numbers.each do |number|
- number.to_c.should be_an_instance_of(Complex)
+ number.to_c.should.instance_of?(Complex)
end
end
@@ -30,7 +30,7 @@ describe "Numeric#to_c" do
@numbers.each do |number|
real = number.to_c.real
if Float === number and number.nan?
- real.nan?.should be_true
+ real.nan?.should == true
else
real.should == number
end
diff --git a/spec/ruby/core/objectspace/_id2ref_spec.rb b/spec/ruby/core/objectspace/_id2ref_spec.rb
index c088ae2743..a9fd526b7d 100644
--- a/spec/ruby/core/objectspace/_id2ref_spec.rb
+++ b/spec/ruby/core/objectspace/_id2ref_spec.rb
@@ -1,52 +1,65 @@
require_relative '../../spec_helper'
-describe "ObjectSpace._id2ref" do
- it "converts an object id to a reference to the object" do
- s = "I am a string"
- r = ObjectSpace._id2ref(s.object_id)
- r.should == s
+ruby_version_is "4.0" do
+ describe "ObjectSpace._id2ref" do
+ it "is deprecated" do
+ id = nil.object_id
+ -> {
+ ObjectSpace._id2ref(id)
+ }.should complain(/warning: ObjectSpace\._id2ref is deprecated/)
+ end
end
+end
- it "retrieves true by object_id" do
- ObjectSpace._id2ref(true.object_id).should == true
- end
+ruby_version_is ""..."4.0" do
+ describe "ObjectSpace._id2ref" do
+ it "converts an object id to a reference to the object" do
+ s = "I am a string"
+ r = ObjectSpace._id2ref(s.object_id)
+ r.should == s
+ end
- it "retrieves false by object_id" do
- ObjectSpace._id2ref(false.object_id).should == false
- end
+ it "retrieves true by object_id" do
+ ObjectSpace._id2ref(true.object_id).should == true
+ end
- it "retrieves nil by object_id" do
- ObjectSpace._id2ref(nil.object_id).should == nil
- end
+ it "retrieves false by object_id" do
+ ObjectSpace._id2ref(false.object_id).should == false
+ end
- it "retrieves a small Integer by object_id" do
- ObjectSpace._id2ref(1.object_id).should == 1
- ObjectSpace._id2ref((-42).object_id).should == -42
- end
+ it "retrieves nil by object_id" do
+ ObjectSpace._id2ref(nil.object_id).should == nil
+ end
- it "retrieves a large Integer by object_id" do
- obj = 1 << 88
- ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
- end
+ it "retrieves a small Integer by object_id" do
+ ObjectSpace._id2ref(1.object_id).should == 1
+ ObjectSpace._id2ref((-42).object_id).should == -42
+ end
- it "retrieves a Symbol by object_id" do
- ObjectSpace._id2ref(:sym.object_id).should.equal?(:sym)
- end
+ it "retrieves a large Integer by object_id" do
+ obj = 1 << 88
+ ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
+ end
- it "retrieves a String by object_id" do
- obj = "str"
- ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
- end
+ it "retrieves a Symbol by object_id" do
+ ObjectSpace._id2ref(:sym.object_id).should.equal?(:sym)
+ end
- it "retrieves a frozen literal String by object_id" do
- ObjectSpace._id2ref("frozen string literal _id2ref".freeze.object_id).should.equal?("frozen string literal _id2ref".freeze)
- end
+ it "retrieves a String by object_id" do
+ obj = "str"
+ ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
+ end
- it "retrieves an Encoding by object_id" do
- ObjectSpace._id2ref(Encoding::UTF_8.object_id).should.equal?(Encoding::UTF_8)
- end
+ it "retrieves a frozen literal String by object_id" do
+ ObjectSpace._id2ref("frozen string literal _id2ref".freeze.object_id).should.equal?("frozen string literal _id2ref".freeze)
+ end
+
+ it "retrieves an Encoding by object_id" do
+ ObjectSpace._id2ref(Encoding::UTF_8.object_id).should.equal?(Encoding::UTF_8)
+ end
- it 'raises RangeError when an object could not be found' do
- proc { ObjectSpace._id2ref(1 << 60) }.should raise_error(RangeError)
+ it 'raises RangeError when an object could not be found' do
+ proc { ObjectSpace._id2ref(1 << 60) }.should.raise(RangeError)
+ end
end
end
diff --git a/spec/ruby/core/objectspace/add_finalizer_spec.rb b/spec/ruby/core/objectspace/add_finalizer_spec.rb
deleted file mode 100644
index 3540ac0413..0000000000
--- a/spec/ruby/core/objectspace/add_finalizer_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.add_finalizer" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/call_finalizer_spec.rb b/spec/ruby/core/objectspace/call_finalizer_spec.rb
deleted file mode 100644
index 6dce92ddd6..0000000000
--- a/spec/ruby/core/objectspace/call_finalizer_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.call_finalizer" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/define_finalizer_spec.rb b/spec/ruby/core/objectspace/define_finalizer_spec.rb
index 281785b0a4..5441cb4a21 100644
--- a/spec/ruby/core/objectspace/define_finalizer_spec.rb
+++ b/spec/ruby/core/objectspace/define_finalizer_spec.rb
@@ -13,7 +13,7 @@ describe "ObjectSpace.define_finalizer" do
it "raises an ArgumentError if the action does not respond to call" do
-> {
ObjectSpace.define_finalizer(Object.new, mock("ObjectSpace.define_finalizer no #call"))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "accepts an object and a proc" do
@@ -42,7 +42,7 @@ describe "ObjectSpace.define_finalizer" do
it "raises ArgumentError trying to define a finalizer on a non-reference" do
-> {
ObjectSpace.define_finalizer(:blah) { 1 }
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
# see [ruby-core:24095]
@@ -52,74 +52,72 @@ describe "ObjectSpace.define_finalizer" do
Proc.new { puts "finalizer run" }
end
handler = scoped
- obj = "Test"
+ obj = +"Test"
ObjectSpace.define_finalizer(obj, handler)
exit 0
RUBY
- ruby_exe(code, :args => "2>&1").should include("finalizer run\n")
+ ruby_exe(code, :args => "2>&1").should.include?("finalizer run\n")
end
- ruby_version_is "3.0" do
- it "warns if the finalizer has the object as the receiver" do
- code = <<-RUBY
- class CapturesSelf
- def initialize
- ObjectSpace.define_finalizer(self, proc {
- puts "finalizer run"
- })
- end
+ it "warns if the finalizer has the object as the receiver" do
+ code = <<-RUBY
+ class CapturesSelf
+ def initialize
+ ObjectSpace.define_finalizer(self, proc {
+ puts "finalizer run"
+ })
end
- CapturesSelf.new
- exit 0
- RUBY
+ end
+ CapturesSelf.new
+ exit 0
+ RUBY
- ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n")
- end
+ ruby_exe(code, :args => "2>&1").should.include?("warning: finalizer references object to be finalized\n")
+ end
- it "warns if the finalizer is a method bound to the receiver" do
- code = <<-RUBY
- class CapturesSelf
- def initialize
- ObjectSpace.define_finalizer(self, method(:finalize))
- end
- def finalize(id)
- puts "finalizer run"
- end
+ it "warns if the finalizer is a method bound to the receiver" do
+ code = <<-RUBY
+ class CapturesSelf
+ def initialize
+ ObjectSpace.define_finalizer(self, method(:finalize))
end
- CapturesSelf.new
- exit 0
- RUBY
+ def finalize(id)
+ puts "finalizer run"
+ end
+ end
+ CapturesSelf.new
+ exit 0
+ RUBY
- ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n")
- end
+ ruby_exe(code, :args => "2>&1").should.include?("warning: finalizer references object to be finalized\n")
+ end
- it "warns if the finalizer was a block in the receiver" do
- code = <<-RUBY
- class CapturesSelf
- def initialize
- ObjectSpace.define_finalizer(self) do
- puts "finalizer run"
- end
+ it "warns if the finalizer was a block in the receiver" do
+ code = <<-RUBY
+ class CapturesSelf
+ def initialize
+ ObjectSpace.define_finalizer(self) do
+ puts "finalizer run"
end
end
- CapturesSelf.new
- exit 0
- RUBY
+ end
+ CapturesSelf.new
+ exit 0
+ RUBY
- ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n")
- end
+ ruby_exe(code, :args => "2>&1").should.include?("warning: finalizer references object to be finalized\n")
end
it "calls a finalizer at exit even if it is self-referencing" do
code = <<-RUBY
- obj = "Test"
+ obj = +"Test"
handler = Proc.new { puts "finalizer run" }
ObjectSpace.define_finalizer(obj, handler)
exit 0
RUBY
- ruby_exe(code).should include("finalizer run\n")
+ ruby_exe(code).should.include?("finalizer run\n")
end
it "calls a finalizer at exit even if it is indirectly self-referencing" do
@@ -138,14 +136,14 @@ describe "ObjectSpace.define_finalizer" do
exit 0
RUBY
- ruby_exe(code, :args => "2>&1").should include("finalizer run\n")
+ ruby_exe(code, :args => "2>&1").should.include?("finalizer run\n")
end
it "calls a finalizer defined in a finalizer running at exit" do
code = <<-RUBY
- obj = "Test"
+ obj = +"Test"
handler = Proc.new do
- obj2 = "Test"
+ obj2 = +"Test"
handler2 = Proc.new { puts "finalizer 2 run" }
ObjectSpace.define_finalizer(obj2, handler2)
exit 0
@@ -154,11 +152,11 @@ describe "ObjectSpace.define_finalizer" do
exit 0
RUBY
- ruby_exe(code, :args => "2>&1").should include("finalizer 2 run\n")
+ ruby_exe(code, :args => "2>&1").should.include?("finalizer 2 run\n")
end
it "allows multiple finalizers with different 'callables' to be defined" do
- code = <<-RUBY
+ code = <<-'RUBY'
obj = Object.new
ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized1\n" })
@@ -169,4 +167,51 @@ describe "ObjectSpace.define_finalizer" do
ruby_exe(code).lines.sort.should == ["finalized1\n", "finalized2\n"]
end
+
+ it "defines same finalizer only once" do
+ code = <<~RUBY
+ obj = Object.new
+ p = proc { |id| print "ok" }
+ ObjectSpace.define_finalizer(obj, p.dup)
+ ObjectSpace.define_finalizer(obj, p.dup)
+ RUBY
+
+ ruby_exe(code).should == "ok"
+ end
+
+ it "returns the defined finalizer" do
+ obj = Object.new
+ p = proc { |id| }
+ p2 = p.dup
+
+ ret = ObjectSpace.define_finalizer(obj, p)
+ ret.should == [0, p]
+ ret[1].should.equal?(p)
+
+ ret = ObjectSpace.define_finalizer(obj, p2)
+ ret.should == [0, p]
+ ret[1].should.equal?(p)
+ end
+
+ describe "when $VERBOSE is not nil" do
+ it "warns if an exception is raised in finalizer" do
+ code = <<-RUBY
+ ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
+ RUBY
+
+ out = ruby_exe(code, args: "2>&1")
+ out.should.include?("warning: Exception in finalizer")
+ out.should.include?("finalizing")
+ end
+ end
+
+ describe "when $VERBOSE is nil" do
+ it "does not warn even if an exception is raised in finalizer" do
+ code = <<-RUBY
+ ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
+ RUBY
+
+ ruby_exe(code, args: "2>&1", options: "-W0").should == ""
+ end
+ end
end
diff --git a/spec/ruby/core/objectspace/each_object_spec.rb b/spec/ruby/core/objectspace/each_object_spec.rb
index 09a582afaf..aee0fd629c 100644
--- a/spec/ruby/core/objectspace/each_object_spec.rb
+++ b/spec/ruby/core/objectspace/each_object_spec.rb
@@ -39,7 +39,7 @@ describe "ObjectSpace.each_object" do
new_obj = klass.new
counter = ObjectSpace.each_object(klass)
- counter.should be_an_instance_of(Enumerator)
+ counter.should.instance_of?(Enumerator)
counter.each{}.should == 1
# this is needed to prevent the new_obj from being GC'd too early
new_obj.should_not == nil
@@ -47,20 +47,20 @@ describe "ObjectSpace.each_object" do
it "finds an object stored in a global variable" do
$object_space_global_variable = ObjectSpaceFixtures::ObjectToBeFound.new(:global)
- ObjectSpaceFixtures.to_be_found_symbols.should include(:global)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:global)
end
it "finds an object stored in a top-level constant" do
- ObjectSpaceFixtures.to_be_found_symbols.should include(:top_level_constant)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:top_level_constant)
end
it "finds an object stored in a second-level constant" do
- ObjectSpaceFixtures.to_be_found_symbols.should include(:second_level_constant)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:second_level_constant)
end
it "finds an object stored in a local variable" do
local = ObjectSpaceFixtures::ObjectToBeFound.new(:local)
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local)
end
it "finds an object stored in a local variable captured in a block explicitly" do
@@ -69,7 +69,7 @@ describe "ObjectSpace.each_object" do
Proc.new { local_in_block }
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_block_explicit)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_block_explicit)
end
it "finds an object stored in a local variable captured in a block implicitly" do
@@ -78,11 +78,11 @@ describe "ObjectSpace.each_object" do
Proc.new { }
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_block_implicit)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_block_implicit)
end
it "finds an object stored in a local variable captured in by a method defined with a block" do
- ObjectSpaceFixtures.to_be_found_symbols.should include(:captured_by_define_method)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:captured_by_define_method)
end
it "finds an object stored in a local variable captured in a Proc#binding" do
@@ -91,7 +91,7 @@ describe "ObjectSpace.each_object" do
Proc.new { }.binding
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_proc_binding)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_proc_binding)
end
it "finds an object stored in a local variable captured in a Kernel#binding" do
@@ -100,45 +100,45 @@ describe "ObjectSpace.each_object" do
binding
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_kernel_binding)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_kernel_binding)
end
it "finds an object stored in a local variable set in a binding manually" do
b = binding
b.eval("local = ObjectSpaceFixtures::ObjectToBeFound.new(:local_in_manual_binding)")
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_manual_binding)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_manual_binding)
end
it "finds an object stored in an array" do
array = [ObjectSpaceFixtures::ObjectToBeFound.new(:array)]
- ObjectSpaceFixtures.to_be_found_symbols.should include(:array)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:array)
end
it "finds an object stored in a hash key" do
hash = {ObjectSpaceFixtures::ObjectToBeFound.new(:hash_key) => :value}
- ObjectSpaceFixtures.to_be_found_symbols.should include(:hash_key)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:hash_key)
end
it "finds an object stored in a hash value" do
hash = {a: ObjectSpaceFixtures::ObjectToBeFound.new(:hash_value)}
- ObjectSpaceFixtures.to_be_found_symbols.should include(:hash_value)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:hash_value)
end
it "finds an object stored in an instance variable" do
local = ObjectSpaceFixtures::ObjectWithInstanceVariable.new
- ObjectSpaceFixtures.to_be_found_symbols.should include(:instance_variable)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:instance_variable)
end
it "finds an object stored in a thread local" do
thread = Thread.new {}
thread.thread_variable_set(:object_space_thread_local, ObjectSpaceFixtures::ObjectToBeFound.new(:thread_local))
- ObjectSpaceFixtures.to_be_found_symbols.should include(:thread_local)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:thread_local)
thread.join
end
it "finds an object stored in a fiber local" do
Thread.current[:object_space_fiber_local] = ObjectSpaceFixtures::ObjectToBeFound.new(:fiber_local)
- ObjectSpaceFixtures.to_be_found_symbols.should include(:fiber_local)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:fiber_local)
end
it "finds an object captured in an at_exit handler" do
@@ -150,7 +150,7 @@ describe "ObjectSpace.each_object" do
end
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:at_exit)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:at_exit)
end
it "finds an object captured in finalizer" do
@@ -164,9 +164,9 @@ describe "ObjectSpace.each_object" do
})
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:finalizer)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:finalizer)
- alive.should_not be_nil
+ alive.should_not == nil
end
describe "on singleton classes" do
@@ -185,8 +185,8 @@ describe "ObjectSpace.each_object" do
end
it "walks singleton classes" do
- @sclass.should be_kind_of(@meta)
- ObjectSpace.each_object(@meta).to_a.should include(@sclass)
+ @sclass.should.is_a?(@meta)
+ ObjectSpace.each_object(@meta).to_a.should.include?(@sclass)
end
end
@@ -202,7 +202,7 @@ describe "ObjectSpace.each_object" do
expected = [ a, b, c, d ]
expected << c_sclass
- c_sclass.should be_kind_of(a.singleton_class)
+ c_sclass.should.is_a?(a.singleton_class)
b.extend Enumerable # included modules should not be walked
diff --git a/spec/ruby/core/objectspace/finalizers_spec.rb b/spec/ruby/core/objectspace/finalizers_spec.rb
deleted file mode 100644
index e7f20fc8a0..0000000000
--- a/spec/ruby/core/objectspace/finalizers_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.finalizers" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/garbage_collect_spec.rb b/spec/ruby/core/objectspace/garbage_collect_spec.rb
index 521eaa8785..d2db22e0aa 100644
--- a/spec/ruby/core/objectspace/garbage_collect_spec.rb
+++ b/spec/ruby/core/objectspace/garbage_collect_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "ObjectSpace.garbage_collect" do
it "can be invoked without any exceptions" do
- -> { ObjectSpace.garbage_collect }.should_not raise_error
+ -> { ObjectSpace.garbage_collect }.should_not.raise
end
it "accepts keyword arguments" do
@@ -11,7 +11,7 @@ describe "ObjectSpace.garbage_collect" do
end
it "ignores the supplied block" do
- -> { ObjectSpace.garbage_collect {} }.should_not raise_error
+ -> { ObjectSpace.garbage_collect {} }.should_not.raise
end
it "always returns nil" do
diff --git a/spec/ruby/core/objectspace/remove_finalizer_spec.rb b/spec/ruby/core/objectspace/remove_finalizer_spec.rb
deleted file mode 100644
index 0b2b8cf16b..0000000000
--- a/spec/ruby/core/objectspace/remove_finalizer_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.remove_finalizer" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/undefine_finalizer_spec.rb b/spec/ruby/core/objectspace/undefine_finalizer_spec.rb
index 11d43121f8..98ffc6a986 100644
--- a/spec/ruby/core/objectspace/undefine_finalizer_spec.rb
+++ b/spec/ruby/core/objectspace/undefine_finalizer_spec.rb
@@ -1,5 +1,33 @@
require_relative '../../spec_helper'
describe "ObjectSpace.undefine_finalizer" do
- it "needs to be reviewed for spec completeness"
+ it "removes finalizers for an object" do
+ code = <<~RUBY
+ obj = Object.new
+ ObjectSpace.define_finalizer(obj, proc { |id| puts "hello" })
+ ObjectSpace.undefine_finalizer(obj)
+ RUBY
+
+ ruby_exe(code).should.empty?
+ end
+
+ it "should not remove finalizers for a frozen object" do
+ code = <<~RUBY
+ obj = Object.new
+ ObjectSpace.define_finalizer(obj, proc { |id| print "ok" })
+ obj.freeze
+ begin
+ ObjectSpace.undefine_finalizer(obj)
+ rescue
+ end
+ RUBY
+
+ ruby_exe(code).should == "ok"
+ end
+
+ it "should raise when removing finalizers for a frozen object" do
+ obj = Object.new
+ obj.freeze
+ -> { ObjectSpace.undefine_finalizer(obj) }.should.raise(FrozenError)
+ end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/clear_spec.rb b/spec/ruby/core/objectspace/weakkeymap/clear_spec.rb
new file mode 100644
index 0000000000..b1804ec9b0
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/clear_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakKeyMap#clear" do
+ it "removes all the entries" do
+ m = ObjectSpace::WeakKeyMap.new
+
+ key = Object.new
+ value = Object.new
+ m[key] = value
+
+ key2 = Object.new
+ value2 = Object.new
+ m[key2] = value2
+
+ m.clear
+
+ m.key?(key).should == false
+ m.key?(key2).should == false
+ end
+
+ it "returns self" do
+ m = ObjectSpace::WeakKeyMap.new
+ m.clear.should.equal?(m)
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb b/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb
new file mode 100644
index 0000000000..ad32c2c75e
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb
@@ -0,0 +1,49 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakKeyMap#delete" do
+ it "removes the entry and returns the deleted value" do
+ m = ObjectSpace::WeakKeyMap.new
+ key = Object.new
+ value = Object.new
+ m[key] = value
+
+ m.delete(key).should == value
+ m.key?(key).should == false
+ end
+
+ it "uses equality semantic" do
+ m = ObjectSpace::WeakKeyMap.new
+ key = "foo".upcase
+ value = Object.new
+ m[key] = value
+
+ m.delete("foo".upcase).should == value
+ m.key?(key).should == false
+ end
+
+ it "calls supplied block if the key is not found" do
+ key = Object.new
+ m = ObjectSpace::WeakKeyMap.new
+ return_value = m.delete(key) do |yielded_key|
+ yielded_key.should == key
+ 5
+ end
+ return_value.should == 5
+ end
+
+ it "returns nil if the key is not found when no block is given" do
+ m = ObjectSpace::WeakKeyMap.new
+ m.delete(Object.new).should == nil
+ end
+
+ it "returns nil when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map.delete(1).should == nil
+ map.delete(1.0).should == nil
+ map.delete(:a).should == nil
+ map.delete(true).should == nil
+ map.delete(false).should == nil
+ map.delete(nil).should == nil
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb b/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb
new file mode 100644
index 0000000000..53eff79c40
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb
@@ -0,0 +1,105 @@
+require_relative '../../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "ObjectSpace::WeakKeyMap#[]" do
+ it "is faithful to the map's content" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+ map[key1] = ref1
+ map[key1].should == ref1
+ map[key1] = ref1
+ map[key1].should == ref1
+ map[key2] = ref2
+ map[key1].should == ref1
+ map[key2].should == ref2
+ end
+
+ it "compares keys with #eql? semantics" do
+ map = ObjectSpace::WeakKeyMap.new
+ key = [1.0]
+ map[key] = "x"
+ map[[1]].should == nil
+ map[[1.0]].should == "x"
+ key.should == [1.0] # keep the key alive until here to keep the map entry
+
+ map = ObjectSpace::WeakKeyMap.new
+ key = [1]
+ map[key] = "x"
+ map[[1.0]].should == nil
+ map[[1]].should == "x"
+ key.should == [1] # keep the key alive until here to keep the map entry
+
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a a].map(&:upcase)
+ ref = "x"
+ map[key1] = ref
+ map[key2].should == ref
+ end
+
+ it "compares key via #hash first" do
+ x = mock('0')
+ x.should_receive(:hash).and_return(0)
+
+ map = ObjectSpace::WeakKeyMap.new
+ key = 'foo'
+ map[key] = :bar
+ map[x].should == nil
+ end
+
+ it "does not compare keys with different #hash values via #eql?" do
+ x = mock('x')
+ x.should_not_receive(:eql?)
+ x.stub!(:hash).and_return(0)
+
+ y = mock('y')
+ y.should_not_receive(:eql?)
+ y.stub!(:hash).and_return(1)
+
+ map = ObjectSpace::WeakKeyMap.new
+ map[y] = 1
+ map[x].should == nil
+ end
+
+ it "compares keys with the same #hash value via #eql?" do
+ x = mock('x')
+ x.should_receive(:eql?).and_return(true)
+ x.stub!(:hash).and_return(42)
+
+ y = mock('y')
+ y.should_not_receive(:eql?)
+ y.stub!(:hash).and_return(42)
+
+ map = ObjectSpace::WeakKeyMap.new
+ map[y] = 1
+ map[x].should == 1
+ end
+
+ it "finds a value via an identical key even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.should_receive(:hash).at_least(1).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ map = ObjectSpace::WeakKeyMap.new
+ map[x] = :x
+ map[x].should == :x
+ end
+
+ it "supports keys with private #hash method" do
+ key = WeakKeyMapSpecs::KeyWithPrivateHash.new
+ map = ObjectSpace::WeakKeyMap.new
+ map[key] = 42
+ map[key].should == 42
+ end
+
+ it "returns nil and does not raise error when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map[1].should == nil
+ map[1.0].should == nil
+ map[:a].should == nil
+ map[true].should == nil
+ map[false].should == nil
+ map[nil].should == nil
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb b/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
new file mode 100644
index 0000000000..cf59aebc6f
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
@@ -0,0 +1,80 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakKeyMap#[]=" do
+ def should_accept(map, key, value)
+ (map[key] = value).should == value
+ map.should.key?(key)
+ map[key].should == value
+ end
+
+ it "is correct" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+ should_accept(map, key1, ref1)
+ should_accept(map, key1, ref1)
+ should_accept(map, key2, ref2)
+ map[key1].should == ref1
+ end
+
+ it "requires the keys to implement #hash" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[BasicObject.new] = 1 }.should.raise(NoMethodError, /undefined method [`']hash' for an instance of BasicObject/)
+ end
+
+ it "accepts frozen keys or values" do
+ map = ObjectSpace::WeakKeyMap.new
+ x = Object.new
+ should_accept(map, x, true)
+ should_accept(map, x, false)
+ should_accept(map, x, 42)
+ should_accept(map, x, :foo)
+
+ y = Object.new.freeze
+ should_accept(map, x, y)
+ should_accept(map, y, x)
+ end
+
+ it "does not duplicate and freeze String keys (like Hash#[]= does)" do
+ map = ObjectSpace::WeakKeyMap.new
+ key = +"a"
+ map[key] = 1
+
+ map.getkey("a").should.equal? key
+ map.getkey("a").should_not.frozen?
+
+ key.should == "a" # keep the key alive until here to keep the map entry
+ end
+
+ context "a key cannot be garbage collected" do
+ it "raises ArgumentError when Integer is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[1] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+
+ it "raises ArgumentError when Float is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[1.0] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+
+ it "raises ArgumentError when Symbol is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[:a] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+
+ it "raises ArgumentError when true is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[true] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+
+ it "raises ArgumentError when false is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[false] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+
+ it "raises ArgumentError when nil is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[nil] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb b/spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb
new file mode 100644
index 0000000000..0fd04551b5
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb
@@ -0,0 +1,5 @@
+module WeakKeyMapSpecs
+ class KeyWithPrivateHash
+ private :hash
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb b/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb
new file mode 100644
index 0000000000..798a2e2cda
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb
@@ -0,0 +1,26 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakKeyMap#getkey" do
+ it "returns the existing equal key" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a a].map(&:upcase)
+
+ map[key1] = true
+ map.getkey(key2).should.equal?(key1)
+ map.getkey("X").should == nil
+
+ key1.should == "A" # keep the key alive until here to keep the map entry
+ key2.should == "A" # keep the key alive until here to keep the map entry
+ end
+
+ it "returns nil when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map.getkey(1).should == nil
+ map.getkey(1.0).should == nil
+ map.getkey(:a).should == nil
+ map.getkey(true).should == nil
+ map.getkey(false).should == nil
+ map.getkey(nil).should == nil
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb b/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb
new file mode 100644
index 0000000000..b6bb469158
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb
@@ -0,0 +1,19 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakKeyMap#inspect" do
+ it "only displays size in output" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2, key3 = "foo", "bar", "bar"
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=0>\z/
+ map[key1] = 1
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=1>\z/
+ map[key2] = 2
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=2>\z/
+ map[key3] = 3
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=2>\z/
+
+ key1.should == "foo" # keep the key alive until here to keep the map entry
+ key2.should == "bar" # keep the key alive until here to keep the map entry
+ key3.should == "bar" # keep the key alive until here to keep the map entry
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/key_spec.rb b/spec/ruby/core/objectspace/weakkeymap/key_spec.rb
new file mode 100644
index 0000000000..e0b6866671
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/key_spec.rb
@@ -0,0 +1,42 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakKeyMap#key?" do
+ it "recognizes keys in use" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+
+ map[key1] = ref1
+ map.key?(key1).should == true
+ map[key1] = ref1
+ map.key?(key1).should == true
+ map[key2] = ref2
+ map.key?(key2).should == true
+ end
+
+ it "matches using equality semantics" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a a].map(&:upcase)
+ ref = "x"
+ map[key1] = ref
+ map.key?(key2).should == true
+ end
+
+ it "reports true if the pair exists and the value is nil" do
+ map = ObjectSpace::WeakKeyMap.new
+ key = Object.new
+ map[key] = nil
+ map.key?(key).should == true
+ end
+
+ it "returns false when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map.key?(1).should == false
+ map.key?(1.0).should == false
+ map.key?(:a).should == false
+ map.key?(true).should == false
+ map.key?(false).should == false
+ map.key?(nil).should == false
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakmap/delete_spec.rb b/spec/ruby/core/objectspace/weakmap/delete_spec.rb
new file mode 100644
index 0000000000..03beebbb83
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/delete_spec.rb
@@ -0,0 +1,28 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakMap#delete" do
+ it "removes the entry and returns the deleted value" do
+ m = ObjectSpace::WeakMap.new
+ key = Object.new
+ value = Object.new
+ m[key] = value
+
+ m.delete(key).should == value
+ m.key?(key).should == false
+ end
+
+ it "calls supplied block if the key is not found" do
+ key = Object.new
+ m = ObjectSpace::WeakMap.new
+ return_value = m.delete(key) do |yielded_key|
+ yielded_key.should == key
+ 5
+ end
+ return_value.should == 5
+ end
+
+ it "returns nil if the key is not found when no block is given" do
+ m = ObjectSpace::WeakMap.new
+ m.delete(Object.new).should == nil
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakmap/shared/each.rb b/spec/ruby/core/objectspace/weakmap/shared/each.rb
index 3d43a19347..771c416dde 100644
--- a/spec/ruby/core/objectspace/weakmap/shared/each.rb
+++ b/spec/ruby/core/objectspace/weakmap/shared/each.rb
@@ -5,6 +5,6 @@ describe :weakmap_each, shared: true do
ref = "x"
map.send(@method).should == map
map[key] = ref
- -> { map.send(@method) }.should raise_error(LocalJumpError)
+ -> { map.send(@method) }.should.raise(LocalJumpError)
end
end
diff --git a/spec/ruby/core/proc/allocate_spec.rb b/spec/ruby/core/proc/allocate_spec.rb
index 54e1b69df9..96c4eb9fa8 100644
--- a/spec/ruby/core/proc/allocate_spec.rb
+++ b/spec/ruby/core/proc/allocate_spec.rb
@@ -4,6 +4,6 @@ describe "Proc.allocate" do
it "raises a TypeError" do
-> {
Proc.allocate
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/proc/arity_spec.rb b/spec/ruby/core/proc/arity_spec.rb
index f7cb5ad0f8..5c7728cb30 100644
--- a/spec/ruby/core/proc/arity_spec.rb
+++ b/spec/ruby/core/proc/arity_spec.rb
@@ -268,6 +268,14 @@ describe "Proc#arity" do
@a.arity.should == 3
@b.arity.should == 3
end
+
+ # implicit rest
+ evaluate <<-ruby do
+ @a = lambda { |a, | }
+ ruby
+
+ @a.arity.should == 1
+ end
end
context "returns negative values" do
@@ -530,6 +538,14 @@ describe "Proc#arity" do
@a.arity.should == 1
@b.arity.should == 5
end
+
+ # implicit rest
+ evaluate <<-ruby do
+ @a = proc { |a, | }
+ ruby
+
+ @a.arity.should == 1
+ end
end
context "returns negative values" do
diff --git a/spec/ruby/core/proc/binding_spec.rb b/spec/ruby/core/proc/binding_spec.rb
index 86ab6bd400..d643cbf89c 100644
--- a/spec/ruby/core/proc/binding_spec.rb
+++ b/spec/ruby/core/proc/binding_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Proc#binding" do
it "returns a Binding instance" do
[Proc.new{}, -> {}, proc {}].each { |p|
- p.binding.should be_kind_of(Binding)
+ p.binding.should.is_a?(Binding)
}
end
diff --git a/spec/ruby/core/proc/block_pass_spec.rb b/spec/ruby/core/proc/block_pass_spec.rb
index 411c0bf3db..82c08db8a7 100644
--- a/spec/ruby/core/proc/block_pass_spec.rb
+++ b/spec/ruby/core/proc/block_pass_spec.rb
@@ -8,14 +8,14 @@ describe "Proc as a block pass argument" do
it "remains the same object if re-vivified by the target method" do
p = Proc.new {}
p2 = revivify(&p)
- p.should equal p2
+ p.should.equal? p2
p.should == p2
end
it "remains the same object if reconstructed with Proc.new" do
p = Proc.new {}
p2 = Proc.new(&p)
- p.should equal p2
+ p.should.equal? p2
p.should == p2
end
end
diff --git a/spec/ruby/core/proc/clone_spec.rb b/spec/ruby/core/proc/clone_spec.rb
index a1a1292654..aee4873e09 100644
--- a/spec/ruby/core/proc/clone_spec.rb
+++ b/spec/ruby/core/proc/clone_spec.rb
@@ -1,6 +1,28 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/common'
require_relative 'shared/dup'
describe "Proc#clone" do
it_behaves_like :proc_dup, :clone
+
+ ruby_bug "cloning a frozen proc is broken on Ruby 3.3", ""..."3.4" do
+ it "preserves frozen status" do
+ proc = Proc.new { }
+ proc.freeze
+ proc.frozen?.should == true
+ proc.clone.frozen?.should == true
+ end
+ end
+
+ it "calls #initialize_clone on subclass" do
+ obj = ProcSpecs::MyProc2.new(:a, 2) { }
+ dup = obj.clone
+
+ dup.should_not.equal?(obj)
+ dup.class.should == ProcSpecs::MyProc2
+
+ dup.first.should == :a
+ dup.second.should == 2
+ dup.initializer.should == :clone
+ end
end
diff --git a/spec/ruby/core/proc/compose_spec.rb b/spec/ruby/core/proc/compose_spec.rb
index 94814d11bc..9e9b57e06f 100644
--- a/spec/ruby/core/proc/compose_spec.rb
+++ b/spec/ruby/core/proc/compose_spec.rb
@@ -37,42 +37,22 @@ describe "Proc#<<" do
(f << g).should_not.lambda?
end
- ruby_version_is(''...'3.0') do
- it "is a Proc when other is lambda" do
- f = proc { |x| x * x }
- g = -> x { x + x }
-
- (f << g).is_a?(Proc).should == true
- (f << g).should_not.lambda?
- end
-
- it "is a lambda when self is lambda" do
- f = -> x { x * x }
- g = proc { |x| x + x }
-
- (f << g).is_a?(Proc).should == true
- (f << g).should.lambda?
- end
- end
-
- ruby_version_is('3.0') do
- it "is a lambda when parameter is lambda" do
- f = -> x { x * x }
- g = proc { |x| x + x }
- lambda_proc = -> x { x }
+ it "is a lambda when parameter is lambda" do
+ f = -> x { x * x }
+ g = proc { |x| x + x }
+ lambda_proc = -> x { x }
- # lambda << proc
- (f << g).is_a?(Proc).should == true
- (f << g).should_not.lambda?
+ # lambda << proc
+ (f << g).is_a?(Proc).should == true
+ (f << g).should_not.lambda?
- # lambda << lambda
- (f << lambda_proc).is_a?(Proc).should == true
- (f << lambda_proc).should.lambda?
+ # lambda << lambda
+ (f << lambda_proc).is_a?(Proc).should == true
+ (f << lambda_proc).should.lambda?
- # proc << lambda
- (g << f).is_a?(Proc).should == true
- (g << f).should.lambda?
- end
+ # proc << lambda
+ (g << f).is_a?(Proc).should == true
+ (g << f).should.lambda?
end
it "may accept multiple arguments" do
diff --git a/spec/ruby/core/proc/curry_spec.rb b/spec/ruby/core/proc/curry_spec.rb
index 24df2a8a72..de13983ca6 100644
--- a/spec/ruby/core/proc/curry_spec.rb
+++ b/spec/ruby/core/proc/curry_spec.rb
@@ -8,12 +8,12 @@ describe "Proc#curry" do
it "returns a Proc when called on a proc" do
p = proc { true }
- p.curry.should be_an_instance_of(Proc)
+ p.curry.should.instance_of?(Proc)
end
it "returns a Proc when called on a lambda" do
p = -> { true }
- p.curry.should be_an_instance_of(Proc)
+ p.curry.should.instance_of?(Proc)
end
it "calls the curried proc with the arguments if sufficient arguments have been given" do
@@ -23,11 +23,11 @@ describe "Proc#curry" do
it "returns a Proc that consumes the remainder of the arguments unless sufficient arguments have been given" do
proc2 = @proc_add.curry[1][2]
- proc2.should be_an_instance_of(Proc)
+ proc2.should.instance_of?(Proc)
proc2.call(3).should == 6
lambda2 = @lambda_add.curry[1][2]
- lambda2.should be_an_instance_of(Proc)
+ lambda2.should.instance_of?(Proc)
lambda2.call(3).should == 6
@proc_add.curry.call(1,2,3).should == 6
@@ -36,10 +36,10 @@ describe "Proc#curry" do
it "can be called multiple times on the same Proc" do
@proc_add.curry
- -> { @proc_add.curry }.should_not raise_error
+ -> { @proc_add.curry }.should_not.raise
@lambda_add.curry
- -> { @lambda_add.curry }.should_not raise_error
+ -> { @lambda_add.curry }.should_not.raise
end
it "can be passed superfluous arguments if created from a proc" do
@@ -49,8 +49,8 @@ describe "Proc#curry" do
end
it "raises an ArgumentError if passed superfluous arguments when created from a lambda" do
- -> { @lambda_add.curry[1,2,3,4] }.should raise_error(ArgumentError)
- -> { @lambda_add.curry[1,2].curry[3,4,5,6] }.should raise_error(ArgumentError)
+ -> { @lambda_add.curry[1,2,3,4] }.should.raise(ArgumentError)
+ -> { @lambda_add.curry[1,2].curry[3,4,5,6] }.should.raise(ArgumentError)
end
it "returns Procs with arities of -1" do
@@ -63,7 +63,7 @@ describe "Proc#curry" do
it "produces Procs that raise ArgumentError for #binding" do
-> do
@proc_add.curry.binding
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "produces Procs that return [[:rest]] for #parameters" do
@@ -98,41 +98,41 @@ describe "Proc#curry with arity argument" do
end
it "accepts an optional Integer argument for the arity" do
- -> { @proc_add.curry(3) }.should_not raise_error
- -> { @lambda_add.curry(3) }.should_not raise_error
+ -> { @proc_add.curry(3) }.should_not.raise
+ -> { @lambda_add.curry(3) }.should_not.raise
end
it "returns a Proc when called on a proc" do
- @proc_add.curry(3).should be_an_instance_of(Proc)
+ @proc_add.curry(3).should.instance_of?(Proc)
end
it "returns a Proc when called on a lambda" do
- @lambda_add.curry(3).should be_an_instance_of(Proc)
+ @lambda_add.curry(3).should.instance_of?(Proc)
end
# [ruby-core:24127]
it "retains the lambda-ness of the Proc on which its called" do
- @lambda_add.curry(3).lambda?.should be_true
- @proc_add.curry(3).lambda?.should be_false
+ @lambda_add.curry(3).lambda?.should == true
+ @proc_add.curry(3).lambda?.should == false
end
it "raises an ArgumentError if called on a lambda that requires more than _arity_ arguments" do
- -> { @lambda_add.curry(2) }.should raise_error(ArgumentError)
- -> { -> x, y, z, *more{}.curry(2) }.should raise_error(ArgumentError)
+ -> { @lambda_add.curry(2) }.should.raise(ArgumentError)
+ -> { -> x, y, z, *more{}.curry(2) }.should.raise(ArgumentError)
end
it 'returns a Proc if called on a lambda that requires fewer than _arity_ arguments but may take more' do
- -> a, b, c, d=nil, e=nil {}.curry(4).should be_an_instance_of(Proc)
- -> a, b, c, d=nil, *e {}.curry(4).should be_an_instance_of(Proc)
- -> a, b, c, *d {}.curry(4).should be_an_instance_of(Proc)
+ -> a, b, c, d=nil, e=nil {}.curry(4).should.instance_of?(Proc)
+ -> a, b, c, d=nil, *e {}.curry(4).should.instance_of?(Proc)
+ -> a, b, c, *d {}.curry(4).should.instance_of?(Proc)
end
it "raises an ArgumentError if called on a lambda that requires fewer than _arity_ arguments" do
- -> { @lambda_add.curry(4) }.should raise_error(ArgumentError)
- -> { -> { true }.curry(1) }.should raise_error(ArgumentError)
- -> { -> a, b=nil {}.curry(5) }.should raise_error(ArgumentError)
- -> { -> a, &b {}.curry(2) }.should raise_error(ArgumentError)
- -> { -> a, b=nil, &c {}.curry(3) }.should raise_error(ArgumentError)
+ -> { @lambda_add.curry(4) }.should.raise(ArgumentError)
+ -> { -> { true }.curry(1) }.should.raise(ArgumentError)
+ -> { -> a, b=nil {}.curry(5) }.should.raise(ArgumentError)
+ -> { -> a, &b {}.curry(2) }.should.raise(ArgumentError)
+ -> { -> a, b=nil, &c {}.curry(3) }.should.raise(ArgumentError)
end
it "calls the curried proc with the arguments if _arity_ arguments have been given" do
@@ -142,32 +142,31 @@ describe "Proc#curry with arity argument" do
it "returns a Proc that consumes the remainder of the arguments when fewer than _arity_ arguments are given" do
proc2 = @proc_add.curry(3)[1][2]
- proc2.should be_an_instance_of(Proc)
+ proc2.should.instance_of?(Proc)
proc2.call(3).should == 6
lambda2 = @lambda_add.curry(3)[1][2]
- lambda2.should be_an_instance_of(Proc)
+ lambda2.should.instance_of?(Proc)
lambda2.call(3).should == 6
end
it "can be specified multiple times on the same Proc" do
@proc_add.curry(2)
- -> { @proc_add.curry(1) }.should_not raise_error
+ -> { @proc_add.curry(1) }.should_not.raise
@lambda_add.curry(3)
- -> { @lambda_add.curry(3) }.should_not raise_error
+ -> { @lambda_add.curry(3) }.should_not.raise
end
it "can be passed more than _arity_ arguments if created from a proc" do
- -> { @proc_add.curry(3)[1,2,3,4].should == 6 }.should_not
- raise_error(ArgumentError)
- -> { @proc_add.curry(1)[1,2].curry(3)[3,4,5,6].should == 6 }.should_not
- raise_error(ArgumentError)
+ @proc_add.curry(3)[1,2,3,4].should == 6
+
+ @proc_add.curry(3)[1,2].curry(3)[3,4,5,6].should == 6
end
it "raises an ArgumentError if passed more than _arity_ arguments when created from a lambda" do
- -> { @lambda_add.curry(3)[1,2,3,4] }.should raise_error(ArgumentError)
- -> { @lambda_add.curry(1)[1,2].curry(3)[3,4,5,6] }.should raise_error(ArgumentError)
+ -> { @lambda_add.curry(3)[1,2,3,4] }.should.raise(ArgumentError)
+ -> { @lambda_add.curry(3)[1,2].curry(3)[3,4,5,6] }.should.raise(ArgumentError)
end
it "returns Procs with arities of -1 regardless of the value of _arity_" do
diff --git a/spec/ruby/core/proc/dup_spec.rb b/spec/ruby/core/proc/dup_spec.rb
index 6da2f3080c..8604389422 100644
--- a/spec/ruby/core/proc/dup_spec.rb
+++ b/spec/ruby/core/proc/dup_spec.rb
@@ -1,6 +1,26 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/common'
require_relative 'shared/dup'
describe "Proc#dup" do
it_behaves_like :proc_dup, :dup
+
+ it "resets frozen status" do
+ proc = Proc.new { }
+ proc.freeze
+ proc.frozen?.should == true
+ proc.dup.frozen?.should == false
+ end
+
+ it "calls #initialize_dup on subclass" do
+ obj = ProcSpecs::MyProc2.new(:a, 2) { }
+ dup = obj.dup
+
+ dup.should_not.equal?(obj)
+ dup.class.should == ProcSpecs::MyProc2
+
+ dup.first.should == :a
+ dup.second.should == 2
+ dup.initializer.should == :dup
+ end
end
diff --git a/spec/ruby/core/proc/element_reference_spec.rb b/spec/ruby/core/proc/element_reference_spec.rb
index 9077e44c34..ea3a915a11 100644
--- a/spec/ruby/core/proc/element_reference_spec.rb
+++ b/spec/ruby/core/proc/element_reference_spec.rb
@@ -17,11 +17,11 @@ describe "Proc#call on a Proc created with Kernel#lambda or Kernel#proc" do
it_behaves_like :proc_call_on_proc_or_lambda, :call
end
-describe "Proc#[] with frozen_string_literals" do
+describe "Proc#[] with frozen_string_literal: true/false" do
it "doesn't duplicate frozen strings" do
- ProcArefSpecs.aref.frozen?.should be_false
- ProcArefSpecs.aref_freeze.frozen?.should be_true
- ProcArefFrozenSpecs.aref.frozen?.should be_true
- ProcArefFrozenSpecs.aref_freeze.frozen?.should be_true
+ ProcArefSpecs.aref.frozen?.should == false
+ ProcArefSpecs.aref_freeze.frozen?.should == true
+ ProcArefFrozenSpecs.aref.frozen?.should == true
+ ProcArefFrozenSpecs.aref_freeze.frozen?.should == true
end
end
diff --git a/spec/ruby/core/proc/eql_spec.rb b/spec/ruby/core/proc/eql_spec.rb
index 06aee272e5..ad8f6749fc 100644
--- a/spec/ruby/core/proc/eql_spec.rb
+++ b/spec/ruby/core/proc/eql_spec.rb
@@ -2,11 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/equal'
describe "Proc#eql?" do
- ruby_version_is ""..."3.0" do
- it_behaves_like :proc_equal_undefined, :eql?
- end
-
- ruby_version_is "3.0" do
- it_behaves_like :proc_equal, :eql?
- end
+ it_behaves_like :proc_equal, :eql?
end
diff --git a/spec/ruby/core/proc/equal_value_spec.rb b/spec/ruby/core/proc/equal_value_spec.rb
index ee88c0537d..ec7f274732 100644
--- a/spec/ruby/core/proc/equal_value_spec.rb
+++ b/spec/ruby/core/proc/equal_value_spec.rb
@@ -2,11 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/equal'
describe "Proc#==" do
- ruby_version_is ""..."3.0" do
- it_behaves_like :proc_equal_undefined, :==
- end
-
- ruby_version_is "3.0" do
- it_behaves_like :proc_equal, :==
- end
+ it_behaves_like :proc_equal, :==
end
diff --git a/spec/ruby/core/proc/fixtures/common.rb b/spec/ruby/core/proc/fixtures/common.rb
index 6e27a2dee7..dfe67d7ba8 100644
--- a/spec/ruby/core/proc/fixtures/common.rb
+++ b/spec/ruby/core/proc/fixtures/common.rb
@@ -32,7 +32,28 @@ module ProcSpecs
@second = b
end
- attr_reader :first, :second
+ attr_reader :first, :second, :initializer
+
+ def initialize_copy(other)
+ super
+ @initializer = :copy
+ @first = other.first
+ @second = other.second
+ end
+
+ def initialize_dup(other)
+ super
+ @initializer = :dup
+ @first = other.first
+ @second = other.second
+ end
+
+ def initialize_clone(other, **options)
+ super
+ @initializer = :clone
+ @first = other.first
+ @second = other.second
+ end
end
class Arity
diff --git a/spec/ruby/core/proc/fixtures/proc_aref.rb b/spec/ruby/core/proc/fixtures/proc_aref.rb
index a305667797..8ee355b14c 100644
--- a/spec/ruby/core/proc/fixtures/proc_aref.rb
+++ b/spec/ruby/core/proc/fixtures/proc_aref.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
module ProcArefSpecs
def self.aref
proc {|a| a }["sometext"]
diff --git a/spec/ruby/core/proc/hash_spec.rb b/spec/ruby/core/proc/hash_spec.rb
index ebe0fde1a0..adcb1ccb78 100644
--- a/spec/ruby/core/proc/hash_spec.rb
+++ b/spec/ruby/core/proc/hash_spec.rb
@@ -2,12 +2,12 @@ require_relative '../../spec_helper'
describe "Proc#hash" do
it "is provided" do
- proc {}.respond_to?(:hash).should be_true
- -> {}.respond_to?(:hash).should be_true
+ proc {}.respond_to?(:hash).should == true
+ -> {}.respond_to?(:hash).should == true
end
it "returns an Integer" do
- proc { 1 + 489 }.hash.should be_kind_of(Integer)
+ proc { 1 + 489 }.hash.should.is_a?(Integer)
end
it "is stable" do
diff --git a/spec/ruby/core/proc/lambda_spec.rb b/spec/ruby/core/proc/lambda_spec.rb
index b2d3f50350..1ff6147319 100644
--- a/spec/ruby/core/proc/lambda_spec.rb
+++ b/spec/ruby/core/proc/lambda_spec.rb
@@ -3,58 +3,53 @@ require_relative 'fixtures/common'
describe "Proc#lambda?" do
it "returns true if the Proc was created from a block with the lambda keyword" do
- -> {}.lambda?.should be_true
+ -> {}.lambda?.should == true
end
it "returns false if the Proc was created from a block with the proc keyword" do
- proc {}.lambda?.should be_false
+ proc {}.lambda?.should == false
end
it "returns false if the Proc was created from a block with Proc.new" do
- Proc.new {}.lambda?.should be_false
- end
-
- it "is preserved when passing a Proc with & to the lambda keyword" do
- suppress_warning {lambda(&->{})}.lambda?.should be_true
- suppress_warning {lambda(&proc{})}.lambda?.should be_false
+ Proc.new {}.lambda?.should == false
end
it "is preserved when passing a Proc with & to the proc keyword" do
- proc(&->{}).lambda?.should be_true
- proc(&proc{}).lambda?.should be_false
+ proc(&->{}).lambda?.should == true
+ proc(&proc{}).lambda?.should == false
end
it "is preserved when passing a Proc with & to Proc.new" do
- Proc.new(&->{}).lambda?.should be_true
- Proc.new(&proc{}).lambda?.should be_false
+ Proc.new(&->{}).lambda?.should == true
+ Proc.new(&proc{}).lambda?.should == false
end
it "returns false if the Proc was created from a block with &" do
- ProcSpecs.new_proc_from_amp{}.lambda?.should be_false
+ ProcSpecs.new_proc_from_amp{}.lambda?.should == false
end
it "is preserved when the Proc was passed using &" do
- ProcSpecs.new_proc_from_amp(&->{}).lambda?.should be_true
- ProcSpecs.new_proc_from_amp(&proc{}).lambda?.should be_false
- ProcSpecs.new_proc_from_amp(&Proc.new{}).lambda?.should be_false
+ ProcSpecs.new_proc_from_amp(&->{}).lambda?.should == true
+ ProcSpecs.new_proc_from_amp(&proc{}).lambda?.should == false
+ ProcSpecs.new_proc_from_amp(&Proc.new{}).lambda?.should == false
end
it "returns true for a Method converted to a Proc" do
m = :foo.method(:to_s)
- m.to_proc.lambda?.should be_true
- ProcSpecs.new_proc_from_amp(&m).lambda?.should be_true
+ m.to_proc.lambda?.should == true
+ ProcSpecs.new_proc_from_amp(&m).lambda?.should == true
end
# [ruby-core:24127]
it "is preserved when a Proc is curried" do
- ->{}.curry.lambda?.should be_true
- proc{}.curry.lambda?.should be_false
- Proc.new{}.curry.lambda?.should be_false
+ ->{}.curry.lambda?.should == true
+ proc{}.curry.lambda?.should == false
+ Proc.new{}.curry.lambda?.should == false
end
it "is preserved when a curried Proc is called without enough arguments" do
- -> x, y{}.curry.call(42).lambda?.should be_true
- proc{|x,y|}.curry.call(42).lambda?.should be_false
- Proc.new{|x,y|}.curry.call(42).lambda?.should be_false
+ -> x, y{}.curry.call(42).lambda?.should == true
+ proc{|x,y|}.curry.call(42).lambda?.should == false
+ Proc.new{|x,y|}.curry.call(42).lambda?.should == false
end
end
diff --git a/spec/ruby/core/proc/new_spec.rb b/spec/ruby/core/proc/new_spec.rb
index cb52e94f44..f0b817f0cb 100644
--- a/spec/ruby/core/proc/new_spec.rb
+++ b/spec/ruby/core/proc/new_spec.rb
@@ -71,7 +71,7 @@ describe "Proc.new with an associated block" do
end
res = some_method()
- -> { res.call }.should raise_error(LocalJumpError)
+ -> { res.call }.should.raise(LocalJumpError)
end
it "returns from within enclosing method when 'return' is used in the block" do
@@ -86,7 +86,7 @@ describe "Proc.new with an associated block" do
it "returns a subclass of Proc" do
obj = ProcSpecs::MyProc.new { }
- obj.should be_kind_of(ProcSpecs::MyProc)
+ obj.should.is_a?(ProcSpecs::MyProc)
end
it "calls initialize on the Proc object" do
@@ -101,7 +101,7 @@ describe "Proc.new with a block argument" do
passed_prc = Proc.new { "hello".size }
prc = Proc.new(&passed_prc)
- prc.should equal(passed_prc)
+ prc.should.equal?(passed_prc)
prc.call.should == 5
end
@@ -110,7 +110,7 @@ describe "Proc.new with a block argument" do
passed_prc = Proc.new(&method)
prc = Proc.new(&passed_prc)
- prc.should equal(passed_prc)
+ prc.should.equal?(passed_prc)
prc.call.should == 5
end
@@ -118,7 +118,7 @@ describe "Proc.new with a block argument" do
passed_prc = Proc.new(&:size)
prc = Proc.new(&passed_prc)
- prc.should equal(passed_prc)
+ prc.should.equal?(passed_prc)
prc.call("hello").should == 5
end
end
@@ -129,7 +129,7 @@ describe "Proc.new with a block argument called indirectly from a subclass" do
passed_prc.class.should == ProcSpecs::MyProc
prc = ProcSpecs::MyProc.new(&passed_prc)
- prc.should equal(passed_prc)
+ prc.should.equal?(passed_prc)
prc.call.should == 5
end
@@ -139,7 +139,7 @@ describe "Proc.new with a block argument called indirectly from a subclass" do
passed_prc.class.should == ProcSpecs::MyProc
prc = ProcSpecs::MyProc.new(&passed_prc)
- prc.should equal(passed_prc)
+ prc.should.equal?(passed_prc)
prc.call.should == 5
end
@@ -148,54 +148,31 @@ describe "Proc.new with a block argument called indirectly from a subclass" do
passed_prc.class.should == ProcSpecs::MyProc
prc = ProcSpecs::MyProc.new(&passed_prc)
- prc.should equal(passed_prc)
+ prc.should.equal?(passed_prc)
prc.call("hello").should == 5
end
end
describe "Proc.new without a block" do
it "raises an ArgumentError" do
- -> { Proc.new }.should raise_error(ArgumentError)
+ -> { Proc.new }.should.raise(ArgumentError)
end
it "raises an ArgumentError if invoked from within a method with no block" do
- -> { ProcSpecs.new_proc_in_method }.should raise_error(ArgumentError)
+ -> { ProcSpecs.new_proc_in_method }.should.raise(ArgumentError)
end
it "raises an ArgumentError if invoked on a subclass from within a method with no block" do
- -> { ProcSpecs.new_proc_subclass_in_method }.should raise_error(ArgumentError)
+ -> { ProcSpecs.new_proc_subclass_in_method }.should.raise(ArgumentError)
end
- ruby_version_is ""..."3.0" do
- it "can be created if invoked from within a method with a block" do
- -> { ProcSpecs.new_proc_in_method { "hello" } }.should complain(/Capturing the given block using Proc.new is deprecated/)
- end
-
- it "can be created if invoked on a subclass from within a method with a block" do
- -> { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should complain(/Capturing the given block using Proc.new is deprecated/)
- end
-
-
- it "can be create when called with no block" do
- def some_method
- Proc.new
- end
-
- -> {
- some_method { "hello" }
- }.should complain(/Capturing the given block using Proc.new is deprecated/)
+ it "raises an ArgumentError when passed no block" do
+ def some_method
+ Proc.new
end
- end
- ruby_version_is "3.0" do
- it "raises an ArgumentError when passed no block" do
- def some_method
- Proc.new
- end
-
- -> { ProcSpecs.new_proc_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
- -> { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
- -> { some_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
- end
+ -> { ProcSpecs.new_proc_in_method { "hello" } }.should.raise(ArgumentError, 'tried to create Proc object without a block')
+ -> { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should.raise(ArgumentError, 'tried to create Proc object without a block')
+ -> { some_method { "hello" } }.should.raise(ArgumentError, 'tried to create Proc object without a block')
end
end
diff --git a/spec/ruby/core/proc/parameters_spec.rb b/spec/ruby/core/proc/parameters_spec.rb
index 3a56b613cd..ac8c6e3560 100644
--- a/spec/ruby/core/proc/parameters_spec.rb
+++ b/spec/ruby/core/proc/parameters_spec.rb
@@ -7,8 +7,8 @@ describe "Proc#parameters" do
it "returns an Array of Arrays for a proc expecting parameters" do
p = proc {|x| }
- p.parameters.should be_an_instance_of(Array)
- p.parameters.first.should be_an_instance_of(Array)
+ p.parameters.should.instance_of?(Array)
+ p.parameters.first.should.instance_of?(Array)
end
it "sets the first element of each sub-Array to :opt for optional arguments" do
@@ -20,19 +20,27 @@ describe "Proc#parameters" do
proc {|x| }.parameters.first.first.should == :opt
end
- ruby_version_is "3.2" do
- it "sets the first element of each sub-Array to :req if argument would be required if a lambda if lambda keyword used" do
- proc {|x| }.parameters(lambda: true).first.first.should == :req
- proc {|y,*x| }.parameters(lambda: true).first.first.should == :req
- end
+ it "sets the first element of each sub-Array to :req for required argument if lambda keyword used" do
+ proc {|x| }.parameters(lambda: true).first.first.should == :req
+ proc {|y,*x| }.parameters(lambda: true).first.first.should == :req
+ end
- it "regards named parameters in procs as required if lambda keyword used" do
- proc {|x| }.parameters(lambda: true).first.first.should == :req
- end
+ it "regards named parameters in procs as required if lambda keyword used" do
+ proc {|x| }.parameters(lambda: true).first.first.should == :req
+ end
- it "regards named parameters in lambda as optional if lambda: false keyword used" do
- -> x { }.parameters(lambda: false).first.first.should == :opt
- end
+ it "regards named parameters in lambda as optional if lambda: false keyword used" do
+ -> x { }.parameters(lambda: false).first.first.should == :opt
+ end
+
+ it "regards named parameters in procs and lambdas as required if lambda keyword is truthy" do
+ proc {|x| }.parameters(lambda: 123).first.first.should == :req
+ -> x { }.parameters(lambda: 123).first.first.should == :req
+ end
+
+ it "ignores the lambda keyword if it is nil" do
+ proc {|x|}.parameters(lambda: nil).first.first.should == :opt
+ -> x { }.parameters(lambda: nil).first.first.should == :req
end
it "regards optional keyword parameters in procs as optional" do
@@ -54,7 +62,7 @@ describe "Proc#parameters" do
end
it "regards keyword parameters in lambdas as required" do
- eval("lambda {|x:| }").parameters.first.first.should == :keyreq
+ -> x: { }.parameters.first.first.should == :keyreq
end
it "sets the first element of each sub-Array to :rest for parameters prefixed with asterisks" do
@@ -91,20 +99,25 @@ describe "Proc#parameters" do
proc {|&block| }.parameters.first.last.should == :block
end
- it "ignores unnamed rest args" do
+ it "ignores unnamed rest arguments" do
-> x {}.parameters.should == [[:req, :x]]
end
- ruby_version_is '3.2' do
- it "adds * rest arg for \"star\" argument" do
- -> x, * {}.parameters.should == [[:req, :x], [:rest, :*]]
- end
+ it "ignores implicit rest arguments" do
+ proc { |x, | }.parameters.should == [[:opt, :x]]
+ -> x { }.parameters.should == [[:req, :x]]
end
- ruby_version_is ''...'3.2' do
- it "adds nameless rest arg for \"star\" argument" do
- -> x, * {}.parameters.should == [[:req, :x], [:rest]]
- end
+ it "adds rest arg with name * for \"star\" argument" do
+ -> * {}.parameters.should == [[:rest, :*]]
+ end
+
+ it "adds keyrest arg with ** as a name for \"double star\" argument" do
+ -> ** {}.parameters.should == [[:keyrest, :**]]
+ end
+
+ it "adds block arg with name & for anonymous block argument" do
+ -> & {}.parameters.should == [[:block, :&]]
end
it "does not add locals as block options with a block and splat" do
@@ -115,4 +128,56 @@ describe "Proc#parameters" do
local_is_not_parameter = {}
end.parameters.should == [[:rest, :args], [:block, :blk]]
end
+
+ it "returns all parameters defined with the name _ as _" do
+ proc = proc {|_, _, _ = 1, *_, _:, _: 2, **_, &_| }
+ proc.parameters.should == [
+ [:opt, :_],
+ [:opt, :_],
+ [:opt, :_],
+ [:rest, :_],
+ [:keyreq, :_],
+ [:key, :_],
+ [:keyrest, :_],
+ [:block, :_]
+ ]
+
+ lambda = -> _, _, _ = 1, *_, _:, _: 2, **_, &_ {}
+ lambda.parameters.should == [
+ [:req, :_],
+ [:req, :_],
+ [:opt, :_],
+ [:rest, :_],
+ [:keyreq, :_],
+ [:key, :_],
+ [:keyrest, :_],
+ [:block, :_]
+ ]
+ end
+
+ it "returns :nokey for **nil parameter" do
+ proc { |**nil| }.parameters.should == [[:nokey]]
+ end
+
+ ruby_version_is "3.4"..."4.0" do
+ it "handles the usage of `it` as a parameter" do
+ eval("proc { it }").parameters.should == [[:opt, nil]]
+ eval("lambda { it }").parameters.should == [[:req]]
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "handles the usage of `it` as a parameter" do
+ eval("proc { it }").parameters.should == [[:opt]]
+ eval("lambda { it }").parameters.should == [[:req]]
+ end
+ end
+
+ ruby_version_is "4.1" do
+ it "returns :noblock for &nil parameter" do
+ eval <<~RUBY
+ proc { |&nil| }.parameters.should == [[:noblock]]
+ RUBY
+ end
+ end
end
diff --git a/spec/ruby/core/proc/ruby2_keywords_spec.rb b/spec/ruby/core/proc/ruby2_keywords_spec.rb
index c6eb03e693..e06fad8693 100644
--- a/spec/ruby/core/proc/ruby2_keywords_spec.rb
+++ b/spec/ruby/core/proc/ruby2_keywords_spec.rb
@@ -25,31 +25,9 @@ describe "Proc#ruby2_keywords" do
Hash.ruby2_keywords_hash?(f4.call(1, 2, a: "a")).should == true
end
- ruby_version_is ""..."3.0" do
- it "fixes delegation warnings when calling a method accepting keywords" do
- obj = Object.new
- def obj.foo(*a, **b) end
-
- f = -> *a { obj.foo(*a) }
-
- -> { f.call(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/)
- f.ruby2_keywords
- -> { f.call(1, 2, {a: "a"}) }.should_not complain
- end
-
- it "fixes delegation warnings when calling a proc accepting keywords" do
- g = -> *a, **b { }
- f = -> *a { g.call(*a) }
-
- -> { f.call(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/)
- f.ruby2_keywords
- -> { f.call(1, 2, {a: "a"}) }.should_not complain
- end
- end
-
it "returns self" do
f = -> *a { }
- f.ruby2_keywords.should equal f
+ f.ruby2_keywords.should.equal? f
end
it "prints warning when a proc does not accept argument splat" do
@@ -61,7 +39,7 @@ describe "Proc#ruby2_keywords" do
end
it "prints warning when a proc accepts keywords" do
- f = -> a:, b: { }
+ f = -> *a, b: { }
-> {
f.ruby2_keywords
@@ -69,10 +47,20 @@ describe "Proc#ruby2_keywords" do
end
it "prints warning when a proc accepts keyword splat" do
- f = -> **a { }
+ f = -> *a, **b { }
-> {
f.ruby2_keywords
}.should complain(/Skipping set of ruby2_keywords flag for/)
end
+
+ ruby_version_is "4.0" do
+ it "prints warning when a proc accepts post arguments" do
+ f = -> *a, b { }
+
+ -> {
+ f.ruby2_keywords
+ }.should complain(/Skipping set of ruby2_keywords flag for/)
+ end
+ end
end
diff --git a/spec/ruby/core/proc/shared/call.rb b/spec/ruby/core/proc/shared/call.rb
index dbec34df4b..fae2331b68 100644
--- a/spec/ruby/core/proc/shared/call.rb
+++ b/spec/ruby/core/proc/shared/call.rb
@@ -70,21 +70,21 @@ describe :proc_call_on_proc_or_lambda, shared: true do
it "raises an ArgumentError on excess arguments when self is a lambda" do
-> {
-> x { x }.send(@method, 1, 2)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
-> x { x }.send(@method, 1, 2, 3)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises an ArgumentError on missing arguments when self is a lambda" do
-> {
-> x { x }.send(@method)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
-> x, y { [x,y] }.send(@method, 1)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "treats a single Array argument as a single argument when self is a lambda" do
diff --git a/spec/ruby/core/proc/shared/compose.rb b/spec/ruby/core/proc/shared/compose.rb
index 3d3f3b310d..c004cec7c9 100644
--- a/spec/ruby/core/proc/shared/compose.rb
+++ b/spec/ruby/core/proc/shared/compose.rb
@@ -5,7 +5,7 @@ describe :proc_compose, shared: true do
-> {
lhs.send(@method, not_callable)
- }.should raise_error(TypeError, "callable object is expected")
+ }.should.raise(TypeError, "callable object is expected")
end
@@ -17,6 +17,6 @@ describe :proc_compose, shared: true do
-> {
lhs.send(@method, succ)
- }.should raise_error(TypeError, "callable object is expected")
+ }.should.raise(TypeError, "callable object is expected")
end
end
diff --git a/spec/ruby/core/proc/shared/dup.rb b/spec/ruby/core/proc/shared/dup.rb
index eda1d6929d..2821d2e00f 100644
--- a/spec/ruby/core/proc/shared/dup.rb
+++ b/spec/ruby/core/proc/shared/dup.rb
@@ -3,8 +3,37 @@ describe :proc_dup, shared: true do
a = -> { "hello" }
b = a.send(@method)
- a.should_not equal(b)
+ a.should_not.equal?(b)
a.call.should == b.call
end
+
+ it "returns an instance of subclass" do
+ cl = Class.new(Proc)
+
+ cl.new{}.send(@method).class.should == cl
+ end
+
+ ruby_version_is "3.4" do
+ it "copies instance variables" do
+ proc = -> { "hello" }
+ proc.instance_variable_set(:@ivar, 1)
+ cl = proc.send(@method)
+ cl.instance_variables.should == [:@ivar]
+ end
+
+ it "copies the finalizer" do
+ code = <<-'RUBY'
+ obj = Proc.new { }
+
+ ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
+
+ obj.clone
+
+ exit 0
+ RUBY
+
+ ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"]
+ end
+ end
end
diff --git a/spec/ruby/core/proc/shared/equal.rb b/spec/ruby/core/proc/shared/equal.rb
index 0c0020ca7f..4f6f6c41be 100644
--- a/spec/ruby/core/proc/shared/equal.rb
+++ b/spec/ruby/core/proc/shared/equal.rb
@@ -3,29 +3,29 @@ require_relative '../fixtures/common'
describe :proc_equal, shared: true do
it "is a public method" do
- Proc.should have_public_instance_method(@method, false)
+ Proc.public_instance_methods(false).should.include?(@method)
end
it "returns true if self and other are the same object" do
p = proc { :foo }
- p.send(@method, p).should be_true
+ p.send(@method, p).should == true
p = Proc.new { :foo }
- p.send(@method, p).should be_true
+ p.send(@method, p).should == true
p = -> { :foo }
- p.send(@method, p).should be_true
+ p.send(@method, p).should == true
end
it "returns true if other is a dup of the original" do
p = proc { :foo }
- p.send(@method, p.dup).should be_true
+ p.send(@method, p.dup).should == true
p = Proc.new { :foo }
- p.send(@method, p.dup).should be_true
+ p.send(@method, p.dup).should == true
p = -> { :foo }
- p.send(@method, p.dup).should be_true
+ p.send(@method, p.dup).should == true
end
# identical here means the same method invocation.
@@ -33,68 +33,51 @@ describe :proc_equal, shared: true do
a = ProcSpecs.proc_for_1
b = ProcSpecs.proc_for_1
- a.send(@method, b).should be_false
+ a.send(@method, b).should == false
end
it "returns false if procs are distinct but have the same body and environment" do
p = proc { :foo }
p2 = proc { :foo }
- p.send(@method, p2).should be_false
+ p.send(@method, p2).should == false
end
it "returns false if lambdas are distinct but have same body and environment" do
x = -> { :foo }
x2 = -> { :foo }
- x.send(@method, x2).should be_false
+ x.send(@method, x2).should == false
end
it "returns false if using comparing lambda to proc, even with the same body and env" do
p = -> { :foo }
p2 = proc { :foo }
- p.send(@method, p2).should be_false
+ p.send(@method, p2).should == false
x = proc { :bar }
x2 = -> { :bar }
- x.send(@method, x2).should be_false
+ x.send(@method, x2).should == false
end
it "returns false if other is not a Proc" do
p = proc { :foo }
- p.send(@method, []).should be_false
+ p.send(@method, []).should == false
p = Proc.new { :foo }
- p.send(@method, Object.new).should be_false
+ p.send(@method, Object.new).should == false
p = -> { :foo }
- p.send(@method, :foo).should be_false
+ p.send(@method, :foo).should == false
end
it "returns false if self and other are both procs but have different bodies" do
p = proc { :bar }
p2 = proc { :foo }
- p.send(@method, p2).should be_false
+ p.send(@method, p2).should == false
end
it "returns false if self and other are both lambdas but have different bodies" do
p = -> { :foo }
p2 = -> { :bar }
- p.send(@method, p2).should be_false
- end
-end
-
-describe :proc_equal_undefined, shared: true do
- it "is not defined" do
- Proc.should_not have_instance_method(@method, false)
- end
-
- it "returns false if other is a dup of the original" do
- p = proc { :foo }
- p.send(@method, p.dup).should be_false
-
- p = Proc.new { :foo }
- p.send(@method, p.dup).should be_false
-
- p = -> { :foo }
- p.send(@method, p.dup).should be_false
+ p.send(@method, p2).should == false
end
end
diff --git a/spec/ruby/core/proc/shared/to_s.rb b/spec/ruby/core/proc/shared/to_s.rb
index f1e2f416fc..a52688a89f 100644
--- a/spec/ruby/core/proc/shared/to_s.rb
+++ b/spec/ruby/core/proc/shared/to_s.rb
@@ -31,13 +31,13 @@ describe :proc_to_s, shared: true do
describe "for a proc created with UnboundMethod#to_proc" do
it "returns a description including '(lambda)' and optionally including file and line number" do
- def hello; end
- s = method("hello").to_proc.send(@method)
- if s.include? __FILE__
- s.should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ - 3} \(lambda\)>$/
- else
- s.should =~ /^#<Proc:([^ ]*?) \(lambda\)>$/
- end
+ def hello; end
+ s = method("hello").to_proc.send(@method)
+ if s.include? __FILE__
+ s.should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ - 3} \(lambda\)>$/
+ else
+ s.should =~ /^#<Proc:([^ ]*?) \(lambda\)>$/
+ end
end
it "has a binary encoding" do
diff --git a/spec/ruby/core/proc/source_location_spec.rb b/spec/ruby/core/proc/source_location_spec.rb
index f268499b82..d27ad0559e 100644
--- a/spec/ruby/core/proc/source_location_spec.rb
+++ b/spec/ruby/core/proc/source_location_spec.rb
@@ -10,45 +10,45 @@ describe "Proc#source_location" do
end
it "returns an Array" do
- @proc.source_location.should be_an_instance_of(Array)
- @proc_new.source_location.should be_an_instance_of(Array)
- @lambda.source_location.should be_an_instance_of(Array)
- @method.source_location.should be_an_instance_of(Array)
+ @proc.source_location.should.instance_of?(Array)
+ @proc_new.source_location.should.instance_of?(Array)
+ @lambda.source_location.should.instance_of?(Array)
+ @method.source_location.should.instance_of?(Array)
end
it "sets the first value to the path of the file in which the proc was defined" do
file = @proc.source_location.first
- file.should be_an_instance_of(String)
- file.should == File.realpath('../fixtures/source_location.rb', __FILE__)
+ file.should.instance_of?(String)
+ file.should == File.realpath('fixtures/source_location.rb', __dir__)
file = @proc_new.source_location.first
- file.should be_an_instance_of(String)
- file.should == File.realpath('../fixtures/source_location.rb', __FILE__)
+ file.should.instance_of?(String)
+ file.should == File.realpath('fixtures/source_location.rb', __dir__)
file = @lambda.source_location.first
- file.should be_an_instance_of(String)
- file.should == File.realpath('../fixtures/source_location.rb', __FILE__)
+ file.should.instance_of?(String)
+ file.should == File.realpath('fixtures/source_location.rb', __dir__)
file = @method.source_location.first
- file.should be_an_instance_of(String)
- file.should == File.realpath('../fixtures/source_location.rb', __FILE__)
+ file.should.instance_of?(String)
+ file.should == File.realpath('fixtures/source_location.rb', __dir__)
end
it "sets the last value to an Integer representing the line on which the proc was defined" do
line = @proc.source_location.last
- line.should be_an_instance_of(Integer)
+ line.should.instance_of?(Integer)
line.should == 4
line = @proc_new.source_location.last
- line.should be_an_instance_of(Integer)
+ line.should.instance_of?(Integer)
line.should == 12
line = @lambda.source_location.last
- line.should be_an_instance_of(Integer)
+ line.should.instance_of?(Integer)
line.should == 8
line = @method.source_location.last
- line.should be_an_instance_of(Integer)
+ line.should.instance_of?(Integer)
line.should == 15
end
@@ -83,4 +83,9 @@ describe "Proc#source_location" do
proc.source_location.should == nil
end
+
+ it "works for eval with a given line" do
+ proc = eval('-> {}', nil, "foo", 100)
+ proc.source_location.should == ["foo", 100]
+ end
end
diff --git a/spec/ruby/core/proc/to_proc_spec.rb b/spec/ruby/core/proc/to_proc_spec.rb
index ffaa34929b..7f35a4f19b 100644
--- a/spec/ruby/core/proc/to_proc_spec.rb
+++ b/spec/ruby/core/proc/to_proc_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Proc#to_proc" do
it "returns self" do
[Proc.new {}, -> {}, proc {}].each { |p|
- p.to_proc.should equal(p)
+ p.to_proc.should.equal?(p)
}
end
end
diff --git a/spec/ruby/core/process/_fork_spec.rb b/spec/ruby/core/process/_fork_spec.rb
new file mode 100644
index 0000000000..620f243ce5
--- /dev/null
+++ b/spec/ruby/core/process/_fork_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+
+describe "Process._fork" do
+ it "for #respond_to? returns the same as Process.respond_to?(:fork)" do
+ Process.respond_to?(:_fork).should == Process.respond_to?(:fork)
+ end
+
+ # Using respond_to? in a guard here is OK because the correct semantics
+ # are that _fork is implemented if and only if fork is (see above).
+ guard_not -> { Process.respond_to?(:fork) } do
+ it "raises a NotImplementedError when called" do
+ -> { Process._fork }.should.raise(NotImplementedError)
+ end
+ end
+
+ guard -> { Process.respond_to?(:fork) } do
+ it "is called by Process#fork" do
+ Process.should_receive(:_fork).once.and_return(42)
+
+ pid = Process.fork {}
+ pid.should.equal?(42)
+ end
+ end
+end
diff --git a/spec/ruby/core/process/argv0_spec.rb b/spec/ruby/core/process/argv0_spec.rb
new file mode 100644
index 0000000000..4c7a2c9ecb
--- /dev/null
+++ b/spec/ruby/core/process/argv0_spec.rb
@@ -0,0 +1,23 @@
+require_relative '../../spec_helper'
+
+describe "Process.argv0" do
+ it "returns a String" do
+ Process.argv0.should.is_a?(String)
+ end
+
+ it "is the path given as the main script and the same as __FILE__" do
+ script = "fixtures/argv0.rb"
+
+ Dir.chdir(__dir__) do
+ ruby_exe(script).should == "#{script}\n#{script}\nOK"
+ end
+ end
+
+ it "returns a frozen object" do
+ Process.argv0.should.frozen?
+ end
+
+ it "returns every time the same object" do
+ Process.argv0.should.equal?(Process.argv0)
+ end
+end
diff --git a/spec/ruby/core/process/clock_gettime_spec.rb b/spec/ruby/core/process/clock_gettime_spec.rb
index 6c1a52f21e..88158904e1 100644
--- a/spec/ruby/core/process/clock_gettime_spec.rb
+++ b/spec/ruby/core/process/clock_gettime_spec.rb
@@ -4,31 +4,31 @@ require_relative 'fixtures/clocks'
describe "Process.clock_gettime" do
ProcessSpecs.clock_constants.each do |name, value|
it "can be called with Process::#{name}" do
- Process.clock_gettime(value).should be_an_instance_of(Float)
+ Process.clock_gettime(value).should.instance_of?(Float)
end
end
describe 'time units' do
it 'handles a fixed set of time units' do
[:nanosecond, :microsecond, :millisecond, :second].each do |unit|
- Process.clock_gettime(Process::CLOCK_MONOTONIC, unit).should be_kind_of(Integer)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, unit).should.is_a?(Integer)
end
[:float_microsecond, :float_millisecond, :float_second].each do |unit|
- Process.clock_gettime(Process::CLOCK_MONOTONIC, unit).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, unit).should.instance_of?(Float)
end
end
it 'raises an ArgumentError for an invalid time unit' do
- -> { Process.clock_gettime(Process::CLOCK_MONOTONIC, :bad) }.should raise_error(ArgumentError)
+ -> { Process.clock_gettime(Process::CLOCK_MONOTONIC, :bad) }.should.raise(ArgumentError)
end
it 'defaults to :float_second' do
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
- t1.should be_an_instance_of(Float)
- t2.should be_an_instance_of(Float)
+ t1.should.instance_of?(Float)
+ t2.should.instance_of?(Float)
t2.should be_close(t1, TIME_TOLERANCE)
end
@@ -36,116 +36,116 @@ describe "Process.clock_gettime" do
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC, nil)
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
- t1.should be_an_instance_of(Float)
- t2.should be_an_instance_of(Float)
+ t1.should.instance_of?(Float)
+ t2.should.instance_of?(Float)
t2.should be_close(t1, TIME_TOLERANCE)
end
end
describe "supports the platform clocks mentioned in the documentation" do
it "CLOCK_REALTIME" do
- Process.clock_gettime(Process::CLOCK_REALTIME).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_REALTIME).should.instance_of?(Float)
end
it "CLOCK_MONOTONIC" do
- Process.clock_gettime(Process::CLOCK_MONOTONIC).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC).should.instance_of?(Float)
end
# These specs need macOS 10.12+ / darwin 16+
guard -> { platform_is_not(:darwin) or kernel_version_is '16' } do
platform_is :linux, :openbsd, :darwin do
it "CLOCK_PROCESS_CPUTIME_ID" do
- Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID).should.instance_of?(Float)
end
end
platform_is :linux, :freebsd, :openbsd, :darwin do
it "CLOCK_THREAD_CPUTIME_ID" do
- Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID).should.instance_of?(Float)
end
end
platform_is :linux, :darwin do
it "CLOCK_MONOTONIC_RAW" do
- Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW).should.instance_of?(Float)
end
end
platform_is :darwin do
it "CLOCK_MONOTONIC_RAW_APPROX" do
- Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW_APPROX).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW_APPROX).should.instance_of?(Float)
end
it "CLOCK_UPTIME_RAW and CLOCK_UPTIME_RAW_APPROX" do
- Process.clock_gettime(Process::CLOCK_UPTIME_RAW).should be_an_instance_of(Float)
- Process.clock_gettime(Process::CLOCK_UPTIME_RAW_APPROX).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_UPTIME_RAW).should.instance_of?(Float)
+ Process.clock_gettime(Process::CLOCK_UPTIME_RAW_APPROX).should.instance_of?(Float)
end
end
end
platform_is :freebsd do
it "CLOCK_VIRTUAL" do
- Process.clock_gettime(Process::CLOCK_VIRTUAL).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_VIRTUAL).should.instance_of?(Float)
end
it "CLOCK_PROF" do
- Process.clock_gettime(Process::CLOCK_PROF).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_PROF).should.instance_of?(Float)
end
end
platform_is :freebsd, :openbsd do
it "CLOCK_UPTIME" do
- Process.clock_gettime(Process::CLOCK_UPTIME).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_UPTIME).should.instance_of?(Float)
end
end
platform_is :freebsd do
it "CLOCK_REALTIME_FAST and CLOCK_REALTIME_PRECISE" do
- Process.clock_gettime(Process::CLOCK_REALTIME_FAST).should be_an_instance_of(Float)
- Process.clock_gettime(Process::CLOCK_REALTIME_PRECISE).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_REALTIME_FAST).should.instance_of?(Float)
+ Process.clock_gettime(Process::CLOCK_REALTIME_PRECISE).should.instance_of?(Float)
end
it "CLOCK_MONOTONIC_FAST and CLOCK_MONOTONIC_PRECISE" do
- Process.clock_gettime(Process::CLOCK_MONOTONIC_FAST).should be_an_instance_of(Float)
- Process.clock_gettime(Process::CLOCK_MONOTONIC_PRECISE).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_FAST).should.instance_of?(Float)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_PRECISE).should.instance_of?(Float)
end
it "CLOCK_UPTIME_FAST and CLOCK_UPTIME_PRECISE" do
- Process.clock_gettime(Process::CLOCK_UPTIME_FAST).should be_an_instance_of(Float)
- Process.clock_gettime(Process::CLOCK_UPTIME_PRECISE).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_UPTIME_FAST).should.instance_of?(Float)
+ Process.clock_gettime(Process::CLOCK_UPTIME_PRECISE).should.instance_of?(Float)
end
it "CLOCK_SECOND" do
- Process.clock_gettime(Process::CLOCK_SECOND).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_SECOND).should.instance_of?(Float)
end
end
guard -> { platform_is :linux and kernel_version_is '2.6.32' } do
it "CLOCK_REALTIME_COARSE" do
- Process.clock_gettime(Process::CLOCK_REALTIME_COARSE).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_REALTIME_COARSE).should.instance_of?(Float)
end
it "CLOCK_MONOTONIC_COARSE" do
- Process.clock_gettime(Process::CLOCK_MONOTONIC_COARSE).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_COARSE).should.instance_of?(Float)
end
end
guard -> { platform_is :linux and kernel_version_is '2.6.39' } do
it "CLOCK_BOOTTIME" do
skip "No Process::CLOCK_BOOTTIME" unless defined?(Process::CLOCK_BOOTTIME)
- Process.clock_gettime(Process::CLOCK_BOOTTIME).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_BOOTTIME).should.instance_of?(Float)
end
end
guard -> { platform_is "x86_64-linux" and kernel_version_is '3.0' } do
it "CLOCK_REALTIME_ALARM" do
skip "No Process::CLOCK_REALTIME_ALARM" unless defined?(Process::CLOCK_REALTIME_ALARM)
- Process.clock_gettime(Process::CLOCK_REALTIME_ALARM).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_REALTIME_ALARM).should.instance_of?(Float)
end
it "CLOCK_BOOTTIME_ALARM" do
skip "No Process::CLOCK_BOOTTIME_ALARM" unless defined?(Process::CLOCK_BOOTTIME_ALARM)
- Process.clock_gettime(Process::CLOCK_BOOTTIME_ALARM).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_BOOTTIME_ALARM).should.instance_of?(Float)
end
end
end
diff --git a/spec/ruby/core/process/constants_spec.rb b/spec/ruby/core/process/constants_spec.rb
index b61f5ab64e..5a4c478e74 100644
--- a/spec/ruby/core/process/constants_spec.rb
+++ b/spec/ruby/core/process/constants_spec.rb
@@ -1,68 +1,107 @@
+require_relative '../../spec_helper'
describe "Process::Constants" do
platform_is :darwin, :netbsd, :freebsd do
- it "has the correct constant values on BSD-like systems" do
- Process::WNOHANG.should == 1
- Process::WUNTRACED.should == 2
- Process::PRIO_PROCESS.should == 0
- Process::PRIO_PGRP.should == 1
- Process::PRIO_USER.should == 2
- Process::RLIM_INFINITY.should == 9223372036854775807
- Process::RLIMIT_CPU.should == 0
- Process::RLIMIT_FSIZE.should == 1
- Process::RLIMIT_DATA.should == 2
- Process::RLIMIT_STACK.should == 3
- Process::RLIMIT_CORE.should == 4
- Process::RLIMIT_RSS.should == 5
- Process::RLIMIT_MEMLOCK.should == 6
- Process::RLIMIT_NPROC.should == 7
- Process::RLIMIT_NOFILE.should == 8
+ describe "on BSD-like systems" do
+ %i[
+ WNOHANG
+ WUNTRACED
+ PRIO_PROCESS
+ PRIO_PGRP
+ PRIO_USER
+ RLIM_INFINITY
+ RLIMIT_CPU
+ RLIMIT_FSIZE
+ RLIMIT_DATA
+ RLIMIT_STACK
+ RLIMIT_CORE
+ RLIMIT_RSS
+ RLIMIT_MEMLOCK
+ RLIMIT_NPROC
+ RLIMIT_NOFILE
+ ].each do |const|
+ it "defines #{const}" do
+ Process.const_defined?(const).should == true
+ Process.const_get(const).should.instance_of?(Integer)
+ end
+ end
end
end
platform_is :darwin do
- it "has the correct constant values on Darwin" do
- Process::RLIM_SAVED_MAX.should == 9223372036854775807
- Process::RLIM_SAVED_CUR.should == 9223372036854775807
- Process::RLIMIT_AS.should == 5
+ describe "on Darwin" do
+ %i[
+ RLIM_SAVED_MAX
+ RLIM_SAVED_CUR
+ RLIMIT_AS
+ ].each do |const|
+ it "defines #{const}" do
+ Process.const_defined?(const).should == true
+ Process.const_get(const).should.instance_of?(Integer)
+ end
+ end
end
end
platform_is :linux do
- it "has the correct constant values on Linux" do
- Process::WNOHANG.should == 1
- Process::WUNTRACED.should == 2
- Process::PRIO_PROCESS.should == 0
- Process::PRIO_PGRP.should == 1
- Process::PRIO_USER.should == 2
- Process::RLIMIT_CPU.should == 0
- Process::RLIMIT_FSIZE.should == 1
- Process::RLIMIT_DATA.should == 2
- Process::RLIMIT_STACK.should == 3
- Process::RLIMIT_CORE.should == 4
- Process::RLIMIT_RSS.should == 5
- Process::RLIMIT_NPROC.should == 6
- Process::RLIMIT_NOFILE.should == 7
- Process::RLIMIT_MEMLOCK.should == 8
- Process::RLIMIT_AS.should == 9
-
- # These values appear to change according to the platform.
- values = [4294967295, 9223372036854775807, 18446744073709551615]
- values.include?(Process::RLIM_INFINITY).should be_true
- values.include?(Process::RLIM_SAVED_MAX).should be_true
- values.include?(Process::RLIM_SAVED_CUR).should be_true
+ describe "on Linux" do
+ %i[
+ WNOHANG
+ WUNTRACED
+ PRIO_PROCESS
+ PRIO_PGRP
+ PRIO_USER
+ RLIMIT_CPU
+ RLIMIT_FSIZE
+ RLIMIT_DATA
+ RLIMIT_STACK
+ RLIMIT_CORE
+ RLIMIT_RSS
+ RLIMIT_NPROC
+ RLIMIT_NOFILE
+ RLIMIT_MEMLOCK
+ RLIMIT_AS
+ RLIM_INFINITY
+ RLIM_SAVED_MAX
+ RLIM_SAVED_CUR
+ ].each do |const|
+ it "defines #{const}" do
+ Process.const_defined?(const).should == true
+ Process.const_get(const).should.instance_of?(Integer)
+ end
+ end
end
end
platform_is :netbsd, :freebsd do
- it "Process::RLIMIT_SBSIZE" do
- Process::RLIMIT_SBSIZE.should == 9 # FIXME: what's it equal?
- Process::RLIMIT_AS.should == 10
+ describe "on NetBSD and FreeBSD" do
+ %i[
+ RLIMIT_SBSIZE
+ RLIMIT_AS
+ ].each do |const|
+ it "defines #{const}" do
+ Process.const_defined?(const).should == true
+ Process.const_get(const).should.instance_of?(Integer)
+ end
+ end
+ end
+ end
+
+ platform_is :freebsd do
+ describe "on FreeBSD" do
+ %i[
+ RLIMIT_NPTS
+ ].each do |const|
+ it "defines #{const}" do
+ Process.const_defined?(const).should == true
+ Process.const_get(const).should.instance_of?(Integer)
+ end
+ end
end
end
platform_is :windows do
- it "does not define RLIMIT constants" do
+ describe "on Windows" do
%i[
RLIMIT_CPU
RLIMIT_FSIZE
@@ -78,7 +117,9 @@ describe "Process::Constants" do
RLIM_SAVED_MAX
RLIM_SAVED_CUR
].each do |const|
- Process.const_defined?(const).should be_false
+ it "does not define #{const}" do
+ Process.const_defined?(const).should == false
+ end
end
end
end
diff --git a/spec/ruby/core/process/daemon_spec.rb b/spec/ruby/core/process/daemon_spec.rb
index 70ffd1b320..9b7eba1411 100644
--- a/spec/ruby/core/process/daemon_spec.rb
+++ b/spec/ruby/core/process/daemon_spec.rb
@@ -2,6 +2,9 @@ require_relative '../../spec_helper'
require_relative 'fixtures/common'
platform_is_not :windows do
+ # macOS 15 is not working this examples
+ return if /darwin/ =~ RUBY_PLATFORM && /15/ =~ `sw_vers -productVersion`
+
describe :process_daemon_keep_stdio_open_false, shared: true do
it "redirects stdout to /dev/null" do
@daemon.invoke("keep_stdio_open_false_stdout", @object).should == ""
@@ -109,7 +112,7 @@ platform_is :windows do
it "raises a NotImplementedError" do
-> {
Process.daemon
- }.should raise_error(NotImplementedError)
+ }.should.raise(NotImplementedError)
end
end
end
diff --git a/spec/ruby/core/process/detach_spec.rb b/spec/ruby/core/process/detach_spec.rb
index 1c27ed9c2c..33c674394e 100644
--- a/spec/ruby/core/process/detach_spec.rb
+++ b/spec/ruby/core/process/detach_spec.rb
@@ -5,7 +5,7 @@ describe "Process.detach" do
it "returns a thread" do
pid = Process.fork { Process.exit! }
thr = Process.detach(pid)
- thr.should be_kind_of(Thread)
+ thr.should.is_a?(Thread)
thr.join
end
@@ -15,7 +15,7 @@ describe "Process.detach" do
thr.join
status = thr.value
- status.should be_kind_of(Process::Status)
+ status.should.is_a?(Process::Status)
status.pid.should == pid
end
@@ -23,7 +23,7 @@ describe "Process.detach" do
it "reaps the child process's status automatically" do
pid = Process.fork { Process.exit! }
Process.detach(pid).join
- -> { Process.waitpid(pid) }.should raise_error(Errno::ECHILD)
+ -> { Process.waitpid(pid) }.should.raise(Errno::ECHILD)
end
end
@@ -42,5 +42,40 @@ describe "Process.detach" do
thr.pid.should == pid
end
+
+ it "tolerates not existing child process pid" do
+ # Use a value that is close to the INT_MAX (pid usually is signed int).
+ # It should (at least) be greater than allowed pid limit value that depends on OS.
+ pid_not_existing = 2.pow(30)
+
+ # Check that there is no a child process with this hardcoded pid.
+ # Command `kill 0 pid`:
+ # - returns "1" if a process exists and
+ # - raises Errno::ESRCH otherwise
+ -> { Process.kill(0, pid_not_existing) }.should.raise(Errno::ESRCH)
+
+ thr = Process.detach(pid_not_existing)
+ thr.join
+
+ thr.should.is_a?(Thread)
+ end
+
+ it "calls #to_int to implicitly convert non-Integer pid to Integer" do
+ pid = MockObject.new('mock-enumerable')
+ pid.should_receive(:to_int).and_return(100500)
+
+ Process.detach(pid).join
+ end
+
+ it "raises TypeError when pid argument does not have #to_int method" do
+ -> { Process.detach(Object.new) }.should.raise(TypeError, "no implicit conversion of Object into Integer")
+ end
+
+ it "raises TypeError when #to_int returns non-Integer value" do
+ pid = MockObject.new('mock-enumerable')
+ pid.should_receive(:to_int).and_return(:symbol)
+
+ -> { Process.detach(pid) }.should raise_consistent_error(TypeError, "can't convert MockObject into Integer (MockObject#to_int gives Symbol)")
+ end
end
end
diff --git a/spec/ruby/core/process/egid_spec.rb b/spec/ruby/core/process/egid_spec.rb
index a67b623d5c..69c86bebe2 100644
--- a/spec/ruby/core/process/egid_spec.rb
+++ b/spec/ruby/core/process/egid_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Process.egid" do
it "returns the effective group ID for this process" do
- Process.egid.should be_kind_of(Integer)
+ Process.egid.should.is_a?(Integer)
end
it "also goes by Process::GID.eid" do
@@ -18,7 +18,7 @@ describe "Process.egid=" do
platform_is_not :windows do
it "raises TypeError if not passed an Integer or String" do
- -> { Process.egid = Object.new }.should raise_error(TypeError)
+ -> { Process.egid = Object.new }.should.raise(TypeError)
end
it "sets the effective group id to its own gid if given the username corresponding to its own gid" do
@@ -33,12 +33,12 @@ describe "Process.egid=" do
as_user do
it "raises Errno::ERPERM if run by a non superuser trying to set the root group id" do
- -> { Process.egid = 0 }.should raise_error(Errno::EPERM)
+ -> { Process.egid = 0 }.should.raise(Errno::EPERM)
end
platform_is :linux do
it "raises Errno::ERPERM if run by a non superuser trying to set the group id from group name" do
- -> { Process.egid = "root" }.should raise_error(Errno::EPERM)
+ -> { Process.egid = "root" }.should.raise(Errno::EPERM)
end
end
end
diff --git a/spec/ruby/core/process/euid_spec.rb b/spec/ruby/core/process/euid_spec.rb
index c1ec4171d0..da76f06e59 100644
--- a/spec/ruby/core/process/euid_spec.rb
+++ b/spec/ruby/core/process/euid_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Process.euid" do
it "returns the effective user ID for this process" do
- Process.euid.should be_kind_of(Integer)
+ Process.euid.should.is_a?(Integer)
end
it "also goes by Process::UID.eid" do
@@ -18,7 +18,7 @@ describe "Process.euid=" do
platform_is_not :windows do
it "raises TypeError if not passed an Integer" do
- -> { Process.euid = Object.new }.should raise_error(TypeError)
+ -> { Process.euid = Object.new }.should.raise(TypeError)
end
it "sets the effective user id to its own uid if given the username corresponding to its own uid" do
@@ -33,11 +33,11 @@ describe "Process.euid=" do
as_user do
it "raises Errno::ERPERM if run by a non superuser trying to set the superuser id" do
- -> { Process.euid = 0 }.should raise_error(Errno::EPERM)
+ -> { Process.euid = 0 }.should.raise(Errno::EPERM)
end
it "raises Errno::ERPERM if run by a non superuser trying to set the superuser id from username" do
- -> { Process.euid = "root" }.should raise_error(Errno::EPERM)
+ -> { Process.euid = "root" }.should.raise(Errno::EPERM)
end
end
diff --git a/spec/ruby/core/process/exec_spec.rb b/spec/ruby/core/process/exec_spec.rb
index deb8913b6b..a48d461b02 100644
--- a/spec/ruby/core/process/exec_spec.rb
+++ b/spec/ruby/core/process/exec_spec.rb
@@ -2,48 +2,48 @@ require_relative '../../spec_helper'
describe "Process.exec" do
it "raises Errno::ENOENT for an empty string" do
- -> { Process.exec "" }.should raise_error(Errno::ENOENT)
+ -> { Process.exec "" }.should.raise(Errno::ENOENT)
end
it "raises Errno::ENOENT for a command which does not exist" do
- -> { Process.exec "bogus-noent-script.sh" }.should raise_error(Errno::ENOENT)
+ -> { Process.exec "bogus-noent-script.sh" }.should.raise(Errno::ENOENT)
end
it "raises an ArgumentError if the command includes a null byte" do
- -> { Process.exec "\000" }.should raise_error(ArgumentError)
+ -> { Process.exec "\000" }.should.raise(ArgumentError)
end
unless File.executable?(__FILE__) # Some FS (e.g. vboxfs) locate all files executable
platform_is_not :windows do
it "raises Errno::EACCES when the file does not have execute permissions" do
- -> { Process.exec __FILE__ }.should raise_error(Errno::EACCES)
+ -> { Process.exec __FILE__ }.should.raise(Errno::EACCES)
end
end
platform_is :windows do
it "raises Errno::EACCES or Errno::ENOEXEC when the file is not an executable file" do
- -> { Process.exec __FILE__ }.should raise_error(SystemCallError) { |e|
- [Errno::EACCES, Errno::ENOEXEC].should include(e.class)
+ -> { Process.exec __FILE__ }.should.raise(SystemCallError) { |e|
+ [Errno::EACCES, Errno::ENOEXEC].should.include?(e.class)
}
end
end
end
it "raises Errno::EACCES when passed a directory" do
- -> { Process.exec File.dirname(__FILE__) }.should raise_error(Errno::EACCES)
+ -> { Process.exec __dir__ }.should.raise(Errno::EACCES)
end
it "runs the specified command, replacing current process" do
- ruby_exe('Process.exec "echo hello"; puts "fail"', escape: true).should == "hello\n"
+ ruby_exe('Process.exec "echo hello"; puts "fail"').should == "hello\n"
end
it "sets the current directory when given the :chdir option" do
tmpdir = tmp("")[0..-2]
platform_is_not :windows do
- ruby_exe("Process.exec(\"pwd\", chdir: #{tmpdir.inspect})", escape: true).should == "#{tmpdir}\n"
+ ruby_exe("Process.exec(\"pwd\", chdir: #{tmpdir.inspect})").should == "#{tmpdir}\n"
end
platform_is :windows do
- ruby_exe("Process.exec(\"cd\", chdir: #{tmpdir.inspect})", escape: true).tr('\\', '/').should == "#{tmpdir}\n"
+ ruby_exe("Process.exec(\"cd\", chdir: #{tmpdir.inspect})").tr('\\', '/').should == "#{tmpdir}\n"
end
end
@@ -73,13 +73,13 @@ describe "Process.exec" do
platform_is_not :windows do
it "subjects the specified command to shell expansion" do
result = Dir.chdir(@dir) do
- ruby_exe('Process.exec "echo *"', escape: true)
+ ruby_exe('Process.exec "echo *"')
end
result.chomp.should == @name
end
it "creates an argument array with shell parsing semantics for whitespace" do
- ruby_exe('Process.exec "echo a b c d"', escape: true).should == "a b c d\n"
+ ruby_exe('Process.exec "echo a b c d"').should == "a b c d\n"
end
end
@@ -87,13 +87,13 @@ describe "Process.exec" do
# There is no shell expansion on Windows
it "does not subject the specified command to shell expansion on Windows" do
result = Dir.chdir(@dir) do
- ruby_exe('Process.exec "echo *"', escape: true)
+ ruby_exe('Process.exec "echo *"')
end
result.should == "*\n"
end
it "does not create an argument array with shell parsing semantics for whitespace on Windows" do
- ruby_exe('Process.exec "echo a b c d"', escape: true).should == "a b c d\n"
+ ruby_exe('Process.exec "echo a b c d"').should == "a b c d\n"
end
end
@@ -105,7 +105,7 @@ describe "Process.exec" do
platform_is :windows do
cmd = '"cmd.exe", "/C", "echo", "*"'
end
- ruby_exe("Process.exec #{cmd}", escape: true).should == "*\n"
+ ruby_exe("Process.exec #{cmd}").should == "*\n"
end
end
@@ -124,29 +124,29 @@ describe "Process.exec" do
end
it "sets environment variables in the child environment" do
- ruby_exe('Process.exec({"FOO" => "BAR"}, "echo ' + var + '")', escape: true).should == "BAR\n"
+ ruby_exe('Process.exec({"FOO" => "BAR"}, "echo ' + var + '")').should == "BAR\n"
end
it "unsets environment variables whose value is nil" do
platform_is_not :windows do
- ruby_exe('Process.exec({"FOO" => nil}, "echo ' + var + '")', escape: true).should == "\n"
+ ruby_exe('Process.exec({"FOO" => nil}, "echo ' + var + '")').should == "\n"
end
platform_is :windows do
# On Windows, echo-ing a non-existent env var is treated as echo-ing any other string of text
- ruby_exe('Process.exec({"FOO" => nil}, "echo ' + var + '")', escape: true).should == var + "\n"
+ ruby_exe('Process.exec({"FOO" => nil}, "echo ' + var + '")').should == var + "\n"
end
end
it "coerces environment argument using to_hash" do
- ruby_exe('o = Object.new; def o.to_hash; {"FOO" => "BAR"}; end; Process.exec(o, "echo ' + var + '")', escape: true).should == "BAR\n"
+ ruby_exe('o = Object.new; def o.to_hash; {"FOO" => "BAR"}; end; Process.exec(o, "echo ' + var + '")').should == "BAR\n"
end
it "unsets other environment variables when given a true :unsetenv_others option" do
platform_is_not :windows do
- ruby_exe('Process.exec("echo ' + var + '", unsetenv_others: true)', escape: true).should == "\n"
+ ruby_exe('Process.exec("echo ' + var + '", unsetenv_others: true)').should == "\n"
end
platform_is :windows do
- ruby_exe('Process.exec("' + ENV['COMSPEC'].gsub('\\', '\\\\\\') + ' /C echo ' + var + '", unsetenv_others: true)', escape: true).should == var + "\n"
+ ruby_exe('Process.exec("' + ENV['COMSPEC'].gsub('\\', '\\\\\\') + ' /C echo ' + var + '", unsetenv_others: true)').should == var + "\n"
end
end
end
@@ -154,26 +154,26 @@ describe "Process.exec" do
describe "with a command array" do
it "uses the first element as the command name and the second as the argv[0] value" do
platform_is_not :windows do
- ruby_exe('Process.exec(["/bin/sh", "argv_zero"], "-c", "echo $0")', escape: true).should == "argv_zero\n"
+ ruby_exe('Process.exec(["/bin/sh", "argv_zero"], "-c", "echo $0")').should == "argv_zero\n"
end
platform_is :windows do
- ruby_exe('Process.exec(["cmd.exe", "/C"], "/C", "echo", "argv_zero")', escape: true).should == "argv_zero\n"
+ ruby_exe('Process.exec(["cmd.exe", "/C"], "/C", "echo", "argv_zero")').should == "argv_zero\n"
end
end
it "coerces the argument using to_ary" do
platform_is_not :windows do
- ruby_exe('o = Object.new; def o.to_ary; ["/bin/sh", "argv_zero"]; end; Process.exec(o, "-c", "echo $0")', escape: true).should == "argv_zero\n"
+ ruby_exe('o = Object.new; def o.to_ary; ["/bin/sh", "argv_zero"]; end; Process.exec(o, "-c", "echo $0")').should == "argv_zero\n"
end
platform_is :windows do
- ruby_exe('o = Object.new; def o.to_ary; ["cmd.exe", "/C"]; end; Process.exec(o, "/C", "echo", "argv_zero")', escape: true).should == "argv_zero\n"
+ ruby_exe('o = Object.new; def o.to_ary; ["cmd.exe", "/C"]; end; Process.exec(o, "/C", "echo", "argv_zero")').should == "argv_zero\n"
end
end
it "raises an ArgumentError if the Array does not have exactly two elements" do
- -> { Process.exec([]) }.should raise_error(ArgumentError)
- -> { Process.exec([:a]) }.should raise_error(ArgumentError)
- -> { Process.exec([:a, :b, :c]) }.should raise_error(ArgumentError)
+ -> { Process.exec([]) }.should.raise(ArgumentError)
+ -> { Process.exec([:a]) }.should.raise(ArgumentError)
+ -> { Process.exec([:a, :b, :c]) }.should.raise(ArgumentError)
end
end
@@ -200,7 +200,7 @@ describe "Process.exec" do
end
EOC
- ruby_exe(cmd, escape: true)
+ ruby_exe(cmd)
child_fd = IO.read(@child_fd_file).to_i
child_fd.to_i.should > STDERR.fileno
@@ -216,7 +216,7 @@ describe "Process.exec" do
Process.exec("#{ruby_cmd(map_fd_fixture)} \#{f.fileno}", f.fileno => f.fileno)
EOC
- output = ruby_exe(cmd, escape: true)
+ output = ruby_exe(cmd)
child_fd, close_on_exec = output.split
child_fd.to_i.should > STDERR.fileno
@@ -232,7 +232,7 @@ describe "Process.exec" do
puts(f.close_on_exec?)
EOC
- output = ruby_exe(cmd, escape: true)
+ output = ruby_exe(cmd)
output.split.should == ['true', 'false']
end
end
diff --git a/spec/ruby/core/process/exit_spec.rb b/spec/ruby/core/process/exit_spec.rb
index 70d79d789d..4f7dc94407 100644
--- a/spec/ruby/core/process/exit_spec.rb
+++ b/spec/ruby/core/process/exit_spec.rb
@@ -6,5 +6,5 @@ describe "Process.exit" do
end
describe "Process.exit!" do
- it_behaves_like :process_exit!, :exit!, Process
+ it_behaves_like :process_exit!, :exit!, "Process"
end
diff --git a/spec/ruby/core/process/fixtures/argv0.rb b/spec/ruby/core/process/fixtures/argv0.rb
new file mode 100644
index 0000000000..847a3e903e
--- /dev/null
+++ b/spec/ruby/core/process/fixtures/argv0.rb
@@ -0,0 +1,6 @@
+puts Process.argv0
+puts __FILE__
+
+if Process.argv0 == __FILE__
+ print "OK"
+end
diff --git a/spec/ruby/core/process/fixtures/clocks.rb b/spec/ruby/core/process/fixtures/clocks.rb
index f043f6ac1f..5757e280be 100644
--- a/spec/ruby/core/process/fixtures/clocks.rb
+++ b/spec/ruby/core/process/fixtures/clocks.rb
@@ -2,7 +2,7 @@ module ProcessSpecs
def self.clock_constants
clocks = []
- platform_is_not :windows, :solaris do
+ platform_is_not :windows do
clocks += Process.constants.select { |c| c.to_s.start_with?('CLOCK_') }
# These require CAP_WAKE_ALARM and are not documented in
diff --git a/spec/ruby/core/process/fixtures/kill.rb b/spec/ruby/core/process/fixtures/kill.rb
index 0b88f8ee1f..b922a043f1 100644
--- a/spec/ruby/core/process/fixtures/kill.rb
+++ b/spec/ruby/core/process/fixtures/kill.rb
@@ -1,5 +1,3 @@
-require 'thread'
-
pid_file = ARGV.shift
scenario = ARGV.shift
diff --git a/spec/ruby/core/process/getpriority_spec.rb b/spec/ruby/core/process/getpriority_spec.rb
index a35e5956a5..53fe7bfe20 100644
--- a/spec/ruby/core/process/getpriority_spec.rb
+++ b/spec/ruby/core/process/getpriority_spec.rb
@@ -5,19 +5,19 @@ describe "Process.getpriority" do
it "coerces arguments to Integers" do
ret = Process.getpriority mock_int(Process::PRIO_PROCESS), mock_int(0)
- ret.should be_kind_of(Integer)
+ ret.should.is_a?(Integer)
end
it "gets the scheduling priority for a specified process" do
- Process.getpriority(Process::PRIO_PROCESS, 0).should be_kind_of(Integer)
+ Process.getpriority(Process::PRIO_PROCESS, 0).should.is_a?(Integer)
end
it "gets the scheduling priority for a specified process group" do
- Process.getpriority(Process::PRIO_PGRP, 0).should be_kind_of(Integer)
+ Process.getpriority(Process::PRIO_PGRP, 0).should.is_a?(Integer)
end
it "gets the scheduling priority for a specified user" do
- Process.getpriority(Process::PRIO_USER, 0).should be_kind_of(Integer)
+ Process.getpriority(Process::PRIO_USER, 0).should.is_a?(Integer)
end
end
end
diff --git a/spec/ruby/core/process/getrlimit_spec.rb b/spec/ruby/core/process/getrlimit_spec.rb
index 883b8fac48..d36d8c3335 100644
--- a/spec/ruby/core/process/getrlimit_spec.rb
+++ b/spec/ruby/core/process/getrlimit_spec.rb
@@ -16,8 +16,8 @@ describe "Process.getrlimit" do
it "returns a two-element Array of Integers" do
result = Process.getrlimit Process::RLIMIT_CORE
result.size.should == 2
- result.first.should be_kind_of(Integer)
- result.last.should be_kind_of(Integer)
+ result.first.should.is_a?(Integer)
+ result.last.should.is_a?(Integer)
end
context "when passed an Object" do
@@ -36,7 +36,7 @@ describe "Process.getrlimit" do
obj = mock("process getrlimit integer")
obj.should_receive(:to_int).and_return(nil)
- -> { Process.getrlimit(obj) }.should raise_error(TypeError)
+ -> { Process.getrlimit(obj) }.should.raise(TypeError)
end
end
@@ -49,7 +49,7 @@ describe "Process.getrlimit" do
end
it "raises ArgumentError when passed an unknown resource" do
- -> { Process.getrlimit(:FOO) }.should raise_error(ArgumentError)
+ -> { Process.getrlimit(:FOO) }.should.raise(ArgumentError)
end
end
@@ -62,7 +62,7 @@ describe "Process.getrlimit" do
end
it "raises ArgumentError when passed an unknown resource" do
- -> { Process.getrlimit("FOO") }.should raise_error(ArgumentError)
+ -> { Process.getrlimit("FOO") }.should.raise(ArgumentError)
end
end
@@ -91,10 +91,10 @@ describe "Process.getrlimit" do
platform_is :windows do
it "is not implemented" do
- Process.respond_to?(:getrlimit).should be_false
+ Process.respond_to?(:getrlimit).should == false
-> do
Process.getrlimit(nil)
- end.should raise_error NotImplementedError
+ end.should.raise NotImplementedError
end
end
end
diff --git a/spec/ruby/core/process/gid_spec.rb b/spec/ruby/core/process/gid_spec.rb
index 07221da420..ca935ed520 100644
--- a/spec/ruby/core/process/gid_spec.rb
+++ b/spec/ruby/core/process/gid_spec.rb
@@ -3,8 +3,8 @@ require_relative '../../spec_helper'
describe "Process.gid" do
platform_is_not :windows do
it "returns the correct gid for the user executing this process" do
- current_gid_according_to_unix = `id -gr`.to_i
- Process.gid.should == current_gid_according_to_unix
+ current_gid_according_to_unix = `id -gr`.to_i
+ Process.gid.should == current_gid_according_to_unix
end
end
diff --git a/spec/ruby/core/process/groups_spec.rb b/spec/ruby/core/process/groups_spec.rb
index 33e0f9d7b3..fa916671a4 100644
--- a/spec/ruby/core/process/groups_spec.rb
+++ b/spec/ruby/core/process/groups_spec.rb
@@ -50,7 +50,7 @@ describe "Process.groups=" do
Process.groups.should == [ Process.gid ]
supplementary = groups - [ Process.gid ]
if supplementary.length > 0
- -> { Process.groups = supplementary }.should raise_error(Errno::EPERM)
+ -> { Process.groups = supplementary }.should.raise(Errno::EPERM)
end
end
end
@@ -59,7 +59,7 @@ describe "Process.groups=" do
it "raises Errno::EPERM" do
-> {
Process.groups = [0]
- }.should raise_error(Errno::EPERM)
+ }.should.raise(Errno::EPERM)
end
end
end
diff --git a/spec/ruby/core/process/initgroups_spec.rb b/spec/ruby/core/process/initgroups_spec.rb
index ffc7f282b6..d9f31936cb 100644
--- a/spec/ruby/core/process/initgroups_spec.rb
+++ b/spec/ruby/core/process/initgroups_spec.rb
@@ -14,7 +14,7 @@ describe "Process.initgroups" do
Process.groups.sort.should == augmented_groups.sort
Process.groups = groups
else
- -> { Process.initgroups(name, gid) }.should raise_error(Errno::EPERM)
+ -> { Process.initgroups(name, gid) }.should.raise(Errno::EPERM)
end
end
end
diff --git a/spec/ruby/core/process/kill_spec.rb b/spec/ruby/core/process/kill_spec.rb
index af9c9e6deb..885c2bf2b7 100644
--- a/spec/ruby/core/process/kill_spec.rb
+++ b/spec/ruby/core/process/kill_spec.rb
@@ -9,18 +9,18 @@ describe "Process.kill" do
end
it "raises an ArgumentError for unknown signals" do
- -> { Process.kill("FOO", @pid) }.should raise_error(ArgumentError)
+ -> { Process.kill("FOO", @pid) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if passed a lowercase signal name" do
- -> { Process.kill("term", @pid) }.should raise_error(ArgumentError)
+ -> { Process.kill("term", @pid) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if signal is not an Integer or String" do
signal = mock("process kill signal")
signal.should_not_receive(:to_int)
- -> { Process.kill(signal, @pid) }.should raise_error(ArgumentError)
+ -> { Process.kill(signal, @pid) }.should.raise(ArgumentError)
end
it "raises Errno::ESRCH if the process does not exist" do
@@ -29,7 +29,7 @@ describe "Process.kill" do
Process.wait(pid)
-> {
Process.kill("SIGKILL", pid)
- }.should raise_error(Errno::ESRCH)
+ }.should.raise(Errno::ESRCH)
end
it "checks for existence and permissions to signal a process, but does not actually signal it, when using signal 0" do
diff --git a/spec/ruby/core/process/last_status_spec.rb b/spec/ruby/core/process/last_status_spec.rb
index 2372f2aae3..1bd8adf798 100644
--- a/spec/ruby/core/process/last_status_spec.rb
+++ b/spec/ruby/core/process/last_status_spec.rb
@@ -13,6 +13,6 @@ describe 'Process#last_status' do
end
it 'raises an ArgumentError if any arguments are provided' do
- -> { Process.last_status(1) }.should raise_error(ArgumentError)
+ -> { Process.last_status(1) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/process/maxgroups_spec.rb b/spec/ruby/core/process/maxgroups_spec.rb
index 2549a7a971..895b384bd0 100644
--- a/spec/ruby/core/process/maxgroups_spec.rb
+++ b/spec/ruby/core/process/maxgroups_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
platform_is_not :windows do
describe "Process.maxgroups" do
it "returns the maximum number of gids allowed in the supplemental group access list" do
- Process.maxgroups.should be_kind_of(Integer)
+ Process.maxgroups.should.is_a?(Integer)
end
it "sets the maximum number of gids allowed in the supplemental group access list" do
diff --git a/spec/ruby/core/process/pid_spec.rb b/spec/ruby/core/process/pid_spec.rb
index 2d008bc4b7..42b0b918b9 100644
--- a/spec/ruby/core/process/pid_spec.rb
+++ b/spec/ruby/core/process/pid_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Process.pid" do
it "returns the process id of this process" do
pid = Process.pid
- pid.should be_kind_of(Integer)
+ pid.should.is_a?(Integer)
Process.pid.should == pid
end
end
diff --git a/spec/ruby/core/process/set_proctitle_spec.rb b/spec/ruby/core/process/set_proctitle_spec.rb
index d022f2021c..28a0fa6cee 100644
--- a/spec/ruby/core/process/set_proctitle_spec.rb
+++ b/spec/ruby/core/process/set_proctitle_spec.rb
@@ -17,7 +17,7 @@ describe 'Process.setproctitle' do
title = 'rubyspec-proctitle-test'
Process.setproctitle(title).should == title
- `ps -ocommand= -p#{$$}`.should include(title)
+ `ps -ocommand= -p#{$$}`.should.include?(title)
end
end
end
diff --git a/spec/ruby/core/process/setrlimit_spec.rb b/spec/ruby/core/process/setrlimit_spec.rb
index b92f98fd40..f02ab46fca 100644
--- a/spec/ruby/core/process/setrlimit_spec.rb
+++ b/spec/ruby/core/process/setrlimit_spec.rb
@@ -9,200 +9,196 @@ describe "Process.setrlimit" do
end
it "calls #to_int to convert resource to an Integer" do
- Process.setrlimit(mock_int(@resource), @limit, @max).should be_nil
+ Process.setrlimit(mock_int(@resource), @limit, @max).should == nil
end
it "raises a TypeError if #to_int for resource does not return an Integer" do
obj = mock("process getrlimit integer")
obj.should_receive(:to_int).and_return(nil)
- -> { Process.setrlimit(obj, @limit, @max) }.should raise_error(TypeError)
+ -> { Process.setrlimit(obj, @limit, @max) }.should.raise(TypeError)
end
it "calls #to_int to convert the soft limit to an Integer" do
- Process.setrlimit(@resource, mock_int(@limit), @max).should be_nil
+ Process.setrlimit(@resource, mock_int(@limit), @max).should == nil
end
it "raises a TypeError if #to_int for resource does not return an Integer" do
obj = mock("process getrlimit integer")
obj.should_receive(:to_int).and_return(nil)
- -> { Process.setrlimit(@resource, obj, @max) }.should raise_error(TypeError)
+ -> { Process.setrlimit(@resource, obj, @max) }.should.raise(TypeError)
end
it "calls #to_int to convert the hard limit to an Integer" do
- Process.setrlimit(@resource, @limit, mock_int(@max)).should be_nil
+ Process.setrlimit(@resource, @limit, mock_int(@max)).should == nil
end
it "raises a TypeError if #to_int for resource does not return an Integer" do
obj = mock("process getrlimit integer")
obj.should_receive(:to_int).and_return(nil)
- -> { Process.setrlimit(@resource, @limit, obj) }.should raise_error(TypeError)
+ -> { Process.setrlimit(@resource, @limit, obj) }.should.raise(TypeError)
end
end
context "when passed a Symbol" do
platform_is_not :openbsd do
it "coerces :AS into RLIMIT_AS" do
- Process.setrlimit(:AS, *Process.getrlimit(Process::RLIMIT_AS)).should be_nil
+ Process.setrlimit(:AS, *Process.getrlimit(Process::RLIMIT_AS)).should == nil
end
end
it "coerces :CORE into RLIMIT_CORE" do
- Process.setrlimit(:CORE, *Process.getrlimit(Process::RLIMIT_CORE)).should be_nil
+ Process.setrlimit(:CORE, *Process.getrlimit(Process::RLIMIT_CORE)).should == nil
end
it "coerces :CPU into RLIMIT_CPU" do
- Process.setrlimit(:CPU, *Process.getrlimit(Process::RLIMIT_CPU)).should be_nil
+ Process.setrlimit(:CPU, *Process.getrlimit(Process::RLIMIT_CPU)).should == nil
end
it "coerces :DATA into RLIMIT_DATA" do
- Process.setrlimit(:DATA, *Process.getrlimit(Process::RLIMIT_DATA)).should be_nil
+ Process.setrlimit(:DATA, *Process.getrlimit(Process::RLIMIT_DATA)).should == nil
end
it "coerces :FSIZE into RLIMIT_FSIZE" do
- Process.setrlimit(:FSIZE, *Process.getrlimit(Process::RLIMIT_FSIZE)).should be_nil
+ Process.setrlimit(:FSIZE, *Process.getrlimit(Process::RLIMIT_FSIZE)).should == nil
end
it "coerces :NOFILE into RLIMIT_NOFILE" do
- Process.setrlimit(:NOFILE, *Process.getrlimit(Process::RLIMIT_NOFILE)).should be_nil
+ Process.setrlimit(:NOFILE, *Process.getrlimit(Process::RLIMIT_NOFILE)).should == nil
end
it "coerces :STACK into RLIMIT_STACK" do
- Process.setrlimit(:STACK, *Process.getrlimit(Process::RLIMIT_STACK)).should be_nil
+ Process.setrlimit(:STACK, *Process.getrlimit(Process::RLIMIT_STACK)).should == nil
end
- platform_is_not :solaris, :aix do
+ platform_is_not :aix do
it "coerces :MEMLOCK into RLIMIT_MEMLOCK" do
- Process.setrlimit(:MEMLOCK, *Process.getrlimit(Process::RLIMIT_MEMLOCK)).should be_nil
+ Process.setrlimit(:MEMLOCK, *Process.getrlimit(Process::RLIMIT_MEMLOCK)).should == nil
end
end
- platform_is_not :solaris do
- it "coerces :NPROC into RLIMIT_NPROC" do
- Process.setrlimit(:NPROC, *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
- end
+ it "coerces :NPROC into RLIMIT_NPROC" do
+ Process.setrlimit(:NPROC, *Process.getrlimit(Process::RLIMIT_NPROC)).should == nil
+ end
- it "coerces :RSS into RLIMIT_RSS" do
- Process.setrlimit(:RSS, *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
- end
+ it "coerces :RSS into RLIMIT_RSS" do
+ Process.setrlimit(:RSS, *Process.getrlimit(Process::RLIMIT_RSS)).should == nil
end
platform_is :netbsd, :freebsd do
it "coerces :SBSIZE into RLIMIT_SBSIZE" do
- Process.setrlimit(:SBSIZE, *Process.getrlimit(Process::RLIMIT_SBSIZE)).should be_nil
+ Process.setrlimit(:SBSIZE, *Process.getrlimit(Process::RLIMIT_SBSIZE)).should == nil
end
end
platform_is :linux do
it "coerces :RTPRIO into RLIMIT_RTPRIO" do
- Process.setrlimit(:RTPRIO, *Process.getrlimit(Process::RLIMIT_RTPRIO)).should be_nil
+ Process.setrlimit(:RTPRIO, *Process.getrlimit(Process::RLIMIT_RTPRIO)).should == nil
end
guard -> { defined?(Process::RLIMIT_RTTIME) } do
it "coerces :RTTIME into RLIMIT_RTTIME" do
- Process.setrlimit(:RTTIME, *Process.getrlimit(Process::RLIMIT_RTTIME)).should be_nil
+ Process.setrlimit(:RTTIME, *Process.getrlimit(Process::RLIMIT_RTTIME)).should == nil
end
end
it "coerces :SIGPENDING into RLIMIT_SIGPENDING" do
- Process.setrlimit(:SIGPENDING, *Process.getrlimit(Process::RLIMIT_SIGPENDING)).should be_nil
+ Process.setrlimit(:SIGPENDING, *Process.getrlimit(Process::RLIMIT_SIGPENDING)).should == nil
end
it "coerces :MSGQUEUE into RLIMIT_MSGQUEUE" do
- Process.setrlimit(:MSGQUEUE, *Process.getrlimit(Process::RLIMIT_MSGQUEUE)).should be_nil
+ Process.setrlimit(:MSGQUEUE, *Process.getrlimit(Process::RLIMIT_MSGQUEUE)).should == nil
end
it "coerces :NICE into RLIMIT_NICE" do
- Process.setrlimit(:NICE, *Process.getrlimit(Process::RLIMIT_NICE)).should be_nil
+ Process.setrlimit(:NICE, *Process.getrlimit(Process::RLIMIT_NICE)).should == nil
end
end
it "raises ArgumentError when passed an unknown resource" do
- -> { Process.setrlimit(:FOO, 1, 1) }.should raise_error(ArgumentError)
+ -> { Process.setrlimit(:FOO, 1, 1) }.should.raise(ArgumentError)
end
end
context "when passed a String" do
platform_is_not :openbsd do
it "coerces 'AS' into RLIMIT_AS" do
- Process.setrlimit("AS", *Process.getrlimit(Process::RLIMIT_AS)).should be_nil
+ Process.setrlimit("AS", *Process.getrlimit(Process::RLIMIT_AS)).should == nil
end
end
it "coerces 'CORE' into RLIMIT_CORE" do
- Process.setrlimit("CORE", *Process.getrlimit(Process::RLIMIT_CORE)).should be_nil
+ Process.setrlimit("CORE", *Process.getrlimit(Process::RLIMIT_CORE)).should == nil
end
it "coerces 'CPU' into RLIMIT_CPU" do
- Process.setrlimit("CPU", *Process.getrlimit(Process::RLIMIT_CPU)).should be_nil
+ Process.setrlimit("CPU", *Process.getrlimit(Process::RLIMIT_CPU)).should == nil
end
it "coerces 'DATA' into RLIMIT_DATA" do
- Process.setrlimit("DATA", *Process.getrlimit(Process::RLIMIT_DATA)).should be_nil
+ Process.setrlimit("DATA", *Process.getrlimit(Process::RLIMIT_DATA)).should == nil
end
it "coerces 'FSIZE' into RLIMIT_FSIZE" do
- Process.setrlimit("FSIZE", *Process.getrlimit(Process::RLIMIT_FSIZE)).should be_nil
+ Process.setrlimit("FSIZE", *Process.getrlimit(Process::RLIMIT_FSIZE)).should == nil
end
it "coerces 'NOFILE' into RLIMIT_NOFILE" do
- Process.setrlimit("NOFILE", *Process.getrlimit(Process::RLIMIT_NOFILE)).should be_nil
+ Process.setrlimit("NOFILE", *Process.getrlimit(Process::RLIMIT_NOFILE)).should == nil
end
it "coerces 'STACK' into RLIMIT_STACK" do
- Process.setrlimit("STACK", *Process.getrlimit(Process::RLIMIT_STACK)).should be_nil
+ Process.setrlimit("STACK", *Process.getrlimit(Process::RLIMIT_STACK)).should == nil
end
- platform_is_not :solaris, :aix do
+ platform_is_not :aix do
it "coerces 'MEMLOCK' into RLIMIT_MEMLOCK" do
- Process.setrlimit("MEMLOCK", *Process.getrlimit(Process::RLIMIT_MEMLOCK)).should be_nil
+ Process.setrlimit("MEMLOCK", *Process.getrlimit(Process::RLIMIT_MEMLOCK)).should == nil
end
end
- platform_is_not :solaris do
- it "coerces 'NPROC' into RLIMIT_NPROC" do
- Process.setrlimit("NPROC", *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
- end
+ it "coerces 'NPROC' into RLIMIT_NPROC" do
+ Process.setrlimit("NPROC", *Process.getrlimit(Process::RLIMIT_NPROC)).should == nil
+ end
- it "coerces 'RSS' into RLIMIT_RSS" do
- Process.setrlimit("RSS", *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
- end
+ it "coerces 'RSS' into RLIMIT_RSS" do
+ Process.setrlimit("RSS", *Process.getrlimit(Process::RLIMIT_RSS)).should == nil
end
platform_is :netbsd, :freebsd do
it "coerces 'SBSIZE' into RLIMIT_SBSIZE" do
- Process.setrlimit("SBSIZE", *Process.getrlimit(Process::RLIMIT_SBSIZE)).should be_nil
+ Process.setrlimit("SBSIZE", *Process.getrlimit(Process::RLIMIT_SBSIZE)).should == nil
end
end
platform_is :linux do
it "coerces 'RTPRIO' into RLIMIT_RTPRIO" do
- Process.setrlimit("RTPRIO", *Process.getrlimit(Process::RLIMIT_RTPRIO)).should be_nil
+ Process.setrlimit("RTPRIO", *Process.getrlimit(Process::RLIMIT_RTPRIO)).should == nil
end
guard -> { defined?(Process::RLIMIT_RTTIME) } do
it "coerces 'RTTIME' into RLIMIT_RTTIME" do
- Process.setrlimit("RTTIME", *Process.getrlimit(Process::RLIMIT_RTTIME)).should be_nil
+ Process.setrlimit("RTTIME", *Process.getrlimit(Process::RLIMIT_RTTIME)).should == nil
end
end
it "coerces 'SIGPENDING' into RLIMIT_SIGPENDING" do
- Process.setrlimit("SIGPENDING", *Process.getrlimit(Process::RLIMIT_SIGPENDING)).should be_nil
+ Process.setrlimit("SIGPENDING", *Process.getrlimit(Process::RLIMIT_SIGPENDING)).should == nil
end
it "coerces 'MSGQUEUE' into RLIMIT_MSGQUEUE" do
- Process.setrlimit("MSGQUEUE", *Process.getrlimit(Process::RLIMIT_MSGQUEUE)).should be_nil
+ Process.setrlimit("MSGQUEUE", *Process.getrlimit(Process::RLIMIT_MSGQUEUE)).should == nil
end
it "coerces 'NICE' into RLIMIT_NICE" do
- Process.setrlimit("NICE", *Process.getrlimit(Process::RLIMIT_NICE)).should be_nil
+ Process.setrlimit("NICE", *Process.getrlimit(Process::RLIMIT_NICE)).should == nil
end
end
it "raises ArgumentError when passed an unknown resource" do
- -> { Process.setrlimit("FOO", 1, 1) }.should raise_error(ArgumentError)
+ -> { Process.setrlimit("FOO", 1, 1) }.should.raise(ArgumentError)
end
end
@@ -217,7 +213,7 @@ describe "Process.setrlimit" do
obj.should_receive(:to_str).and_return("CORE")
obj.should_not_receive(:to_int)
- Process.setrlimit(obj, @limit, @max).should be_nil
+ Process.setrlimit(obj, @limit, @max).should == nil
end
it "calls #to_int if #to_str does not return a String" do
@@ -225,17 +221,17 @@ describe "Process.setrlimit" do
obj.should_receive(:to_str).and_return(nil)
obj.should_receive(:to_int).and_return(@resource)
- Process.setrlimit(obj, @limit, @max).should be_nil
+ Process.setrlimit(obj, @limit, @max).should == nil
end
end
end
platform_is :windows do
it "is not implemented" do
- Process.respond_to?(:setrlimit).should be_false
+ Process.respond_to?(:setrlimit).should == false
-> do
Process.setrlimit(nil, nil)
- end.should raise_error NotImplementedError
+ end.should.raise NotImplementedError
end
end
end
diff --git a/spec/ruby/core/process/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb
index 9aa8da8125..fb619dce42 100644
--- a/spec/ruby/core/process/spawn_spec.rb
+++ b/spec/ruby/core/process/spawn_spec.rb
@@ -51,7 +51,7 @@ describe "Process.spawn" do
it "returns the process ID of the new process as an Integer" do
pid = Process.spawn(*ruby_exe, "-e", "exit")
Process.wait pid
- pid.should be_an_instance_of(Integer)
+ pid.should.instance_of?(Integer)
end
it "returns immediately" do
@@ -93,11 +93,11 @@ describe "Process.spawn" do
end
it "raises an ArgumentError if the command includes a null byte" do
- -> { Process.spawn "\000" }.should raise_error(ArgumentError)
+ -> { Process.spawn "\000" }.should.raise(ArgumentError)
end
it "raises a TypeError if the argument does not respond to #to_str" do
- -> { Process.spawn :echo }.should raise_error(TypeError)
+ -> { Process.spawn :echo }.should.raise(TypeError)
end
end
@@ -122,11 +122,11 @@ describe "Process.spawn" do
end
it "raises an ArgumentError if an argument includes a null byte" do
- -> { Process.spawn "echo", "\000" }.should raise_error(ArgumentError)
+ -> { Process.spawn "echo", "\000" }.should.raise(ArgumentError)
end
it "raises a TypeError if an argument does not respond to #to_str" do
- -> { Process.spawn "echo", :foo }.should raise_error(TypeError)
+ -> { Process.spawn "echo", :foo }.should.raise(TypeError)
end
end
@@ -178,19 +178,19 @@ describe "Process.spawn" do
end
it "raises an ArgumentError if the Array does not have exactly two elements" do
- -> { Process.spawn([]) }.should raise_error(ArgumentError)
- -> { Process.spawn([:a]) }.should raise_error(ArgumentError)
- -> { Process.spawn([:a, :b, :c]) }.should raise_error(ArgumentError)
+ -> { Process.spawn([]) }.should.raise(ArgumentError)
+ -> { Process.spawn([:a]) }.should.raise(ArgumentError)
+ -> { Process.spawn([:a, :b, :c]) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the Strings in the Array include a null byte" do
- -> { Process.spawn ["\000", "echo"] }.should raise_error(ArgumentError)
- -> { Process.spawn ["echo", "\000"] }.should raise_error(ArgumentError)
+ -> { Process.spawn ["\000", "echo"] }.should.raise(ArgumentError)
+ -> { Process.spawn ["echo", "\000"] }.should.raise(ArgumentError)
end
it "raises a TypeError if an element in the Array does not respond to #to_str" do
- -> { Process.spawn ["echo", :echo] }.should raise_error(TypeError)
- -> { Process.spawn [:echo, "echo"] }.should raise_error(TypeError)
+ -> { Process.spawn ["echo", :echo] }.should.raise(TypeError)
+ -> { Process.spawn [:echo, "echo"] }.should.raise(TypeError)
end
end
@@ -256,19 +256,19 @@ describe "Process.spawn" do
it "raises an ArgumentError if an environment key includes an equals sign" do
-> do
Process.spawn({"FOO=" => "BAR"}, "echo #{@var}>#{@name}")
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "raises an ArgumentError if an environment key includes a null byte" do
-> do
Process.spawn({"\000" => "BAR"}, "echo #{@var}>#{@name}")
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "raises an ArgumentError if an environment value includes a null byte" do
-> do
Process.spawn({"FOO" => "\000"}, "echo #{@var}>#{@name}")
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
# :unsetenv_others
@@ -285,7 +285,7 @@ describe "Process.spawn" do
it "unsets other environment variables when given a true :unsetenv_others option" do
ENV["FOO"] = "BAR"
Process.wait Process.spawn(*@common_env_spawn_args, unsetenv_others: true)
- $?.success?.should be_true
+ $?.success?.should == true
File.read(@name).should == "\n"
end
end
@@ -293,7 +293,7 @@ describe "Process.spawn" do
it "does not unset other environment variables when given a false :unsetenv_others option" do
ENV["FOO"] = "BAR"
Process.wait Process.spawn(*@common_env_spawn_args, unsetenv_others: false)
- $?.success?.should be_true
+ $?.success?.should == true
File.read(@name).should == "BAR\n"
end
@@ -301,7 +301,7 @@ describe "Process.spawn" do
it "does not unset environment variables included in the environment hash" do
env = @minimal_env.merge({"FOO" => "BAR"})
Process.wait Process.spawn(env, "echo #{@var}>#{@name}", unsetenv_others: true)
- $?.success?.should be_true
+ $?.success?.should == true
File.read(@name).should == "BAR\n"
end
end
@@ -363,17 +363,17 @@ describe "Process.spawn" do
end
it "raises an ArgumentError if given a negative :pgroup option" do
- -> { Process.spawn("echo", pgroup: -1) }.should raise_error(ArgumentError)
+ -> { Process.spawn("echo", pgroup: -1) }.should.raise(ArgumentError)
end
it "raises a TypeError if given a symbol as :pgroup option" do
- -> { Process.spawn("echo", pgroup: :true) }.should raise_error(TypeError)
+ -> { Process.spawn("echo", pgroup: :true) }.should.raise(TypeError)
end
end
platform_is :windows do
it "raises an ArgumentError if given :pgroup option" do
- -> { Process.spawn("echo", pgroup: false) }.should raise_error(ArgumentError)
+ -> { Process.spawn("echo", pgroup: false) }.should.raise(ArgumentError)
end
end
@@ -452,7 +452,7 @@ describe "Process.spawn" do
children.each do |child|
-> do
Process.kill("TERM", child)
- end.should raise_error(Errno::ESRCH)
+ end.should.raise(Errno::ESRCH)
end
end
end
@@ -477,6 +477,16 @@ describe "Process.spawn" do
# redirection
+ it 'redirects to the wrapped IO using wrapped_io.to_io if out: wrapped_io' do
+ File.open(@name, 'w') do |file|
+ -> do
+ wrapped_io = mock('wrapped IO')
+ wrapped_io.should_receive(:to_io).and_return(file)
+ Process.wait Process.spawn('echo Hello World', out: wrapped_io)
+ end.should output_to_fd("Hello World\n", file)
+ end
+ end
+
it "redirects STDOUT to the given file descriptor if out: Integer" do
File.open(@name, 'w') do |file|
-> do
@@ -567,6 +577,24 @@ describe "Process.spawn" do
end
end
+ platform_is_not :windows do
+ it "redirects non-default file descriptor to itself" do
+ File.open(@name, 'w') do |file|
+ -> do
+ Process.wait Process.spawn(
+ ruby_cmd("f = IO.new(#{file.fileno}, 'w'); f.print(:bang); f.flush"), file.fileno => file.fileno)
+ end.should output_to_fd("bang", file)
+ end
+ end
+ end
+
+ it "redirects default file descriptor to itself" do
+ -> do
+ Process.wait Process.spawn(
+ ruby_cmd("f = IO.new(#{STDOUT.fileno}, 'w'); f.print(:bang); f.flush"), STDOUT.fileno => STDOUT.fileno)
+ end.should output_to_fd("bang", STDOUT)
+ end
+
# :close_others
platform_is_not :windows do
@@ -650,53 +678,93 @@ describe "Process.spawn" do
# error handling
it "raises an ArgumentError if passed no command arguments" do
- -> { Process.spawn }.should raise_error(ArgumentError)
+ -> { Process.spawn }.should.raise(ArgumentError)
end
it "raises an ArgumentError if passed env or options but no command arguments" do
- -> { Process.spawn({}) }.should raise_error(ArgumentError)
+ -> { Process.spawn({}) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if passed env and options but no command arguments" do
- -> { Process.spawn({}, {}) }.should raise_error(ArgumentError)
+ -> { Process.spawn({}, {}) }.should.raise(ArgumentError)
end
it "raises an Errno::ENOENT for an empty string" do
- -> { Process.spawn "" }.should raise_error(Errno::ENOENT)
+ -> { Process.spawn "" }.should.raise(Errno::ENOENT)
end
it "raises an Errno::ENOENT if the command does not exist" do
- -> { Process.spawn "nonesuch" }.should raise_error(Errno::ENOENT)
+ -> { Process.spawn "nonesuch" }.should.raise(Errno::ENOENT, "No such file or directory - nonesuch")
+ end
+
+ it "sets $? to exit status 127 when the command does not exist" do
+ Process.spawn("nonesuch") rescue nil
+ $?.exitstatus.should == 127
+ end
+
+ it "raises an Errno::ENOENT if the file does not exist" do
+ -> { Process.spawn "./nonesuch" }.should.raise(Errno::ENOENT, "No such file or directory - ./nonesuch")
+ end
+
+ it "sets $? to exit status 127 when the file does not exist" do
+ Process.spawn("./nonesuch") rescue nil
+ $?.exitstatus.should == 127
+ end
+
+ platform_is_not :windows do
+ it "raises an Errno::EACCES when the path is a directory" do
+ -> { Process.spawn "./" }.should.raise(Errno::EACCES, "Permission denied - ./")
+ end
end
unless File.executable?(__FILE__) # Some FS (e.g. vboxfs) locate all files executable
platform_is_not :windows do
it "raises an Errno::EACCES when the file does not have execute permissions" do
- -> { Process.spawn __FILE__ }.should raise_error(Errno::EACCES)
+ -> { Process.spawn __FILE__ }.should.raise(Errno::EACCES, "Permission denied - #{__FILE__}")
+ end
+
+ it "sets $? to exit status 127 when the file does not have execute permissions" do
+ Process.spawn(__FILE__) rescue nil
+ $?.exitstatus.should == 127
+ end
+
+ it "raises an Errno::ENOENT when a non-executable file is found in PATH" do
+ dir = tmp("spawn_path_non_executable_dir")
+ mkdir_p dir
+ begin
+ exe = 'process-spawn-non-executable-in-path'
+ File.write("#{dir}/#{exe}", "#!/bin/sh\necho hi")
+ File.chmod(0644, "#{dir}/#{exe}")
+ env = { "PATH" => "#{dir}#{File::PATH_SEPARATOR}#{ENV['PATH']}" }
+ -> { Process.spawn(env, exe) }.should.raise(Errno::ENOENT, "No such file or directory - #{exe}")
+ $?.exitstatus.should == 127
+ ensure
+ rm_r dir
+ end
end
end
platform_is :windows do
it "raises Errno::EACCES or Errno::ENOEXEC when the file is not an executable file" do
- -> { Process.spawn __FILE__ }.should raise_error(SystemCallError) { |e|
- [Errno::EACCES, Errno::ENOEXEC].should include(e.class)
+ -> { Process.spawn __FILE__ }.should.raise(SystemCallError) { |e|
+ [Errno::EACCES, Errno::ENOEXEC].should.include?(e.class)
}
end
end
end
it "raises an Errno::EACCES or Errno::EISDIR when passed a directory" do
- -> { Process.spawn File.dirname(__FILE__) }.should raise_error(SystemCallError) { |e|
- [Errno::EACCES, Errno::EISDIR].should include(e.class)
+ -> { Process.spawn __dir__ }.should.raise(SystemCallError) { |e|
+ [Errno::EACCES, Errno::EISDIR].should.include?(e.class)
}
end
it "raises an ArgumentError when passed a string key in options" do
- -> { Process.spawn("echo", "chdir" => Dir.pwd) }.should raise_error(ArgumentError)
+ -> { Process.spawn("echo", "chdir" => Dir.pwd) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when passed an unknown option key" do
- -> { Process.spawn("echo", nonesuch: :foo) }.should raise_error(ArgumentError)
+ -> { Process.spawn("echo", nonesuch: :foo) }.should.raise(ArgumentError)
end
platform_is_not :windows, :aix do
diff --git a/spec/ruby/core/process/status/bit_and_spec.rb b/spec/ruby/core/process/status/bit_and_spec.rb
index 97f768fdc1..a5b1123e90 100644
--- a/spec/ruby/core/process/status/bit_and_spec.rb
+++ b/spec/ruby/core/process/status/bit_and_spec.rb
@@ -1,5 +1,38 @@
require_relative '../../../spec_helper'
-describe "Process::Status#&" do
- it "needs to be reviewed for spec completeness"
+ruby_version_is ""..."4.0" do
+
+ describe "Process::Status#&" do
+ it "returns a bitwise and of the integer status of an exited child" do
+ suppress_warning do
+ ruby_exe("exit(29)", exit_status: 29)
+ ($? & 0).should == 0
+ ($? & $?.to_i).should == $?.to_i
+
+ # Actual value is implementation specific
+ platform_is :linux do
+ # 29 == 0b11101
+ ($? & 0b1011100000000).should == 0b1010100000000
+ end
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "raises an ArgumentError if mask is negative" do
+ suppress_warning do
+ ruby_exe("exit(0)")
+ -> {
+ $? & -1
+ }.should.raise(ArgumentError, 'negative mask value: -1')
+ end
+ end
+
+ it "shows a deprecation warning" do
+ ruby_exe("exit(0)")
+ -> {
+ $? & 0
+ }.should complain(/warning: Process::Status#& is deprecated and will be removed .*use other Process::Status predicates instead/)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/process/status/exited_spec.rb b/spec/ruby/core/process/status/exited_spec.rb
index a61292b146..ad14b35000 100644
--- a/spec/ruby/core/process/status/exited_spec.rb
+++ b/spec/ruby/core/process/status/exited_spec.rb
@@ -7,7 +7,7 @@ describe "Process::Status#exited?" do
end
it "returns true" do
- $?.exited?.should be_true
+ $?.exited?.should == true
end
end
@@ -19,13 +19,13 @@ describe "Process::Status#exited?" do
platform_is_not :windows do
it "returns false" do
- $?.exited?.should be_false
+ $?.exited?.should == false
end
end
platform_is :windows do
it "always returns true" do
- $?.exited?.should be_true
+ $?.exited?.should == true
end
end
end
diff --git a/spec/ruby/core/process/status/right_shift_spec.rb b/spec/ruby/core/process/status/right_shift_spec.rb
index e9dda437e8..5689526f54 100644
--- a/spec/ruby/core/process/status/right_shift_spec.rb
+++ b/spec/ruby/core/process/status/right_shift_spec.rb
@@ -1,5 +1,37 @@
require_relative '../../../spec_helper'
-describe "Process::Status#>>" do
- it "needs to be reviewed for spec completeness"
+ruby_version_is ""..."4.0" do
+
+ describe "Process::Status#>>" do
+ it "returns a right shift of the integer status of an exited child" do
+ suppress_warning do
+ ruby_exe("exit(29)", exit_status: 29)
+ ($? >> 0).should == $?.to_i
+ ($? >> 1).should == $?.to_i >> 1
+
+ # Actual value is implementation specific
+ platform_is :linux do
+ ($? >> 8).should == 29
+ end
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "raises an ArgumentError if shift value is negative" do
+ suppress_warning do
+ ruby_exe("exit(0)")
+ -> {
+ $? >> -1
+ }.should.raise(ArgumentError, 'negative shift value: -1')
+ end
+ end
+
+ it "shows a deprecation warning" do
+ ruby_exe("exit(0)")
+ -> {
+ $? >> 0
+ }.should complain(/warning: Process::Status#>> is deprecated and will be removed .*use other Process::Status attributes instead/)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/process/status/signaled_spec.rb b/spec/ruby/core/process/status/signaled_spec.rb
index c0de7b8006..8cf409bb42 100644
--- a/spec/ruby/core/process/status/signaled_spec.rb
+++ b/spec/ruby/core/process/status/signaled_spec.rb
@@ -7,7 +7,7 @@ describe "Process::Status#signaled?" do
end
it "returns false" do
- $?.signaled?.should be_false
+ $?.signaled?.should == false
end
end
@@ -18,13 +18,13 @@ describe "Process::Status#signaled?" do
platform_is_not :windows do
it "returns true" do
- $?.signaled?.should be_true
+ $?.signaled?.should == true
end
end
platform_is :windows do
it "always returns false" do
- $?.signaled?.should be_false
+ $?.signaled?.should == false
end
end
end
diff --git a/spec/ruby/core/process/status/success_spec.rb b/spec/ruby/core/process/status/success_spec.rb
index 3589cc611f..f61243c667 100644
--- a/spec/ruby/core/process/status/success_spec.rb
+++ b/spec/ruby/core/process/status/success_spec.rb
@@ -7,7 +7,7 @@ describe "Process::Status#success?" do
end
it "returns true" do
- $?.success?.should be_true
+ $?.success?.should == true
end
end
@@ -17,7 +17,7 @@ describe "Process::Status#success?" do
end
it "returns false" do
- $?.success?.should be_false
+ $?.success?.should == false
end
end
@@ -28,13 +28,13 @@ describe "Process::Status#success?" do
platform_is_not :windows do
it "returns nil" do
- $?.success?.should be_nil
+ $?.success?.should == nil
end
end
platform_is :windows do
it "always returns true" do
- $?.success?.should be_true
+ $?.success?.should == true
end
end
end
diff --git a/spec/ruby/core/process/status/termsig_spec.rb b/spec/ruby/core/process/status/termsig_spec.rb
index 5d286950f8..1d57724d12 100644
--- a/spec/ruby/core/process/status/termsig_spec.rb
+++ b/spec/ruby/core/process/status/termsig_spec.rb
@@ -6,8 +6,8 @@ describe "Process::Status#termsig" do
ruby_exe("exit(0)")
end
- it "returns true" do
- $?.termsig.should be_nil
+ it "returns nil" do
+ $?.termsig.should == nil
end
end
@@ -36,7 +36,7 @@ describe "Process::Status#termsig" do
platform_is :windows do
it "always returns nil" do
- $?.termsig.should be_nil
+ $?.termsig.should == nil
end
end
end
diff --git a/spec/ruby/core/process/status/to_i_spec.rb b/spec/ruby/core/process/status/to_i_spec.rb
index 39f8e2d84c..0bfb883d23 100644
--- a/spec/ruby/core/process/status/to_i_spec.rb
+++ b/spec/ruby/core/process/status/to_i_spec.rb
@@ -3,11 +3,11 @@ require_relative '../../../spec_helper'
describe "Process::Status#to_i" do
it "returns an integer when the child exits" do
ruby_exe('exit 48', exit_status: 48)
- $?.to_i.should be_an_instance_of(Integer)
+ $?.to_i.should.instance_of?(Integer)
end
it "returns an integer when the child is signaled" do
ruby_exe('raise SignalException, "TERM"', exit_status: platform_is(:windows) ? 3 : :SIGTERM)
- $?.to_i.should be_an_instance_of(Integer)
+ $?.to_i.should.instance_of?(Integer)
end
end
diff --git a/spec/ruby/core/process/status/wait_spec.rb b/spec/ruby/core/process/status/wait_spec.rb
index b9d80e31f4..18ecc14f6f 100644
--- a/spec/ruby/core/process/status/wait_spec.rb
+++ b/spec/ruby/core/process/status/wait_spec.rb
@@ -1,102 +1,100 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/common'
-ruby_version_is "3.0" do
- describe "Process::Status.wait" do
- ProcessSpecs.use_system_ruby(self)
-
- before :all do
- begin
- leaked = Process.waitall
- # Ruby-space should not see PIDs used by mjit
- raise "subprocesses leaked before wait specs: #{leaked}" unless leaked.empty?
- rescue NotImplementedError
- end
+describe "Process::Status.wait" do
+ ProcessSpecs.use_system_ruby(self)
+
+ before :all do
+ begin
+ leaked = Process.waitall
+ # Ruby-space should not see PIDs used by rjit
+ raise "subprocesses leaked before wait specs: #{leaked}" unless leaked.empty?
+ rescue NotImplementedError
end
+ end
+
+ it "returns a status with pid -1 if there are no child processes" do
+ Process::Status.wait.pid.should == -1
+ end
- it "returns a status with pid -1 if there are no child processes" do
- Process::Status.wait.pid.should == -1
+ platform_is_not :windows do
+ it "returns a status with its child pid" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ status = Process::Status.wait
+ status.should.instance_of?(Process::Status)
+ status.pid.should == pid
end
- platform_is_not :windows do
- it "returns a status with its child pid" do
- pid = Process.spawn(ruby_cmd('exit'))
- status = Process::Status.wait
- status.should be_an_instance_of(Process::Status)
- status.pid.should == pid
- end
+ it "should not set $? to the Process::Status" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ status = Process::Status.wait
+ $?.should_not.equal?(status)
+ end
- it "should not set $? to the Process::Status" do
- pid = Process.spawn(ruby_cmd('exit'))
- status = Process::Status.wait
- $?.should_not equal(status)
- end
+ it "should not change the value of $?" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ Process.wait
+ status = $?
+ Process::Status.wait
+ status.should.equal?($?)
+ end
- it "should not change the value of $?" do
- pid = Process.spawn(ruby_cmd('exit'))
- Process.wait
- status = $?
- Process::Status.wait
- status.should equal($?)
- end
+ it "waits for any child process if no pid is given" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ Process::Status.wait.pid.should == pid
+ -> { Process.kill(0, pid) }.should.raise(Errno::ESRCH)
+ end
- it "waits for any child process if no pid is given" do
- pid = Process.spawn(ruby_cmd('exit'))
- Process::Status.wait.pid.should == pid
- -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
- end
+ it "waits for a specific child if a pid is given" do
+ pid1 = Process.spawn(ruby_cmd('exit'))
+ pid2 = Process.spawn(ruby_cmd('exit'))
+ Process::Status.wait(pid2).pid.should == pid2
+ Process::Status.wait(pid1).pid.should == pid1
+ -> { Process.kill(0, pid1) }.should.raise(Errno::ESRCH)
+ -> { Process.kill(0, pid2) }.should.raise(Errno::ESRCH)
+ end
- it "waits for a specific child if a pid is given" do
- pid1 = Process.spawn(ruby_cmd('exit'))
- pid2 = Process.spawn(ruby_cmd('exit'))
- Process::Status.wait(pid2).pid.should == pid2
- Process::Status.wait(pid1).pid.should == pid1
- -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
- -> { Process.kill(0, pid2) }.should raise_error(Errno::ESRCH)
- end
+ it "coerces the pid to an Integer" do
+ pid1 = Process.spawn(ruby_cmd('exit'))
+ Process::Status.wait(mock_int(pid1)).pid.should == pid1
+ -> { Process.kill(0, pid1) }.should.raise(Errno::ESRCH)
+ end
- it "coerces the pid to an Integer" do
- pid1 = Process.spawn(ruby_cmd('exit'))
- Process::Status.wait(mock_int(pid1)).pid.should == pid1
- -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
- end
+ # This spec is probably system-dependent.
+ it "waits for a child whose process group ID is that of the calling process" do
+ pid1 = Process.spawn(ruby_cmd('exit'), pgroup: true)
+ pid2 = Process.spawn(ruby_cmd('exit'))
- # This spec is probably system-dependent.
- it "waits for a child whose process group ID is that of the calling process" do
- pid1 = Process.spawn(ruby_cmd('exit'), pgroup: true)
- pid2 = Process.spawn(ruby_cmd('exit'))
+ Process::Status.wait(0).pid.should == pid2
+ Process::Status.wait.pid.should == pid1
+ end
- Process::Status.wait(0).pid.should == pid2
- Process::Status.wait.pid.should == pid1
+ # This spec is probably system-dependent.
+ it "doesn't block if no child is available when WNOHANG is used" do
+ read, write = IO.pipe
+ pid = Process.fork do
+ read.close
+ Signal.trap("TERM") { Process.exit! }
+ write << 1
+ write.close
+ sleep
end
- # This spec is probably system-dependent.
- it "doesn't block if no child is available when WNOHANG is used" do
- read, write = IO.pipe
- pid = Process.fork do
- read.close
- Signal.trap("TERM") { Process.exit! }
- write << 1
- write.close
- sleep
- end
+ Process::Status.wait(pid, Process::WNOHANG).should == nil
- Process::Status.wait(pid, Process::WNOHANG).should be_nil
+ # wait for the child to setup its TERM handler
+ write.close
+ read.read(1)
+ read.close
- # wait for the child to setup its TERM handler
- write.close
- read.read(1)
- read.close
-
- Process.kill("TERM", pid)
- Process::Status.wait.pid.should == pid
- end
+ Process.kill("TERM", pid)
+ Process::Status.wait.pid.should == pid
+ end
- it "always accepts flags=0" do
- pid = Process.spawn(ruby_cmd('exit'))
- Process::Status.wait(-1, 0).pid.should == pid
- -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
- end
+ it "always accepts flags=0" do
+ pid = Process.spawn(ruby_cmd('exit'))
+ Process::Status.wait(-1, 0).pid.should == pid
+ -> { Process.kill(0, pid) }.should.raise(Errno::ESRCH)
end
end
end
diff --git a/spec/ruby/core/process/times_spec.rb b/spec/ruby/core/process/times_spec.rb
index b47189a7e7..a7ffbb79e5 100644
--- a/spec/ruby/core/process/times_spec.rb
+++ b/spec/ruby/core/process/times_spec.rb
@@ -2,34 +2,18 @@ require_relative '../../spec_helper'
describe "Process.times" do
it "returns a Process::Tms" do
- Process.times.should be_kind_of(Process::Tms)
+ Process.times.should.is_a?(Process::Tms)
end
- it "returns current cpu times" do
- t = Process.times
- user = t.utime
+ # TODO: Intel C Compiler does not work this example
+ # http://rubyci.s3.amazonaws.com/icc-x64/ruby-master/log/20221013T030005Z.fail.html.gz
+ unless RbConfig::CONFIG['CC']&.include?("icx")
+ it "returns current cpu times" do
+ t = Process.times
+ user = t.utime
- 1 until Process.times.utime > user
- Process.times.utime.should > user
- end
-
- platform_is_not :windows do
- it "uses getrusage when available to improve precision beyond milliseconds" do
- max = 10_000
- has_getrusage = max.times.find do
- time = Process.clock_gettime(:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
- ('%.6f' % time).end_with?('000')
- end
- unless has_getrusage
- skip "getrusage is not supported on this environment"
- end
-
- found = (max * 100).times.find do
- time = Process.times.utime
- ('%.6f' % time).end_with?('000')
- end
-
- found.should_not == nil
+ 1 until Process.times.utime > user
+ Process.times.utime.should > user
end
end
end
diff --git a/spec/ruby/core/process/tms/cstime_spec.rb b/spec/ruby/core/process/tms/cstime_spec.rb
new file mode 100644
index 0000000000..9c2d9e8632
--- /dev/null
+++ b/spec/ruby/core/process/tms/cstime_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../../spec_helper'
+
+describe "Process::Tms#cstime" do
+ it "returns cstime attribute" do
+ cstime = Object.new
+ Process::Tms.new(nil, nil, nil, cstime).cstime.should == cstime
+ end
+end
+
+describe "Process::Tms#cstime=" do
+ it "assigns a value to the cstime attribute" do
+ cstime = Object.new
+ tms = Process::Tms.new
+ tms.cstime = cstime
+ tms.cstime.should == cstime
+ end
+end
diff --git a/spec/ruby/core/process/tms/cutime_spec.rb b/spec/ruby/core/process/tms/cutime_spec.rb
new file mode 100644
index 0000000000..0ac3ff1964
--- /dev/null
+++ b/spec/ruby/core/process/tms/cutime_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../../spec_helper'
+
+describe "Process::Tms#cutime" do
+ it "returns cutime attribute" do
+ cutime = Object.new
+ Process::Tms.new(nil, nil, cutime, nil).cutime.should == cutime
+ end
+end
+
+describe "Process::Tms#cutime=" do
+ it "assigns a value to the cutime attribute" do
+ cutime = Object.new
+ tms = Process::Tms.new
+ tms.cutime = cutime
+ tms.cutime.should == cutime
+ end
+end
diff --git a/spec/ruby/core/process/tms/stime_spec.rb b/spec/ruby/core/process/tms/stime_spec.rb
new file mode 100644
index 0000000000..1e8371475f
--- /dev/null
+++ b/spec/ruby/core/process/tms/stime_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../../spec_helper'
+
+describe "Process::Tms#stime" do
+ it "returns stime attribute" do
+ stime = Object.new
+ Process::Tms.new(nil, stime, nil, nil).stime.should == stime
+ end
+end
+
+describe "Process::Tms#stime=" do
+ it "assigns a value to the stime attribute" do
+ stime = Object.new
+ tms = Process::Tms.new
+ tms.stime = stime
+ tms.stime.should == stime
+ end
+end
diff --git a/spec/ruby/core/process/tms/utime_spec.rb b/spec/ruby/core/process/tms/utime_spec.rb
new file mode 100644
index 0000000000..403a31e2e6
--- /dev/null
+++ b/spec/ruby/core/process/tms/utime_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../../spec_helper'
+
+describe "Process::Tms#utime" do
+ it "returns utime attribute" do
+ utime = Object.new
+ Process::Tms.new(utime, nil, nil, nil).utime.should == utime
+ end
+end
+
+describe "Process::Tms#utime=" do
+ it "assigns a value to the ctime attribute" do
+ utime = Object.new
+ tms = Process::Tms.new
+ tms.utime = utime
+ tms.utime.should == utime
+ end
+end
diff --git a/spec/ruby/core/process/uid_spec.rb b/spec/ruby/core/process/uid_spec.rb
index a068b1a2c1..1e218ef4fe 100644
--- a/spec/ruby/core/process/uid_spec.rb
+++ b/spec/ruby/core/process/uid_spec.rb
@@ -20,16 +20,16 @@ end
describe "Process.uid=" do
platform_is_not :windows do
it "raises TypeError if not passed an Integer" do
- -> { Process.uid = Object.new }.should raise_error(TypeError)
+ -> { Process.uid = Object.new }.should.raise(TypeError)
end
as_user do
it "raises Errno::ERPERM if run by a non privileged user trying to set the superuser id" do
- -> { (Process.uid = 0)}.should raise_error(Errno::EPERM)
+ -> { (Process.uid = 0)}.should.raise(Errno::EPERM)
end
it "raises Errno::ERPERM if run by a non privileged user trying to set the superuser id from username" do
- -> { Process.uid = "root" }.should raise_error(Errno::EPERM)
+ -> { Process.uid = "root" }.should.raise(Errno::EPERM)
end
end
diff --git a/spec/ruby/core/process/wait2_spec.rb b/spec/ruby/core/process/wait2_spec.rb
index 673d3cdb9d..5c57dd40fb 100644
--- a/spec/ruby/core/process/wait2_spec.rb
+++ b/spec/ruby/core/process/wait2_spec.rb
@@ -4,15 +4,15 @@ describe "Process.wait2" do
before :all do
# HACK: this kludge is temporarily necessary because some
# misbehaving spec somewhere else does not clear processes
- # Note: background processes are unavoidable with MJIT,
+ # Note: background processes are unavoidable with RJIT,
# but we shouldn't reap them from Ruby-space
begin
Process.wait(-1, Process::WNOHANG)
$stderr.puts "Leaked process before wait2 specs! Waiting for it"
leaked = Process.waitall
$stderr.puts "leaked before wait2 specs: #{leaked}" unless leaked.empty?
- # Ruby-space should not see PIDs used by mjit
- leaked.should be_empty
+ # Ruby-space should not see PIDs used by rjit
+ leaked.should.empty?
rescue Errno::ECHILD # No child processes
rescue NotImplementedError
end
@@ -30,15 +30,15 @@ describe "Process.wait2" do
end
it "raises a StandardError if no child processes exist" do
- -> { Process.wait2 }.should raise_error(Errno::ECHILD)
- -> { Process.wait2 }.should raise_error(StandardError)
+ -> { Process.wait2 }.should.raise(Errno::ECHILD)
+ -> { Process.wait2 }.should.raise(StandardError)
end
it "returns nil if the child process is still running when given the WNOHANG flag" do
IO.popen(ruby_cmd('STDIN.getbyte'), "w") do |io|
pid, status = Process.wait2(io.pid, Process::WNOHANG)
- pid.should be_nil
- status.should be_nil
+ pid.should == nil
+ status.should == nil
io.write('a')
end
end
diff --git a/spec/ruby/core/process/wait_spec.rb b/spec/ruby/core/process/wait_spec.rb
index 44c95d6304..0b2e715f65 100644
--- a/spec/ruby/core/process/wait_spec.rb
+++ b/spec/ruby/core/process/wait_spec.rb
@@ -7,14 +7,14 @@ describe "Process.wait" do
before :all do
begin
leaked = Process.waitall
- # Ruby-space should not see PIDs used by mjit
+ # Ruby-space should not see PIDs used by rjit
raise "subprocesses leaked before wait specs: #{leaked}" unless leaked.empty?
rescue NotImplementedError
end
end
it "raises an Errno::ECHILD if there are no child processes" do
- -> { Process.wait }.should raise_error(Errno::ECHILD)
+ -> { Process.wait }.should.raise(Errno::ECHILD)
end
platform_is_not :windows do
@@ -26,14 +26,14 @@ describe "Process.wait" do
it "sets $? to a Process::Status" do
pid = Process.spawn(ruby_cmd('exit'))
Process.wait
- $?.should be_kind_of(Process::Status)
+ $?.should.is_a?(Process::Status)
$?.pid.should == pid
end
it "waits for any child process if no pid is given" do
pid = Process.spawn(ruby_cmd('exit'))
Process.wait.should == pid
- -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid) }.should.raise(Errno::ESRCH)
end
it "waits for a specific child if a pid is given" do
@@ -41,14 +41,14 @@ describe "Process.wait" do
pid2 = Process.spawn(ruby_cmd('exit'))
Process.wait(pid2).should == pid2
Process.wait(pid1).should == pid1
- -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
- -> { Process.kill(0, pid2) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid1) }.should.raise(Errno::ESRCH)
+ -> { Process.kill(0, pid2) }.should.raise(Errno::ESRCH)
end
it "coerces the pid to an Integer" do
pid1 = Process.spawn(ruby_cmd('exit'))
Process.wait(mock_int(pid1)).should == pid1
- -> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid1) }.should.raise(Errno::ESRCH)
end
# This spec is probably system-dependent.
@@ -71,7 +71,7 @@ describe "Process.wait" do
sleep
end
- Process.wait(pid, Process::WNOHANG).should be_nil
+ Process.wait(pid, Process::WNOHANG).should == nil
# wait for the child to setup its TERM handler
write.close
@@ -85,7 +85,7 @@ describe "Process.wait" do
it "always accepts flags=0" do
pid = Process.spawn(ruby_cmd('exit'))
Process.wait(-1, 0).should == pid
- -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid) }.should.raise(Errno::ESRCH)
end
end
end
diff --git a/spec/ruby/core/process/waitall_spec.rb b/spec/ruby/core/process/waitall_spec.rb
index 6cf4e32bc9..a77873f553 100644
--- a/spec/ruby/core/process/waitall_spec.rb
+++ b/spec/ruby/core/process/waitall_spec.rb
@@ -13,7 +13,7 @@ describe "Process.waitall" do
end
it "takes no arguments" do
- -> { Process.waitall(0) }.should raise_error(ArgumentError)
+ -> { Process.waitall(0) }.should.raise(ArgumentError)
end
platform_is_not :windows do
@@ -24,7 +24,7 @@ describe "Process.waitall" do
pids << Process.fork { Process.exit! 0 }
Process.waitall
pids.each { |pid|
- -> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
+ -> { Process.kill(0, pid) }.should.raise(Errno::ESRCH)
}
end
@@ -34,14 +34,14 @@ describe "Process.waitall" do
pids << Process.fork { Process.exit! 1 }
pids << Process.fork { Process.exit! 0 }
a = Process.waitall
- a.should be_kind_of(Array)
+ a.should.is_a?(Array)
a.size.should == 3
pids.each { |pid|
pid_status = a.assoc(pid)
- pid_status.should be_kind_of(Array)
+ pid_status.should.is_a?(Array)
pid_status.size.should == 2
pid_status.first.should == pid
- pid_status.last.should be_kind_of(Process::Status)
+ pid_status.last.should.is_a?(Process::Status)
}
end
end
diff --git a/spec/ruby/core/process/waitpid_spec.rb b/spec/ruby/core/process/waitpid_spec.rb
index f7cf1a45a8..a02147b663 100644
--- a/spec/ruby/core/process/waitpid_spec.rb
+++ b/spec/ruby/core/process/waitpid_spec.rb
@@ -2,7 +2,8 @@ require_relative '../../spec_helper'
describe "Process.waitpid" do
it "returns nil when the process has not yet completed and WNOHANG is specified" do
- pid = spawn("sleep 5")
+ cmd = platform_is(:windows) ? "timeout" : "sleep"
+ pid = spawn("#{cmd} 5")
begin
Process.waitpid(pid, Process::WNOHANG).should == nil
Process.kill("KILL", pid)
diff --git a/spec/ruby/core/process/warmup_spec.rb b/spec/ruby/core/process/warmup_spec.rb
new file mode 100644
index 0000000000..4530ae222c
--- /dev/null
+++ b/spec/ruby/core/process/warmup_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+
+describe "Process.warmup" do
+ # The behavior is entirely implementation specific.
+ # Other implementations are free to just make it a noop
+ it "is implemented" do
+ Process.warmup.should == true
+ end
+end
diff --git a/spec/ruby/core/queue/deq_spec.rb b/spec/ruby/core/queue/deq_spec.rb
index 9510978eac..a2784e6a63 100644
--- a/spec/ruby/core/queue/deq_spec.rb
+++ b/spec/ruby/core/queue/deq_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/deque'
+require_relative '../../shared/types/rb_num2dbl_fails'
describe "Queue#deq" do
it_behaves_like :queue_deq, :deq, -> { Queue.new }
end
+
+describe "Queue operations with timeout" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.deq(timeout: v) }
+end
diff --git a/spec/ruby/core/queue/freeze_spec.rb b/spec/ruby/core/queue/freeze_spec.rb
new file mode 100644
index 0000000000..ced2cc52dd
--- /dev/null
+++ b/spec/ruby/core/queue/freeze_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative '../../shared/queue/freeze'
+
+describe "Queue#freeze" do
+ it_behaves_like :queue_freeze, :freeze, -> { Queue.new }
+end
diff --git a/spec/ruby/core/queue/initialize_spec.rb b/spec/ruby/core/queue/initialize_spec.rb
index 83c7e595fe..080e4d0abd 100644
--- a/spec/ruby/core/queue/initialize_spec.rb
+++ b/spec/ruby/core/queue/initialize_spec.rb
@@ -7,17 +7,21 @@ describe "Queue#initialize" do
q.should.empty?
end
- ruby_version_is '3.1' do
- it "adds all elements of the passed Enumerable to self" do
- q = Queue.new([1, 2, 3])
- q.size.should == 3
- q.should_not.empty?
- q.pop.should == 1
- q.pop.should == 2
- q.pop.should == 3
- q.should.empty?
- end
+ it "is a private method" do
+ Queue.private_instance_methods.include?(:initialize).should == true
+ end
+
+ it "adds all elements of the passed Enumerable to self" do
+ q = Queue.new([1, 2, 3])
+ q.size.should == 3
+ q.should_not.empty?
+ q.pop.should == 1
+ q.pop.should == 2
+ q.pop.should == 3
+ q.should.empty?
+ end
+ describe "converts the given argument to an Array using #to_a" do
it "uses #to_a on the provided Enumerable" do
enumerable = MockObject.new('mock-enumerable')
enumerable.should_receive(:to_a).and_return([1, 2, 3])
@@ -30,9 +34,27 @@ describe "Queue#initialize" do
q.should.empty?
end
- it "raises if the provided Enumerable does not respond to #to_a" do
+ it "raises a TypeError if the given argument can't be converted to an Array" do
+ -> { Queue.new(42) }.should.raise(TypeError)
+ -> { Queue.new(:abc) }.should.raise(TypeError)
+ end
+
+ it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to an Array" do
enumerable = MockObject.new('mock-enumerable')
- -> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject into Array")
+ enumerable.should_receive(:to_a).and_raise(NoMethodError)
+ -> { Queue.new(enumerable) }.should.raise(NoMethodError)
end
end
+
+ it "raises TypeError if the provided Enumerable does not respond to #to_a" do
+ enumerable = MockObject.new('mock-enumerable')
+ -> { Queue.new(enumerable) }.should.raise(TypeError, "can't convert MockObject into Array")
+ end
+
+ it "raises TypeError if #to_a does not return Array" do
+ enumerable = MockObject.new('mock-enumerable')
+ enumerable.should_receive(:to_a).and_return("string")
+
+ -> { Queue.new(enumerable) }.should raise_consistent_error(TypeError, "can't convert MockObject into Array (MockObject#to_a gives String)")
+ end
end
diff --git a/spec/ruby/core/queue/pop_spec.rb b/spec/ruby/core/queue/pop_spec.rb
index 1ce9231685..3dff7db242 100644
--- a/spec/ruby/core/queue/pop_spec.rb
+++ b/spec/ruby/core/queue/pop_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/deque'
+require_relative '../../shared/types/rb_num2dbl_fails'
describe "Queue#pop" do
it_behaves_like :queue_deq, :pop, -> { Queue.new }
end
+
+describe "Queue operations with timeout" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.pop(timeout: v) }
+end
diff --git a/spec/ruby/core/queue/shift_spec.rb b/spec/ruby/core/queue/shift_spec.rb
index f84058e1df..c105da74b2 100644
--- a/spec/ruby/core/queue/shift_spec.rb
+++ b/spec/ruby/core/queue/shift_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/deque'
+require_relative '../../shared/types/rb_num2dbl_fails'
describe "Queue#shift" do
it_behaves_like :queue_deq, :shift, -> { Queue.new }
end
+
+describe "Queue operations with timeout" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.shift(timeout: v) }
+end
diff --git a/spec/ruby/core/random/bytes_spec.rb b/spec/ruby/core/random/bytes_spec.rb
index ed1b3a7b41..c9be07cd3f 100644
--- a/spec/ruby/core/random/bytes_spec.rb
+++ b/spec/ruby/core/random/bytes_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/bytes'
@@ -9,7 +9,6 @@ describe "Random#bytes" do
Random.new(33).bytes(2).should == Random.new(33).bytes(2)
end
- # Should double check this is official spec
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\\"
diff --git a/spec/ruby/core/random/default_spec.rb b/spec/ruby/core/random/default_spec.rb
index b4ffcb81f4..9e4845986d 100644
--- a/spec/ruby/core/random/default_spec.rb
+++ b/spec/ruby/core/random/default_spec.rb
@@ -1,45 +1,7 @@
require_relative '../../spec_helper'
describe "Random::DEFAULT" do
- ruby_version_is ''...'3.2' do
- it "returns a random number generator" do
- suppress_warning do
- Random::DEFAULT.should respond_to(:rand)
- end
- end
-
- it "changes seed on reboot" do
- seed1 = ruby_exe('p Random::DEFAULT.seed', options: '--disable-gems')
- seed2 = ruby_exe('p Random::DEFAULT.seed', options: '--disable-gems')
- seed1.should != seed2
- end
-
- ruby_version_is ''...'3.0' do
- it "returns a Random instance" do
- suppress_warning do
- Random::DEFAULT.should be_an_instance_of(Random)
- end
- end
- end
-
- ruby_version_is '3.0' do
- it "refers to the Random class" do
- suppress_warning do
- Random::DEFAULT.should.equal?(Random)
- end
- end
-
- it "is deprecated" do
- -> {
- Random::DEFAULT.should.equal?(Random)
- }.should complain(/constant Random::DEFAULT is deprecated/)
- end
- end
- end
-
- ruby_version_is '3.2' do
- it "is no longer defined" do
- Random.should_not.const_defined?(:DEFAULT)
- end
+ it "is no longer defined" do
+ Random.should_not.const_defined?(:DEFAULT)
end
end
diff --git a/spec/ruby/core/random/new_seed_spec.rb b/spec/ruby/core/random/new_seed_spec.rb
index 7a93da99aa..b2741aaa31 100644
--- a/spec/ruby/core/random/new_seed_spec.rb
+++ b/spec/ruby/core/random/new_seed_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Random.new_seed" do
it "returns an Integer" do
- Random.new_seed.should be_an_instance_of(Integer)
+ Random.new_seed.should.instance_of?(Integer)
end
it "returns an arbitrary seed value each time" do
diff --git a/spec/ruby/core/random/new_spec.rb b/spec/ruby/core/random/new_spec.rb
index 4280b5b9c3..e20d487137 100644
--- a/spec/ruby/core/random/new_spec.rb
+++ b/spec/ruby/core/random/new_spec.rb
@@ -1,16 +1,17 @@
+require_relative "../../spec_helper"
describe "Random.new" do
it "returns a new instance of Random" do
- Random.new.should be_an_instance_of(Random)
+ Random.new.should.instance_of?(Random)
end
it "uses a random seed value if none is supplied" do
- Random.new.seed.should be_an_instance_of(Integer)
+ Random.new.seed.should.instance_of?(Integer)
end
it "returns Random instances initialized with different seeds" do
first = Random.new
second = Random.new
- (0..20).map { first.rand } .should_not == (0..20).map { second.rand }
+ (0..20).map { first.rand }.should_not == (0..20).map { second.rand }
end
it "accepts an Integer seed value as an argument" do
@@ -32,6 +33,6 @@ describe "Random.new" do
it "raises a RangeError if passed a Complex (with imaginary part) seed value as an argument" do
-> do
Random.new(Complex(20,2))
- end.should raise_error(RangeError)
+ end.should.raise(RangeError)
end
end
diff --git a/spec/ruby/core/random/rand_spec.rb b/spec/ruby/core/random/rand_spec.rb
index 9244177ab5..c882db6381 100644
--- a/spec/ruby/core/random/rand_spec.rb
+++ b/spec/ruby/core/random/rand_spec.rb
@@ -45,13 +45,13 @@ describe "Random.rand" do
it "coerces arguments to Integers with #to_int" do
obj = mock_numeric('int')
obj.should_receive(:to_int).and_return(99)
- Random.rand(obj).should be_kind_of(Integer)
+ Random.rand(obj).should.is_a?(Integer)
end
end
describe "Random#rand with Fixnum" do
it "returns an Integer" do
- Random.new.rand(20).should be_an_instance_of(Integer)
+ Random.new.rand(20).should.instance_of?(Integer)
end
it "returns a Fixnum greater than or equal to 0" do
@@ -82,20 +82,20 @@ describe "Random#rand with Fixnum" do
it "raises an ArgumentError when the argument is 0" do
-> do
Random.new.rand(0)
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "raises an ArgumentError when the argument is negative" do
-> do
Random.new.rand(-12)
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
end
describe "Random#rand with Bignum" do
it "typically returns a Bignum" do
rnd = Random.new(1)
- 10.times.map{ rnd.rand(bignum_value*2) }.max.should be_an_instance_of(Integer)
+ 10.times.map{ rnd.rand(bignum_value*2) }.max.should.instance_of?(Integer)
end
it "returns a Bignum greater than or equal to 0" do
@@ -121,13 +121,13 @@ describe "Random#rand with Bignum" do
it "raises an ArgumentError when the argument is negative" do
-> do
Random.new.rand(-bignum_value)
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
end
describe "Random#rand with Float" do
it "returns a Float" do
- Random.new.rand(20.43).should be_an_instance_of(Float)
+ Random.new.rand(20.43).should.instance_of?(Float)
end
it "returns a Float greater than or equal to 0.0" do
@@ -153,25 +153,25 @@ describe "Random#rand with Float" do
it "raises an ArgumentError when the argument is negative" do
-> do
Random.new.rand(-1.234567)
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
end
describe "Random#rand with Range" do
it "returns an element from the Range" do
- Random.new.rand(20..43).should be_an_instance_of(Integer)
+ Random.new.rand(20..43).should.instance_of?(Integer)
end
it "supports custom object types" do
- rand(RandomSpecs::CustomRangeInteger.new(1)..RandomSpecs::CustomRangeInteger.new(42)).should be_an_instance_of(RandomSpecs::CustomRangeInteger)
- rand(RandomSpecs::CustomRangeFloat.new(1.0)..RandomSpecs::CustomRangeFloat.new(42.0)).should be_an_instance_of(RandomSpecs::CustomRangeFloat)
- rand(Time.now..Time.now).should be_an_instance_of(Time)
+ rand(RandomSpecs::CustomRangeInteger.new(1)..RandomSpecs::CustomRangeInteger.new(42)).should.instance_of?(RandomSpecs::CustomRangeInteger)
+ rand(RandomSpecs::CustomRangeFloat.new(1.0)..RandomSpecs::CustomRangeFloat.new(42.0)).should.instance_of?(RandomSpecs::CustomRangeFloat)
+ rand(Time.now..Time.now).should.instance_of?(Time)
end
it "returns an object that is a member of the Range" do
prng = Random.new
r = 20..30
- 20.times { r.member?(prng.rand(r)).should be_true }
+ 20.times { r.member?(prng.rand(r)).should == true }
end
it "works with inclusive ranges" do
@@ -201,8 +201,8 @@ describe "Random#rand with Range" do
end
it "considers Integers as Floats if one end point is a float" do
- Random.new(42).rand(0.0..1).should be_kind_of(Float)
- Random.new(42).rand(0..1.0).should be_kind_of(Float)
+ Random.new(42).rand(0.0..1).should.is_a?(Float)
+ Random.new(42).rand(0..1.0).should.is_a?(Float)
end
it "returns a float within a given float range" do
@@ -213,12 +213,12 @@ describe "Random#rand with Range" do
it "raises an ArgumentError when the startpoint lacks #+ and #- methods" do
-> do
Random.new.rand(Object.new..67)
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "raises an ArgumentError when the endpoint lacks #+ and #- methods" do
-> do
Random.new.rand(68..Object.new)
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/random/seed_spec.rb b/spec/ruby/core/random/seed_spec.rb
index bf4524fdd9..6529b2c873 100644
--- a/spec/ruby/core/random/seed_spec.rb
+++ b/spec/ruby/core/random/seed_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Random#seed" do
it "returns an Integer" do
- Random.new.seed.should be_kind_of(Integer)
+ Random.new.seed.should.is_a?(Integer)
end
it "returns an arbitrary seed if the constructor was called without arguments" do
diff --git a/spec/ruby/core/random/shared/bytes.rb b/spec/ruby/core/random/shared/bytes.rb
index 9afad3b7f8..86c64d5696 100644
--- a/spec/ruby/core/random/shared/bytes.rb
+++ b/spec/ruby/core/random/shared/bytes.rb
@@ -1,6 +1,6 @@
describe :random_bytes, shared: true do
it "returns a String" do
- @object.send(@method, 1).should be_an_instance_of(String)
+ @object.send(@method, 1).should.instance_of?(String)
end
it "returns a String of the length given as argument" do
diff --git a/spec/ruby/core/random/shared/rand.rb b/spec/ruby/core/random/shared/rand.rb
index d3b24b8851..655c75c9f1 100644
--- a/spec/ruby/core/random/shared/rand.rb
+++ b/spec/ruby/core/random/shared/rand.rb
@@ -1,9 +1,9 @@
describe :random_number, shared: true do
it "returns a Float if no max argument is passed" do
- @object.send(@method).should be_kind_of(Float)
+ @object.send(@method).should.is_a?(Float)
end
it "returns an Integer if an Integer argument is passed" do
- @object.send(@method, 20).should be_kind_of(Integer)
+ @object.send(@method, 20).should.is_a?(Integer)
end
end
diff --git a/spec/ruby/core/random/urandom_spec.rb b/spec/ruby/core/random/urandom_spec.rb
index 6f180e54ac..94e9423a06 100644
--- a/spec/ruby/core/random/urandom_spec.rb
+++ b/spec/ruby/core/random/urandom_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Random.urandom" do
it "returns a String" do
- Random.urandom(1).should be_an_instance_of(String)
+ Random.urandom(1).should.instance_of?(String)
end
it "returns a String of the length given as argument" do
@@ -12,7 +12,7 @@ describe "Random.urandom" do
it "raises an ArgumentError on a negative size" do
-> {
Random.urandom(-1)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "returns a binary String" do
diff --git a/spec/ruby/core/range/bsearch_spec.rb b/spec/ruby/core/range/bsearch_spec.rb
index 9c93671d85..151a1798cf 100644
--- a/spec/ruby/core/range/bsearch_spec.rb
+++ b/spec/ruby/core/range/bsearch_spec.rb
@@ -3,38 +3,46 @@ require_relative '../enumerable/shared/enumeratorized'
describe "Range#bsearch" do
it "returns an Enumerator when not passed a block" do
- (0..1).bsearch.should be_an_instance_of(Enumerator)
+ (0..1).bsearch.should.instance_of?(Enumerator)
end
it_behaves_like :enumeratorized_with_unknown_size, :bsearch, (1..3)
it "raises a TypeError if the block returns an Object" do
- -> { (0..1).bsearch { Object.new } }.should raise_error(TypeError)
+ -> { (0..1).bsearch { Object.new } }.should.raise(TypeError, "wrong argument type Object (must be numeric, true, false or nil)")
end
- it "raises a TypeError if the block returns a String" do
- -> { (0..1).bsearch { "1" } }.should raise_error(TypeError)
+ it "raises a TypeError if the block returns a String and boundaries are Integer values" do
+ -> { (0..1).bsearch { "1" } }.should.raise(TypeError, "wrong argument type String (must be numeric, true, false or nil)")
+ end
+
+ it "raises a TypeError if the block returns a String and boundaries are Float values" do
+ -> { (0.0..1.0).bsearch { "1" } }.should.raise(TypeError, "wrong argument type String (must be numeric, true, false or nil)")
end
it "raises a TypeError if the Range has Object values" do
value = mock("range bsearch")
r = Range.new value, value
- -> { r.bsearch { true } }.should raise_error(TypeError)
+ -> { r.bsearch { true } }.should.raise(TypeError, "can't do binary search for MockObject")
end
it "raises a TypeError if the Range has String values" do
- -> { ("a".."e").bsearch { true } }.should raise_error(TypeError)
+ -> { ("a".."e").bsearch { true } }.should.raise(TypeError, "can't do binary search for String")
+ end
+
+ it "raises TypeError when non-Numeric begin/end and block not passed" do
+ -> { ("a".."e").bsearch }.should.raise(TypeError, "can't do binary search for String")
end
context "with Integer values" do
context "with a block returning true or false" do
it "returns nil if the block returns false for every element" do
- (0...3).bsearch { |x| x > 3 }.should be_nil
+ (0...3).bsearch { |x| x > 3 }.should == nil
end
it "returns nil if the block returns nil for every element" do
- (0..3).bsearch { |x| nil }.should be_nil
+ (0..3).bsearch { |x| nil }.should == nil
end
it "returns minimum element if the block returns true for every element" do
@@ -54,21 +62,21 @@ describe "Range#bsearch" do
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
- (0..3).bsearch { |x| x <=> 5 }.should be_nil
+ (0..3).bsearch { |x| x <=> 5 }.should == nil
end
it "returns nil if the block returns greater than zero for every element" do
- (0..3).bsearch { |x| x <=> -1 }.should be_nil
+ (0..3).bsearch { |x| x <=> -1 }.should == nil
end
it "returns nil if the block never returns zero" do
- (0..3).bsearch { |x| x < 2 ? 1 : -1 }.should be_nil
+ (0..3).bsearch { |x| x < 2 ? 1 : -1 }.should == nil
end
it "accepts (+/-)Float::INFINITY from the block" do
- (0..4).bsearch { |x| Float::INFINITY }.should be_nil
- (0..4).bsearch { |x| -Float::INFINITY }.should be_nil
+ (0..4).bsearch { |x| Float::INFINITY }.should == nil
+ (0..4).bsearch { |x| -Float::INFINITY }.should == nil
end
it "returns an element at an index for which block returns 0.0" do
@@ -78,7 +86,7 @@ describe "Range#bsearch" do
it "returns an element at an index for which block returns 0" do
result = (0..4).bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
- [1, 2].should include(result)
+ [1, 2].should.include?(result)
end
end
@@ -94,16 +102,20 @@ describe "Range#bsearch" do
(4..2).bsearch { 0 }.should == nil
(4..2).bsearch { -1 }.should == nil
end
+
+ it "returns enumerator when block not passed" do
+ (0...3).bsearch.kind_of?(Enumerator).should == true
+ end
end
context "with Float values" do
context "with a block returning true or false" do
it "returns nil if the block returns false for every element" do
- (0.1...2.3).bsearch { |x| x > 3 }.should be_nil
+ (0.1...2.3).bsearch { |x| x > 3 }.should == nil
end
it "returns nil if the block returns nil for every element" do
- (-0.0..2.3).bsearch { |x| nil }.should be_nil
+ (-0.0..2.3).bsearch { |x| nil }.should == nil
end
it "returns minimum element if the block returns true for every element" do
@@ -151,21 +163,20 @@ describe "Range#bsearch" do
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
- (-2.0..3.2).bsearch { |x| x <=> 5 }.should be_nil
+ (-2.0..3.2).bsearch { |x| x <=> 5 }.should == nil
end
it "returns nil if the block returns greater than zero for every element" do
- (0.3..3.0).bsearch { |x| x <=> -1 }.should be_nil
-
+ (0.3..3.0).bsearch { |x| x <=> -1 }.should == nil
end
it "returns nil if the block never returns zero" do
- (0.2..2.3).bsearch { |x| x < 2 ? 1 : -1 }.should be_nil
+ (0.2..2.3).bsearch { |x| x < 2 ? 1 : -1 }.should == nil
end
it "accepts (+/-)Float::INFINITY from the block" do
- (0.1..4.5).bsearch { |x| Float::INFINITY }.should be_nil
- (-5.0..4.0).bsearch { |x| -Float::INFINITY }.should be_nil
+ (0.1..4.5).bsearch { |x| Float::INFINITY }.should == nil
+ (-5.0..4.0).bsearch { |x| -Float::INFINITY }.should == nil
end
it "returns an element at an index for which block returns 0.0" do
@@ -213,6 +224,10 @@ describe "Range#bsearch" do
(0...inf).bsearch { |x| x >= Float::MAX ? 0 : 1 }.should == Float::MAX
end
end
+
+ it "returns enumerator when block not passed" do
+ (0.1...2.3).bsearch.kind_of?(Enumerator).should == true
+ end
end
context "with endless ranges and Integer values" do
@@ -229,15 +244,15 @@ describe "Range#bsearch" do
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
- eval("(0..)").bsearch { |x| -1 }.should be_nil
+ eval("(0..)").bsearch { |x| -1 }.should == nil
end
it "returns nil if the block never returns zero" do
- eval("(0..)").bsearch { |x| x > 5 ? -1 : 1 }.should be_nil
+ eval("(0..)").bsearch { |x| x > 5 ? -1 : 1 }.should == nil
end
it "accepts -Float::INFINITY from the block" do
- eval("(0..)").bsearch { |x| -Float::INFINITY }.should be_nil
+ eval("(0..)").bsearch { |x| -Float::INFINITY }.should == nil
end
it "returns an element at an index for which block returns 0.0" do
@@ -247,21 +262,25 @@ describe "Range#bsearch" do
it "returns an element at an index for which block returns 0" do
result = eval("(0..)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
- [1, 2, 3].should include(result)
+ [1, 2, 3].should.include?(result)
end
end
+
+ it "returns enumerator when block not passed" do
+ eval("(-2..)").bsearch.kind_of?(Enumerator).should == true
+ end
end
context "with endless ranges and Float values" do
context "with a block returning true or false" do
it "returns nil if the block returns false for every element" do
- eval("(0.1..)").bsearch { |x| x < 0.0 }.should be_nil
- eval("(0.1...)").bsearch { |x| x < 0.0 }.should be_nil
+ eval("(0.1..)").bsearch { |x| x < 0.0 }.should == nil
+ eval("(0.1...)").bsearch { |x| x < 0.0 }.should == nil
end
it "returns nil if the block returns nil for every element" do
- eval("(-0.0..)").bsearch { |x| nil }.should be_nil
- eval("(-0.0...)").bsearch { |x| nil }.should be_nil
+ eval("(-0.0..)").bsearch { |x| nil }.should == nil
+ eval("(-0.0...)").bsearch { |x| nil }.should == nil
end
it "returns minimum element if the block returns true for every element" do
@@ -285,22 +304,22 @@ describe "Range#bsearch" do
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
- eval("(-2.0..)").bsearch { |x| -1 }.should be_nil
- eval("(-2.0...)").bsearch { |x| -1 }.should be_nil
+ eval("(-2.0..)").bsearch { |x| -1 }.should == nil
+ eval("(-2.0...)").bsearch { |x| -1 }.should == nil
end
it "returns nil if the block returns greater than zero for every element" do
- eval("(0.3..)").bsearch { |x| 1 }.should be_nil
- eval("(0.3...)").bsearch { |x| 1 }.should be_nil
+ eval("(0.3..)").bsearch { |x| 1 }.should == nil
+ eval("(0.3...)").bsearch { |x| 1 }.should == nil
end
it "returns nil if the block never returns zero" do
- eval("(0.2..)").bsearch { |x| x < 2 ? 1 : -1 }.should be_nil
+ eval("(0.2..)").bsearch { |x| x < 2 ? 1 : -1 }.should == nil
end
it "accepts (+/-)Float::INFINITY from the block" do
- eval("(0.1..)").bsearch { |x| Float::INFINITY }.should be_nil
- eval("(-5.0..)").bsearch { |x| -Float::INFINITY }.should be_nil
+ eval("(0.1..)").bsearch { |x| Float::INFINITY }.should == nil
+ eval("(-5.0..)").bsearch { |x| -Float::INFINITY }.should == nil
end
it "returns an element at an index for which block returns 0.0" do
@@ -327,8 +346,11 @@ describe "Range#bsearch" do
eval("(0.0...)").bsearch { 0 }.should != inf
end
end
- end
+ it "returns enumerator when block not passed" do
+ eval("(0.1..)").bsearch.kind_of?(Enumerator).should == true
+ end
+ end
context "with beginless ranges and Integer values" do
context "with a block returning true or false" do
@@ -340,15 +362,15 @@ describe "Range#bsearch" do
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns greater than zero for every element" do
- (..0).bsearch { |x| 1 }.should be_nil
+ (..0).bsearch { |x| 1 }.should == nil
end
it "returns nil if the block never returns zero" do
- (..0).bsearch { |x| x > 5 ? -1 : 1 }.should be_nil
+ (..0).bsearch { |x| x > 5 ? -1 : 1 }.should == nil
end
it "accepts Float::INFINITY from the block" do
- (..0).bsearch { |x| Float::INFINITY }.should be_nil
+ (..0).bsearch { |x| Float::INFINITY }.should == nil
end
it "returns an element at an index for which block returns 0.0" do
@@ -358,21 +380,25 @@ describe "Range#bsearch" do
it "returns an element at an index for which block returns 0" do
result = (...10).bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
- [1, 2, 3].should include(result)
+ [1, 2, 3].should.include?(result)
end
end
+
+ it "returns enumerator when block not passed" do
+ (..10).bsearch.kind_of?(Enumerator).should == true
+ end
end
context "with beginless ranges and Float values" do
context "with a block returning true or false" do
it "returns nil if the block returns true for every element" do
- (..-0.1).bsearch { |x| x > 0.0 }.should be_nil
- (...-0.1).bsearch { |x| x > 0.0 }.should be_nil
+ (..-0.1).bsearch { |x| x > 0.0 }.should == nil
+ (...-0.1).bsearch { |x| x > 0.0 }.should == nil
end
it "returns nil if the block returns nil for every element" do
- (..-0.1).bsearch { |x| nil }.should be_nil
- (...-0.1).bsearch { |x| nil }.should be_nil
+ (..-0.1).bsearch { |x| nil }.should == nil
+ (...-0.1).bsearch { |x| nil }.should == nil
end
it "returns the smallest element for which block returns true" do
@@ -391,22 +417,22 @@ describe "Range#bsearch" do
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
- (..5.0).bsearch { |x| -1 }.should be_nil
- (...5.0).bsearch { |x| -1 }.should be_nil
+ (..5.0).bsearch { |x| -1 }.should == nil
+ (...5.0).bsearch { |x| -1 }.should == nil
end
it "returns nil if the block returns greater than zero for every element" do
- (..1.1).bsearch { |x| 1 }.should be_nil
- (...1.1).bsearch { |x| 1 }.should be_nil
+ (..1.1).bsearch { |x| 1 }.should == nil
+ (...1.1).bsearch { |x| 1 }.should == nil
end
it "returns nil if the block never returns zero" do
- (..6.3).bsearch { |x| x < 2 ? 1 : -1 }.should be_nil
+ (..6.3).bsearch { |x| x < 2 ? 1 : -1 }.should == nil
end
it "accepts (+/-)Float::INFINITY from the block" do
- (..5.0).bsearch { |x| Float::INFINITY }.should be_nil
- (..7.0).bsearch { |x| -Float::INFINITY }.should be_nil
+ (..5.0).bsearch { |x| Float::INFINITY }.should == nil
+ (..7.0).bsearch { |x| -Float::INFINITY }.should == nil
end
it "returns an element at an index for which block returns 0.0" do
@@ -432,5 +458,9 @@ describe "Range#bsearch" do
(...inf).bsearch { |x| 3 - x }.should == 3
end
end
+
+ it "returns enumerator when block not passed" do
+ (..-0.1).bsearch.kind_of?(Enumerator).should == true
+ end
end
end
diff --git a/spec/ruby/core/range/case_compare_spec.rb b/spec/ruby/core/range/case_compare_spec.rb
index 4a3faa3163..7a76487d68 100644
--- a/spec/ruby/core/range/case_compare_spec.rb
+++ b/spec/ruby/core/range/case_compare_spec.rb
@@ -10,4 +10,8 @@ describe "Range#===" do
it_behaves_like :range_cover_and_include, :===
it_behaves_like :range_cover, :===
+
+ it "returns true on any value if begin and end are both nil" do
+ (nil..nil).should === 1
+ end
end
diff --git a/spec/ruby/core/range/cover_spec.rb b/spec/ruby/core/range/cover_spec.rb
index fa881607e9..eb8d5453bf 100644
--- a/spec/ruby/core/range/cover_spec.rb
+++ b/spec/ruby/core/range/cover_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/cover_and_include'
require_relative 'shared/cover'
@@ -7,4 +7,8 @@ describe "Range#cover?" do
it_behaves_like :range_cover_and_include, :cover?
it_behaves_like :range_cover, :cover?
it_behaves_like :range_cover_subrange, :cover?
+
+ it "covers U+9995 in the range U+0999..U+9999" do
+ ("\u{999}".."\u{9999}").cover?("\u{9995}").should == true
+ end
end
diff --git a/spec/ruby/core/range/each_spec.rb b/spec/ruby/core/range/each_spec.rb
index ecae17c881..b4389f864d 100644
--- a/spec/ruby/core/range/each_spec.rb
+++ b/spec/ruby/core/range/each_spec.rb
@@ -40,69 +40,56 @@ describe "Range#each" do
it "works with endless ranges" do
a = []
- eval("(-2..)").each { |x| break if x > 2; a << x }
+ (-2..).each { |x| break if x > 2; a << x }
a.should == [-2, -1, 0, 1, 2]
a = []
- eval("(-2...)").each { |x| break if x > 2; a << x }
+ (-2...).each { |x| break if x > 2; a << x }
a.should == [-2, -1, 0, 1, 2]
end
it "works with String endless ranges" do
a = []
- eval("('A'..)").each { |x| break if x > "D"; a << x }
+ ('A'..).each { |x| break if x > "D"; a << x }
a.should == ["A", "B", "C", "D"]
a = []
- eval("('A'...)").each { |x| break if x > "D"; a << x }
+ ('A'...).each { |x| break if x > "D"; a << x }
a.should == ["A", "B", "C", "D"]
end
it "raises a TypeError beginless ranges" do
- -> { (..2).each { |x| x } }.should raise_error(TypeError)
+ -> { (..2).each { |x| x } }.should.raise(TypeError)
end
it "raises a TypeError if the first element does not respond to #succ" do
- -> { (0.5..2.4).each { |i| i } }.should raise_error(TypeError)
+ -> { (0.5..2.4).each { |i| i } }.should.raise(TypeError)
b = mock('x')
(a = mock('1')).should_receive(:<=>).with(b).and_return(1)
- -> { (a..b).each { |i| i } }.should raise_error(TypeError)
+ -> { (a..b).each { |i| i } }.should.raise(TypeError)
end
it "returns self" do
range = 1..10
- range.each{}.should equal(range)
+ range.each{}.should.equal?(range)
end
it "returns an enumerator when no block given" do
enum = (1..3).each
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.should == [1, 2, 3]
end
- ruby_version_is "3.1" do
- it "supports Time objects that respond to #succ" do
- t = Time.utc(1970)
- def t.succ; self + 1 end
- t_succ = t.succ
- def t_succ.succ; self + 1; end
+ it "supports Time objects that respond to #succ" do
+ t = Time.utc(1970)
+ def t.succ; self + 1 end
+ t_succ = t.succ
+ def t_succ.succ; self + 1; end
- (t..t_succ).to_a.should == [Time.utc(1970), Time.utc(1970, nil, nil, nil, nil, 1)]
- (t...t_succ).to_a.should == [Time.utc(1970)]
- end
- end
-
- ruby_version_is ""..."3.1" do
- it "raises a TypeError if the first element is a Time object even if it responds to #succ" do
- t = Time.utc(1970)
- def t.succ; self + 1 end
- t_succ = t.succ
- def t_succ.succ; self + 1; end
-
- -> { (t..t_succ).each { |i| i } }.should raise_error(TypeError)
- end
+ (t..t_succ).to_a.should == [Time.utc(1970), Time.utc(1970, nil, nil, nil, nil, 1)]
+ (t...t_succ).to_a.should == [Time.utc(1970)]
end
it "passes each Symbol element by using #succ" do
diff --git a/spec/ruby/core/range/eql_spec.rb b/spec/ruby/core/range/eql_spec.rb
index fa6c71840e..cdc19c9331 100644
--- a/spec/ruby/core/range/eql_spec.rb
+++ b/spec/ruby/core/range/eql_spec.rb
@@ -5,6 +5,6 @@ describe "Range#eql?" do
it_behaves_like :range_eql, :eql?
it "returns false if the endpoints are not eql?" do
- (0..1).should_not eql(0..1.0)
+ (0..1).should_not.eql?(0..1.0)
end
end
diff --git a/spec/ruby/core/range/first_spec.rb b/spec/ruby/core/range/first_spec.rb
index 2af935f439..54bd73a4e8 100644
--- a/spec/ruby/core/range/first_spec.rb
+++ b/spec/ruby/core/range/first_spec.rb
@@ -21,7 +21,7 @@ describe "Range#first" do
end
it "raises an ArgumentError when count is negative" do
- -> { (0..2).first(-1) }.should raise_error(ArgumentError)
+ -> { (0..2).first(-1) }.should.raise(ArgumentError)
end
it "calls #to_int to convert the argument" do
@@ -32,7 +32,7 @@ describe "Range#first" do
it "raises a TypeError if #to_int does not return an Integer" do
obj = mock("to_int")
obj.should_receive(:to_int).and_return("1")
- -> { (2..3).first(obj) }.should raise_error(TypeError)
+ -> { (2..3).first(obj) }.should.raise(TypeError)
end
it "truncates the value when passed a Float" do
@@ -40,14 +40,14 @@ describe "Range#first" do
end
it "raises a TypeError when passed nil" do
- -> { (2..3).first(nil) }.should raise_error(TypeError)
+ -> { (2..3).first(nil) }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- -> { (2..3).first("1") }.should raise_error(TypeError)
+ -> { (2..3).first("1") }.should.raise(TypeError)
end
it "raises a RangeError when called on an beginless range" do
- -> { (..1).first }.should raise_error(RangeError)
+ -> { (..1).first }.should.raise(RangeError)
end
end
diff --git a/spec/ruby/core/range/frozen_spec.rb b/spec/ruby/core/range/frozen_spec.rb
index 298ffc87cb..8dab5e5339 100644
--- a/spec/ruby/core/range/frozen_spec.rb
+++ b/spec/ruby/core/range/frozen_spec.rb
@@ -2,26 +2,24 @@ require_relative '../../spec_helper'
# There is no Range#frozen? method but this feels like the best place for these specs
describe "Range#frozen?" do
- ruby_version_is "3.0" do
- it "is true for literal ranges" do
- (1..2).should.frozen?
- (1..).should.frozen?
- (..1).should.frozen?
- end
+ it "is true for literal ranges" do
+ (1..2).should.frozen?
+ (1..).should.frozen?
+ (..1).should.frozen?
+ end
- it "is true for Range.new" do
- Range.new(1, 2).should.frozen?
- Range.new(1, nil).should.frozen?
- Range.new(nil, 1).should.frozen?
- end
+ it "is true for Range.new" do
+ Range.new(1, 2).should.frozen?
+ Range.new(1, nil).should.frozen?
+ Range.new(nil, 1).should.frozen?
+ end
- it "is false for instances of a subclass of Range" do
- sub_range = Class.new(Range).new(1, 2)
- sub_range.should_not.frozen?
- end
+ it "is false for instances of a subclass of Range" do
+ sub_range = Class.new(Range).new(1, 2)
+ sub_range.should_not.frozen?
+ end
- it "is false for Range.allocate" do
- Range.allocate.should_not.frozen?
- end
+ it "is false for Range.allocate" do
+ Range.allocate.should_not.frozen?
end
end
diff --git a/spec/ruby/core/range/hash_spec.rb b/spec/ruby/core/range/hash_spec.rb
index 4f2681e86e..087f5d6de8 100644
--- a/spec/ruby/core/range/hash_spec.rb
+++ b/spec/ruby/core/range/hash_spec.rb
@@ -15,10 +15,10 @@ describe "Range#hash" do
end
it "generates an Integer for the hash value" do
- (0..0).hash.should be_an_instance_of(Integer)
- (0..1).hash.should be_an_instance_of(Integer)
- (0...10).hash.should be_an_instance_of(Integer)
- (0..10).hash.should be_an_instance_of(Integer)
+ (0..0).hash.should.instance_of?(Integer)
+ (0..1).hash.should.instance_of?(Integer)
+ (0...10).hash.should.instance_of?(Integer)
+ (0..10).hash.should.instance_of?(Integer)
end
end
diff --git a/spec/ruby/core/range/include_spec.rb b/spec/ruby/core/range/include_spec.rb
index b2c7a54545..66a049a90d 100644
--- a/spec/ruby/core/range/include_spec.rb
+++ b/spec/ruby/core/range/include_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/cover_and_include'
require_relative 'shared/include'
@@ -7,4 +7,8 @@ require_relative 'shared/cover'
describe "Range#include?" do
it_behaves_like :range_cover_and_include, :include?
it_behaves_like :range_include, :include?
+
+ it "does not include U+9995 in the range U+0999..U+9999" do
+ ("\u{999}".."\u{9999}").include?("\u{9995}").should == false
+ end
end
diff --git a/spec/ruby/core/range/initialize_spec.rb b/spec/ruby/core/range/initialize_spec.rb
index 8a6ca65daa..b1a0565ab2 100644
--- a/spec/ruby/core/range/initialize_spec.rb
+++ b/spec/ruby/core/range/initialize_spec.rb
@@ -6,45 +6,36 @@ describe "Range#initialize" do
end
it "is private" do
- Range.should have_private_instance_method("initialize")
+ Range.private_instance_methods(false).should.include?(:initialize)
end
it "initializes correctly the Range object when given 2 arguments" do
- -> { @range.send(:initialize, 0, 1) }.should_not raise_error
+ -> { @range.send(:initialize, 0, 1) }.should_not.raise
end
it "initializes correctly the Range object when given 3 arguments" do
- -> { @range.send(:initialize, 0, 1, true) }.should_not raise_error
+ -> { @range.send(:initialize, 0, 1, true) }.should_not.raise
end
it "raises an ArgumentError if passed without or with only one argument" do
- -> { @range.send(:initialize) }.should raise_error(ArgumentError)
- -> { @range.send(:initialize, 1) }.should raise_error(ArgumentError)
+ -> { @range.send(:initialize) }.should.raise(ArgumentError)
+ -> { @range.send(:initialize, 1) }.should.raise(ArgumentError)
end
it "raises an ArgumentError if passed with four or more arguments" do
- -> { @range.send(:initialize, 1, 3, 5, 7) }.should raise_error(ArgumentError)
- -> { @range.send(:initialize, 1, 3, 5, 7, 9) }.should raise_error(ArgumentError)
+ -> { @range.send(:initialize, 1, 3, 5, 7) }.should.raise(ArgumentError)
+ -> { @range.send(:initialize, 1, 3, 5, 7, 9) }.should.raise(ArgumentError)
end
- ruby_version_is ""..."3.0" do
- it "raises a NameError if called on an already initialized Range" do
- -> { (0..1).send(:initialize, 1, 3) }.should raise_error(NameError)
- -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(NameError)
- end
- end
-
- ruby_version_is "3.0" do
- it "raises a FrozenError if called on an already initialized Range" do
- -> { (0..1).send(:initialize, 1, 3) }.should raise_error(FrozenError)
- -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(FrozenError)
- end
+ it "raises a FrozenError if called on an already initialized Range" do
+ -> { (0..1).send(:initialize, 1, 3) }.should.raise(FrozenError)
+ -> { (0..1).send(:initialize, 1, 3, true) }.should.raise(FrozenError)
end
it "raises an ArgumentError if arguments don't respond to <=>" do
o1 = Object.new
o2 = Object.new
- -> { @range.send(:initialize, o1, o2) }.should raise_error(ArgumentError)
+ -> { @range.send(:initialize, o1, o2) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/range/last_spec.rb b/spec/ruby/core/range/last_spec.rb
index d7ef776b42..a7db7f85a7 100644
--- a/spec/ruby/core/range/last_spec.rb
+++ b/spec/ruby/core/range/last_spec.rb
@@ -8,6 +8,10 @@ describe "Range#last" do
(1..5).last(3).should == [3, 4, 5]
end
+ it "returns the specified number if elements for single element inclusive range" do
+ (1..1).last(1).should == [1]
+ end
+
it "returns an empty array for an empty Range" do
(0...0).last(2).should == []
end
@@ -21,7 +25,7 @@ describe "Range#last" do
end
it "raises an ArgumentError when count is negative" do
- -> { (0..2).last(-1) }.should raise_error(ArgumentError)
+ -> { (0..2).last(-1) }.should.raise(ArgumentError)
end
it "calls #to_int to convert the argument" do
@@ -32,7 +36,7 @@ describe "Range#last" do
it "raises a TypeError if #to_int does not return an Integer" do
obj = mock("to_int")
obj.should_receive(:to_int).and_return("1")
- -> { (2..3).last(obj) }.should raise_error(TypeError)
+ -> { (2..3).last(obj) }.should.raise(TypeError)
end
it "truncates the value when passed a Float" do
@@ -40,14 +44,14 @@ describe "Range#last" do
end
it "raises a TypeError when passed nil" do
- -> { (2..3).last(nil) }.should raise_error(TypeError)
+ -> { (2..3).last(nil) }.should.raise(TypeError)
end
it "raises a TypeError when passed a String" do
- -> { (2..3).last("1") }.should raise_error(TypeError)
+ -> { (2..3).last("1") }.should.raise(TypeError)
end
it "raises a RangeError when called on an endless range" do
- -> { eval("(1..)").last }.should raise_error(RangeError)
+ -> { eval("(1..)").last }.should.raise(RangeError)
end
end
diff --git a/spec/ruby/core/range/max_spec.rb b/spec/ruby/core/range/max_spec.rb
index 6c9ada2a3c..57714967ce 100644
--- a/spec/ruby/core/range/max_spec.rb
+++ b/spec/ruby/core/range/max_spec.rb
@@ -14,54 +14,66 @@ describe "Range#max" do
end
it "raises TypeError when called on an exclusive range and a non Integer value" do
- -> { (303.20...908.1111).max }.should raise_error(TypeError)
+ -> { (303.20...908.1111).max }.should.raise(TypeError)
end
it "returns nil when the endpoint is less than the start point" do
- (100..10).max.should be_nil
- ('z'..'l').max.should be_nil
+ (100..10).max.should == nil
+ ('z'..'l').max.should == nil
end
it "returns nil when the endpoint equals the start point and the range is exclusive" do
- (5...5).max.should be_nil
+ (5...5).max.should == nil
end
it "returns the endpoint when the endpoint equals the start point and the range is inclusive" do
- (5..5).max.should equal(5)
+ (5..5).max.should.equal?(5)
end
it "returns nil when the endpoint is less than the start point in a Float range" do
- (3003.20..908.1111).max.should be_nil
+ (3003.20..908.1111).max.should == nil
end
it "returns end point when the range is Time..Time(included end point)" do
time_start = Time.now
time_end = Time.now + 1.0
- (time_start..time_end).max.should equal(time_end)
+ (time_start..time_end).max.should.equal?(time_end)
end
it "raises TypeError when called on a Time...Time(excluded end point)" do
time_start = Time.now
time_end = Time.now + 1.0
- -> { (time_start...time_end).max }.should raise_error(TypeError)
+ -> { (time_start...time_end).max }.should.raise(TypeError)
end
it "raises RangeError when called on an endless range" do
- -> { eval("(1..)").max }.should raise_error(RangeError)
+ -> { eval("(1..)").max }.should.raise(RangeError)
end
- ruby_version_is "3.0" do
- it "returns the end point for beginless ranges" do
- (..1).max.should == 1
- (..1.0).max.should == 1.0
- end
+ it "returns the end point for beginless ranges" do
+ (..1).max.should == 1
+ (..1.0).max.should == 1.0
+ end
- it "raises for an exclusive beginless range" do
+ ruby_version_is ""..."4.0" do
+ it "raises for an exclusive beginless Integer range" do
-> {
(...1).max
- }.should raise_error(TypeError, 'cannot exclude end value with non Integer begin value')
+ }.should.raise(TypeError, 'cannot exclude end value with non Integer begin value')
end
end
+
+ ruby_version_is "4.0" do
+ it "returns the end point for exclusive beginless Integer ranges" do
+ (...1).max.should == 0
+ end
+ end
+
+ it "raises for an exclusive beginless non Integer range" do
+ -> {
+ (...1.0).max
+ }.should.raise(TypeError, 'cannot exclude non Integer end value')
+ end
end
describe "Range#max given a block" do
@@ -70,7 +82,7 @@ describe "Range#max given a block" do
(1..10).max {|a,b| acc << [a,b]; a }
acc.flatten!
(1..10).each do |value|
- acc.include?(value).should be_true
+ acc.include?(value).should == true
end
end
@@ -92,12 +104,12 @@ describe "Range#max given a block" do
end
it "returns nil when the endpoint is less than the start point" do
- (100..10).max {|x,y| x <=> y}.should be_nil
- ('z'..'l').max {|x,y| x <=> y}.should be_nil
- (5...5).max {|x,y| x <=> y}.should be_nil
+ (100..10).max {|x,y| x <=> y}.should == nil
+ ('z'..'l').max {|x,y| x <=> y}.should == nil
+ (5...5).max {|x,y| x <=> y}.should == nil
end
it "raises RangeError when called with custom comparison method on an beginless range" do
- -> { (..1).max {|a, b| a} }.should raise_error(RangeError)
+ -> { (..1).max {|a, b| a} }.should.raise(RangeError)
end
end
diff --git a/spec/ruby/core/range/member_spec.rb b/spec/ruby/core/range/member_spec.rb
index ab61f92951..78299ae9e5 100644
--- a/spec/ruby/core/range/member_spec.rb
+++ b/spec/ruby/core/range/member_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/cover_and_include'
require_relative 'shared/include'
diff --git a/spec/ruby/core/range/min_spec.rb b/spec/ruby/core/range/min_spec.rb
index 89310ee589..9c83d3deca 100644
--- a/spec/ruby/core/range/min_spec.rb
+++ b/spec/ruby/core/range/min_spec.rb
@@ -11,32 +11,32 @@ describe "Range#min" do
end
it "returns nil when the start point is greater than the endpoint" do
- (100..10).min.should be_nil
- ('z'..'l').min.should be_nil
+ (100..10).min.should == nil
+ ('z'..'l').min.should == nil
end
it "returns nil when the endpoint equals the start point and the range is exclusive" do
- (7...7).min.should be_nil
+ (7...7).min.should == nil
end
it "returns the start point when the endpoint equals the start point and the range is inclusive" do
- (7..7).min.should equal(7)
+ (7..7).min.should.equal?(7)
end
it "returns nil when the start point is greater than the endpoint in a Float range" do
- (3003.20..908.1111).min.should be_nil
+ (3003.20..908.1111).min.should == nil
end
it "returns start point when the range is Time..Time(included end point)" do
time_start = Time.now
time_end = Time.now + 1.0
- (time_start..time_end).min.should equal(time_start)
+ (time_start..time_end).min.should.equal?(time_start)
end
it "returns start point when the range is Time...Time(excluded end point)" do
time_start = Time.now
time_end = Time.now + 1.0
- (time_start...time_end).min.should equal(time_start)
+ (time_start...time_end).min.should.equal?(time_start)
end
it "returns the start point for endless ranges" do
@@ -45,7 +45,7 @@ describe "Range#min" do
end
it "raises RangeError when called on an beginless range" do
- -> { (..1).min }.should raise_error(RangeError)
+ -> { (..1).min }.should.raise(RangeError)
end
end
@@ -55,7 +55,7 @@ describe "Range#min given a block" do
(1..10).min {|a,b| acc << [a,b]; a }
acc.flatten!
(1..10).each do |value|
- acc.include?(value).should be_true
+ acc.include?(value).should == true
end
end
@@ -77,12 +77,12 @@ describe "Range#min given a block" do
end
it "returns nil when the start point is greater than the endpoint" do
- (100..10).min {|x,y| x <=> y}.should be_nil
- ('z'..'l').min {|x,y| x <=> y}.should be_nil
- (7...7).min {|x,y| x <=> y}.should be_nil
+ (100..10).min {|x,y| x <=> y}.should == nil
+ ('z'..'l').min {|x,y| x <=> y}.should == nil
+ (7...7).min {|x,y| x <=> y}.should == nil
end
it "raises RangeError when called with custom comparison method on an endless range" do
- -> { eval("(1..)").min {|a, b| a} }.should raise_error(RangeError)
+ -> { eval("(1..)").min {|a, b| a} }.should.raise(RangeError)
end
end
diff --git a/spec/ruby/core/range/minmax_spec.rb b/spec/ruby/core/range/minmax_spec.rb
index b2b4fd61a1..16c7626ea3 100644
--- a/spec/ruby/core/range/minmax_spec.rb
+++ b/spec/ruby/core/range/minmax_spec.rb
@@ -17,19 +17,19 @@ describe 'Range#minmax' do
range = (@x..)
- -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range')
+ -> { range.minmax }.should.raise(RangeError, 'cannot get the maximum of endless range')
end
it 'raises RangeError or ArgumentError on a beginless range' do
range = (..@x)
- -> { range.minmax }.should raise_error(StandardError) { |e|
+ -> { range.minmax }.should.raise(StandardError) { |e|
if RangeError === e
# error from #min
- -> { raise e }.should raise_error(RangeError, 'cannot get the minimum of beginless range')
+ -> { raise e }.should.raise(RangeError, 'cannot get the minimum of beginless range')
else
# error from #max
- -> { raise e }.should raise_error(ArgumentError, 'comparison of NilClass with MockObject failed')
+ -> { raise e }.should.raise(ArgumentError, 'comparison of NilClass with MockObject failed')
end
}
end
@@ -76,34 +76,32 @@ describe 'Range#minmax' do
@x.should_not_receive(:succ)
range = (@x...)
- -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range')
+ -> { range.minmax }.should.raise(RangeError, 'cannot get the maximum of endless range')
end
it 'should raise RangeError on a beginless range' do
range = (...@x)
- -> { range.minmax }.should raise_error(RangeError,
+ -> { range.minmax }.should.raise(RangeError,
/cannot get the maximum of beginless range with custom comparison method|cannot get the minimum of beginless range/)
end
- ruby_bug "#17014", ""..."3.0" do
- it 'should return nil pair if beginning and end are equal without iterating the range' do
- @x.should_not_receive(:succ)
+ it 'should return nil pair if beginning and end are equal without iterating the range' do
+ @x.should_not_receive(:succ)
- (@x...@x).minmax.should == [nil, nil]
- end
+ (@x...@x).minmax.should == [nil, nil]
+ end
- it 'should return nil pair if beginning is greater than end without iterating the range' do
- @y.should_not_receive(:succ)
+ it 'should return nil pair if beginning is greater than end without iterating the range' do
+ @y.should_not_receive(:succ)
- (@y...@x).minmax.should == [nil, nil]
- end
+ (@y...@x).minmax.should == [nil, nil]
+ end
- it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do
- @x.should_receive(:succ).once.and_return(@y)
+ it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do
+ @x.should_receive(:succ).once.and_return(@y)
- (@x...@y).minmax.should == [@x, @x]
- end
+ (@x...@y).minmax.should == [@x, @x]
end
it 'should return the minimum and maximum values for a numeric range' do
@@ -120,7 +118,7 @@ describe 'Range#minmax' do
it 'raises TypeError if the end value is not an integer' do
range = (0...Float::INFINITY)
- -> { range.minmax }.should raise_error(TypeError, 'cannot exclude non Integer end value')
+ -> { range.minmax }.should.raise(TypeError, 'cannot exclude non Integer end value')
end
it 'should return the minimum and maximum values according to the provided block by iterating the range' do
diff --git a/spec/ruby/core/range/new_spec.rb b/spec/ruby/core/range/new_spec.rb
index 40df914b83..9a35f28c7e 100644
--- a/spec/ruby/core/range/new_spec.rb
+++ b/spec/ruby/core/range/new_spec.rb
@@ -25,12 +25,12 @@ describe "Range.new" do
end
it "raises an ArgumentError when the given start and end can't be compared by using #<=>" do
- -> { Range.new(1, mock('x')) }.should raise_error(ArgumentError)
- -> { Range.new(mock('x'), mock('y')) }.should raise_error(ArgumentError)
+ -> { Range.new(1, mock('x')) }.should.raise(ArgumentError)
+ -> { Range.new(mock('x'), mock('y')) }.should.raise(ArgumentError)
b = mock('x')
(a = mock('nil')).should_receive(:<=>).with(b).and_return(nil)
- -> { Range.new(a, b) }.should raise_error(ArgumentError)
+ -> { Range.new(a, b) }.should.raise(ArgumentError)
end
it "does not rescue exception raised in #<=> when compares the given start and end" do
@@ -38,7 +38,7 @@ describe "Range.new" do
a = mock('b')
a.should_receive(:<=>).with(b).and_raise(RangeSpecs::ComparisonError)
- -> { Range.new(a, b) }.should raise_error(RangeSpecs::ComparisonError)
+ -> { Range.new(a, b) }.should.raise(RangeSpecs::ComparisonError)
end
describe "beginless/endless range" do
@@ -66,14 +66,12 @@ describe "Range.new" do
range_exclude.should_not == range_include
end
- ruby_version_is "3.0" do
- it "creates a frozen range if the class is Range.class" do
- Range.new(1, 2).should.frozen?
- end
+ it "creates a frozen range if the class is Range.class" do
+ Range.new(1, 2).should.frozen?
+ end
- it "does not create a frozen range if the class is not Range.class" do
- Class.new(Range).new(1, 2).should_not.frozen?
- end
+ it "does not create a frozen range if the class is not Range.class" do
+ Class.new(Range).new(1, 2).should_not.frozen?
end
end
end
diff --git a/spec/ruby/core/range/overlap_spec.rb b/spec/ruby/core/range/overlap_spec.rb
new file mode 100644
index 0000000000..201cd2b1ff
--- /dev/null
+++ b/spec/ruby/core/range/overlap_spec.rb
@@ -0,0 +1,87 @@
+require_relative '../../spec_helper'
+
+describe "Range#overlap?" do
+ it "returns true if other Range overlaps self" do
+ (0..2).overlap?(1..3).should == true
+ (1..3).overlap?(0..2).should == true
+ (0..2).overlap?(0..2).should == true
+ (0..3).overlap?(1..2).should == true
+ (1..2).overlap?(0..3).should == true
+
+ ('a'..'c').overlap?('b'..'d').should == true
+ end
+
+ it "returns false if other Range does not overlap self" do
+ (0..2).overlap?(3..4).should == false
+ (0..2).overlap?(-4..-1).should == false
+
+ ('a'..'c').overlap?('d'..'f').should == false
+ end
+
+ it "raises TypeError when called with non-Range argument" do
+ -> {
+ (0..2).overlap?(1)
+ }.should.raise(TypeError, "wrong argument type Integer (expected Range)")
+ end
+
+ it "returns true when beginningless and endless Ranges overlap" do
+ (0..2).overlap?(..3).should == true
+ (0..2).overlap?(..1).should == true
+ (0..2).overlap?(..0).should == true
+
+ (..3).overlap?(0..2).should == true
+ (..1).overlap?(0..2).should == true
+ (..0).overlap?(0..2).should == true
+
+ (0..2).overlap?(-1..).should == true
+ (0..2).overlap?(1..).should == true
+ (0..2).overlap?(2..).should == true
+
+ (-1..).overlap?(0..2).should == true
+ (1..).overlap?(0..2).should == true
+ (2..).overlap?(0..2).should == true
+
+ (0..).overlap?(2..).should == true
+ (..0).overlap?(..2).should == true
+ end
+
+ it "returns false when beginningless and endless Ranges do not overlap" do
+ (0..2).overlap?(..-1).should == false
+ (0..2).overlap?(3..).should == false
+
+ (..-1).overlap?(0..2).should == false
+ (3..).overlap?(0..2).should == false
+ end
+
+ it "returns false when Ranges are not compatible" do
+ (0..2).overlap?('a'..'d').should == false
+ end
+
+ it "return false when self is empty" do
+ (2..0).overlap?(1..3).should == false
+ (2...2).overlap?(1..3).should == false
+ (1...1).overlap?(1...1).should == false
+ (2..0).overlap?(2..0).should == false
+
+ ('c'..'a').overlap?('b'..'d').should == false
+ ('a'...'a').overlap?('b'..'d').should == false
+ ('b'...'b').overlap?('b'...'b').should == false
+ ('c'...'a').overlap?('c'...'a').should == false
+ end
+
+ it "return false when other Range is empty" do
+ (1..3).overlap?(2..0).should == false
+ (1..3).overlap?(2...2).should == false
+
+ ('b'..'d').overlap?('c'..'a').should == false
+ ('b'..'d').overlap?('c'...'c').should == false
+ end
+
+ it "takes into account exclusive end" do
+ (0...2).overlap?(2..4).should == false
+ (2..4).overlap?(0...2).should == false
+
+ ('a'...'c').overlap?('c'..'e').should == false
+ ('c'..'e').overlap?('a'...'c').should == false
+ end
+end
diff --git a/spec/ruby/core/range/reverse_each_spec.rb b/spec/ruby/core/range/reverse_each_spec.rb
new file mode 100644
index 0000000000..49790e8b0a
--- /dev/null
+++ b/spec/ruby/core/range/reverse_each_spec.rb
@@ -0,0 +1,125 @@
+require_relative '../../spec_helper'
+
+describe "Range#reverse_each" do
+ it "traverses the Range in reverse order and passes each element to block" do
+ a = []
+ (1..3).reverse_each { |i| a << i }
+ a.should == [3, 2, 1]
+
+ a = []
+ (1...3).reverse_each { |i| a << i }
+ a.should == [2, 1]
+ end
+
+ it "returns self" do
+ r = (1..3)
+ r.reverse_each { |x| }.should.equal?(r)
+ end
+
+ it "returns an Enumerator if no block given" do
+ enum = (1..3).reverse_each
+ enum.should.instance_of?(Enumerator)
+ enum.to_a.should == [3, 2, 1]
+ end
+
+ it "raises a TypeError for endless Ranges of Integers" do
+ -> {
+ (1..).reverse_each.take(3)
+ }.should.raise(TypeError, "can't iterate from NilClass")
+ end
+
+ it "raises a TypeError for endless Ranges of non-Integers" do
+ -> {
+ ("a"..).reverse_each.take(3)
+ }.should.raise(TypeError, "can't iterate from NilClass")
+ end
+
+ context "Integer boundaries" do
+ it "supports beginningless Ranges" do
+ (..5).reverse_each.take(3).should == [5, 4, 3]
+ end
+ end
+
+ context "non-Integer boundaries" do
+ it "uses #succ to iterate a Range of non-Integer elements" do
+ y = mock('y')
+ x = mock('x')
+
+ x.should_receive(:succ).any_number_of_times.and_return(y)
+ x.should_receive(:<=>).with(y).any_number_of_times.and_return(-1)
+ x.should_receive(:<=>).with(x).any_number_of_times.and_return(0)
+ y.should_receive(:<=>).with(x).any_number_of_times.and_return(1)
+ y.should_receive(:<=>).with(y).any_number_of_times.and_return(0)
+
+ a = []
+ (x..y).each { |i| a << i }
+ a.should == [x, y]
+ end
+
+ it "uses #succ to iterate a Range of Strings" do
+ a = []
+ ('A'..'D').reverse_each { |i| a << i }
+ a.should == ['D','C','B','A']
+ end
+
+ it "uses #succ to iterate a Range of Symbols" do
+ a = []
+ (:A..:D).reverse_each { |i| a << i }
+ a.should == [:D, :C, :B, :A]
+ end
+
+ it "raises a TypeError when `begin` value does not respond to #succ" do
+ -> { (Time.now..Time.now).reverse_each { |x| x } }.should.raise(TypeError, /can't iterate from Time/)
+ -> { (//..//).reverse_each { |x| x } }.should.raise(TypeError, /can't iterate from Regexp/)
+ -> { ([]..[]).reverse_each { |x| x } }.should.raise(TypeError, /can't iterate from Array/)
+ end
+
+ it "does not support beginningless Ranges" do
+ -> {
+ (..'a').reverse_each { |x| x }
+ }.should.raise(TypeError, /can't iterate from NilClass/)
+ end
+ end
+
+ context "when no block is given" do
+ describe "returned Enumerator size" do
+ it "returns the Range size when Range size is finite" do
+ (1..3).reverse_each.size.should == 3
+ (1...3).reverse_each.size.should == 2
+
+ (1..3.3).reverse_each.size.should == 3
+ (1...3.3).reverse_each.size.should == 3
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "returns a size when it is not iterable" do
+ (1.1..3).reverse_each.size.should == 2
+ (1.1..3.3).reverse_each.size.should == 3
+ (1.1..nil).reverse_each.size.should == Float::INFINITY
+ (nil..3.3).reverse_each.size.should == Float::INFINITY
+ (nil..nil).reverse_each.size.should == nil
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises TypeError when the range is not iterable" do
+ -> { (1.1..3).reverse_each.size }.should.raise(TypeError, /can't iterate from Integer/)
+ -> { (1.1..3.3).reverse_each.size }.should.raise(TypeError, /can't iterate from Float/)
+ -> { (1.1..nil).reverse_each.size }.should.raise(TypeError, /can't iterate from NilClass/)
+ -> { (nil..3.3).reverse_each.size }.should.raise(TypeError, /can't iterate from Float/)
+ -> { (nil..nil).reverse_each.size }.should.raise(TypeError, /can't iterate from NilClass/)
+ end
+ end
+
+ ruby_bug "#20936", "3.4"..."4.0" do
+ it "returns Infinity when Range size is infinite" do
+ (..3).reverse_each.size.should == Float::INFINITY
+ end
+ end
+
+ it "returns nil when Range size is unknown" do
+ ('a'..'z').reverse_each.size.should == nil
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/range/shared/cover.rb b/spec/ruby/core/range/shared/cover.rb
index 0b41a26455..189f3da4bf 100644
--- a/spec/ruby/core/range/shared/cover.rb
+++ b/spec/ruby/core/range/shared/cover.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
@@ -6,26 +6,26 @@ describe :range_cover, shared: true do
it "uses the range element's <=> to make the comparison" do
a = mock('a')
a.should_receive(:<=>).twice.and_return(-1,-1)
- (a..'z').send(@method, 'b').should be_true
+ (a..'z').send(@method, 'b').should == true
end
it "uses a continuous inclusion test" do
- ('a'..'f').send(@method, 'aa').should be_true
- ('a'..'f').send(@method, 'babe').should be_true
- ('a'..'f').send(@method, 'baby').should be_true
- ('a'..'f').send(@method, 'ga').should be_false
- (-10..-2).send(@method, -2.5).should be_true
+ ('a'..'f').send(@method, 'aa').should == true
+ ('a'..'f').send(@method, 'babe').should == true
+ ('a'..'f').send(@method, 'baby').should == true
+ ('a'..'f').send(@method, 'ga').should == false
+ (-10..-2).send(@method, -2.5).should == true
end
describe "on string elements" do
it "returns true if other is matched by element.succ" do
- ('a'..'c').send(@method, 'b').should be_true
- ('a'...'c').send(@method, 'b').should be_true
+ ('a'..'c').send(@method, 'b').should == true
+ ('a'...'c').send(@method, 'b').should == true
end
it "returns true if other is not matched by element.succ" do
- ('a'..'c').send(@method, 'bc').should be_true
- ('a'...'c').send(@method, 'bc').should be_true
+ ('a'..'c').send(@method, 'bc').should == true
+ ('a'...'c').send(@method, 'bc').should == true
end
end
@@ -36,27 +36,27 @@ describe :range_cover, shared: true do
end
it "returns false if other is less than first element" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should == false
end
it "returns true if other is equal as first element" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should == true
end
it "returns true if other is matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should == true
end
it "returns true if other is not matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should == true
end
it "returns true if other is equal as last element but not matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should == true
end
it "returns false if other is greater than last element but matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should == false
end
end
@@ -66,27 +66,27 @@ describe :range_cover, shared: true do
end
it "returns false if other is less than first element" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should == false
end
it "returns true if other is equal as first element" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should == true
end
it "returns true if other is matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should == true
end
it "returns true if other is not matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should == true
end
it "returns false if other is equal as last element but not matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should == false
end
it "returns false if other is greater than last element but matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should == false
end
end
end
@@ -95,99 +95,99 @@ end
describe :range_cover_subrange, shared: true do
context "range argument" do
it "accepts range argument" do
- (0..10).send(@method, (3..7)).should be_true
- (0..10).send(@method, (3..15)).should be_false
- (0..10).send(@method, (-2..7)).should be_false
+ (0..10).send(@method, (3..7)).should == true
+ (0..10).send(@method, (3..15)).should == false
+ (0..10).send(@method, (-2..7)).should == false
- (1.1..7.9).send(@method, (2.5..6.5)).should be_true
- (1.1..7.9).send(@method, (2.5..8.5)).should be_false
- (1.1..7.9).send(@method, (0.5..6.5)).should be_false
+ (1.1..7.9).send(@method, (2.5..6.5)).should == true
+ (1.1..7.9).send(@method, (2.5..8.5)).should == false
+ (1.1..7.9).send(@method, (0.5..6.5)).should == false
- ('c'..'i').send(@method, ('d'..'f')).should be_true
- ('c'..'i').send(@method, ('d'..'z')).should be_false
- ('c'..'i').send(@method, ('a'..'f')).should be_false
+ ('c'..'i').send(@method, ('d'..'f')).should == true
+ ('c'..'i').send(@method, ('d'..'z')).should == false
+ ('c'..'i').send(@method, ('a'..'f')).should == false
range_10_100 = RangeSpecs::TenfoldSucc.new(10)..RangeSpecs::TenfoldSucc.new(100)
range_20_90 = RangeSpecs::TenfoldSucc.new(20)..RangeSpecs::TenfoldSucc.new(90)
range_20_110 = RangeSpecs::TenfoldSucc.new(20)..RangeSpecs::TenfoldSucc.new(110)
range_0_90 = RangeSpecs::TenfoldSucc.new(0)..RangeSpecs::TenfoldSucc.new(90)
- range_10_100.send(@method, range_20_90).should be_true
- range_10_100.send(@method, range_20_110).should be_false
- range_10_100.send(@method, range_0_90).should be_false
+ range_10_100.send(@method, range_20_90).should == true
+ range_10_100.send(@method, range_20_110).should == false
+ range_10_100.send(@method, range_0_90).should == false
end
it "supports boundaries of different comparable types" do
- (0..10).send(@method, (3.1..7.9)).should be_true
- (0..10).send(@method, (3.1..15.9)).should be_false
- (0..10).send(@method, (-2.1..7.9)).should be_false
+ (0..10).send(@method, (3.1..7.9)).should == true
+ (0..10).send(@method, (3.1..15.9)).should == false
+ (0..10).send(@method, (-2.1..7.9)).should == false
end
it "returns false if types are not comparable" do
- (0..10).send(@method, ('a'..'z')).should be_false
- (0..10).send(@method, (RangeSpecs::TenfoldSucc.new(0)..RangeSpecs::TenfoldSucc.new(100))).should be_false
+ (0..10).send(@method, ('a'..'z')).should == false
+ (0..10).send(@method, (RangeSpecs::TenfoldSucc.new(0)..RangeSpecs::TenfoldSucc.new(100))).should == false
end
it "honors exclusion of right boundary (:exclude_end option)" do
# Integer
- (0..10).send(@method, (0..10)).should be_true
- (0...10).send(@method, (0...10)).should be_true
+ (0..10).send(@method, (0..10)).should == true
+ (0...10).send(@method, (0...10)).should == true
- (0..10).send(@method, (0...10)).should be_true
- (0...10).send(@method, (0..10)).should be_false
+ (0..10).send(@method, (0...10)).should == true
+ (0...10).send(@method, (0..10)).should == false
- (0...11).send(@method, (0..10)).should be_true
- (0..10).send(@method, (0...11)).should be_true
+ (0...11).send(@method, (0..10)).should == true
+ (0..10).send(@method, (0...11)).should == true
# Float
- (0..10.1).send(@method, (0..10.1)).should be_true
- (0...10.1).send(@method, (0...10.1)).should be_true
+ (0..10.1).send(@method, (0..10.1)).should == true
+ (0...10.1).send(@method, (0...10.1)).should == true
- (0..10.1).send(@method, (0...10.1)).should be_true
- (0...10.1).send(@method, (0..10.1)).should be_false
+ (0..10.1).send(@method, (0...10.1)).should == true
+ (0...10.1).send(@method, (0..10.1)).should == false
- (0...11.1).send(@method, (0..10.1)).should be_true
- (0..10.1).send(@method, (0...11.1)).should be_false
+ (0...11.1).send(@method, (0..10.1)).should == true
+ (0..10.1).send(@method, (0...11.1)).should == false
end
end
it "allows self to be a beginless range" do
- (...10).send(@method, (3..7)).should be_true
- (...10).send(@method, (3..15)).should be_false
+ (...10).send(@method, (3..7)).should == true
+ (...10).send(@method, (3..15)).should == false
- (..7.9).send(@method, (2.5..6.5)).should be_true
- (..7.9).send(@method, (2.5..8.5)).should be_false
+ (..7.9).send(@method, (2.5..6.5)).should == true
+ (..7.9).send(@method, (2.5..8.5)).should == false
- (..'i').send(@method, ('d'..'f')).should be_true
- (..'i').send(@method, ('d'..'z')).should be_false
+ (..'i').send(@method, ('d'..'f')).should == true
+ (..'i').send(@method, ('d'..'z')).should == false
end
it "allows self to be a endless range" do
- eval("(0...)").send(@method, (3..7)).should be_true
- eval("(5...)").send(@method, (3..15)).should be_false
+ eval("(0...)").send(@method, (3..7)).should == true
+ eval("(5...)").send(@method, (3..15)).should == false
- eval("(1.1..)").send(@method, (2.5..6.5)).should be_true
- eval("(3.3..)").send(@method, (2.5..8.5)).should be_false
+ eval("(1.1..)").send(@method, (2.5..6.5)).should == true
+ eval("(3.3..)").send(@method, (2.5..8.5)).should == false
- eval("('a'..)").send(@method, ('d'..'f')).should be_true
- eval("('p'..)").send(@method, ('d'..'z')).should be_false
+ eval("('a'..)").send(@method, ('d'..'f')).should == true
+ eval("('p'..)").send(@method, ('d'..'z')).should == false
end
it "accepts beginless range argument" do
- (..10).send(@method, (...10)).should be_true
- (0..10).send(@method, (...10)).should be_false
+ (..10).send(@method, (...10)).should == true
+ (0..10).send(@method, (...10)).should == false
- (1.1..7.9).send(@method, (...10.5)).should be_false
+ (1.1..7.9).send(@method, (...10.5)).should == false
- ('c'..'i').send(@method, (..'i')).should be_false
+ ('c'..'i').send(@method, (..'i')).should == false
end
it "accepts endless range argument" do
- eval("(0..)").send(@method, eval("(0...)")).should be_true
- (0..10).send(@method, eval("(0...)")).should be_false
+ eval("(0..)").send(@method, eval("(0...)")).should == true
+ (0..10).send(@method, eval("(0...)")).should == false
- (1.1..7.9).send(@method, eval("(0.8...)")).should be_false
+ (1.1..7.9).send(@method, eval("(0.8...)")).should == false
- ('c'..'i').send(@method, eval("('a'..)")).should be_false
+ ('c'..'i').send(@method, eval("('a'..)")).should == false
end
end
diff --git a/spec/ruby/core/range/shared/cover_and_include.rb b/spec/ruby/core/range/shared/cover_and_include.rb
index 7028afaa89..97721a7307 100644
--- a/spec/ruby/core/range/shared/cover_and_include.rb
+++ b/spec/ruby/core/range/shared/cover_and_include.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe :range_cover_and_include, shared: true do
@@ -20,8 +20,8 @@ describe :range_cover_and_include, shared: true do
end
it "returns true if other is an element of self for endless ranges" do
- eval("(1..)").send(@method, 2.4).should == true
- eval("(0.5...)").send(@method, 2.4).should == true
+ (1..).send(@method, 2.4).should == true
+ (0.5...).send(@method, 2.4).should == true
end
it "returns true if other is an element of self for beginless ranges" do
@@ -29,48 +29,58 @@ describe :range_cover_and_include, shared: true do
(...10.5).send(@method, 2.4).should == true
end
+ it "returns false if values are not comparable" do
+ (1..10).send(@method, nil).should == false
+ (1...10).send(@method, nil).should == false
+
+ (..10).send(@method, nil).should == false
+ (...10).send(@method, nil).should == false
+
+ (1..).send(@method, nil).should == false
+ (1...).send(@method, nil).should == false
+ end
+
it "compares values using <=>" do
rng = (1..5)
m = mock("int")
m.should_receive(:coerce).and_return([1, 2])
m.should_receive(:<=>).and_return(1)
- rng.send(@method, m).should be_false
+ rng.send(@method, m).should == false
end
it "raises an ArgumentError without exactly one argument" do
- ->{ (1..2).send(@method) }.should raise_error(ArgumentError)
- ->{ (1..2).send(@method, 1, 2) }.should raise_error(ArgumentError)
+ ->{ (1..2).send(@method) }.should.raise(ArgumentError)
+ ->{ (1..2).send(@method, 1, 2) }.should.raise(ArgumentError)
end
it "returns true if argument is equal to the first value of the range" do
- (0..5).send(@method, 0).should be_true
- ('f'..'s').send(@method, 'f').should be_true
+ (0..5).send(@method, 0).should == true
+ ('f'..'s').send(@method, 'f').should == true
end
it "returns true if argument is equal to the last value of the range" do
- (0..5).send(@method, 5).should be_true
- (0...5).send(@method, 4).should be_true
- ('f'..'s').send(@method, 's').should be_true
+ (0..5).send(@method, 5).should == true
+ (0...5).send(@method, 4).should == true
+ ('f'..'s').send(@method, 's').should == true
end
it "returns true if argument is less than the last value of the range and greater than the first value" do
- (20..30).send(@method, 28).should be_true
- ('e'..'h').send(@method, 'g').should be_true
- ("\u{999}".."\u{9999}").send @method, "\u{9995}"
+ (20..30).send(@method, 28).should == true
+ ('e'..'h').send(@method, 'g').should == true
end
it "returns true if argument is sole element in the range" do
- (30..30).send(@method, 30).should be_true
+ (30..30).send(@method, 30).should == true
end
it "returns false if range is empty" do
- (30...30).send(@method, 30).should be_false
- (30...30).send(@method, nil).should be_false
+ (30...30).send(@method, 30).should == false
+ (30...30).send(@method, nil).should == false
end
it "returns false if the range does not contain the argument" do
- ('A'..'C').send(@method, 20.9).should be_false
- ('A'...'C').send(@method, 'C').should be_false
+ ('A'..'C').send(@method, 20.9).should == false
+ ('A'...'C').send(@method, 'C').should == false
end
end
diff --git a/spec/ruby/core/range/shared/include.rb b/spec/ruby/core/range/shared/include.rb
index c6c5c2becf..5f0db48008 100644
--- a/spec/ruby/core/range/shared/include.rb
+++ b/spec/ruby/core/range/shared/include.rb
@@ -1,17 +1,17 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
describe :range_include, shared: true do
describe "on string elements" do
it "returns true if other is matched by element.succ" do
- ('a'..'c').send(@method, 'b').should be_true
- ('a'...'c').send(@method, 'b').should be_true
+ ('a'..'c').send(@method, 'b').should == true
+ ('a'...'c').send(@method, 'b').should == true
end
it "returns false if other is not matched by element.succ" do
- ('a'..'c').send(@method, 'bc').should be_false
- ('a'...'c').send(@method, 'bc').should be_false
+ ('a'..'c').send(@method, 'bc').should == false
+ ('a'...'c').send(@method, 'bc').should == false
end
end
@@ -22,27 +22,27 @@ describe :range_include, shared: true do
end
it "returns false if other is less than first element" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should == false
end
it "returns true if other is equal as first element" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should == true
end
it "returns true if other is matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should == true
end
it "returns false if other is not matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should == false
end
it "returns false if other is equal as last element but not matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should == false
end
it "returns false if other is greater than last element but matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should == false
end
end
@@ -52,27 +52,27 @@ describe :range_include, shared: true do
end
it "returns false if other is less than first element" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should == false
end
it "returns true if other is equal as first element" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should == true
end
it "returns true if other is matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should be_true
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should == true
end
it "returns false if other is not matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should == false
end
it "returns false if other is equal as last element but not matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should == false
end
it "returns false if other is greater than last element but matched by element.succ" do
- @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should be_false
+ @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should == false
end
end
end
diff --git a/spec/ruby/core/range/size_spec.rb b/spec/ruby/core/range/size_spec.rb
index 5462a1a5e1..3a8843b99d 100644
--- a/spec/ruby/core/range/size_spec.rb
+++ b/spec/ruby/core/range/size_spec.rb
@@ -4,45 +4,89 @@ describe "Range#size" do
it "returns the number of elements in the range" do
(1..16).size.should == 16
(1...16).size.should == 15
-
- (1.0..16.0).size.should == 16
- (1.0...16.0).size.should == 15
- (1.0..15.9).size.should == 15
- (1.1..16.0).size.should == 15
- (1.1..15.9).size.should == 15
end
it "returns 0 if last is less than first" do
(16..0).size.should == 0
- (16.0..0.0).size.should == 0
- (Float::INFINITY..0).size.should == 0
end
it 'returns Float::INFINITY for increasing, infinite ranges' do
(0..Float::INFINITY).size.should == Float::INFINITY
- (-Float::INFINITY..0).size.should == Float::INFINITY
- (-Float::INFINITY..Float::INFINITY).size.should == Float::INFINITY
end
it 'returns Float::INFINITY for endless ranges if the start is numeric' do
eval("(1..)").size.should == Float::INFINITY
- eval("(0.5...)").size.should == Float::INFINITY
end
it 'returns nil for endless ranges if the start is not numeric' do
eval("('z'..)").size.should == nil
- eval("([]...)").size.should == nil
end
- it 'returns Float::INFINITY for all beginless ranges' do
- (..1).size.should == Float::INFINITY
- (...0.5).size.should == Float::INFINITY
- (..nil).size.should == Float::INFINITY
- (...'o').size.should == Float::INFINITY
+ ruby_version_is ""..."3.4" do
+ it 'returns Float::INFINITY for all beginless ranges if the end is numeric' do
+ (..1).size.should == Float::INFINITY
+ (...0.5).size.should == Float::INFINITY
+ end
+
+ it 'returns nil for all beginless ranges if the end is not numeric' do
+ (...'o').size.should == nil
+ end
+
+ it 'returns nil if the start and the end is both nil' do
+ (nil..nil).size.should == nil
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "returns the number of elements in the range" do
+ (1.0..16.0).size.should == 16
+ (1.0...16.0).size.should == 15
+ (1.0..15.9).size.should == 15
+ (1.1..16.0).size.should == 15
+ (1.1..15.9).size.should == 15
+ end
+
+ it "returns 0 if last is less than first" do
+ (16.0..0.0).size.should == 0
+ (Float::INFINITY..0).size.should == 0
+ end
+
+ it 'returns Float::INFINITY for increasing, infinite ranges' do
+ (-Float::INFINITY..0).size.should == Float::INFINITY
+ (-Float::INFINITY..Float::INFINITY).size.should == Float::INFINITY
+ end
+
+ it 'returns Float::INFINITY for endless ranges if the start is numeric' do
+ eval("(0.5...)").size.should == Float::INFINITY
+ end
+
+ it 'returns nil for endless ranges if the start is not numeric' do
+ eval("([]...)").size.should == nil
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it 'raises TypeError if a range is not iterable' do
+ -> { (1.0..16.0).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (1.0...16.0).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (1.0..15.9).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (1.1..16.0).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (1.1..15.9).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (16.0..0.0).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (Float::INFINITY..0).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (-Float::INFINITY..0).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (-Float::INFINITY..Float::INFINITY).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (..1).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (...0.5).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (..nil).size }.should.raise(TypeError, /can't iterate from/)
+ -> { (...'o').size }.should.raise(TypeError, /can't iterate from/)
+ -> { eval("(0.5...)").size }.should.raise(TypeError, /can't iterate from/)
+ -> { eval("([]...)").size }.should.raise(TypeError, /can't iterate from/)
+ end
end
it "returns nil if first and last are not Numeric" do
- (:a..:z).size.should be_nil
- ('a'..'z').size.should be_nil
+ (:a..:z).size.should == nil
+ ('a'..'z').size.should == nil
end
end
diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb
index 61ddc5205d..faab95d88d 100644
--- a/spec/ruby/core/range/step_spec.rb
+++ b/spec/ruby/core/range/step_spec.rb
@@ -7,143 +7,188 @@ describe "Range#step" do
it "returns self" do
r = 1..2
- r.step { }.should equal(r)
+ r.step { }.should.equal?(r)
end
- it "raises TypeError if step" do
- obj = mock("mock")
- -> { (1..10).step(obj) { } }.should raise_error(TypeError)
- end
+ ruby_version_is ""..."3.4" do
+ it "calls #to_int to coerce step to an Integer" do
+ obj = mock("Range#step")
+ obj.should_receive(:to_int).and_return(1)
- it "calls #to_int to coerce step to an Integer" do
- obj = mock("Range#step")
- obj.should_receive(:to_int).and_return(1)
+ (1..2).step(obj) { |x| ScratchPad << x }
+ ScratchPad.recorded.should.eql?([1, 2])
+ end
- (1..2).step(obj) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([1, 2])
- end
+ it "raises a TypeError if step does not respond to #to_int" do
+ obj = mock("Range#step non-integer")
- it "raises a TypeError if step does not respond to #to_int" do
- obj = mock("Range#step non-integer")
+ -> { (1..2).step(obj) { } }.should.raise(TypeError)
+ end
- -> { (1..2).step(obj) { } }.should raise_error(TypeError)
- end
+ it "raises a TypeError if #to_int does not return an Integer" do
+ obj = mock("Range#step non-integer")
+ obj.should_receive(:to_int).and_return("1")
+
+ -> { (1..2).step(obj) { } }.should.raise(TypeError)
+ end
- it "raises a TypeError if #to_int does not return an Integer" do
- obj = mock("Range#step non-integer")
- obj.should_receive(:to_int).and_return("1")
+ it "raises a TypeError if the first element does not respond to #succ" do
+ obj = mock("Range#step non-comparable")
+ obj.should_receive(:<=>).with(obj).and_return(1)
- -> { (1..2).step(obj) { } }.should raise_error(TypeError)
+ -> { (obj..obj).step { |x| x } }.should.raise(TypeError)
+ end
end
- it "coerces the argument to integer by invoking to_int" do
- (obj = mock("2")).should_receive(:to_int).and_return(2)
- res = []
- (1..10).step(obj) {|x| res << x}
- res.should == [1, 3, 5, 7, 9]
- end
+ ruby_version_is "3.4" do
+ it "calls #coerce to coerce step to an Integer" do
+ obj = mock("Range#step")
+ obj.should_receive(:coerce).at_least(:once).and_return([1, 2])
- it "raises a TypeError if the first element does not respond to #succ" do
- obj = mock("Range#step non-comparable")
- obj.should_receive(:<=>).with(obj).and_return(1)
+ (1..3).step(obj) { |x| ScratchPad << x }
+ ScratchPad.recorded.should.eql?([1, 3])
+ end
+
+ it "raises a TypeError if step does not respond to #coerce" do
+ obj = mock("Range#step non-coercible")
- -> { (obj..obj).step { |x| x } }.should raise_error(TypeError)
+ -> { (1..2).step(obj) { } }.should.raise(TypeError)
+ end
end
it "raises an ArgumentError if step is 0" do
- -> { (-1..1).step(0) { |x| x } }.should raise_error(ArgumentError)
+ -> { (-1..1).step(0) { |x| x } }.should.raise(ArgumentError)
end
it "raises an ArgumentError if step is 0.0" do
- -> { (-1..1).step(0.0) { |x| x } }.should raise_error(ArgumentError)
+ -> { (-1..1).step(0.0) { |x| x } }.should.raise(ArgumentError)
end
- it "raises an ArgumentError if step is negative" do
- -> { (-1..1).step(-2) { |x| x } }.should raise_error(ArgumentError)
+ ruby_version_is "3.4" do
+ it "does not iterate if step is 0 for bounded non-numeric ranges" do
+ t = Time.utc(2023, 2, 24)
+ (t..t + 1).step(0) { |x| ScratchPad << x }
+ ScratchPad.recorded.should == []
+ end
+
+ it "raises an ArgumentError when iterating a beginless range" do
+ -> { (..10).step(1) { break } }.should.raise(ArgumentError,
+ "#step iteration for beginless ranges is meaningless")
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "raises an ArgumentError if step is negative" do
+ -> { (-1..1).step(-2) { |x| x } }.should.raise(ArgumentError)
+ end
end
describe "with inclusive end" do
describe "and Integer values" do
it "yields Integer values incremented by 1 and less than or equal to end when not passed a step" do
(-2..2).step { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2, -1, 0, 1, 2])
+ ScratchPad.recorded.should.eql?([-2, -1, 0, 1, 2])
end
it "yields Integer values incremented by an Integer step" do
(-5..5).step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-5, -3, -1, 1, 3, 5])
+ ScratchPad.recorded.should.eql?([-5, -3, -1, 1, 3, 5])
end
it "yields Float values incremented by a Float step" do
(-2..2).step(1.5) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -0.5, 1.0])
+ ScratchPad.recorded.should.eql?([-2.0, -0.5, 1.0])
+ end
+
+ ruby_version_is "3.4" do
+ it "does not iterate if step is negative for forward range" do
+ (-1..1).step(-1) { |x| ScratchPad << x }
+ ScratchPad.recorded.should.eql?([])
+ end
+
+ it "iterates backward if step is negative for backward range" do
+ (1..-1).step(-1) { |x| ScratchPad << x }
+ ScratchPad.recorded.should.eql?([1, 0, -1])
+ end
end
end
describe "and Float values" do
it "yields Float values incremented by 1 and less than or equal to end when not passed a step" do
(-2.0..2.0).step { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0, 2.0])
+ ScratchPad.recorded.should.eql?([-2.0, -1.0, 0.0, 1.0, 2.0])
end
it "yields Float values incremented by an Integer step" do
(-5.0..5.0).step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0, 5.0])
+ ScratchPad.recorded.should.eql?([-5.0, -3.0, -1.0, 1.0, 3.0, 5.0])
end
it "yields Float values incremented by a Float step" do
(-1.0..1.0).step(0.5) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5, 1.0])
+ ScratchPad.recorded.should.eql?([-1.0, -0.5, 0.0, 0.5, 1.0])
end
it "returns Float values of 'step * n + begin <= end'" do
(1.0..6.4).step(1.8) { |x| ScratchPad << x }
(1.0..12.7).step(1.3) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([1.0, 2.8, 4.6, 6.4, 1.0, 2.3, 3.6,
+ ScratchPad.recorded.should.eql?([1.0, 2.8, 4.6, 6.4, 1.0, 2.3, 3.6,
4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.7])
end
it "handles infinite values at either end" do
(-Float::INFINITY..0.0).step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
- ScratchPad.recorded.should eql([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
+ ScratchPad.recorded.should.eql?([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
ScratchPad.record []
(0.0..Float::INFINITY).step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
- ScratchPad.recorded.should eql([0.0, 2.0, 4.0])
+ ScratchPad.recorded.should.eql?([0.0, 2.0, 4.0])
+ end
+
+ ruby_version_is "3.4" do
+ it "does not iterate if step is negative for forward range" do
+ (-1.0..1.0).step(-0.5) { |x| ScratchPad << x }
+ ScratchPad.recorded.should.eql?([])
+ end
+
+ it "iterates backward if step is negative for backward range" do
+ (1.0..-1.0).step(-0.5) { |x| ScratchPad << x }
+ ScratchPad.recorded.should.eql?([1.0, 0.5, 0.0, -0.5, -1.0])
+ end
end
end
describe "and Integer, Float values" do
it "yields Float values incremented by 1 and less than or equal to end when not passed a step" do
(-2..2.0).step { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0, 2.0])
+ ScratchPad.recorded.should.eql?([-2.0, -1.0, 0.0, 1.0, 2.0])
end
it "yields Float values incremented by an Integer step" do
(-5..5.0).step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0, 5.0])
+ ScratchPad.recorded.should.eql?([-5.0, -3.0, -1.0, 1.0, 3.0, 5.0])
end
it "yields Float values incremented by a Float step" do
(-1..1.0).step(0.5) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5, 1.0])
+ ScratchPad.recorded.should.eql?([-1.0, -0.5, 0.0, 0.5, 1.0])
end
end
describe "and Float, Integer values" do
it "yields Float values incremented by 1 and less than or equal to end when not passed a step" do
(-2.0..2).step { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0, 2.0])
+ ScratchPad.recorded.should.eql?([-2.0, -1.0, 0.0, 1.0, 2.0])
end
it "yields Float values incremented by an Integer step" do
(-5.0..5).step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0, 5.0])
+ ScratchPad.recorded.should.eql?([-5.0, -3.0, -1.0, 1.0, 3.0, 5.0])
end
it "yields Float values incremented by a Float step" do
(-1.0..1).step(0.5) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5, 1.0])
+ ScratchPad.recorded.should.eql?([-1.0, -0.5, 0.0, 0.5, 1.0])
end
end
@@ -159,16 +204,99 @@ describe "Range#step" do
end
it "raises a TypeError when passed a Float step" do
- -> { ("A".."G").step(2.0) { } }.should raise_error(TypeError)
+ -> { ("A".."G").step(2.0) { } }.should.raise(TypeError)
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "calls #succ on begin and each element returned by #succ" do
+ obj = mock("Range#step String start")
+ obj.should_receive(:<=>).exactly(3).times.and_return(-1, -1, -1, 0)
+ obj.should_receive(:succ).exactly(2).times.and_return(obj)
+
+ (obj..obj).step { |x| ScratchPad << x }
+ ScratchPad.recorded.should == [obj, obj, obj]
+ end
end
- it "calls #succ on begin and each element returned by #succ" do
- obj = mock("Range#step String start")
- obj.should_receive(:<=>).exactly(3).times.and_return(-1, -1, -1, 0)
- obj.should_receive(:succ).exactly(2).times.and_return(obj)
+ ruby_version_is "3.4" do
+ it "yields String values adjusted by step and less than or equal to end" do
+ ("A".."AAA").step("A") { |x| ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "AA", "AAA"]
+ end
+
+ it "raises a TypeError when passed an incompatible type step" do
+ -> { ("A".."G").step([]) { } }.should.raise(TypeError)
+ end
+
+ it "calls #+ on begin and each element returned by #+" do
+ start = mock("Range#step String start")
+ stop = mock("Range#step String stop")
+
+ mid1 = mock("Range#step String mid1")
+ mid2 = mock("Range#step String mid2")
+
+ step = mock("Range#step String step")
+
+ # Deciding on the direction of iteration
+ start.should_receive(:<=>).with(stop).at_least(:twice).and_return(-1)
+ # Deciding whether the step moves iteration in the right direction
+ start.should_receive(:<=>).with(mid1).and_return(-1)
+ # Iteration 1
+ start.should_receive(:+).at_least(:once).with(step).and_return(mid1)
+ # Iteration 2
+ mid1.should_receive(:<=>).with(stop).and_return(-1)
+ mid1.should_receive(:+).with(step).and_return(mid2)
+ # Iteration 3
+ mid2.should_receive(:<=>).with(stop).and_return(0)
+
+ (start..stop).step(step) { |x| ScratchPad << x }
+ ScratchPad.recorded.should == [start, mid1, mid2]
+ end
+
+ it "iterates backward if the step is decreasing values, and the range is backward" do
+ start = mock("Range#step String start")
+ stop = mock("Range#step String stop")
+
+ mid1 = mock("Range#step String mid1")
+ mid2 = mock("Range#step String mid2")
+
+ step = mock("Range#step String step")
+
+ # Deciding on the direction of iteration
+ start.should_receive(:<=>).with(stop).at_least(:twice).and_return(1)
+ # Deciding whether the step moves iteration in the right direction
+ start.should_receive(:<=>).with(mid1).and_return(1)
+ # Iteration 1
+ start.should_receive(:+).at_least(:once).with(step).and_return(mid1)
+ # Iteration 2
+ mid1.should_receive(:<=>).with(stop).and_return(1)
+ mid1.should_receive(:+).with(step).and_return(mid2)
+ # Iteration 3
+ mid2.should_receive(:<=>).with(stop).and_return(0)
+
+ (start..stop).step(step) { |x| ScratchPad << x }
+ ScratchPad.recorded.should == [start, mid1, mid2]
+ end
+
+ it "does no iteration of the direction of the range and of the step don't match" do
+ start = mock("Range#step String start")
+ stop = mock("Range#step String stop")
+
+ mid1 = mock("Range#step String mid1")
+ mid2 = mock("Range#step String mid2")
+
+ step = mock("Range#step String step")
- (obj..obj).step { |x| ScratchPad << x }
- ScratchPad.recorded.should == [obj, obj, obj]
+ # Deciding on the direction of iteration: stop > start
+ start.should_receive(:<=>).with(stop).at_least(:twice).and_return(1)
+ # Deciding whether the step moves iteration in the right direction
+ # start + step < start, the direction is opposite to the range's
+ start.should_receive(:+).with(step).and_return(mid1)
+ start.should_receive(:<=>).with(mid1).and_return(-1)
+
+ (start..stop).step(step) { |x| ScratchPad << x }
+ ScratchPad.recorded.should == []
+ end
end
end
end
@@ -177,107 +305,125 @@ describe "Range#step" do
describe "and Integer values" do
it "yields Integer values incremented by 1 and less than end when not passed a step" do
(-2...2).step { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2, -1, 0, 1])
+ ScratchPad.recorded.should.eql?([-2, -1, 0, 1])
end
it "yields Integer values incremented by an Integer step" do
(-5...5).step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-5, -3, -1, 1, 3])
+ ScratchPad.recorded.should.eql?([-5, -3, -1, 1, 3])
end
it "yields Float values incremented by a Float step" do
(-2...2).step(1.5) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -0.5, 1.0])
+ ScratchPad.recorded.should.eql?([-2.0, -0.5, 1.0])
end
end
describe "and Float values" do
it "yields Float values incremented by 1 and less than end when not passed a step" do
(-2.0...2.0).step { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0])
+ ScratchPad.recorded.should.eql?([-2.0, -1.0, 0.0, 1.0])
end
it "yields Float values incremented by an Integer step" do
(-5.0...5.0).step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0])
+ ScratchPad.recorded.should.eql?([-5.0, -3.0, -1.0, 1.0, 3.0])
end
it "yields Float values incremented by a Float step" do
(-1.0...1.0).step(0.5) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5])
+ ScratchPad.recorded.should.eql?([-1.0, -0.5, 0.0, 0.5])
end
it "returns Float values of 'step * n + begin < end'" do
(1.0...6.4).step(1.8) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([1.0, 2.8, 4.6])
+ ScratchPad.recorded.should.eql?([1.0, 2.8, 4.6])
end
- ruby_version_is '3.1' do
- it "correctly handles values near the upper limit" do # https://bugs.ruby-lang.org/issues/16612
- (1.0...55.6).step(18.2) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([1.0, 19.2, 37.4, 55.599999999999994])
+ it "correctly handles values near the upper limit" do # https://bugs.ruby-lang.org/issues/16612
+ (1.0...55.6).step(18.2) { |x| ScratchPad << x }
+ ScratchPad.recorded.should.eql?([1.0, 19.2, 37.4, 55.599999999999994])
- (1.0...55.6).step(18.2).size.should == 4
- end
+ (1.0...55.6).step(18.2).size.should == 4
end
it "handles infinite values at either end" do
(-Float::INFINITY...0.0).step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
- ScratchPad.recorded.should eql([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
+ ScratchPad.recorded.should.eql?([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
ScratchPad.record []
(0.0...Float::INFINITY).step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
- ScratchPad.recorded.should eql([0.0, 2.0, 4.0])
+ ScratchPad.recorded.should.eql?([0.0, 2.0, 4.0])
+ end
+
+ ruby_version_is "3.4" do
+ it "iterates backward with exclusive end if step is negative" do
+ (1.0...-1.0).step(-0.5) { |x| ScratchPad << x }
+ ScratchPad.recorded.should.eql?([1.0, 0.5, 0.0, -0.5])
+ end
end
end
describe "and Integer, Float values" do
it "yields Float values incremented by 1 and less than end when not passed a step" do
(-2...2.0).step { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0])
+ ScratchPad.recorded.should.eql?([-2.0, -1.0, 0.0, 1.0])
end
it "yields Float values incremented by an Integer step" do
(-5...5.0).step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0])
+ ScratchPad.recorded.should.eql?([-5.0, -3.0, -1.0, 1.0, 3.0])
end
it "yields an Float and then Float values incremented by a Float step" do
(-1...1.0).step(0.5) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5])
+ ScratchPad.recorded.should.eql?([-1.0, -0.5, 0.0, 0.5])
end
end
describe "and Float, Integer values" do
it "yields Float values incremented by 1 and less than end when not passed a step" do
(-2.0...2).step { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0])
+ ScratchPad.recorded.should.eql?([-2.0, -1.0, 0.0, 1.0])
end
it "yields Float values incremented by an Integer step" do
(-5.0...5).step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0])
+ ScratchPad.recorded.should.eql?([-5.0, -3.0, -1.0, 1.0, 3.0])
end
it "yields Float values incremented by a Float step" do
(-1.0...1).step(0.5) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5])
+ ScratchPad.recorded.should.eql?([-1.0, -0.5, 0.0, 0.5])
end
end
describe "and String values" do
- it "yields String values incremented by #succ and less than or equal to end when not passed a step" do
- ("A"..."E").step { |x| ScratchPad << x }
- ScratchPad.recorded.should == ["A", "B", "C", "D"]
- end
+ ruby_version_is ""..."3.4" do
+ it "yields String values incremented by #succ and less than or equal to end when not passed a step" do
+ ("A"..."E").step { |x| ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "B", "C", "D"]
+ end
- it "yields String values incremented by #succ called Integer step times" do
- ("A"..."G").step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should == ["A", "C", "E"]
+ it "yields String values incremented by #succ called Integer step times" do
+ ("A"..."G").step(2) { |x| ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "C", "E"]
+ end
+
+ it "raises a TypeError when passed a Float step" do
+ -> { ("A"..."G").step(2.0) { } }.should.raise(TypeError)
+ end
end
- it "raises a TypeError when passed a Float step" do
- -> { ("A"..."G").step(2.0) { } }.should raise_error(TypeError)
+ ruby_version_is "3.4" do
+ it "yields String values adjusted by step and less than or equal to end" do
+ ("A"..."AAA").step("A") { |x| ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "AA"]
+ end
+
+ it "raises a TypeError when passed an incompatible type step" do
+ -> { ("A".."G").step([]) { } }.should.raise(TypeError)
+ end
end
end
end
@@ -285,139 +431,144 @@ describe "Range#step" do
describe "with an endless range" do
describe "and Integer values" do
it "yield Integer values incremented by 1 when not passed a step" do
- eval("(-2..)").step { |x| break if x > 2; ScratchPad << x }
- ScratchPad.recorded.should eql([-2, -1, 0, 1, 2])
+ (-2..).step { |x| break if x > 2; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-2, -1, 0, 1, 2])
ScratchPad.record []
- eval("(-2...)").step { |x| break if x > 2; ScratchPad << x }
- ScratchPad.recorded.should eql([-2, -1, 0, 1, 2])
+ (-2...).step { |x| break if x > 2; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-2, -1, 0, 1, 2])
end
it "yields Integer values incremented by an Integer step" do
- eval("(-5..)").step(2) { |x| break if x > 3; ScratchPad << x }
- ScratchPad.recorded.should eql([-5, -3, -1, 1, 3])
+ (-5..).step(2) { |x| break if x > 3; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-5, -3, -1, 1, 3])
ScratchPad.record []
- eval("(-5...)").step(2) { |x| break if x > 3; ScratchPad << x }
- ScratchPad.recorded.should eql([-5, -3, -1, 1, 3])
+ (-5...).step(2) { |x| break if x > 3; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-5, -3, -1, 1, 3])
end
it "yields Float values incremented by a Float step" do
- eval("(-2..)").step(1.5) { |x| break if x > 1.0; ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -0.5, 1.0])
+ (-2..).step(1.5) { |x| break if x > 1.0; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-2.0, -0.5, 1.0])
ScratchPad.record []
- eval("(-2..)").step(1.5) { |x| break if x > 1.0; ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -0.5, 1.0])
+ (-2..).step(1.5) { |x| break if x > 1.0; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-2.0, -0.5, 1.0])
end
end
describe "and Float values" do
it "yields Float values incremented by 1 and less than end when not passed a step" do
- eval("(-2.0..)").step { |x| break if x > 1.5; ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0])
+ (-2.0..).step { |x| break if x > 1.5; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-2.0, -1.0, 0.0, 1.0])
ScratchPad.record []
- eval("(-2.0...)").step { |x| break if x > 1.5; ScratchPad << x }
- ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0])
+ (-2.0...).step { |x| break if x > 1.5; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-2.0, -1.0, 0.0, 1.0])
end
it "yields Float values incremented by an Integer step" do
- eval("(-5.0..)").step(2) { |x| break if x > 3.5; ScratchPad << x }
- ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0])
+ (-5.0..).step(2) { |x| break if x > 3.5; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-5.0, -3.0, -1.0, 1.0, 3.0])
ScratchPad.record []
- eval("(-5.0...)").step(2) { |x| break if x > 3.5; ScratchPad << x }
- ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0])
+ (-5.0...).step(2) { |x| break if x > 3.5; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-5.0, -3.0, -1.0, 1.0, 3.0])
end
it "yields Float values incremented by a Float step" do
- eval("(-1.0..)").step(0.5) { |x| break if x > 0.6; ScratchPad << x }
- ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5])
+ (-1.0..).step(0.5) { |x| break if x > 0.6; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-1.0, -0.5, 0.0, 0.5])
ScratchPad.record []
- eval("(-1.0...)").step(0.5) { |x| break if x > 0.6; ScratchPad << x }
- ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5])
+ (-1.0...).step(0.5) { |x| break if x > 0.6; ScratchPad << x }
+ ScratchPad.recorded.should.eql?([-1.0, -0.5, 0.0, 0.5])
+ end
+
+ it "computes each value independently to avoid accumulating floating-point errors" do
+ result = []
+ (0.0..).step(0.1) { |x| result << x; break if result.size == 20 }
+ expected = 20.times.map { |i| i * 0.1 + 0.0 }
+ result.should.eql?(expected)
end
it "handles infinite values at the start" do
- eval("(-Float::INFINITY..)").step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
- ScratchPad.recorded.should eql([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
+ (-Float::INFINITY..).step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
+ ScratchPad.recorded.should.eql?([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
ScratchPad.record []
- eval("(-Float::INFINITY...)").step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
- ScratchPad.recorded.should eql([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
+ (-Float::INFINITY...).step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
+ ScratchPad.recorded.should.eql?([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
end
end
describe "and String values" do
it "yields String values incremented by #succ and less than or equal to end when not passed a step" do
- eval("('A'..)").step { |x| break if x > "D"; ScratchPad << x }
+ ('A'..).step { |x| break if x > "D"; ScratchPad << x }
ScratchPad.recorded.should == ["A", "B", "C", "D"]
ScratchPad.record []
- eval("('A'...)").step { |x| break if x > "D"; ScratchPad << x }
+ ('A'...).step { |x| break if x > "D"; ScratchPad << x }
ScratchPad.recorded.should == ["A", "B", "C", "D"]
end
it "yields String values incremented by #succ called Integer step times" do
- eval("('A'..)").step(2) { |x| break if x > "F"; ScratchPad << x }
+ ('A'..).step(2) { |x| break if x > "F"; ScratchPad << x }
ScratchPad.recorded.should == ["A", "C", "E"]
ScratchPad.record []
- eval("('A'...)").step(2) { |x| break if x > "F"; ScratchPad << x }
+ ('A'...).step(2) { |x| break if x > "F"; ScratchPad << x }
ScratchPad.recorded.should == ["A", "C", "E"]
end
it "raises a TypeError when passed a Float step" do
- -> { eval("('A'..)").step(2.0) { } }.should raise_error(TypeError)
- -> { eval("('A'...)").step(2.0) { } }.should raise_error(TypeError)
+ -> { ('A'..).step(2.0) { } }.should.raise(TypeError)
+ -> { ('A'...).step(2.0) { } }.should.raise(TypeError)
+ end
+
+ ruby_version_is "3.4" do
+ it "yields String values adjusted by step" do
+ ('A'..).step("A") { |x| break if x > "AAA"; ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "AA", "AAA"]
+
+ ScratchPad.record []
+ ('A'...).step("A") { |x| break if x > "AAA"; ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "AA", "AAA"]
+ end
+
+ it "raises a TypeError when passed an incompatible type step" do
+ -> { ('A'..).step([]) { } }.should.raise(TypeError)
+ -> { ('A'...).step([]) { } }.should.raise(TypeError)
+ end
end
end
end
describe "when no block is given" do
- ruby_version_is "3.0" do
- it "raises an ArgumentError if step is 0" do
- -> { (-1..1).step(0) }.should raise_error(ArgumentError)
- end
+ it "raises an ArgumentError if step is 0" do
+ -> { (-1..1).step(0) }.should.raise(ArgumentError)
end
describe "returned Enumerator" do
describe "size" do
- ruby_version_is ""..."3.0" do
+ ruby_version_is ""..."3.4" do
it "raises a TypeError if step does not respond to #to_int" do
obj = mock("Range#step non-integer")
- enum = (1..2).step(obj)
- -> { enum.size }.should raise_error(TypeError)
+ -> { (1..2).step(obj) }.should.raise(TypeError)
end
it "raises a TypeError if #to_int does not return an Integer" do
obj = mock("Range#step non-integer")
obj.should_receive(:to_int).and_return("1")
- enum = (1..2).step(obj)
-
- -> { enum.size }.should raise_error(TypeError)
+ -> { (1..2).step(obj) }.should.raise(TypeError)
end
end
- ruby_version_is "3.0" do
- it "raises a TypeError if step does not respond to #to_int" do
+ ruby_version_is "3.4" do
+ it "does not raise if step is incompatible" do
obj = mock("Range#step non-integer")
- -> { (1..2).step(obj) }.should raise_error(TypeError)
- end
-
- it "raises a TypeError if #to_int does not return an Integer" do
- obj = mock("Range#step non-integer")
- obj.should_receive(:to_int).and_return("1")
- -> { (1..2).step(obj) }.should raise_error(TypeError)
- end
- end
-
- ruby_version_is ""..."3.0" do
- it "returns Float::INFINITY for zero step" do
- (-1..1).step(0).size.should == Float::INFINITY
- (-1..1).step(0.0).size.should == Float::INFINITY
+ -> { (1..2).step(obj) }.should_not.raise
end
end
@@ -458,26 +609,47 @@ describe "Range#step" do
(1.0...6.4).step(1.8).size.should == 3
end
- it "returns nil with begin and end are String" do
- ("A".."E").step(2).size.should == nil
- ("A"..."E").step(2).size.should == nil
- ("A".."E").step.size.should == nil
- ("A"..."E").step.size.should == nil
+ ruby_version_is ""..."3.4" do
+ it "returns nil with begin and end are String" do
+ ("A".."E").step(2).size.should == nil
+ ("A"..."E").step(2).size.should == nil
+ ("A".."E").step.size.should == nil
+ ("A"..."E").step.size.should == nil
+ end
+
+ it "return nil and not raises a TypeError if the first element does not respond to #succ" do
+ obj = mock("Range#step non-comparable")
+ obj.should_receive(:<=>).with(obj).and_return(1)
+ enum = (obj..obj).step
+ -> { enum.size }.should_not.raise
+ enum.size.should == nil
+ end
end
- it "return nil and not raises a TypeError if the first element does not respond to #succ" do
- obj = mock("Range#step non-comparable")
- obj.should_receive(:<=>).with(obj).and_return(1)
- enum = (obj..obj).step
- -> { enum.size }.should_not raise_error
- enum.size.should == nil
+ ruby_version_is "3.4" do
+ it "returns nil with begin and end are String" do
+ ("A".."E").step("A").size.should == nil
+ ("A"..."E").step("A").size.should == nil
+ end
+
+ it "return nil and not raises a TypeError if the first element is not of compatible type" do
+ obj = mock("Range#step non-comparable")
+ obj.should_receive(:<=>).with(obj).and_return(1)
+ enum = (obj..obj).step(obj)
+ -> { enum.size }.should_not.raise
+ enum.size.should == nil
+ end
end
end
+ # We use .take below to ensure the enumerator works
+ # because that's an Enumerable method and so it uses the Enumerator behavior
+ # not just a method overridden in Enumerator::ArithmeticSequence.
describe "type" do
context "when both begin and end are numerics" do
it "returns an instance of Enumerator::ArithmeticSequence" do
(1..10).step.class.should == Enumerator::ArithmeticSequence
+ (1..10).step(3).take(4).should == [1, 4, 7, 10]
end
end
@@ -490,22 +662,61 @@ describe "Range#step" do
context "when range is endless" do
it "returns an instance of Enumerator::ArithmeticSequence when begin is numeric" do
(1..).step.class.should == Enumerator::ArithmeticSequence
+ (1..).step(2).take(3).should == [1, 3, 5]
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "returns an instance of Enumerator when begin is not numeric" do
+ ("a"..).step.class.should == Enumerator
+ ("a"..).step(2).take(3).should == %w[a c e]
+ end
end
- it "returns an instance of Enumerator when begin is not numeric" do
- ("a"..).step.class.should == Enumerator
+ ruby_version_is "3.4" do
+ it "returns an instance of Enumerator when begin is not numeric" do
+ ("a"..).step("a").class.should == Enumerator
+ ("a"..).step("a").take(3).should == %w[a aa aaa]
+ end
end
end
context "when range is beginless and endless" do
- it "returns an instance of Enumerator" do
- Range.new(nil, nil).step.class.should == Enumerator
+ ruby_version_is ""..."3.4" do
+ it "returns an instance of Enumerator" do
+ Range.new(nil, nil).step.class.should == Enumerator
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError" do
+ -> { Range.new(nil, nil).step(1) }.should.raise(ArgumentError,
+ "#step for non-numeric beginless ranges is meaningless")
+ end
+ end
+ end
+
+ context "when range is beginless and finite" do
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError if step is non-numeric" do
+ -> { (..10).step("a") }.should.raise(ArgumentError,
+ "#step for non-numeric beginless ranges is meaningless")
+ end
end
end
context "when begin and end are not numerics" do
- it "returns an instance of Enumerator" do
- ("a".."z").step.class.should == Enumerator
+ ruby_version_is ""..."3.4" do
+ it "returns an instance of Enumerator" do
+ ("a".."z").step.class.should == Enumerator
+ ("a".."z").step(3).take(4).should == %w[a d g j]
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "returns an instance of Enumerator" do
+ ("a".."z").step("a").class.should == Enumerator
+ ("a".."z").step("a").take(4).should == %w[a aa aaa aaaa]
+ end
end
end
end
diff --git a/spec/ruby/core/range/to_a_spec.rb b/spec/ruby/core/range/to_a_spec.rb
index b1d3de32db..6221ae5f71 100644
--- a/spec/ruby/core/range/to_a_spec.rb
+++ b/spec/ruby/core/range/to_a_spec.rb
@@ -6,7 +6,7 @@ describe "Range#to_a" do
('A'..'D').to_a.should == ['A','B','C','D']
('A'...'D').to_a.should == ['A','B','C']
(0xfffd...0xffff).to_a.should == [0xfffd,0xfffe]
- -> { (0.5..2.4).to_a }.should raise_error(TypeError)
+ -> { (0.5..2.4).to_a }.should.raise(TypeError)
end
it "returns empty array for descending-ordered" do
@@ -30,10 +30,10 @@ describe "Range#to_a" do
end
it "throws an exception for endless ranges" do
- -> { eval("(1..)").to_a }.should raise_error(RangeError)
+ -> { eval("(1..)").to_a }.should.raise(RangeError)
end
it "throws an exception for beginless ranges" do
- -> { (..1).to_a }.should raise_error(TypeError)
+ -> { (..1).to_a }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/range/to_set_spec.rb b/spec/ruby/core/range/to_set_spec.rb
new file mode 100644
index 0000000000..ac81d2cc4b
--- /dev/null
+++ b/spec/ruby/core/range/to_set_spec.rb
@@ -0,0 +1,54 @@
+require_relative '../../spec_helper'
+require_relative '../enumerable/fixtures/classes'
+
+describe "Range#to_set" do
+ it "returns a new Set created from self" do
+ (1..4).to_set.should == Set[1, 2, 3, 4]
+ (1...4).to_set.should == Set[1, 2, 3]
+ end
+
+ it "passes down passed blocks" do
+ (1..3).to_set { |x| x * x }.should == Set[1, 4, 9]
+ end
+
+ it "raises a TypeError for a beginningless range" do
+ -> {
+ (..0).to_set
+ }.should.raise(TypeError, "can't iterate from NilClass")
+ end
+
+ ruby_version_is "4.0" do
+ it "raises a RangeError if the range is endless" do
+ -> { (1..).to_set }.should.raise(RangeError, "cannot convert endless range to a set")
+ -> { (1...).to_set }.should.raise(RangeError, "cannot convert endless range to a set")
+ end
+ end
+
+ context "given positional arguments" do
+ ruby_version_is ""..."4.0" do
+ it "instantiates an object of provided as the first argument set class" do
+ set = (1..3).to_set(EnumerableSpecs::SetSubclass)
+ set.should.is_a?(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
+ end
+ end
+
+ ruby_version_is "4.0"..."4.1" do
+ it "instantiates an object of provided as the first argument set class and warns" do
+ -> {
+ set = (1..3).to_set(EnumerableSpecs::SetSubclass)
+ set.should.is_a?(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
+ }.should complain(/warning: passing arguments to Enumerable#to_set is deprecated/)
+ end
+ end
+
+ ruby_version_is "4.1" do
+ it "does not accept any positional argument" do
+ -> {
+ (1..3).to_set(EnumerableSpecs::SetSubclass)
+ }.should.raise(ArgumentError, "wrong number of arguments (given 1, expected 0)")
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/rational/abs_spec.rb b/spec/ruby/core/rational/abs_spec.rb
index aed7713058..54099aa14d 100644
--- a/spec/ruby/core/rational/abs_spec.rb
+++ b/spec/ruby/core/rational/abs_spec.rb
@@ -1,4 +1,5 @@
-require_relative '../../shared/rational/abs'
+require_relative "../../spec_helper"
+require_relative 'shared/abs'
describe "Rational#abs" do
it_behaves_like :rational_abs, :abs
diff --git a/spec/ruby/core/rational/ceil_spec.rb b/spec/ruby/core/rational/ceil_spec.rb
index 5b0ca4a9d6..0464eab101 100644
--- a/spec/ruby/core/rational/ceil_spec.rb
+++ b/spec/ruby/core/rational/ceil_spec.rb
@@ -1,5 +1,48 @@
-require_relative '../../shared/rational/ceil'
+require_relative "../../spec_helper"
+require_relative "../integer/shared/integer_ceil_precision"
describe "Rational#ceil" do
- it_behaves_like :rational_ceil, :ceil
+ context "with values equal to integers" do
+ it_behaves_like :integer_ceil_precision, :Rational
+ end
+
+ before do
+ @rational = Rational(2200, 7)
+ end
+
+ describe "with no arguments (precision = 0)" do
+ it "returns the Integer value rounded toward positive infinity" do
+ @rational.ceil.should.eql? 315
+
+ Rational(1, 2).ceil.should.eql? 1
+ Rational(-1, 2).ceil.should.eql? 0
+ Rational(1, 1).ceil.should.eql? 1
+ end
+ end
+
+ describe "with a precision < 0" do
+ it "moves the rounding point n decimal places left, returning an Integer" do
+ @rational.ceil(-3).should.eql? 1000
+ @rational.ceil(-2).should.eql? 400
+ @rational.ceil(-1).should.eql? 320
+
+ Rational(100, 2).ceil(-1).should.eql? 50
+ Rational(100, 2).ceil(-2).should.eql? 100
+ Rational(-100, 2).ceil(-1).should.eql?(-50)
+ Rational(-100, 2).ceil(-2).should.eql?(0)
+ end
+ end
+
+ describe "with precision > 0" do
+ it "moves the rounding point n decimal places right, returning a Rational" do
+ @rational.ceil(1).should.eql? Rational(3143, 10)
+ @rational.ceil(2).should.eql? Rational(31429, 100)
+ @rational.ceil(3).should.eql? Rational(157143, 500)
+
+ Rational(100, 2).ceil(1).should.eql? Rational(50, 1)
+ Rational(100, 2).ceil(2).should.eql? Rational(50, 1)
+ Rational(-100, 2).ceil(1).should.eql? Rational(-50, 1)
+ Rational(-100, 2).ceil(2).should.eql? Rational(-50, 1)
+ end
+ end
end
diff --git a/spec/ruby/core/rational/coerce_spec.rb b/spec/ruby/core/rational/coerce_spec.rb
deleted file mode 100644
index 3f78f0bcd6..0000000000
--- a/spec/ruby/core/rational/coerce_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../shared/rational/coerce'
-
-describe "Rational#coerce" do
- it_behaves_like :rational_coerce, :coerce
-end
diff --git a/spec/ruby/core/rational/comparison_spec.rb b/spec/ruby/core/rational/comparison_spec.rb
index 9d8e7fd7ee..482e904989 100644
--- a/spec/ruby/core/rational/comparison_spec.rb
+++ b/spec/ruby/core/rational/comparison_spec.rb
@@ -1,22 +1,93 @@
-require_relative '../../shared/rational/comparison'
+require_relative "../../spec_helper"
+require_relative 'fixtures/rational'
describe "Rational#<=> when passed a Rational object" do
- it_behaves_like :rational_cmp_rat, :<=>
+ it "returns 1 when self is greater than the passed argument" do
+ (Rational(4, 4) <=> Rational(3, 4)).should.equal?(1)
+ (Rational(-3, 4) <=> Rational(-4, 4)).should.equal?(1)
+ end
+
+ it "returns 0 when self is equal to the passed argument" do
+ (Rational(4, 4) <=> Rational(4, 4)).should.equal?(0)
+ (Rational(-3, 4) <=> Rational(-3, 4)).should.equal?(0)
+ end
+
+ it "returns -1 when self is less than the passed argument" do
+ (Rational(3, 4) <=> Rational(4, 4)).should.equal?(-1)
+ (Rational(-4, 4) <=> Rational(-3, 4)).should.equal?(-1)
+ end
end
describe "Rational#<=> when passed an Integer object" do
- it_behaves_like :rational_cmp_int, :<=>
+ it "returns 1 when self is greater than the passed argument" do
+ (Rational(4, 4) <=> 0).should.equal?(1)
+ (Rational(4, 4) <=> -10).should.equal?(1)
+ (Rational(-3, 4) <=> -1).should.equal?(1)
+ end
+
+ it "returns 0 when self is equal to the passed argument" do
+ (Rational(4, 4) <=> 1).should.equal?(0)
+ (Rational(-8, 4) <=> -2).should.equal?(0)
+ end
+
+ it "returns -1 when self is less than the passed argument" do
+ (Rational(3, 4) <=> 1).should.equal?(-1)
+ (Rational(-4, 4) <=> 0).should.equal?(-1)
+ end
end
describe "Rational#<=> when passed a Float object" do
- it_behaves_like :rational_cmp_float, :<=>
+ it "returns 1 when self is greater than the passed argument" do
+ (Rational(4, 4) <=> 0.5).should.equal?(1)
+ (Rational(4, 4) <=> -1.5).should.equal?(1)
+ (Rational(-3, 4) <=> -0.8).should.equal?(1)
+ end
+
+ it "returns 0 when self is equal to the passed argument" do
+ (Rational(4, 4) <=> 1.0).should.equal?(0)
+ (Rational(-6, 4) <=> -1.5).should.equal?(0)
+ end
+
+ it "returns -1 when self is less than the passed argument" do
+ (Rational(3, 4) <=> 1.2).should.equal?(-1)
+ (Rational(-4, 4) <=> 0.5).should.equal?(-1)
+ end
end
describe "Rational#<=> when passed an Object that responds to #coerce" do
- it_behaves_like :rational_cmp_coerce, :<=>
- it_behaves_like :rational_cmp_coerce_exception, :<=>
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational <=> obj
+ end
+
+ it "calls #<=> on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:<=>).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational <=> obj).should == :result
+ end
+
+ it "does not rescue exception raised in other#coerce" do
+ b = mock("numeric with failed #coerce")
+ b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError)
+
+ -> { Rational(3, 4) <=> b }.should.raise(RationalSpecs::CoerceError)
+ end
end
describe "Rational#<=> when passed a non-Numeric Object that doesn't respond to #coerce" do
- it_behaves_like :rational_cmp_other, :<=>
+ it "returns nil" do
+ (Rational <=> mock("Object")).should == nil
+ end
end
diff --git a/spec/ruby/core/rational/denominator_spec.rb b/spec/ruby/core/rational/denominator_spec.rb
index 6214b40587..ba6e936d60 100644
--- a/spec/ruby/core/rational/denominator_spec.rb
+++ b/spec/ruby/core/rational/denominator_spec.rb
@@ -1,5 +1,14 @@
-require_relative '../../shared/rational/denominator'
+require_relative "../../spec_helper"
describe "Rational#denominator" do
- it_behaves_like :rational_denominator, :denominator
+ it "returns the denominator" do
+ Rational(3, 4).denominator.should.equal?(4)
+ Rational(3, -4).denominator.should.equal?(4)
+
+ Rational(1, bignum_value).denominator.should == bignum_value
+ end
+
+ it "returns 1 if no denominator was given" do
+ Rational(80).denominator.should == 1
+ end
end
diff --git a/spec/ruby/core/rational/div_spec.rb b/spec/ruby/core/rational/div_spec.rb
index 1cd8606b90..a679663543 100644
--- a/spec/ruby/core/rational/div_spec.rb
+++ b/spec/ruby/core/rational/div_spec.rb
@@ -1,17 +1,54 @@
-require_relative '../../shared/rational/div'
+require_relative "../../spec_helper"
describe "Rational#div" do
- it_behaves_like :rational_div, :div
+ it "returns an Integer" do
+ Rational(229, 21).div(82).should.is_a?(Integer)
+ end
+
+ it "raises an ArgumentError if passed more than one argument" do
+ -> { Rational(3, 4).div(2,3) }.should.raise(ArgumentError)
+ end
+
+ # See http://redmine.ruby-lang.org/issues/show/1648
+ it "raises a TypeError if passed a non-numeric argument" do
+ -> { Rational(3, 4).div([]) }.should.raise(TypeError)
+ end
end
describe "Rational#div passed a Rational" do
- it_behaves_like :rational_div_rat, :div
+ it "performs integer division and returns the result" do
+ Rational(2, 3).div(Rational(2, 3)).should == 1
+ Rational(-2, 9).div(Rational(-9, 2)).should == 0
+ end
+
+ it "raises a ZeroDivisionError when the argument has a numerator of 0" do
+ -> { Rational(3, 4).div(Rational(0, 3)) }.should.raise(ZeroDivisionError)
+ end
+
+ it "raises a ZeroDivisionError when the argument has a numerator of 0.0" do
+ -> { Rational(3, 4).div(Rational(0.0, 3)) }.should.raise(ZeroDivisionError)
+ end
end
describe "Rational#div passed an Integer" do
- it_behaves_like :rational_div_int, :div
+ it "performs integer division and returns the result" do
+ Rational(2, 1).div(1).should == 2
+ Rational(25, 5).div(-50).should == -1
+ end
+
+ it "raises a ZeroDivisionError when the argument is 0" do
+ -> { Rational(3, 4).div(0) }.should.raise(ZeroDivisionError)
+ end
end
describe "Rational#div passed a Float" do
- it_behaves_like :rational_div_float, :div
+ it "performs integer division and returns the result" do
+ Rational(2, 3).div(30.333).should == 0
+ Rational(2, 9).div(Rational(-8.6)).should == -1
+ Rational(3.12).div(0.5).should == 6
+ end
+
+ it "raises a ZeroDivisionError when the argument is 0.0" do
+ -> { Rational(3, 4).div(0.0) }.should.raise(ZeroDivisionError)
+ end
end
diff --git a/spec/ruby/core/rational/divide_spec.rb b/spec/ruby/core/rational/divide_spec.rb
index d8e3a44dc2..c45d1fca2f 100644
--- a/spec/ruby/core/rational/divide_spec.rb
+++ b/spec/ruby/core/rational/divide_spec.rb
@@ -1,19 +1,74 @@
-require_relative '../../shared/rational/divide'
-require_relative '../../shared/rational/arithmetic_exception_in_coerce'
+require_relative "../../spec_helper"
+require_relative 'shared/arithmetic_exception_in_coerce'
describe "Rational#/" do
- it_behaves_like :rational_divide, :/
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational / obj
+ end
+
+ it "calls #/ on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:/).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational / obj).should == :result
+ end
+
it_behaves_like :rational_arithmetic_exception_in_coerce, :/
end
describe "Rational#/ when passed an Integer" do
- it_behaves_like :rational_divide_int, :/
+ it "returns self divided by other as a Rational" do
+ (Rational(3, 4) / 2).should.eql?(Rational(3, 8))
+ (Rational(2, 4) / 2).should.eql?(Rational(1, 4))
+ (Rational(6, 7) / -2).should.eql?(Rational(-3, 7))
+ end
+
+ it "raises a ZeroDivisionError when passed 0" do
+ -> { Rational(3, 4) / 0 }.should.raise(ZeroDivisionError)
+ end
end
describe "Rational#/ when passed a Rational" do
- it_behaves_like :rational_divide_rat, :/
+ it "returns self divided by other as a Rational" do
+ (Rational(3, 4) / Rational(3, 4)).should.eql?(Rational(1, 1))
+ (Rational(2, 4) / Rational(1, 4)).should.eql?(Rational(2, 1))
+
+ (Rational(2, 4) / 2).should == Rational(1, 4)
+ (Rational(6, 7) / -2).should == Rational(-3, 7)
+ end
+
+ it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do
+ -> { Rational(3, 4) / Rational(0, 1) }.should.raise(ZeroDivisionError)
+ end
end
describe "Rational#/ when passed a Float" do
- it_behaves_like :rational_divide_float, :/
+ it "returns self divided by other as a Float" do
+ (Rational(3, 4) / 0.75).should.eql?(1.0)
+ (Rational(3, 4) / 0.25).should.eql?(3.0)
+ (Rational(3, 4) / 0.3).should.eql?(2.5)
+
+ (Rational(-3, 4) / 0.3).should.eql?(-2.5)
+ (Rational(3, -4) / 0.3).should.eql?(-2.5)
+ (Rational(3, 4) / -0.3).should.eql?(-2.5)
+ end
+
+ it "returns infinity when passed 0" do
+ (Rational(3, 4) / 0.0).infinite?.should.eql?(1)
+ (Rational(-3, -4) / 0.0).infinite?.should.eql?(1)
+
+ (Rational(-3, 4) / 0.0).infinite?.should.eql?(-1)
+ (Rational(3, -4) / 0.0).infinite?.should.eql?(-1)
+ end
end
diff --git a/spec/ruby/core/rational/divmod_spec.rb b/spec/ruby/core/rational/divmod_spec.rb
index 6be1f8bd73..68f8ecfd2d 100644
--- a/spec/ruby/core/rational/divmod_spec.rb
+++ b/spec/ruby/core/rational/divmod_spec.rb
@@ -1,13 +1,42 @@
-require_relative '../../shared/rational/divmod'
+require_relative "../../spec_helper"
describe "Rational#divmod when passed a Rational" do
- it_behaves_like :rational_divmod_rat, :divmod
+ it "returns the quotient as Integer and the remainder as Rational" do
+ Rational(7, 4).divmod(Rational(1, 2)).should.eql?([3, Rational(1, 4)])
+ Rational(7, 4).divmod(Rational(-1, 2)).should.eql?([-4, Rational(-1, 4)])
+ Rational(0, 4).divmod(Rational(4, 3)).should.eql?([0, Rational(0, 1)])
+
+ Rational(bignum_value, 4).divmod(Rational(4, 3)).should.eql?([3458764513820540928, Rational(0, 1)])
+ end
+
+ it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do
+ -> { Rational(7, 4).divmod(Rational(0, 3)) }.should.raise(ZeroDivisionError)
+ end
end
describe "Rational#divmod when passed an Integer" do
- it_behaves_like :rational_divmod_int, :divmod
+ it "returns the quotient as Integer and the remainder as Rational" do
+ Rational(7, 4).divmod(2).should.eql?([0, Rational(7, 4)])
+ Rational(7, 4).divmod(-2).should.eql?([-1, Rational(-1, 4)])
+
+ Rational(bignum_value, 4).divmod(3).should.eql?([1537228672809129301, Rational(1, 1)])
+ end
+
+ it "raises a ZeroDivisionError when passed 0" do
+ -> { Rational(7, 4).divmod(0) }.should.raise(ZeroDivisionError)
+ end
end
describe "Rational#divmod when passed a Float" do
- it_behaves_like :rational_divmod_float, :divmod
+ it "returns the quotient as Integer and the remainder as Float" do
+ Rational(7, 4).divmod(0.5).should.eql?([3, 0.25])
+ end
+
+ it "returns the quotient as Integer and the remainder as Float" do
+ Rational(7, 4).divmod(-0.5).should.eql?([-4, -0.25])
+ end
+
+ it "raises a ZeroDivisionError when passed 0" do
+ -> { Rational(7, 4).divmod(0.0) }.should.raise(ZeroDivisionError)
+ end
end
diff --git a/spec/ruby/core/rational/equal_value_spec.rb b/spec/ruby/core/rational/equal_value_spec.rb
index 8e7acb1354..1dd077ea41 100644
--- a/spec/ruby/core/rational/equal_value_spec.rb
+++ b/spec/ruby/core/rational/equal_value_spec.rb
@@ -1,17 +1,39 @@
-require_relative '../../shared/rational/equal_value'
+require_relative "../../spec_helper"
describe "Rational#==" do
- it_behaves_like :rational_equal_value, :==
+ it "returns the result of calling #== with self on the passed argument" do
+ obj = mock("Object")
+ obj.should_receive(:==).and_return(:result)
+
+ (Rational(3, 4) == obj).should_not == false
+ end
end
describe "Rational#== when passed a Rational" do
- it_behaves_like :rational_equal_value_rat, :==
+ it "returns true if self has the same numerator and denominator as the passed argument" do
+ (Rational(3, 4) == Rational(3, 4)).should == true
+ (Rational(-3, -4) == Rational(3, 4)).should == true
+ (Rational(-4, 5) == Rational(4, -5)).should == true
+
+ (Rational(bignum_value, 3) == Rational(bignum_value, 3)).should == true
+ (Rational(-bignum_value, 3) == Rational(bignum_value, -3)).should == true
+ end
end
describe "Rational#== when passed a Float" do
- it_behaves_like :rational_equal_value_float, :==
+ it "converts self to a Float and compares it with the passed argument" do
+ (Rational(3, 4) == 0.75).should == true
+ (Rational(4, 2) == 2.0).should == true
+ (Rational(-4, 2) == -2.0).should == true
+ (Rational(4, -2) == -2.0).should == true
+ end
end
describe "Rational#== when passed an Integer" do
- it_behaves_like :rational_equal_value_int, :==
+ it "returns true if self has the passed argument as numerator and a denominator of 1" do
+ # Rational(x, y) reduces x and y automatically
+ (Rational(4, 2) == 2).should == true
+ (Rational(-4, 2) == -2).should == true
+ (Rational(4, -2) == -2).should == true
+ end
end
diff --git a/spec/ruby/core/rational/exponent_spec.rb b/spec/ruby/core/rational/exponent_spec.rb
index 622cf22782..88b4a43796 100644
--- a/spec/ruby/core/rational/exponent_spec.rb
+++ b/spec/ruby/core/rational/exponent_spec.rb
@@ -1,5 +1,236 @@
-require_relative '../../shared/rational/exponent'
+require_relative "../../spec_helper"
describe "Rational#**" do
- it_behaves_like :rational_exponent, :**
+ describe "when passed Rational" do
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ it "returns Rational(1) if the exponent is Rational(0)" do
+ (Rational(0) ** Rational(0)).should.eql?(Rational(1))
+ (Rational(1) ** Rational(0)).should.eql?(Rational(1))
+ (Rational(3, 4) ** Rational(0)).should.eql?(Rational(1))
+ (Rational(-1) ** Rational(0)).should.eql?(Rational(1))
+ (Rational(-3, 4) ** Rational(0)).should.eql?(Rational(1))
+ (Rational(bignum_value) ** Rational(0)).should.eql?(Rational(1))
+ (Rational(-bignum_value) ** Rational(0)).should.eql?(Rational(1))
+ end
+
+ it "returns self raised to the argument as a Rational if the exponent's denominator is 1" do
+ (Rational(3, 4) ** Rational(1, 1)).should.eql?(Rational(3, 4))
+ (Rational(3, 4) ** Rational(2, 1)).should.eql?(Rational(9, 16))
+ (Rational(3, 4) ** Rational(-1, 1)).should.eql?(Rational(4, 3))
+ (Rational(3, 4) ** Rational(-2, 1)).should.eql?(Rational(16, 9))
+ end
+
+ it "returns self raised to the argument as a Float if the exponent's denominator is not 1" do
+ (Rational(3, 4) ** Rational(4, 3)).should be_close(0.681420222312052, TOLERANCE)
+ (Rational(3, 4) ** Rational(-4, 3)).should be_close(1.46752322173095, TOLERANCE)
+ (Rational(3, 4) ** Rational(4, -3)).should be_close(1.46752322173095, TOLERANCE)
+ end
+
+ it "returns a complex number when self is negative and the passed argument is not 0" do
+ (Rational(-3, 4) ** Rational(-4, 3)).should be_close(Complex(-0.7337616108654732, 1.2709123906625817), TOLERANCE)
+ end
+ end
+ end
+
+ describe "when passed Integer" do
+ it "returns the Rational value of self raised to the passed argument" do
+ (Rational(3, 4) ** 4).should == Rational(81, 256)
+ (Rational(3, 4) ** -4).should == Rational(256, 81)
+ (Rational(-3, 4) ** -4).should == Rational(256, 81)
+ (Rational(3, -4) ** -4).should == Rational(256, 81)
+
+ (Rational(bignum_value, 4) ** 4).should == Rational(452312848583266388373324160190187140051835877600158453279131187530910662656, 1)
+ (Rational(3, bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81)
+ (Rational(-bignum_value, 4) ** -4).should == Rational(1, 452312848583266388373324160190187140051835877600158453279131187530910662656)
+ (Rational(3, -bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81)
+ end
+
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ it "returns Rational(1, 1) when the passed argument is 0" do
+ (Rational(3, 4) ** 0).should.eql?(Rational(1, 1))
+ (Rational(-3, 4) ** 0).should.eql?(Rational(1, 1))
+ (Rational(3, -4) ** 0).should.eql?(Rational(1, 1))
+
+ (Rational(bignum_value, 4) ** 0).should.eql?(Rational(1, 1))
+ (Rational(3, -bignum_value) ** 0).should.eql?(Rational(1, 1))
+ end
+ end
+ end
+
+ describe "when passed Bignum" do
+ # #5713
+ it "returns Rational(0) when self is Rational(0) and the exponent is positive" do
+ (Rational(0) ** bignum_value).should.eql?(Rational(0))
+ end
+
+ it "raises ZeroDivisionError when self is Rational(0) and the exponent is negative" do
+ -> { Rational(0) ** -bignum_value }.should.raise(ZeroDivisionError)
+ end
+
+ it "returns Rational(1) when self is Rational(1)" do
+ (Rational(1) ** bignum_value).should.eql?(Rational(1))
+ (Rational(1) ** -bignum_value).should.eql?(Rational(1))
+ end
+
+ it "returns Rational(1) when self is Rational(-1) and the exponent is positive and even" do
+ (Rational(-1) ** bignum_value(0)).should.eql?(Rational(1))
+ (Rational(-1) ** bignum_value(2)).should.eql?(Rational(1))
+ end
+
+ it "returns Rational(-1) when self is Rational(-1) and the exponent is positive and odd" do
+ (Rational(-1) ** bignum_value(1)).should.eql?(Rational(-1))
+ (Rational(-1) ** bignum_value(3)).should.eql?(Rational(-1))
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "returns positive Infinity when self is > 1" do
+ -> {
+ (Rational(2) ** bignum_value).infinite?.should == 1
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ -> {
+ (Rational(fixnum_max) ** bignum_value).infinite?.should == 1
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ end
+
+ it "returns 0.0 when self is > 1 and the exponent is negative" do
+ -> {
+ (Rational(2) ** -bignum_value).should.eql?(0.0)
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ -> {
+ (Rational(fixnum_max) ** -bignum_value).should.eql?(0.0)
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError when self is > 1" do
+ -> {
+ (Rational(2) ** bignum_value)
+ }.should.raise(ArgumentError, "exponent is too large")
+ -> {
+ (Rational(fixnum_max) ** bignum_value)
+ }.should.raise(ArgumentError, "exponent is too large")
+ end
+
+ it "raises an ArgumentError when self is > 1 and the exponent is negative" do
+ -> {
+ (Rational(2) ** -bignum_value)
+ }.should.raise(ArgumentError, "exponent is too large")
+ -> {
+ (Rational(fixnum_max) ** -bignum_value)
+ }.should.raise(ArgumentError, "exponent is too large")
+ end
+
+ it "raises an ArgumentError when self is < -1" do
+ -> {
+ (Rational(-2) ** bignum_value)
+ }.should.raise(ArgumentError, "exponent is too large")
+ -> {
+ (Rational(fixnum_min) ** bignum_value)
+ }.should.raise(ArgumentError, "exponent is too large")
+ end
+
+ it "raises an ArgumentError when self is < -1 and the exponent is negative" do
+ -> {
+ (Rational(-2) ** -bignum_value)
+ }.should.raise(ArgumentError, "exponent is too large")
+ -> {
+ (Rational(fixnum_min) ** -bignum_value)
+ }.should.raise(ArgumentError, "exponent is too large")
+ end
+ end
+
+ # Fails on linux due to pow() bugs in glibc: http://sources.redhat.com/bugzilla/show_bug.cgi?id=3866
+ platform_is_not :linux do
+ ruby_version_is ""..."3.4" do
+ it "returns positive Infinity when self < -1" do
+ -> {
+ (Rational(-2) ** bignum_value).infinite?.should == 1
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ -> {
+ (Rational(-2) ** (bignum_value + 1)).infinite?.should == 1
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ -> {
+ (Rational(fixnum_min) ** bignum_value).infinite?.should == 1
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ end
+
+ it "returns 0.0 when self is < -1 and the exponent is negative" do
+ -> {
+ (Rational(-2) ** -bignum_value).should.eql?(0.0)
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ -> {
+ (Rational(fixnum_min) ** -bignum_value).should.eql?(0.0)
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ end
+ end
+ end
+ end
+
+ describe "when passed Float" do
+ it "returns self converted to Float and raised to the passed argument" do
+ (Rational(3, 1) ** 3.0).should.eql?(27.0)
+ (Rational(3, 1) ** 1.5).should be_close(5.19615242270663, TOLERANCE)
+ (Rational(3, 1) ** -1.5).should be_close(0.192450089729875, TOLERANCE)
+ end
+
+ it "returns a complex number if self is negative and the passed argument is not 0" do
+ (Rational(-3, 2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE)
+ (Rational(3, -2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE)
+ (Rational(3, -2) ** -1.5).should be_close(Complex(0.0, 0.5443310539518174), TOLERANCE)
+ end
+
+ it "returns Complex(1.0) when the passed argument is 0.0" do
+ (Rational(3, 4) ** 0.0).should == Complex(1.0)
+ (Rational(-3, 4) ** 0.0).should == Complex(1.0)
+ (Rational(-3, 4) ** 0.0).should == Complex(1.0)
+ end
+ end
+
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational ** obj
+ end
+
+ it "calls #** on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:**).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational ** obj).should == :result
+ end
+
+ it "raises ZeroDivisionError for Rational(0, 1) passed a negative Integer" do
+ [-1, -4, -9999].each do |exponent|
+ -> { Rational(0, 1) ** exponent }.should.raise(ZeroDivisionError, "divided by 0")
+ end
+ end
+
+ it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational with denominator 1" do
+ [Rational(-1, 1), Rational(-3, 1)].each do |exponent|
+ -> { Rational(0, 1) ** exponent }.should.raise(ZeroDivisionError, "divided by 0")
+ end
+ end
+
+ # #7513
+ it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational" do
+ -> { Rational(0, 1) ** Rational(-3, 2) }.should.raise(ZeroDivisionError, "divided by 0")
+ end
+
+ it "returns Infinity for Rational(0, 1) passed a negative Float" do
+ [-1.0, -3.0, -3.14].each do |exponent|
+ (Rational(0, 1) ** exponent).infinite?.should == 1
+ end
+ end
end
diff --git a/spec/ruby/core/rational/fdiv_spec.rb b/spec/ruby/core/rational/fdiv_spec.rb
index bfb321abaa..118d93dbe7 100644
--- a/spec/ruby/core/rational/fdiv_spec.rb
+++ b/spec/ruby/core/rational/fdiv_spec.rb
@@ -1,5 +1,5 @@
-require_relative '../../shared/rational/fdiv'
+require_relative "../../spec_helper"
describe "Rational#fdiv" do
- it_behaves_like :rational_fdiv, :fdiv
+ it "needs to be reviewed for spec completeness"
end
diff --git a/spec/ruby/fixtures/rational.rb b/spec/ruby/core/rational/fixtures/rational.rb
index 844d7f9820..844d7f9820 100644
--- a/spec/ruby/fixtures/rational.rb
+++ b/spec/ruby/core/rational/fixtures/rational.rb
diff --git a/spec/ruby/core/rational/floor_spec.rb b/spec/ruby/core/rational/floor_spec.rb
index 752a2d8815..6d4cee79a9 100644
--- a/spec/ruby/core/rational/floor_spec.rb
+++ b/spec/ruby/core/rational/floor_spec.rb
@@ -1,5 +1,49 @@
-require_relative '../../shared/rational/floor'
+require_relative "../../spec_helper"
+require_relative "../integer/shared/integer_floor_precision"
describe "Rational#floor" do
- it_behaves_like :rational_floor, :floor
+ context "with values equal to integers" do
+ it_behaves_like :integer_floor_precision, :Rational
+ end
+
+ before do
+ @rational = Rational(2200, 7)
+ end
+
+ describe "with no arguments (precision = 0)" do
+
+ it "returns the Integer value rounded toward negative infinity" do
+ @rational.floor.should.eql? 314
+
+ Rational(1, 2).floor.should.eql? 0
+ Rational(-1, 2).floor.should.eql?(-1)
+ Rational(1, 1).floor.should.eql? 1
+ end
+ end
+
+ describe "with a precision < 0" do
+ it "moves the rounding point n decimal places left, returning an Integer" do
+ @rational.floor(-3).should.eql? 0
+ @rational.floor(-2).should.eql? 300
+ @rational.floor(-1).should.eql? 310
+
+ Rational(100, 2).floor(-1).should.eql? 50
+ Rational(100, 2).floor(-2).should.eql? 0
+ Rational(-100, 2).floor(-1).should.eql?(-50)
+ Rational(-100, 2).floor(-2).should.eql?(-100)
+ end
+ end
+
+ describe "with a precision > 0" do
+ it "moves the rounding point n decimal places right, returning a Rational" do
+ @rational.floor(1).should.eql? Rational(1571, 5)
+ @rational.floor(2).should.eql? Rational(7857, 25)
+ @rational.floor(3).should.eql? Rational(62857, 200)
+
+ Rational(100, 2).floor(1).should.eql? Rational(50, 1)
+ Rational(100, 2).floor(2).should.eql? Rational(50, 1)
+ Rational(-100, 2).floor(1).should.eql? Rational(-50, 1)
+ Rational(-100, 2).floor(2).should.eql? Rational(-50, 1)
+ end
+ end
end
diff --git a/spec/ruby/core/rational/hash_spec.rb b/spec/ruby/core/rational/hash_spec.rb
index 84cd31518a..528638056a 100644
--- a/spec/ruby/core/rational/hash_spec.rb
+++ b/spec/ruby/core/rational/hash_spec.rb
@@ -1,5 +1,9 @@
-require_relative '../../shared/rational/hash'
+require_relative "../../spec_helper"
describe "Rational#hash" do
- it_behaves_like :rational_hash, :hash
+ # BUG: Rational(2, 3).hash == Rational(3, 2).hash
+ it "is static" do
+ Rational(2, 3).hash.should == Rational(2, 3).hash
+ Rational(2, 4).hash.should_not == Rational(2, 3).hash
+ end
end
diff --git a/spec/ruby/core/rational/inspect_spec.rb b/spec/ruby/core/rational/inspect_spec.rb
index ef337ef0ce..edc5cffee9 100644
--- a/spec/ruby/core/rational/inspect_spec.rb
+++ b/spec/ruby/core/rational/inspect_spec.rb
@@ -1,5 +1,14 @@
-require_relative '../../shared/rational/inspect'
+require_relative "../../spec_helper"
describe "Rational#inspect" do
- it_behaves_like :rational_inspect, :inspect
+ it "returns a string representation of self" do
+ Rational(3, 4).inspect.should == "(3/4)"
+ Rational(-5, 8).inspect.should == "(-5/8)"
+ Rational(-1, -2).inspect.should == "(1/2)"
+
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ Rational(bignum_value, 1).inspect.should == "(#{bignum_value}/1)"
+ end
+ end
end
diff --git a/spec/ruby/core/rational/integer_spec.rb b/spec/ruby/core/rational/integer_spec.rb
index 0f9a3bdead..cd7fa97fcf 100644
--- a/spec/ruby/core/rational/integer_spec.rb
+++ b/spec/ruby/core/rational/integer_spec.rb
@@ -1,12 +1,13 @@
+require_relative "../../spec_helper"
describe "Rational#integer?" do
# Guard against the Mathn library
guard -> { !defined?(Math.rsqrt) } do
it "returns false for a rational with a numerator and no denominator" do
- Rational(20).integer?.should be_false
+ Rational(20).integer?.should == false
end
end
it "returns false for a rational with a numerator and a denominator" do
- Rational(20,3).integer?.should be_false
+ Rational(20,3).integer?.should == false
end
end
diff --git a/spec/ruby/core/rational/magnitude_spec.rb b/spec/ruby/core/rational/magnitude_spec.rb
index 878fc8f879..f5f667edb1 100644
--- a/spec/ruby/core/rational/magnitude_spec.rb
+++ b/spec/ruby/core/rational/magnitude_spec.rb
@@ -1,4 +1,5 @@
-require_relative '../../shared/rational/abs'
+require_relative "../../spec_helper"
+require_relative 'shared/abs'
describe "Rational#abs" do
it_behaves_like :rational_abs, :magnitude
diff --git a/spec/ruby/core/rational/marshal_dump_spec.rb b/spec/ruby/core/rational/marshal_dump_spec.rb
index 17a6107cd5..06bf36f166 100644
--- a/spec/ruby/core/rational/marshal_dump_spec.rb
+++ b/spec/ruby/core/rational/marshal_dump_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Rational#marshal_dump" do
it "is a private method" do
- Rational.should have_private_instance_method(:marshal_dump, false)
+ Rational.private_instance_methods(false).should.include?(:marshal_dump)
end
it "dumps numerator and denominator" do
diff --git a/spec/ruby/core/rational/minus_spec.rb b/spec/ruby/core/rational/minus_spec.rb
index a61b62ebe6..4e10e118b9 100644
--- a/spec/ruby/core/rational/minus_spec.rb
+++ b/spec/ruby/core/rational/minus_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/rational/arithmetic_exception_in_coerce'
+require_relative 'shared/arithmetic_exception_in_coerce'
describe "Rational#-" do
it_behaves_like :rational_arithmetic_exception_in_coerce, :-
@@ -29,23 +29,23 @@ end
describe "Rational#- passed 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))
+ (Rational(3, 4) - Rational(0, 1)).should.eql?(Rational(3, 4))
+ (Rational(3, 4) - Rational(1, 4)).should.eql?(Rational(1, 2))
- (Rational(3, 4) - Rational(2, 1)).should eql(Rational(-5, 4))
+ (Rational(3, 4) - Rational(2, 1)).should.eql?(Rational(-5, 4))
end
end
describe "Rational#- passed 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)
+ (Rational(3, 4) - 0.2).should.eql?(0.55)
+ (Rational(3, 4) - 2.5).should.eql?(-1.75)
end
end
describe "Rational#- passed an Integer" 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))
+ (Rational(3, 4) - 1).should.eql?(Rational(-1, 4))
+ (Rational(3, 4) - 2).should.eql?(Rational(-5, 4))
end
end
diff --git a/spec/ruby/core/rational/modulo_spec.rb b/spec/ruby/core/rational/modulo_spec.rb
index c43f7788e3..6241077f68 100644
--- a/spec/ruby/core/rational/modulo_spec.rb
+++ b/spec/ruby/core/rational/modulo_spec.rb
@@ -1,5 +1,43 @@
-require_relative '../../shared/rational/modulo'
+require_relative "../../spec_helper"
describe "Rational#%" do
- it_behaves_like :rational_modulo, :%
+ it "returns the remainder when this value is divided by other" do
+ (Rational(2, 3) % Rational(2, 3)).should == Rational(0, 1)
+ (Rational(4, 3) % Rational(2, 3)).should == Rational(0, 1)
+ (Rational(2, -3) % Rational(-2, 3)).should == Rational(0, 1)
+ (Rational(0, -1) % -1).should == Rational(0, 1)
+
+ (Rational(7, 4) % Rational(1, 2)).should == Rational(1, 4)
+ (Rational(7, 4) % 1).should == Rational(3, 4)
+ (Rational(7, 4) % Rational(1, 7)).should == Rational(1, 28)
+
+ (Rational(3, 4) % -1).should == Rational(-1, 4)
+ (Rational(1, -5) % -1).should == Rational(-1, 5)
+ end
+
+ it "returns a Float value when the argument is Float" do
+ (Rational(7, 4) % 1.0).should.is_a?(Float)
+ (Rational(7, 4) % 1.0).should == 0.75
+ (Rational(7, 4) % 0.26).should be_close(0.19, 0.0001)
+ end
+
+ it "raises ZeroDivisionError on zero denominator" do
+ -> {
+ Rational(3, 5) % Rational(0, 1)
+ }.should.raise(ZeroDivisionError)
+
+ -> {
+ Rational(0, 1) % Rational(0, 1)
+ }.should.raise(ZeroDivisionError)
+
+ -> {
+ Rational(3, 5) % 0
+ }.should.raise(ZeroDivisionError)
+ end
+
+ it "raises a ZeroDivisionError when the argument is 0.0" do
+ -> {
+ Rational(3, 5) % 0.0
+ }.should.raise(ZeroDivisionError)
+ end
end
diff --git a/spec/ruby/core/rational/multiply_spec.rb b/spec/ruby/core/rational/multiply_spec.rb
index ea644074e9..3e059cbc1c 100644
--- a/spec/ruby/core/rational/multiply_spec.rb
+++ b/spec/ruby/core/rational/multiply_spec.rb
@@ -1,19 +1,65 @@
-require_relative '../../shared/rational/multiply'
-require_relative '../../shared/rational/arithmetic_exception_in_coerce'
+require_relative "../../spec_helper"
+require_relative 'shared/arithmetic_exception_in_coerce'
describe "Rational#*" do
- it_behaves_like :rational_multiply, :*
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational * obj
+ end
+
+ it "calls #* on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:*).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational * obj).should == :result
+ end
+
it_behaves_like :rational_arithmetic_exception_in_coerce, :*
end
describe "Rational#* passed a Rational" do
- it_behaves_like :rational_multiply_rat, :*
+ it "returns self divided by other as a Rational" do
+ (Rational(3, 4) * Rational(3, 4)).should.eql?(Rational(9, 16))
+ (Rational(2, 4) * Rational(1, 4)).should.eql?(Rational(1, 8))
+
+ (Rational(3, 4) * Rational(0, 1)).should.eql?(Rational(0, 4))
+ end
end
describe "Rational#* passed a Float" do
- it_behaves_like :rational_multiply_float, :*
+ it "returns self divided by other as a Float" do
+ (Rational(3, 4) * 0.75).should.eql?(0.5625)
+ (Rational(3, 4) * 0.25).should.eql?(0.1875)
+ (Rational(3, 4) * 0.3).should be_close(0.225, TOLERANCE)
+
+ (Rational(-3, 4) * 0.3).should be_close(-0.225, TOLERANCE)
+ (Rational(3, -4) * 0.3).should be_close(-0.225, TOLERANCE)
+ (Rational(3, 4) * -0.3).should be_close(-0.225, TOLERANCE)
+
+ (Rational(3, 4) * 0.0).should.eql?(0.0)
+ (Rational(-3, -4) * 0.0).should.eql?(0.0)
+
+ (Rational(-3, 4) * 0.0).should.eql?(0.0)
+ (Rational(3, -4) * 0.0).should.eql?(0.0)
+ end
end
describe "Rational#* passed an Integer" do
- it_behaves_like :rational_multiply_int, :*
+ it "returns self divided by other as a Rational" do
+ (Rational(3, 4) * 2).should.eql?(Rational(3, 2))
+ (Rational(2, 4) * 2).should.eql?(Rational(1, 1))
+ (Rational(6, 7) * -2).should.eql?(Rational(-12, 7))
+
+ (Rational(3, 4) * 0).should.eql?(Rational(0, 4))
+ end
end
diff --git a/spec/ruby/core/rational/numerator_spec.rb b/spec/ruby/core/rational/numerator_spec.rb
index 85b2ed9e86..631bb4703c 100644
--- a/spec/ruby/core/rational/numerator_spec.rb
+++ b/spec/ruby/core/rational/numerator_spec.rb
@@ -1,5 +1,10 @@
-require_relative '../../shared/rational/numerator'
+require_relative "../../spec_helper"
describe "Rational#numerator" do
- it_behaves_like :rational_numerator, :numerator
+ it "returns the numerator" do
+ Rational(3, 4).numerator.should.equal?(3)
+ Rational(3, -4).numerator.should.equal?(-3)
+
+ Rational(bignum_value, 1).numerator.should == bignum_value
+ end
end
diff --git a/spec/ruby/core/rational/plus_spec.rb b/spec/ruby/core/rational/plus_spec.rb
index e7ef3a8f92..92f830a105 100644
--- a/spec/ruby/core/rational/plus_spec.rb
+++ b/spec/ruby/core/rational/plus_spec.rb
@@ -1,18 +1,50 @@
-require_relative '../../shared/rational/plus'
-require_relative '../../shared/rational/arithmetic_exception_in_coerce'
+require_relative "../../spec_helper"
+require_relative 'shared/arithmetic_exception_in_coerce'
describe "Rational#+" do
- it_behaves_like :rational_plus, :+
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational + obj
+ end
+
+ it "calls #+ on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:+).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational + obj).should == :result
+ end
+
it_behaves_like :rational_arithmetic_exception_in_coerce, :+
end
describe "Rational#+ with a Rational" do
- it_behaves_like :rational_plus_rat, :+
+ 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))
+
+ (Rational(3, 4) + Rational(2, 1)).should.eql?(Rational(11, 4))
+ end
end
describe "Rational#+ with a Float" do
- it_behaves_like :rational_plus_float, :+
+ 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
end
describe "Rational#+ with an Integer" do
- it_behaves_like :rational_plus_int, :+
+ 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
diff --git a/spec/ruby/core/rational/quo_spec.rb b/spec/ruby/core/rational/quo_spec.rb
index 119aca1955..907898ad34 100644
--- a/spec/ruby/core/rational/quo_spec.rb
+++ b/spec/ruby/core/rational/quo_spec.rb
@@ -1,5 +1,25 @@
-require_relative '../../shared/rational/divide'
+require_relative "../../spec_helper"
describe "Rational#quo" do
- it_behaves_like :rational_divide, :quo
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational.quo(obj)
+ end
+
+ it "calls #/ on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:/).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ rational.quo(obj).should == :result
+ end
end
diff --git a/spec/ruby/core/rational/rational_spec.rb b/spec/ruby/core/rational/rational_spec.rb
index 482deab38d..278c4116a4 100644
--- a/spec/ruby/core/rational/rational_spec.rb
+++ b/spec/ruby/core/rational/rational_spec.rb
@@ -6,6 +6,6 @@ describe "Rational" do
end
it "does not respond to new" do
- -> { Rational.new(1) }.should raise_error(NoMethodError)
+ -> { Rational.new(1) }.should.raise(NoMethodError)
end
end
diff --git a/spec/ruby/core/rational/rationalize_spec.rb b/spec/ruby/core/rational/rationalize_spec.rb
index 3db027d446..9c86824ddd 100644
--- a/spec/ruby/core/rational/rationalize_spec.rb
+++ b/spec/ruby/core/rational/rationalize_spec.rb
@@ -30,7 +30,7 @@ describe "Rational#rationalize" do
end
it "raises ArgumentError when passed more than one argument" do
- -> { Rational(1,1).rationalize(0.1, 0.1) }.should raise_error(ArgumentError)
- -> { Rational(1,1).rationalize(0.1, 0.1, 2) }.should raise_error(ArgumentError)
+ -> { Rational(1,1).rationalize(0.1, 0.1) }.should.raise(ArgumentError)
+ -> { Rational(1,1).rationalize(0.1, 0.1, 2) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/rational/remainder_spec.rb b/spec/ruby/core/rational/remainder_spec.rb
index 0f9442f6f5..86ba4674e6 100644
--- a/spec/ruby/core/rational/remainder_spec.rb
+++ b/spec/ruby/core/rational/remainder_spec.rb
@@ -1,5 +1,5 @@
-require_relative '../../shared/rational/remainder'
+require_relative "../../spec_helper"
describe "Rational#remainder" do
- it_behaves_like :rational_remainder, :remainder
+ it "needs to be reviewed for spec completeness"
end
diff --git a/spec/ruby/core/rational/round_spec.rb b/spec/ruby/core/rational/round_spec.rb
index 36614a552d..dd6f66f408 100644
--- a/spec/ruby/core/rational/round_spec.rb
+++ b/spec/ruby/core/rational/round_spec.rb
@@ -1,6 +1,106 @@
require_relative '../../spec_helper'
-require_relative '../../shared/rational/round'
describe "Rational#round" do
- it_behaves_like :rational_round, :round
+ before do
+ @rational = Rational(2200, 7)
+ end
+
+ describe "with no arguments (precision = 0)" do
+ it "returns an integer" do
+ @rational.round.should.is_a?(Integer)
+ Rational(0, 1).round(0).should.is_a?(Integer)
+ Rational(124, 1).round(0).should.is_a?(Integer)
+ end
+
+ it "returns the truncated value toward the nearest integer" do
+ @rational.round.should == 314
+ Rational(0, 1).round(0).should == 0
+ Rational(2, 1).round(0).should == 2
+ end
+
+ it "returns the rounded value toward the nearest integer" do
+ Rational(1, 2).round.should == 1
+ Rational(-1, 2).round.should == -1
+ Rational(3, 2).round.should == 2
+ Rational(-3, 2).round.should == -2
+ Rational(5, 2).round.should == 3
+ Rational(-5, 2).round.should == -3
+ end
+ end
+
+ describe "with a precision < 0" do
+ it "returns an integer" do
+ @rational.round(-2).should.is_a?(Integer)
+ @rational.round(-1).should.is_a?(Integer)
+ Rational(0, 1).round(-1).should.is_a?(Integer)
+ Rational(2, 1).round(-1).should.is_a?(Integer)
+ end
+
+ it "moves the truncation point n decimal places left" do
+ @rational.round(-3).should == 0
+ @rational.round(-2).should == 300
+ @rational.round(-1).should == 310
+ end
+ end
+
+ describe "with a precision > 0" do
+ it "returns a Rational" do
+ @rational.round(1).should.is_a?(Rational)
+ @rational.round(2).should.is_a?(Rational)
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ Rational(0, 1).round(1).should.is_a?(Rational)
+ Rational(2, 1).round(1).should.is_a?(Rational)
+ end
+ end
+
+ it "moves the truncation point n decimal places right" do
+ @rational.round(1).should == Rational(3143, 10)
+ @rational.round(2).should == Rational(31429, 100)
+ @rational.round(3).should == Rational(157143, 500)
+ Rational(0, 1).round(1).should == Rational(0, 1)
+ Rational(2, 1).round(1).should == Rational(2, 1)
+ end
+
+ it "doesn't alter the value if the precision is too great" do
+ Rational(3, 2).round(10).should == Rational(3, 2).round(20)
+ end
+
+ # #6605
+ it "doesn't fail when rounding to an absurdly large positive precision" do
+ Rational(3, 2).round(2_097_171).should == Rational(3, 2)
+ end
+ end
+
+ describe "with half option" do
+ it "returns an Integer when precision is not passed" do
+ Rational(10, 4).round(half: nil).should == 3
+ 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: nil).should == -3
+ 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: nil).should == Rational(3, 10)
+ 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: nil).should == Rational(2, 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: nil).should == Rational(-3, 10)
+ 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
+
+ it "raise for a non-existent round mode" do
+ -> { Rational(10, 4).round(half: :nonsense) }.should.raise(ArgumentError, "invalid rounding mode: nonsense")
+ end
+ end
end
diff --git a/spec/ruby/core/rational/shared/abs.rb b/spec/ruby/core/rational/shared/abs.rb
new file mode 100644
index 0000000000..3d64bcc1a0
--- /dev/null
+++ b/spec/ruby/core/rational/shared/abs.rb
@@ -0,0 +1,11 @@
+require_relative '../../../spec_helper'
+
+describe :rational_abs, shared: true do
+ it "returns self's absolute value" do
+ Rational(3, 4).send(@method).should == Rational(3, 4)
+ Rational(-3, 4).send(@method).should == Rational(3, 4)
+ Rational(3, -4).send(@method).should == Rational(3, 4)
+
+ Rational(bignum_value, -bignum_value).send(@method).should == Rational(bignum_value, bignum_value)
+ end
+end
diff --git a/spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb b/spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb
new file mode 100644
index 0000000000..e15169c912
--- /dev/null
+++ b/spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb
@@ -0,0 +1,11 @@
+require_relative '../fixtures/rational'
+
+describe :rational_arithmetic_exception_in_coerce, shared: true do
+ it "does not rescue exception raised in other#coerce" do
+ b = mock("numeric with failed #coerce")
+ b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError)
+
+ # e.g. Rational(3, 4) + b
+ -> { Rational(3, 4).send(@method, b) }.should.raise(RationalSpecs::CoerceError)
+ end
+end
diff --git a/spec/ruby/core/rational/to_f_spec.rb b/spec/ruby/core/rational/to_f_spec.rb
index 15bf1e88dc..40e3f11c0c 100644
--- a/spec/ruby/core/rational/to_f_spec.rb
+++ b/spec/ruby/core/rational/to_f_spec.rb
@@ -1,5 +1,16 @@
-require_relative '../../shared/rational/to_f'
+require_relative "../../spec_helper"
describe "Rational#to_f" do
- it_behaves_like :rational_to_f, :to_f
+ it "returns self converted to a Float" do
+ Rational(3, 4).to_f.should.eql?(0.75)
+ Rational(3, -4).to_f.should.eql?(-0.75)
+ Rational(-1, 4).to_f.should.eql?(-0.25)
+ Rational(-1, -4).to_f.should.eql?(0.25)
+ end
+
+ it "converts to a Float for large numerator and denominator" do
+ num = 1000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146009
+ den = 2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ Rational(num, den).to_f.should == 500.0
+ end
end
diff --git a/spec/ruby/core/rational/to_i_spec.rb b/spec/ruby/core/rational/to_i_spec.rb
index 3deb3664e1..e61b1b6c3b 100644
--- a/spec/ruby/core/rational/to_i_spec.rb
+++ b/spec/ruby/core/rational/to_i_spec.rb
@@ -1,5 +1,12 @@
-require_relative '../../shared/rational/to_i'
+require_relative "../../spec_helper"
describe "Rational#to_i" do
- it_behaves_like :rational_to_i, :to_i
+ it "converts self to an Integer by truncation" do
+ Rational(7, 4).to_i.should.eql?(1)
+ Rational(11, 4).to_i.should.eql?(2)
+ end
+
+ it "converts self to an Integer by truncation" do
+ Rational(-7, 4).to_i.should.eql?(-1)
+ end
end
diff --git a/spec/ruby/core/rational/to_r_spec.rb b/spec/ruby/core/rational/to_r_spec.rb
index cc704c965e..eb6097f595 100644
--- a/spec/ruby/core/rational/to_r_spec.rb
+++ b/spec/ruby/core/rational/to_r_spec.rb
@@ -1,11 +1,17 @@
-require_relative '../../shared/rational/to_r'
+require_relative "../../spec_helper"
describe "Rational#to_r" do
- it_behaves_like :rational_to_r, :to_r
+ it "returns self" do
+ a = Rational(3, 4)
+ a.to_r.should.equal?(a)
+
+ a = Rational(bignum_value, 4)
+ a.to_r.should.equal?(a)
+ end
it "raises TypeError trying to convert BasicObject" do
obj = BasicObject.new
- -> { Rational(obj) }.should raise_error(TypeError)
+ -> { Rational(obj) }.should.raise(TypeError)
end
it "works when a BasicObject has to_r" do
@@ -15,6 +21,6 @@ describe "Rational#to_r" do
it "fails when a BasicObject's to_r does not return a Rational" do
obj = BasicObject.new; def obj.to_r; 1 end
- -> { Rational(obj) }.should raise_error(TypeError)
+ -> { Rational(obj) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/rational/to_s_spec.rb b/spec/ruby/core/rational/to_s_spec.rb
index c5c419787c..24e30778e5 100644
--- a/spec/ruby/core/rational/to_s_spec.rb
+++ b/spec/ruby/core/rational/to_s_spec.rb
@@ -1,5 +1,14 @@
-require_relative '../../shared/rational/to_s'
+require_relative "../../spec_helper"
describe "Rational#to_s" do
- it_behaves_like :rational_to_s, :to_s
+ it "returns a string representation of self" do
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ Rational(1, 1).to_s.should == "1/1"
+ Rational(2, 1).to_s.should == "2/1"
+ end
+ Rational(1, 2).to_s.should == "1/2"
+ Rational(-1, 3).to_s.should == "-1/3"
+ Rational(1, -3).to_s.should == "-1/3"
+ end
end
diff --git a/spec/ruby/core/rational/truncate_spec.rb b/spec/ruby/core/rational/truncate_spec.rb
index 4e72339752..3614431a7f 100644
--- a/spec/ruby/core/rational/truncate_spec.rb
+++ b/spec/ruby/core/rational/truncate_spec.rb
@@ -1,5 +1,71 @@
-require_relative '../../shared/rational/truncate'
+require_relative "../../spec_helper"
describe "Rational#truncate" do
- it_behaves_like :rational_truncate, :truncate
+ before do
+ @rational = Rational(2200, 7)
+ end
+
+ describe "with no arguments (precision = 0)" do
+ it "returns an integer" do
+ @rational.truncate.should.is_a?(Integer)
+ end
+
+ it "returns the truncated value toward 0" do
+ @rational.truncate.should == 314
+ Rational(1, 2).truncate.should == 0
+ Rational(-1, 2).truncate.should == 0
+ end
+ end
+
+ describe "with an explicit precision = 0" do
+ it "returns an integer" do
+ @rational.truncate(0).should.is_a?(Integer)
+ end
+
+ it "returns the truncated value toward 0" do
+ @rational.truncate(0).should == 314
+ Rational(1, 2).truncate(0).should == 0
+ Rational(-1, 2).truncate(0).should == 0
+ end
+ end
+
+ describe "with a precision < 0" do
+ it "returns an integer" do
+ @rational.truncate(-2).should.is_a?(Integer)
+ @rational.truncate(-1).should.is_a?(Integer)
+ end
+
+ it "moves the truncation point n decimal places left" do
+ @rational.truncate(-3).should == 0
+ @rational.truncate(-2).should == 300
+ @rational.truncate(-1).should == 310
+ end
+ end
+
+ describe "with a precision > 0" do
+ it "returns a Rational" do
+ @rational.truncate(1).should.is_a?(Rational)
+ @rational.truncate(2).should.is_a?(Rational)
+ end
+
+ it "moves the truncation point n decimal places right" do
+ @rational.truncate(1).should == Rational(1571, 5)
+ @rational.truncate(2).should == Rational(7857, 25)
+ @rational.truncate(3).should == Rational(62857, 200)
+ end
+ end
+
+ describe "with an invalid value for precision" do
+ it "raises a TypeError" do
+ -> { @rational.truncate(nil) }.should.raise(TypeError, "not an integer")
+ -> { @rational.truncate(1.0) }.should.raise(TypeError, "not an integer")
+ -> { @rational.truncate('') }.should.raise(TypeError, "not an integer")
+ end
+
+ it "does not call to_int on the argument" do
+ object = Object.new
+ object.should_not_receive(:to_int)
+ -> { @rational.truncate(object) }.should.raise(TypeError, "not an integer")
+ end
+ end
end
diff --git a/spec/ruby/core/rational/zero_spec.rb b/spec/ruby/core/rational/zero_spec.rb
index e6dd751922..2e4f783d5c 100644
--- a/spec/ruby/core/rational/zero_spec.rb
+++ b/spec/ruby/core/rational/zero_spec.rb
@@ -1,13 +1,14 @@
+require_relative "../../spec_helper"
describe "Rational#zero?" do
it "returns true if the numerator is 0" do
- Rational(0,26).zero?.should be_true
+ Rational(0,26).zero?.should == true
end
it "returns true if the numerator is 0.0" do
- Rational(0.0,26).zero?.should be_true
+ Rational(0.0,26).zero?.should == true
end
it "returns false if the numerator isn't 0" do
- Rational(26).zero?.should be_false
+ Rational(26).zero?.should == false
end
end
diff --git a/spec/ruby/core/refinement/append_features_spec.rb b/spec/ruby/core/refinement/append_features_spec.rb
index fb84f245bd..cffc9ed308 100644
--- a/spec/ruby/core/refinement/append_features_spec.rb
+++ b/spec/ruby/core/refinement/append_features_spec.rb
@@ -1,20 +1,18 @@
require_relative '../../spec_helper'
describe "Refinement#append_features" do
- ruby_version_is "3.2" do
- it "is not defined" do
- Refinement.should_not have_private_instance_method(:append_features)
- end
+ it "is not defined" do
+ Refinement.private_instance_methods(true).should_not.include?(:append_features)
+ end
- it "is not called by Module#include" do
- c = Class.new
- Module.new do
- refine c do
- called = false
- define_method(:append_features){called = true}
- proc{c.include(self)}.should raise_error(TypeError)
- called.should == false
- end
+ it "is not called by Module#include" do
+ c = Class.new
+ Module.new do
+ refine c do
+ called = false
+ define_method(:append_features){called = true}
+ proc{c.include(self)}.should.raise(TypeError)
+ called.should == false
end
end
end
diff --git a/spec/ruby/core/refinement/extend_object_spec.rb b/spec/ruby/core/refinement/extend_object_spec.rb
index e44e9f46d8..f6fe2a60ea 100644
--- a/spec/ruby/core/refinement/extend_object_spec.rb
+++ b/spec/ruby/core/refinement/extend_object_spec.rb
@@ -1,20 +1,20 @@
require_relative '../../spec_helper'
describe "Refinement#extend_object" do
- ruby_version_is "3.2" do
- it "is not defined" do
- Refinement.should_not have_private_instance_method(:extend_object)
- end
+ it "is not defined" do
+ Refinement.private_instance_methods(true).should_not.include?(:extend_object)
+ end
- it "is not called by Object#extend" do
- c = Class.new
- Module.new do
- refine c do
- called = false
- define_method(:extend_object){called = true}
- proc{c.extend(self)}.should raise_error(TypeError)
- called.should == false
- end
+ it "is not called by Object#extend" do
+ c = Class.new
+ Module.new do
+ refine c do
+ called = false
+ define_method(:extend_object) { called = true }
+ -> {
+ c.extend(self)
+ }.should.raise(TypeError)
+ called.should == false
end
end
end
diff --git a/spec/ruby/core/refinement/fixtures/classes.rb b/spec/ruby/core/refinement/fixtures/classes.rb
new file mode 100644
index 0000000000..94324db47c
--- /dev/null
+++ b/spec/ruby/core/refinement/fixtures/classes.rb
@@ -0,0 +1,10 @@
+module RefinementSpec
+
+ module ModuleWithAncestors
+ include Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/import_methods_spec.rb b/spec/ruby/core/refinement/import_methods_spec.rb
new file mode 100644
index 0000000000..bcb5e9b066
--- /dev/null
+++ b/spec/ruby/core/refinement/import_methods_spec.rb
@@ -0,0 +1,287 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Refinement#import_methods" do
+ context "when methods are defined in Ruby code" do
+ it "imports methods" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils
+ "foo".indent(3).should == " foo"
+ end
+ end
+ end
+
+ it "throws an exception when argument is not a module" do
+ Module.new do
+ refine String do
+ -> {
+ import_methods Integer
+ }.should.raise(TypeError, "wrong argument type Class (expected Module)")
+ end
+ end
+ end
+
+ it "imports methods from multiple modules" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ str_utils_fancy = Module.new do
+ def indent_star(level)
+ "*" * level + self
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils, str_utils_fancy
+ "foo".indent(3).should == " foo"
+ "foo".indent_star(3).should == "***foo"
+ end
+ end
+ end
+
+ it "imports a method defined in the last module if method with same name is defined in multiple modules" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ str_utils_fancy = Module.new do
+ def indent(level)
+ "*" * level + self
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils, str_utils_fancy
+ "foo".indent(3).should == "***foo"
+ end
+ end
+ end
+
+ it "still imports methods of modules listed before a module that contains method not defined in Ruby" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ string_refined = Module.new do
+ refine String do
+ -> {
+ import_methods str_utils, Kernel
+ }.should.raise(ArgumentError)
+ end
+ end
+
+ Module.new do
+ using string_refined
+ "foo".indent(3).should == " foo"
+ end
+ end
+ end
+
+ it "warns if a module includes/prepends some other module" do
+ module1 = Module.new do
+ end
+
+ module2 = Module.new do
+ include module1
+ end
+
+ Module.new do
+ refine String do
+ -> {
+ import_methods module2
+ }.should complain(/warning: #<Module:\w*> has ancestors, but Refinement#import_methods doesn't import their methods/)
+ end
+ end
+
+ Module.new do
+ refine String do
+ -> {
+ import_methods RefinementSpec::ModuleWithAncestors
+ }.should complain(/warning: RefinementSpec::ModuleWithAncestors has ancestors, but Refinement#import_methods doesn't import their methods/)
+ end
+ end
+ end
+
+ it "doesn't import methods from included/prepended modules" do
+ Module.new do
+ refine String do
+ suppress_warning { import_methods RefinementSpec::ModuleWithAncestors }
+ end
+
+ using self
+ -> {
+ "foo".indent(3)
+ }.should.raise(NoMethodError, /undefined method [`']indent' for ("foo":String|an instance of String)/)
+ end
+ end
+
+ it "doesn't import any methods if one of the arguments is not a module" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ string_refined = Module.new do
+ refine String do
+ -> {
+ import_methods str_utils, Integer
+ }.should.raise(TypeError)
+ end
+ end
+
+ Module.new do
+ using string_refined
+ -> {
+ "foo".indent(3)
+ }.should.raise(NoMethodError)
+ end
+ end
+
+ it "imports methods from multiple modules so that methods see other's module's methods" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ str_utils_normal = Module.new do
+ def indent_normal(level)
+ self.indent(level)
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils, str_utils_normal
+ end
+
+ using self
+ "foo".indent_normal(3).should == " foo"
+ end
+ end
+
+ it "imports methods from module so that methods can see each other" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+
+ def indent_with_dot(level)
+ self.indent(level) + "."
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils
+ end
+
+ using self
+ "foo".indent_with_dot(3).should == " foo."
+ end
+ end
+
+ it "doesn't import module's class methods" do
+ str_utils = Module.new do
+ def self.indent(level)
+ " " * level + self
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils
+ end
+
+ using self
+ -> {
+ String.indent(3)
+ }.should.raise(NoMethodError, /undefined method [`']indent' for (String:Class|class String)/)
+ end
+ end
+
+ it "imports module methods with super" do
+ class_to_refine = Class.new do
+ def foo(number)
+ 2 * number
+ end
+ end
+
+ extension = Module.new do
+ def foo(number)
+ super * 2
+ end
+ end
+
+ refinement = Module.new do
+ refine class_to_refine do
+ import_methods extension
+ end
+ end
+
+ Module.new do
+ using refinement
+ class_to_refine.new.foo(2).should == 8
+ end
+ end
+
+ it "correctly sets owner as the refinement module" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ refinement = Module.new do
+ refine String do
+ import_methods str_utils
+ end
+ end
+
+ Module.new do
+ using refinement
+
+ String.instance_method(:indent).owner.should == refinement.refinements.first
+ end
+ end
+
+ context "when methods are not defined in Ruby code" do
+ it "raises ArgumentError" do
+ Module.new do
+ refine String do
+ -> {
+ import_methods Kernel
+ }.should.raise(ArgumentError)
+ end
+ end
+ end
+
+ it "raises ArgumentError when importing methods from C extension" do
+ require 'zlib'
+ Module.new do
+ refine String do
+ -> {
+ import_methods Zlib
+ }.should.raise(ArgumentError, /Can't import method which is not defined with Ruby code: Zlib#*/)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/include_spec.rb b/spec/ruby/core/refinement/include_spec.rb
new file mode 100644
index 0000000000..55ac89ffb5
--- /dev/null
+++ b/spec/ruby/core/refinement/include_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+
+describe "Refinement#include" do
+ it "raises a TypeError" do
+ Module.new do
+ refine String do
+ -> {
+ include Module.new
+ }.should.raise(TypeError, "Refinement#include has been removed")
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/prepend_features_spec.rb b/spec/ruby/core/refinement/prepend_features_spec.rb
index 9fdea199a2..9dc5838f1f 100644
--- a/spec/ruby/core/refinement/prepend_features_spec.rb
+++ b/spec/ruby/core/refinement/prepend_features_spec.rb
@@ -1,20 +1,18 @@
require_relative '../../spec_helper'
describe "Refinement#prepend_features" do
- ruby_version_is "3.2" do
- it "is not defined" do
- Refinement.should_not have_private_instance_method(:prepend_features)
- end
+ it "is not defined" do
+ Refinement.private_instance_methods(true).should_not.include?(:prepend_features)
+ end
- it "is not called by Module#prepend" do
- c = Class.new
- Module.new do
- refine c do
- called = false
- define_method(:prepend_features){called = true}
- proc{c.prepend(self)}.should raise_error(TypeError)
- called.should == false
- end
+ it "is not called by Module#prepend" do
+ c = Class.new
+ Module.new do
+ refine c do
+ called = false
+ define_method(:prepend_features){called = true}
+ proc{c.prepend(self)}.should.raise(TypeError)
+ called.should == false
end
end
end
diff --git a/spec/ruby/core/refinement/prepend_spec.rb b/spec/ruby/core/refinement/prepend_spec.rb
new file mode 100644
index 0000000000..fd70dd6f97
--- /dev/null
+++ b/spec/ruby/core/refinement/prepend_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+
+describe "Refinement#prepend" do
+ it "raises a TypeError" do
+ Module.new do
+ refine String do
+ -> {
+ prepend Module.new
+ }.should.raise(TypeError, "Refinement#prepend has been removed")
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/refined_class_spec.rb b/spec/ruby/core/refinement/refined_class_spec.rb
new file mode 100644
index 0000000000..b532d9a773
--- /dev/null
+++ b/spec/ruby/core/refinement/refined_class_spec.rb
@@ -0,0 +1,34 @@
+require_relative "../../spec_helper"
+require_relative 'shared/target'
+
+describe "Refinement#refined_class" do
+ ruby_version_is ""..."3.4" do
+ it "has been deprecated in favour of Refinement#target" do
+ refinement_int = nil
+
+ Module.new do
+ refine Integer do
+ refinement_int = self
+ end
+ end
+
+ -> {
+ refinement_int.refined_class
+ }.should complain(/warning: Refinement#refined_class is deprecated and will be removed in Ruby 3.4; use Refinement#target instead/)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "has been removed" do
+ refinement_int = nil
+
+ Module.new do
+ refine Integer do
+ refinement_int = self
+ end
+ end
+
+ refinement_int.should_not.respond_to?(:refined_class)
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/shared/target.rb b/spec/ruby/core/refinement/shared/target.rb
new file mode 100644
index 0000000000..79557bea0b
--- /dev/null
+++ b/spec/ruby/core/refinement/shared/target.rb
@@ -0,0 +1,13 @@
+describe :refinement_target, shared: true do
+ it "returns the class refined by the receiver" do
+ refinement_int = nil
+
+ Module.new do
+ refine Integer do
+ refinement_int = self
+ end
+ end
+
+ refinement_int.send(@method).should == Integer
+ end
+end
diff --git a/spec/ruby/core/refinement/target_spec.rb b/spec/ruby/core/refinement/target_spec.rb
new file mode 100644
index 0000000000..8bd816aea6
--- /dev/null
+++ b/spec/ruby/core/refinement/target_spec.rb
@@ -0,0 +1,6 @@
+require_relative "../../spec_helper"
+require_relative 'shared/target'
+
+describe "Refinement#target" do
+ it_behaves_like :refinement_target, :target
+end
diff --git a/spec/ruby/core/regexp/case_compare_spec.rb b/spec/ruby/core/regexp/case_compare_spec.rb
index 5ae8b56c6a..29aada70bc 100644
--- a/spec/ruby/core/regexp/case_compare_spec.rb
+++ b/spec/ruby/core/regexp/case_compare_spec.rb
@@ -2,25 +2,25 @@ require_relative '../../spec_helper'
describe "Regexp#===" do
it "is true if there is a match" do
- (/abc/ === "aabcc").should be_true
+ (/abc/ === "aabcc").should == true
end
it "is false if there is no match" do
- (/abc/ === "xyz").should be_false
+ (/abc/ === "xyz").should == false
end
it "returns true if it matches a Symbol" do
- (/a/ === :a).should be_true
+ (/a/ === :a).should == true
end
it "returns false if it does not match a Symbol" do
- (/a/ === :b).should be_false
+ (/a/ === :b).should == false
end
# mirroring https://github.com/ruby/ruby/blob/master/test/ruby/test_regexp.rb
it "returns false if the other value cannot be coerced to a string" do
- (/abc/ === nil).should be_false
- (/abc/ === /abc/).should be_false
+ (/abc/ === nil).should == false
+ (/abc/ === /abc/).should == false
end
it "uses #to_str on string-like objects" do
@@ -30,6 +30,6 @@ describe "Regexp#===" do
end
end.new
- (/abc/ === stringlike).should be_true
+ (/abc/ === stringlike).should == true
end
end
diff --git a/spec/ruby/core/regexp/compile_spec.rb b/spec/ruby/core/regexp/compile_spec.rb
index 329cb4f753..887c8d77dc 100644
--- a/spec/ruby/core/regexp/compile_spec.rb
+++ b/spec/ruby/core/regexp/compile_spec.rb
@@ -13,3 +13,7 @@ end
describe "Regexp.compile given a Regexp" do
it_behaves_like :regexp_new_regexp, :compile
end
+
+describe "Regexp.compile given a non-String/Regexp" do
+ it_behaves_like :regexp_new_non_string_or_regexp, :compile
+end
diff --git a/spec/ruby/core/regexp/encoding_spec.rb b/spec/ruby/core/regexp/encoding_spec.rb
index dfc835b4e4..fb4fdba064 100644
--- a/spec/ruby/core/regexp/encoding_spec.rb
+++ b/spec/ruby/core/regexp/encoding_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Regexp#encoding" do
it "returns an Encoding object" do
- /glar/.encoding.should be_an_instance_of(Encoding)
+ /glar/.encoding.should.instance_of?(Encoding)
end
it "defaults to US-ASCII if the Regexp contains only US-ASCII character" do
diff --git a/spec/ruby/core/regexp/fixed_encoding_spec.rb b/spec/ruby/core/regexp/fixed_encoding_spec.rb
index 29d0a22c53..5d8b1c2860 100644
--- a/spec/ruby/core/regexp/fixed_encoding_spec.rb
+++ b/spec/ruby/core/regexp/fixed_encoding_spec.rb
@@ -3,34 +3,34 @@ require_relative '../../spec_helper'
describe "Regexp#fixed_encoding?" do
it "returns false by default" do
- /needle/.fixed_encoding?.should be_false
+ /needle/.fixed_encoding?.should == false
end
it "returns false if the 'n' modifier was supplied to the Regexp" do
- /needle/n.fixed_encoding?.should be_false
+ /needle/n.fixed_encoding?.should == false
end
it "returns true if the 'u' modifier was supplied to the Regexp" do
- /needle/u.fixed_encoding?.should be_true
+ /needle/u.fixed_encoding?.should == true
end
it "returns true if the 's' modifier was supplied to the Regexp" do
- /needle/s.fixed_encoding?.should be_true
+ /needle/s.fixed_encoding?.should == true
end
it "returns true if the 'e' modifier was supplied to the Regexp" do
- /needle/e.fixed_encoding?.should be_true
+ /needle/e.fixed_encoding?.should == true
end
it "returns true if the Regexp contains a \\u escape" do
- /needle \u{8768}/.fixed_encoding?.should be_true
+ /needle \u{8768}/.fixed_encoding?.should == true
end
it "returns true if the Regexp contains a UTF-8 literal" do
- /文字化け/.fixed_encoding?.should be_true
+ /文字化け/.fixed_encoding?.should == true
end
it "returns true if the Regexp was created with the Regexp::FIXEDENCODING option" do
- Regexp.new("", Regexp::FIXEDENCODING).fixed_encoding?.should be_true
+ Regexp.new("", Regexp::FIXEDENCODING).fixed_encoding?.should == true
end
end
diff --git a/spec/ruby/core/regexp/initialize_spec.rb b/spec/ruby/core/regexp/initialize_spec.rb
index 772a233e82..1c0133acae 100644
--- a/spec/ruby/core/regexp/initialize_spec.rb
+++ b/spec/ruby/core/regexp/initialize_spec.rb
@@ -2,22 +2,28 @@ require_relative '../../spec_helper'
describe "Regexp#initialize" do
it "is a private method" do
- Regexp.should have_private_method(:initialize)
+ Regexp.private_instance_methods(false).should.include?(:initialize)
end
- ruby_version_is ""..."3.0" do
- it "raises a SecurityError on a Regexp literal" do
- -> { //.send(:initialize, "") }.should raise_error(SecurityError)
+ it "raises a FrozenError on a Regexp literal" do
+ -> { //.send(:initialize, "") }.should.raise(FrozenError)
+ end
+
+ ruby_version_is "4.1" do
+ it "raises a FrozenError on an initialized non-literal Regexp" do
+ regexp = Regexp.new("")
+ -> { regexp.send(:initialize, "") }.should.raise(FrozenError)
end
end
- ruby_version_is "3.0" do
- it "raises a FrozenError on a Regexp literal" do
- -> { //.send(:initialize, "") }.should raise_error(FrozenError)
+ ruby_version_is ""..."4.1" do
+ it "raises a TypeError on an initialized non-literal Regexp" do
+ -> { Regexp.new("").send(:initialize, "") }.should.raise(TypeError)
end
end
- it "raises a TypeError on an initialized non-literal Regexp" do
- -> { Regexp.new("").send(:initialize, "") }.should raise_error(TypeError)
+ it "raises a TypeError on an initialized non-literal Regexp subclass" do
+ r = Class.new(Regexp).new("")
+ -> { r.send(:initialize, "") }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/regexp/last_match_spec.rb b/spec/ruby/core/regexp/last_match_spec.rb
index 0bfed32051..6c256cc1cf 100644
--- a/spec/ruby/core/regexp/last_match_spec.rb
+++ b/spec/ruby/core/regexp/last_match_spec.rb
@@ -4,7 +4,7 @@ describe "Regexp.last_match" do
it "returns MatchData instance when not passed arguments" do
/c(.)t/ =~ 'cat'
- Regexp.last_match.should be_kind_of(MatchData)
+ Regexp.last_match.should.is_a?(MatchData)
end
it "returns the nth field in this MatchData when passed an Integer" do
@@ -28,7 +28,7 @@ describe "Regexp.last_match" do
it "raises an IndexError when given a missing name" do
/(?<test>[A-Z]+.*)/ =~ "TEST123"
- -> { Regexp.last_match(:missing) }.should raise_error(IndexError)
+ -> { Regexp.last_match(:missing) }.should.raise(IndexError)
end
end
@@ -50,7 +50,7 @@ describe "Regexp.last_match" do
it "raises a TypeError when unable to coerce" do
obj = Object.new
/(?<test>[A-Z]+.*)/ =~ "TEST123"
- -> { Regexp.last_match(obj) }.should raise_error(TypeError)
+ -> { Regexp.last_match(obj) }.should.raise(TypeError)
end
end
end
diff --git a/spec/ruby/core/regexp/linear_time_spec.rb b/spec/ruby/core/regexp/linear_time_spec.rb
new file mode 100644
index 0000000000..f70021dfed
--- /dev/null
+++ b/spec/ruby/core/regexp/linear_time_spec.rb
@@ -0,0 +1,80 @@
+require_relative '../../spec_helper'
+
+describe "Regexp.linear_time?" do
+ it "returns true if matching can be done in linear time" do
+ Regexp.linear_time?(/a/).should == true
+ Regexp.linear_time?('a').should == true
+ end
+
+ it "returns true if matching can be done in linear time for a binary Regexp" do
+ Regexp.linear_time?(/[\x80-\xff]/n).should == true
+ end
+
+ it "return false if matching can't be done in linear time" do
+ Regexp.linear_time?(/(a)\1/).should == false
+ Regexp.linear_time?("(a)\\1").should == false
+ end
+
+ it "accepts flags for string argument" do
+ Regexp.linear_time?('a', Regexp::IGNORECASE).should == true
+ end
+
+ it "warns about flags being ignored for regexp arguments" do
+ -> {
+ Regexp.linear_time?(/a/, Regexp::IGNORECASE)
+ }.should complain(/warning: flags ignored/)
+ end
+
+ it "returns true for positive lookahead" do
+ Regexp.linear_time?(/a*(?:(?=a*)a)*b/).should == true
+ end
+
+ it "returns true for positive lookbehind" do
+ Regexp.linear_time?(/a*(?:(?<=a)a*)*b/).should == true
+ end
+
+ it "returns true for negative lookbehind" do
+ Regexp.linear_time?(/a*(?:(?<!a)a*)*b/).should == true
+ end
+
+ # There are two known ways to make Regexp linear:
+ # * Using a DFA (deterministic finite-state automaton) Regexp engine, which always matches in linear time (e.g. TruffleRuby with TRegex)
+ # * Caching position and state to avoid catastrophic backtracking (e.g. CRuby: https://bugs.ruby-lang.org/issues/19104)
+ #
+ # Both approach should be allowed and given that DFA Regexp engines
+ # are much faster there should be no specs preventing using them.
+ uses_regexp_caching = RUBY_ENGINE == 'ruby'
+ uses_dfa_regexp_engine = !uses_regexp_caching
+
+ # The following specs should not be relied upon,
+ # they are here only to illustrate differences between Regexp engines.
+ guard -> { uses_regexp_caching } do
+ it "returns true for negative lookahead" do
+ Regexp.linear_time?(/a*(?:(?!a*)a*)*b/).should == true
+ end
+
+ it "returns true for atomic groups" do
+ Regexp.linear_time?(/a*(?:(?>a)a*)*b/).should == true
+ end
+
+ it "returns true for possessive quantifiers" do
+ Regexp.linear_time?(/a*(?:(?:a)?+a*)*b/).should == true
+ end
+
+ it "returns true for positive lookbehind with capture group" do
+ Regexp.linear_time?(/.(?<=(a))/).should == true
+ end
+ end
+
+ # The following specs should not be relied upon,
+ # they are here only to illustrate differences between Regexp engines.
+ guard -> { uses_dfa_regexp_engine } do
+ it "returns true for non-recursive subexpression call" do
+ Regexp.linear_time?(/(?<a>a){0}\g<a>/).should == true
+ end
+
+ it "returns true for positive lookahead with capture group" do
+ Regexp.linear_time?(/x+(?=(a))/).should == true
+ end
+ end
+end
diff --git a/spec/ruby/core/regexp/match_spec.rb b/spec/ruby/core/regexp/match_spec.rb
index 80dbfb4c10..276cecc8e4 100644
--- a/spec/ruby/core/regexp/match_spec.rb
+++ b/spec/ruby/core/regexp/match_spec.rb
@@ -3,11 +3,11 @@ require_relative '../../spec_helper'
describe :regexp_match, shared: true do
it "returns nil if there is no match" do
- /xyz/.send(@method,"abxyc").should be_nil
+ /xyz/.send(@method,"abxyc").should == nil
end
it "returns nil if the object is nil" do
- /\w+/.send(@method, nil).should be_nil
+ /\w+/.send(@method, nil).should == nil
end
end
@@ -27,19 +27,19 @@ describe "Regexp#match" do
it_behaves_like :regexp_match, :match
it "returns a MatchData object" do
- /(.)(.)(.)/.match("abc").should be_kind_of(MatchData)
+ /(.)(.)(.)/.match("abc").should.is_a?(MatchData)
end
it "returns a MatchData object, when argument is a Symbol" do
- /(.)(.)(.)/.match(:abc).should be_kind_of(MatchData)
+ /(.)(.)(.)/.match(:abc).should.is_a?(MatchData)
end
it "raises a TypeError on an uninitialized Regexp" do
- -> { Regexp.allocate.match('foo') }.should raise_error(TypeError)
+ -> { Regexp.allocate.match('foo') }.should.raise(TypeError)
end
it "raises TypeError on an uninitialized Regexp" do
- -> { Regexp.allocate.match('foo'.encode("UTF-16LE")) }.should raise_error(TypeError)
+ -> { Regexp.allocate.match('foo'.encode("UTF-16LE")) }.should.raise(TypeError)
end
describe "with [string, position]" do
@@ -54,7 +54,7 @@ describe "Regexp#match" do
it "raises an ArgumentError for an invalid encoding" do
x96 = ([150].pack('C')).force_encoding('utf-8')
- -> { /(.).(.)/.match("Hello, #{x96} world!", 1) }.should raise_error(ArgumentError)
+ -> { /(.).(.)/.match("Hello, #{x96} world!", 1) }.should.raise(ArgumentError)
end
end
@@ -69,14 +69,14 @@ describe "Regexp#match" do
it "raises an ArgumentError for an invalid encoding" do
x96 = ([150].pack('C')).force_encoding('utf-8')
- -> { /(.).(.)/.match("Hello, #{x96} world!", -1) }.should raise_error(ArgumentError)
+ -> { /(.).(.)/.match("Hello, #{x96} world!", -1) }.should.raise(ArgumentError)
end
end
describe "when passed a block" do
it "yields the MatchData" do
/./.match("abc") {|m| ScratchPad.record m }
- ScratchPad.recorded.should be_kind_of(MatchData)
+ ScratchPad.recorded.should.is_a?(MatchData)
end
it "returns the block result" do
@@ -94,20 +94,20 @@ describe "Regexp#match" do
it "resets $~ if passed nil" do
# set $~
/./.match("a")
- $~.should be_kind_of(MatchData)
+ $~.should.is_a?(MatchData)
/1/.match(nil)
- $~.should be_nil
+ $~.should == nil
end
it "raises TypeError when the given argument cannot be coerced to String" do
f = 1
- -> { /foo/.match(f)[0] }.should raise_error(TypeError)
+ -> { /foo/.match(f)[0] }.should.raise(TypeError)
end
it "raises TypeError when the given argument is an Exception" do
f = Exception.new("foo")
- -> { /foo/.match(f)[0] }.should raise_error(TypeError)
+ -> { /foo/.match(f)[0] }.should.raise(TypeError)
end
end
@@ -119,22 +119,22 @@ describe "Regexp#match?" do
context "when matches the given value" do
it "returns true but does not set Regexp.last_match" do
- /string/i.match?('string').should be_true
- Regexp.last_match.should be_nil
+ /string/i.match?('string').should == true
+ Regexp.last_match.should == nil
end
end
it "returns false when does not match the given value" do
- /STRING/.match?('string').should be_false
+ /STRING/.match?('string').should == false
end
it "takes matching position as the 2nd argument" do
- /str/i.match?('string', 0).should be_true
- /str/i.match?('string', 1).should be_false
+ /str/i.match?('string', 0).should == true
+ /str/i.match?('string', 1).should == false
end
it "returns false when given nil" do
- /./.match?(nil).should be_false
+ /./.match?(nil).should == false
end
end
diff --git a/spec/ruby/core/regexp/named_captures_spec.rb b/spec/ruby/core/regexp/named_captures_spec.rb
index 1a68d7877b..4d3fdd23ab 100644
--- a/spec/ruby/core/regexp/named_captures_spec.rb
+++ b/spec/ruby/core/regexp/named_captures_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Regexp#named_captures" do
it "returns a Hash" do
- /foo/.named_captures.should be_an_instance_of(Hash)
+ /foo/.named_captures.should.instance_of?(Hash)
end
it "returns an empty Hash when there are no capture groups" do
@@ -17,7 +17,7 @@ describe "Regexp#named_captures" do
it "sets the values of the Hash to Arrays" do
rex = /this (?<is>is) [aA] (?<pat>pate?rn)/
rex.named_captures.values.each do |value|
- value.should be_an_instance_of(Array)
+ value.should.instance_of?(Array)
end
end
diff --git a/spec/ruby/core/regexp/names_spec.rb b/spec/ruby/core/regexp/names_spec.rb
index 099768fd26..9013f41e20 100644
--- a/spec/ruby/core/regexp/names_spec.rb
+++ b/spec/ruby/core/regexp/names_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Regexp#names" do
it "returns an Array" do
- /foo/.names.should be_an_instance_of(Array)
+ /foo/.names.should.instance_of?(Array)
end
it "returns an empty Array if there are no named captures" do
@@ -11,7 +11,7 @@ describe "Regexp#names" do
it "returns each named capture as a String" do
/n(?<cap>ee)d(?<ture>le)/.names.each do |name|
- name.should be_an_instance_of(String)
+ name.should.instance_of?(String)
end
end
diff --git a/spec/ruby/core/regexp/new_spec.rb b/spec/ruby/core/regexp/new_spec.rb
index ce662b7a4f..79210e9a23 100644
--- a/spec/ruby/core/regexp/new_spec.rb
+++ b/spec/ruby/core/regexp/new_spec.rb
@@ -7,21 +7,13 @@ end
describe "Regexp.new given a String" do
it_behaves_like :regexp_new_string, :new
+ it_behaves_like :regexp_new_string_binary, :new
end
describe "Regexp.new given a Regexp" do
it_behaves_like :regexp_new_regexp, :new
- it_behaves_like :regexp_new_string_binary, :compile
end
-describe "Regexp.new given an Integer" do
- it "raises a TypeError" do
- -> { Regexp.new(1) }.should raise_error(TypeError)
- end
-end
-
-describe "Regexp.new given a Float" do
- it "raises a TypeError" do
- -> { Regexp.new(1.0) }.should raise_error(TypeError)
- end
+describe "Regexp.new given a non-String/Regexp" do
+ it_behaves_like :regexp_new_non_string_or_regexp, :new
end
diff --git a/spec/ruby/core/regexp/options_spec.rb b/spec/ruby/core/regexp/options_spec.rb
index 527b51a3b2..c3401cee6e 100644
--- a/spec/ruby/core/regexp/options_spec.rb
+++ b/spec/ruby/core/regexp/options_spec.rb
@@ -2,9 +2,9 @@ require_relative '../../spec_helper'
describe "Regexp#options" do
it "returns an Integer bitvector of regexp options for the Regexp object" do
- /cat/.options.should be_kind_of(Integer)
+ /cat/.options.should.is_a?(Integer)
not_supported_on :opal do
- /cat/ix.options.should be_kind_of(Integer)
+ /cat/ix.options.should.is_a?(Integer)
end
end
@@ -29,7 +29,7 @@ describe "Regexp#options" do
end
it "raises a TypeError on an uninitialized Regexp" do
- -> { Regexp.allocate.options }.should raise_error(TypeError)
+ -> { Regexp.allocate.options }.should.raise(TypeError)
end
it "includes Regexp::FIXEDENCODING for a Regexp literal with the 'u' option" do
diff --git a/spec/ruby/core/regexp/shared/new.rb b/spec/ruby/core/regexp/shared/new.rb
index a6d9c48112..affdaf855c 100644
--- a/spec/ruby/core/regexp/shared/new.rb
+++ b/spec/ruby/core/regexp/shared/new.rb
@@ -1,10 +1,16 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :regexp_new, shared: true do
it "requires one argument and creates a new regular expression object" do
Regexp.send(@method, '').is_a?(Regexp).should == true
end
+ ruby_version_is "4.1" do
+ it "is frozen" do
+ Regexp.send(@method, '').should.frozen?
+ end
+ end
+
it "works by default for subclasses with overridden #initialize" do
class RegexpSpecsSubclass < Regexp
def initialize(*args)
@@ -17,10 +23,36 @@ describe :regexp_new, shared: true do
class RegexpSpecsSubclassTwo < Regexp; end
- RegexpSpecsSubclass.send(@method, "hi").should be_kind_of(RegexpSpecsSubclass)
+ RegexpSpecsSubclass.send(@method, "hi").should.is_a?(RegexpSpecsSubclass)
RegexpSpecsSubclass.send(@method, "hi").args.first.should == "hi"
- RegexpSpecsSubclassTwo.send(@method, "hi").should be_kind_of(RegexpSpecsSubclassTwo)
+ RegexpSpecsSubclassTwo.send(@method, "hi").should.is_a?(RegexpSpecsSubclassTwo)
+ end
+end
+
+describe :regexp_new_non_string_or_regexp, shared: true do
+ it "calls #to_str method for non-String/Regexp argument" do
+ obj = Object.new
+ def obj.to_str() "a" end
+
+ Regexp.send(@method, obj).should == /a/
+ end
+
+ it "raises TypeError if there is no #to_str method for non-String/Regexp argument" do
+ obj = Object.new
+ -> { Regexp.send(@method, obj) }.should.raise(TypeError, "no implicit conversion of Object into String")
+
+ -> { Regexp.send(@method, 1) }.should.raise(TypeError, "no implicit conversion of Integer into String")
+ -> { Regexp.send(@method, 1.0) }.should.raise(TypeError, "no implicit conversion of Float into String")
+ -> { Regexp.send(@method, :symbol) }.should.raise(TypeError, "no implicit conversion of Symbol into String")
+ -> { Regexp.send(@method, []) }.should.raise(TypeError, "no implicit conversion of Array into String")
+ end
+
+ it "raises TypeError if #to_str returns non-String value" do
+ obj = Object.new
+ def obj.to_str() [] end
+
+ -> { Regexp.send(@method, obj) }.should raise_consistent_error(TypeError, /can't convert Object into String/)
end
end
@@ -30,7 +62,7 @@ describe :regexp_new_string, shared: true do
end
it "raises a RegexpError when passed an incorrect regexp" do
- -> { Regexp.send(@method, "^[$", 0) }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "^[$", 0) }.should.raise(RegexpError, Regexp.new(Regexp.escape("premature end of char-class: /^[$/")))
end
it "does not set Regexp options if only given one argument" do
@@ -97,313 +129,100 @@ describe :regexp_new_string, shared: true do
(r.options & Regexp::EXTENDED).should_not == 0
end
- ruby_version_is ""..."3.2" do
- it "treats any non-Integer, non-nil, non-false second argument as IGNORECASE" do
+ it "does not try to convert the second argument to Integer with #to_int method call" do
+ ScratchPad.clear
+ obj = Object.new
+ def obj.to_int() ScratchPad.record(:called) end
+
+ -> {
+ Regexp.send(@method, "Hi", obj)
+ }.should complain(/expected true or false as ignorecase/, {verbose: true})
+
+ ScratchPad.recorded.should == nil
+ end
+
+ it "warns any non-Integer, non-nil, non-false second argument" do
+ r = nil
+ -> {
r = Regexp.send(@method, 'Hi', Object.new)
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
+ }.should complain(/expected true or false as ignorecase/, {verbose: true})
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
end
end
- ruby_version_is "3.2" do
- it "warns any non-Integer, non-nil, non-false second argument" do
- r = nil
- -> {
- r = Regexp.send(@method, 'Hi', Object.new)
- }.should complain(/expected true or false as ignorecase/, {verbose: true})
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
+ it "accepts a String of supported flags as the second argument" do
+ r = Regexp.send(@method, 'Hi', 'i')
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
end
- it "accepts a String of supported flags as the second argument" do
- r = Regexp.send(@method, 'Hi', 'i')
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
-
- r = Regexp.send(@method, 'Hi', 'imx')
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should_not == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should_not == 0
- end
-
- r = Regexp.send(@method, 'Hi', 'mimi')
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should_not == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
-
- r = Regexp.send(@method, 'Hi', '')
- (r.options & Regexp::IGNORECASE).should == 0
- (r.options & Regexp::MULTILINE).should == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
+ r = Regexp.send(@method, 'Hi', 'imx')
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should_not == 0
end
- it "raises an Argument error if the second argument contains unsupported chars" do
- -> { Regexp.send(@method, 'Hi', 'e') }.should raise_error(ArgumentError)
- -> { Regexp.send(@method, 'Hi', 'n') }.should raise_error(ArgumentError)
- -> { Regexp.send(@method, 'Hi', 's') }.should raise_error(ArgumentError)
- -> { Regexp.send(@method, 'Hi', 'u') }.should raise_error(ArgumentError)
- -> { Regexp.send(@method, 'Hi', 'j') }.should raise_error(ArgumentError)
- -> { Regexp.send(@method, 'Hi', 'mjx') }.should raise_error(ArgumentError)
+ r = Regexp.send(@method, 'Hi', 'mimi')
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
end
- end
-
- it "ignores the third argument if it is 'e' or 'euc' (case-insensitive)" do
- -> {
- Regexp.send(@method, 'Hi', nil, 'e').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'euc').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'E').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'EUC').encoding.should == Encoding::US_ASCII
- }.should complain(/encoding option is ignored/)
- end
- it "ignores the third argument if it is 's' or 'sjis' (case-insensitive)" do
- -> {
- Regexp.send(@method, 'Hi', nil, 's').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'sjis').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'S').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'SJIS').encoding.should == Encoding::US_ASCII
- }.should complain(/encoding option is ignored/)
- end
-
- it "ignores the third argument if it is 'u' or 'utf8' (case-insensitive)" do
- -> {
- Regexp.send(@method, 'Hi', nil, 'u').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'utf8').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'U').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'UTF8').encoding.should == Encoding::US_ASCII
- }.should complain(/encoding option is ignored/)
- end
-
- it "uses US_ASCII encoding if third argument is 'n' or 'none' (case insensitive) and only ascii characters" do
- Regexp.send(@method, 'Hi', nil, 'n').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'none').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'N').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'NONE').encoding.should == Encoding::US_ASCII
+ r = Regexp.send(@method, 'Hi', '')
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
end
- it "uses ASCII_8BIT encoding if third argument is 'n' or 'none' (case insensitive) and non-ascii characters" do
- a = "(?:[\x8E\xA1-\xFE])"
- str = "\A(?:#{a}|x*)\z"
-
- Regexp.send(@method, str, nil, 'N').encoding.should == Encoding::BINARY
- Regexp.send(@method, str, nil, 'n').encoding.should == Encoding::BINARY
- Regexp.send(@method, str, nil, 'none').encoding.should == Encoding::BINARY
- Regexp.send(@method, str, nil, 'NONE').encoding.should == Encoding::BINARY
+ it "raises an Argument error if the second argument contains unsupported chars" do
+ -> { Regexp.send(@method, 'Hi', 'e') }.should.raise(ArgumentError, "unknown regexp option: e")
+ -> { Regexp.send(@method, 'Hi', 'n') }.should.raise(ArgumentError, "unknown regexp option: n")
+ -> { Regexp.send(@method, 'Hi', 's') }.should.raise(ArgumentError, "unknown regexp option: s")
+ -> { Regexp.send(@method, 'Hi', 'u') }.should.raise(ArgumentError, "unknown regexp option: u")
+ -> { Regexp.send(@method, 'Hi', 'j') }.should.raise(ArgumentError, "unknown regexp option: j")
+ -> { Regexp.send(@method, 'Hi', 'mjx') }.should.raise(ArgumentError, /unknown regexp option: mjx\b/)
end
describe "with escaped characters" do
it "raises a Regexp error if there is a trailing backslash" do
- -> { Regexp.send(@method, "\\") }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "\\") }.should.raise(RegexpError, Regexp.new(Regexp.escape("too short escape sequence: /\\/")))
end
it "does not raise a Regexp error if there is an escaped trailing backslash" do
- -> { Regexp.send(@method, "\\\\") }.should_not raise_error(RegexpError)
+ -> { Regexp.send(@method, "\\\\") }.should_not.raise(RegexpError)
end
- it "accepts a backspace followed by a character" do
+ it "accepts a backspace followed by a non-special character" do
Regexp.send(@method, "\\N").should == /#{"\x5c"+"N"}/
end
- it "accepts a one-digit octal value" do
- Regexp.send(@method, "\0").should == /#{"\x00"}/
- end
-
- it "accepts a two-digit octal value" do
- Regexp.send(@method, "\11").should == /#{"\x09"}/
- end
-
- it "accepts a one-digit hexadecimal value" do
- Regexp.send(@method, "\x9n").should == /#{"\x09n"}/
- end
-
- it "accepts a two-digit hexadecimal value" do
- Regexp.send(@method, "\x23").should == /#{"\x23"}/
- end
-
- it "interprets a digit following a two-digit hexadecimal value as a character" do
- Regexp.send(@method, "\x420").should == /#{"\x420"}/
- end
-
it "raises a RegexpError if \\x is not followed by any hexadecimal digits" do
- -> { Regexp.send(@method, "\\" + "xn") }.should raise_error(RegexpError)
- end
-
- it "accepts an escaped string interpolation" do
- Regexp.send(@method, "\#{abc}").should == /#{"\#{abc}"}/
- end
-
- it "accepts '\\n'" do
- Regexp.send(@method, "\n").should == /#{"\x0a"}/
- end
-
- it "accepts '\\t'" do
- Regexp.send(@method, "\t").should == /#{"\x09"}/
- end
-
- it "accepts '\\r'" do
- Regexp.send(@method, "\r").should == /#{"\x0d"}/
- end
-
- it "accepts '\\f'" do
- Regexp.send(@method, "\f").should == /#{"\x0c"}/
- end
-
- it "accepts '\\v'" do
- Regexp.send(@method, "\v").should == /#{"\x0b"}/
- end
-
- it "accepts '\\a'" do
- Regexp.send(@method, "\a").should == /#{"\x07"}/
- end
-
- it "accepts '\\e'" do
- Regexp.send(@method, "\e").should == /#{"\x1b"}/
- end
-
- it "accepts '\\C-\\n'" do
- Regexp.send(@method, "\C-\n").should == /#{"\x0a"}/
- end
-
- it "accepts '\\C-\\t'" do
- Regexp.send(@method, "\C-\t").should == /#{"\x09"}/
- end
-
- it "accepts '\\C-\\r'" do
- Regexp.send(@method, "\C-\r").should == /#{"\x0d"}/
- end
-
- it "accepts '\\C-\\f'" do
- Regexp.send(@method, "\C-\f").should == /#{"\x0c"}/
- end
-
- it "accepts '\\C-\\v'" do
- Regexp.send(@method, "\C-\v").should == /#{"\x0b"}/
- end
-
- it "accepts '\\C-\\a'" do
- Regexp.send(@method, "\C-\a").should == /#{"\x07"}/
- end
-
- it "accepts '\\C-\\e'" do
- Regexp.send(@method, "\C-\e").should == /#{"\x1b"}/
- end
-
- it "accepts multiple consecutive '\\' characters" do
- Regexp.send(@method, "\\\\\\N").should == /#{"\\\\\\"+"N"}/
- end
-
- it "accepts characters and escaped octal digits" do
- Regexp.send(@method, "abc\076").should == /#{"abc\x3e"}/
- end
-
- it "accepts escaped octal digits and characters" do
- Regexp.send(@method, "\076abc").should == /#{"\x3eabc"}/
- end
-
- it "accepts characters and escaped hexadecimal digits" do
- Regexp.send(@method, "abc\x42").should == /#{"abc\x42"}/
- end
-
- it "accepts escaped hexadecimal digits and characters" do
- Regexp.send(@method, "\x3eabc").should == /#{"\x3eabc"}/
- end
-
- it "accepts escaped hexadecimal and octal digits" do
- Regexp.send(@method, "\061\x42").should == /#{"\x31\x42"}/
- end
-
- it "accepts \\u{H} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{f}").should == /#{"\x0f"}/
- end
-
- it "accepts \\u{HH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{7f}").should == /#{"\x7f"}/
- end
-
- it "accepts \\u{HHH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{07f}").should == /#{"\x7f"}/
- end
-
- it "accepts \\u{HHHH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{0000}").should == /#{"\x00"}/
- end
-
- it "accepts \\u{HHHHH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{00001}").should == /#{"\x01"}/
- end
-
- it "accepts \\u{HHHHHH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{000000}").should == /#{"\x00"}/
- end
-
- it "accepts characters followed by \\u{HHHH}" do
- Regexp.send(@method, "abc\u{3042}").should == /#{"abc\u3042"}/
- end
-
- it "accepts \\u{HHHH} followed by characters" do
- Regexp.send(@method, "\u{3042}abc").should == /#{"\u3042abc"}/
- end
-
- it "accepts escaped hexadecimal digits followed by \\u{HHHH}" do
- Regexp.send(@method, "\x42\u{3042}").should == /#{"\x42\u3042"}/
- end
-
- it "accepts escaped octal digits followed by \\u{HHHH}" do
- Regexp.send(@method, "\056\u{3042}").should == /#{"\x2e\u3042"}/
- end
-
- it "accepts a combination of escaped octal and hexadecimal digits and \\u{HHHH}" do
- Regexp.send(@method, "\056\x42\u{3042}\x52\076").should == /#{"\x2e\x42\u3042\x52\x3e"}/
- end
-
- it "accepts \\uHHHH for a single Unicode codepoint" do
- Regexp.send(@method, "\u3042").should == /#{"\u3042"}/
- end
-
- it "accepts characters followed by \\uHHHH" do
- Regexp.send(@method, "abc\u3042").should == /#{"abc\u3042"}/
- end
-
- it "accepts \\uHHHH followed by characters" do
- Regexp.send(@method, "\u3042abc").should == /#{"\u3042abc"}/
- end
-
- it "accepts escaped hexadecimal digits followed by \\uHHHH" do
- Regexp.send(@method, "\x42\u3042").should == /#{"\x42\u3042"}/
- end
-
- it "accepts escaped octal digits followed by \\uHHHH" do
- Regexp.send(@method, "\056\u3042").should == /#{"\x2e\u3042"}/
- end
-
- it "accepts a combination of escaped octal and hexadecimal digits and \\uHHHH" do
- Regexp.send(@method, "\056\x42\u3042\x52\076").should == /#{"\x2e\x42\u3042\x52\x3e"}/
+ -> { Regexp.send(@method, "\\" + "xn") }.should.raise(RegexpError, Regexp.new(Regexp.escape("invalid hex escape: /\\xn/")))
end
it "raises a RegexpError if less than four digits are given for \\uHHHH" do
- -> { Regexp.send(@method, "\\" + "u304") }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "\\" + "u304") }.should.raise(RegexpError, Regexp.new(Regexp.escape("invalid Unicode escape: /\\u304/")))
end
it "raises a RegexpError if the \\u{} escape is empty" do
- -> { Regexp.send(@method, "\\" + "u{}") }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "\\" + "u{}") }.should.raise(RegexpError, Regexp.new(Regexp.escape("invalid Unicode list: /\\u{}/")))
+ end
+
+ it "raises a RegexpError if the \\u{} escape contains non hexadecimal digits" do
+ -> { Regexp.send(@method, "\\" + "u{abcX}") }.should.raise(RegexpError, Regexp.new(Regexp.escape("invalid Unicode list: /\\u{abcX}/")))
end
it "raises a RegexpError if more than six hexadecimal digits are given" do
- -> { Regexp.send(@method, "\\" + "u{0ffffff}") }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "\\" + "u{0ffffff}") }.should.raise(RegexpError, Regexp.new(Regexp.escape("invalid Unicode range: /\\u{0ffffff}/")))
end
it "returns a Regexp with US-ASCII encoding if only 7-bit ASCII characters are present regardless of the input String's encoding" do
@@ -431,12 +250,12 @@ describe :regexp_new_string, shared: true do
end
it "returns a Regexp with the input String's encoding" do
- str = "\x82\xa0".force_encoding(Encoding::Shift_JIS)
+ str = "\x82\xa0".dup.force_encoding(Encoding::Shift_JIS)
Regexp.send(@method, str).encoding.should == Encoding::Shift_JIS
end
it "returns a Regexp with source String having the input String's encoding" do
- str = "\x82\xa0".force_encoding(Encoding::Shift_JIS)
+ str = "\x82\xa0".dup.force_encoding(Encoding::Shift_JIS)
Regexp.send(@method, str).source.encoding.should == Encoding::Shift_JIS
end
end
@@ -444,69 +263,6 @@ end
describe :regexp_new_string_binary, shared: true do
describe "with escaped characters" do
- it "accepts a three-digit octal value" do
- Regexp.send(@method, "\315").should == /#{"\xcd"}/
- end
-
- it "interprets a digit following a three-digit octal value as a character" do
- Regexp.send(@method, "\3762").should == /#{"\xfe2"}/
- end
-
- it "accepts '\\M-\\n'" do
- Regexp.send(@method, "\M-\n").should == /#{"\x8a"}/
- end
-
- it "accepts '\\M-\\t'" do
- Regexp.send(@method, "\M-\t").should == /#{"\x89"}/
- end
-
- it "accepts '\\M-\\r'" do
- Regexp.send(@method, "\M-\r").should == /#{"\x8d"}/
- end
-
- it "accepts '\\M-\\f'" do
- Regexp.send(@method, "\M-\f").should == /#{"\x8c"}/
- end
-
- it "accepts '\\M-\\v'" do
- Regexp.send(@method, "\M-\v").should == /#{"\x8b"}/
- end
-
- it "accepts '\\M-\\a'" do
- Regexp.send(@method, "\M-\a").should == /#{"\x87"}/
- end
-
- it "accepts '\\M-\\e'" do
- Regexp.send(@method, "\M-\e").should == /#{"\x9b"}/
- end
-
- it "accepts '\\M-\\C-\\n'" do
- Regexp.send(@method, "\M-\C-\n").should == /#{"\x8a"}/
- end
-
- it "accepts '\\M-\\C-\\t'" do
- Regexp.send(@method, "\M-\C-\t").should == /#{"\x89"}/
- end
-
- it "accepts '\\M-\\C-\\r'" do
- Regexp.send(@method, "\M-\C-\r").should == /#{"\x8d"}/
- end
-
- it "accepts '\\M-\\C-\\f'" do
- Regexp.send(@method, "\M-\C-\f").should == /#{"\x8c"}/
- end
-
- it "accepts '\\M-\\C-\\v'" do
- Regexp.send(@method, "\M-\C-\v").should == /#{"\x8b"}/
- end
-
- it "accepts '\\M-\\C-\\a'" do
- Regexp.send(@method, "\M-\C-\a").should == /#{"\x87"}/
- end
-
- it "accepts '\\M-\\C-\\e'" do
- Regexp.send(@method, "\M-\C-\e").should == /#{"\x9b"}/
- end
end
end
@@ -561,9 +317,5 @@ describe :regexp_new_regexp, shared: true do
it "sets the encoding to US-ASCII if the Regexp literal has the 'n' option and the source String is ASCII only" do
Regexp.send(@method, /Hi/n).encoding.should == Encoding::US_ASCII
end
-
- it "sets the encoding to source String's encoding if the Regexp literal has the 'n' option and the source String is not ASCII only" do
- Regexp.send(@method, Regexp.new("\\xff", nil, 'n')).encoding.should == Encoding::BINARY
- end
end
end
diff --git a/spec/ruby/core/regexp/shared/quote.rb b/spec/ruby/core/regexp/shared/quote.rb
index 9533102766..083f12d78c 100644
--- a/spec/ruby/core/regexp/shared/quote.rb
+++ b/spec/ruby/core/regexp/shared/quote.rb
@@ -1,9 +1,9 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :regexp_quote, shared: true do
it "escapes any characters with special meaning in a regular expression" do
- Regexp.send(@method, '\*?{}.+^[]()- ').should == '\\\\\*\?\{\}\.\+\^\[\]\(\)\-\\ '
- Regexp.send(@method, "\*?{}.+^[]()- ").should == '\\*\\?\\{\\}\\.\\+\\^\\[\\]\\(\\)\\-\\ '
+ Regexp.send(@method, '\*?{}.+^$[]()- ').should == '\\\\\*\?\{\}\.\+\^\$\[\]\(\)\-\\ '
+ Regexp.send(@method, "\*?{}.+^$[]()- ").should == '\\*\\?\\{\\}\\.\\+\\^\\$\\[\\]\\(\\)\\-\\ '
Regexp.send(@method, '\n\r\f\t').should == '\\\\n\\\\r\\\\f\\\\t'
Regexp.send(@method, "\n\r\f\t").should == '\\n\\r\\f\\t'
end
@@ -18,24 +18,24 @@ describe :regexp_quote, shared: true do
end
it "works for broken strings" do
- Regexp.send(@method, "a.\x85b.".force_encoding("US-ASCII")).should =="a\\.\x85b\\.".force_encoding("US-ASCII")
- Regexp.send(@method, "a.\x80".force_encoding("UTF-8")).should == "a\\.\x80".force_encoding("UTF-8")
+ Regexp.send(@method, "a.\x85b.".dup.force_encoding("US-ASCII")).should =="a\\.\x85b\\.".dup.force_encoding("US-ASCII")
+ Regexp.send(@method, "a.\x80".dup.force_encoding("UTF-8")).should == "a\\.\x80".dup.force_encoding("UTF-8")
end
it "sets the encoding of the result to US-ASCII if there are only US-ASCII characters present in the input String" do
- str = "abc".force_encoding("euc-jp")
+ str = "abc".dup.force_encoding("euc-jp")
Regexp.send(@method, str).encoding.should == Encoding::US_ASCII
end
it "sets the encoding of the result to the encoding of the String if any non-US-ASCII characters are present in an input String with valid encoding" do
- str = "ありがとう".force_encoding("utf-8")
- str.valid_encoding?.should be_true
+ str = "ありがとう".dup.force_encoding("utf-8")
+ str.valid_encoding?.should == true
Regexp.send(@method, str).encoding.should == Encoding::UTF_8
end
it "sets the encoding of the result to BINARY if any non-US-ASCII characters are present in an input String with invalid encoding" do
- str = "\xff".force_encoding "us-ascii"
- str.valid_encoding?.should be_false
+ str = "\xff".dup.force_encoding "us-ascii"
+ str.valid_encoding?.should == false
Regexp.send(@method, "\xff").encoding.should == Encoding::BINARY
end
end
diff --git a/spec/ruby/core/regexp/source_spec.rb b/spec/ruby/core/regexp/source_spec.rb
index 5f253da9ea..4eebf280f0 100644
--- a/spec/ruby/core/regexp/source_spec.rb
+++ b/spec/ruby/core/regexp/source_spec.rb
@@ -34,14 +34,14 @@ describe "Regexp#source" do
not_supported_on :opal do
it "has US-ASCII encoding when created from an ASCII-only \\u{} literal" do
re = /[\u{20}-\u{7E}]/
- re.source.encoding.should equal(Encoding::US_ASCII)
+ re.source.encoding.should.equal?(Encoding::US_ASCII)
end
end
not_supported_on :opal do
it "has UTF-8 encoding when created from a non-ASCII-only \\u{} literal" do
re = /[\u{20}-\u{7EE}]/
- re.source.encoding.should equal(Encoding::UTF_8)
+ re.source.encoding.should.equal?(Encoding::UTF_8)
end
end
end
diff --git a/spec/ruby/core/regexp/timeout_spec.rb b/spec/ruby/core/regexp/timeout_spec.rb
new file mode 100644
index 0000000000..a1ec475ef3
--- /dev/null
+++ b/spec/ruby/core/regexp/timeout_spec.rb
@@ -0,0 +1,33 @@
+require_relative '../../spec_helper'
+
+describe "Regexp.timeout" do
+ after :each do
+ Regexp.timeout = nil
+ end
+
+ it "returns global timeout" do
+ Regexp.timeout = 3
+ Regexp.timeout.should == 3
+ end
+
+ it "raises Regexp::TimeoutError after global timeout elapsed" do
+ Regexp.timeout = 0.001
+ Regexp.timeout.should == 0.001
+
+ -> {
+ # A typical ReDoS case
+ /^(a*)*$/ =~ "a" * 1000000 + "x"
+ }.should.raise(Regexp::TimeoutError, "regexp match timeout")
+ end
+
+ it "raises Regexp::TimeoutError after timeout keyword value elapsed" do
+ Regexp.timeout = 3 # This should be ignored
+ Regexp.timeout.should == 3
+
+ re = Regexp.new("^a*b?a*$", timeout: 0.001)
+
+ -> {
+ re =~ "a" * 1000000 + "x"
+ }.should.raise(Regexp::TimeoutError, "regexp match timeout")
+ end
+end
diff --git a/spec/ruby/core/regexp/try_convert_spec.rb b/spec/ruby/core/regexp/try_convert_spec.rb
index be567e2130..da5e10adce 100644
--- a/spec/ruby/core/regexp/try_convert_spec.rb
+++ b/spec/ruby/core/regexp/try_convert_spec.rb
@@ -9,7 +9,7 @@ describe "Regexp.try_convert" do
it "returns nil if given an argument that can't be converted to a Regexp" do
['', 'glark', [], Object.new, :pat].each do |arg|
- Regexp.try_convert(arg).should be_nil
+ Regexp.try_convert(arg).should == nil
end
end
@@ -18,4 +18,10 @@ describe "Regexp.try_convert" do
rex.should_receive(:to_regexp).and_return(/(p(a)t[e]rn)/)
Regexp.try_convert(rex).should == /(p(a)t[e]rn)/
end
+
+ it "raises a TypeError if the object does not return an Regexp from #to_regexp" do
+ obj = mock("regexp")
+ obj.should_receive(:to_regexp).and_return("string")
+ -> { Regexp.try_convert(obj) }.should raise_consistent_error(TypeError, "can't convert MockObject into Regexp (MockObject#to_regexp gives String)")
+ end
end
diff --git a/spec/ruby/core/regexp/union_spec.rb b/spec/ruby/core/regexp/union_spec.rb
index 8076836471..c0a9d12fed 100644
--- a/spec/ruby/core/regexp/union_spec.rb
+++ b/spec/ruby/core/regexp/union_spec.rb
@@ -43,6 +43,27 @@ describe "Regexp.union" do
Regexp.union("\u00A9".encode("ISO-8859-1"), "a".encode("UTF-8")).encoding.should == Encoding::ISO_8859_1
end
+ it "returns ASCII-8BIT if the regexp encodings are ASCII-8BIT and at least one has non-ASCII characters" do
+ us_ascii_implicit, us_ascii_explicit, binary = /abc/, /[\x00-\x7f]/n, /[\x80-\xBF]/n
+ us_ascii_implicit.encoding.should == Encoding::US_ASCII
+ us_ascii_explicit.encoding.should == Encoding::US_ASCII
+ binary.encoding.should == Encoding::BINARY
+
+ Regexp.union(us_ascii_implicit, us_ascii_explicit, binary).encoding.should == Encoding::BINARY
+ Regexp.union(us_ascii_implicit, binary, us_ascii_explicit).encoding.should == Encoding::BINARY
+ Regexp.union(us_ascii_explicit, us_ascii_implicit, binary).encoding.should == Encoding::BINARY
+ Regexp.union(us_ascii_explicit, binary, us_ascii_implicit).encoding.should == Encoding::BINARY
+ Regexp.union(binary, us_ascii_implicit, us_ascii_explicit).encoding.should == Encoding::BINARY
+ Regexp.union(binary, us_ascii_explicit, us_ascii_implicit).encoding.should == Encoding::BINARY
+ end
+
+ it "return US-ASCII if all patterns are ASCII-only" do
+ Regexp.union(/abc/e, /def/e).encoding.should == Encoding::US_ASCII
+ Regexp.union(/abc/n, /def/n).encoding.should == Encoding::US_ASCII
+ Regexp.union(/abc/s, /def/s).encoding.should == Encoding::US_ASCII
+ Regexp.union(/abc/u, /def/u).encoding.should == Encoding::US_ASCII
+ end
+
it "returns a Regexp with UTF-8 if one part is UTF-8" do
Regexp.union(/probl[éeè]me/i, /help/i).encoding.should == Encoding::UTF_8
end
@@ -54,83 +75,83 @@ describe "Regexp.union" do
it "raises ArgumentError if the arguments include conflicting ASCII-incompatible Strings" do
-> {
Regexp.union("a".encode("UTF-16LE"), "b".encode("UTF-16BE"))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, 'incompatible encodings: UTF-16LE and UTF-16BE')
end
it "raises ArgumentError if the arguments include conflicting ASCII-incompatible Regexps" do
-> {
Regexp.union(Regexp.new("a".encode("UTF-16LE")),
Regexp.new("b".encode("UTF-16BE")))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, 'incompatible encodings: UTF-16LE and UTF-16BE')
end
it "raises ArgumentError if the arguments include conflicting fixed encoding Regexps" do
-> {
Regexp.union(Regexp.new("a".encode("UTF-8"), Regexp::FIXEDENCODING),
Regexp.new("b".encode("US-ASCII"), Regexp::FIXEDENCODING))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, 'incompatible encodings: UTF-8 and US-ASCII')
end
it "raises ArgumentError if the arguments include a fixed encoding Regexp and a String containing non-ASCII-compatible characters in a different encoding" do
-> {
Regexp.union(Regexp.new("a".encode("UTF-8"), Regexp::FIXEDENCODING),
"\u00A9".encode("ISO-8859-1"))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, 'incompatible encodings: UTF-8 and ISO-8859-1')
end
it "raises ArgumentError if the arguments include a String containing non-ASCII-compatible characters and a fixed encoding Regexp in a different encoding" do
-> {
Regexp.union("\u00A9".encode("ISO-8859-1"),
Regexp.new("a".encode("UTF-8"), Regexp::FIXEDENCODING))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, 'incompatible encodings: ISO-8859-1 and UTF-8')
end
it "raises ArgumentError if the arguments include an ASCII-incompatible String and an ASCII-only String" do
-> {
Regexp.union("a".encode("UTF-16LE"), "b".encode("UTF-8"))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, /ASCII incompatible encoding: UTF-16LE|incompatible encodings: UTF-16LE and US-ASCII/)
end
it "raises ArgumentError if the arguments include an ASCII-incompatible Regexp and an ASCII-only String" do
-> {
Regexp.union(Regexp.new("a".encode("UTF-16LE")), "b".encode("UTF-8"))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, /ASCII incompatible encoding: UTF-16LE|incompatible encodings: UTF-16LE and US-ASCII/)
end
it "raises ArgumentError if the arguments include an ASCII-incompatible String and an ASCII-only Regexp" do
-> {
Regexp.union("a".encode("UTF-16LE"), Regexp.new("b".encode("UTF-8")))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, /ASCII incompatible encoding: UTF-16LE|incompatible encodings: UTF-16LE and US-ASCII/)
end
it "raises ArgumentError if the arguments include an ASCII-incompatible Regexp and an ASCII-only Regexp" do
-> {
Regexp.union(Regexp.new("a".encode("UTF-16LE")), Regexp.new("b".encode("UTF-8")))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, /ASCII incompatible encoding: UTF-16LE|incompatible encodings: UTF-16LE and US-ASCII/)
end
it "raises ArgumentError if the arguments include an ASCII-incompatible String and a String containing non-ASCII-compatible characters in a different encoding" do
-> {
Regexp.union("a".encode("UTF-16LE"), "\u00A9".encode("ISO-8859-1"))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, 'incompatible encodings: UTF-16LE and ISO-8859-1')
end
it "raises ArgumentError if the arguments include an ASCII-incompatible Regexp and a String containing non-ASCII-compatible characters in a different encoding" do
-> {
Regexp.union(Regexp.new("a".encode("UTF-16LE")), "\u00A9".encode("ISO-8859-1"))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, 'incompatible encodings: UTF-16LE and ISO-8859-1')
end
it "raises ArgumentError if the arguments include an ASCII-incompatible String and a Regexp containing non-ASCII-compatible characters in a different encoding" do
-> {
Regexp.union("a".encode("UTF-16LE"), Regexp.new("\u00A9".encode("ISO-8859-1")))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, 'incompatible encodings: UTF-16LE and ISO-8859-1')
end
it "raises ArgumentError if the arguments include an ASCII-incompatible Regexp and a Regexp containing non-ASCII-compatible characters in a different encoding" do
-> {
Regexp.union(Regexp.new("a".encode("UTF-16LE")), Regexp.new("\u00A9".encode("ISO-8859-1")))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, 'incompatible encodings: UTF-16LE and ISO-8859-1')
end
it "uses to_str to convert arguments (if not Regexp)" do
@@ -154,6 +175,8 @@ describe "Regexp.union" do
not_supported_on :opal do
Regexp.union([/dogs/, /cats/i]).should == /(?-mix:dogs)|(?i-mx:cats)/
end
- ->{Regexp.union(["skiing", "sledding"], [/dogs/, /cats/i])}.should raise_error(TypeError)
+ -> {
+ Regexp.union(["skiing", "sledding"], [/dogs/, /cats/i])
+ }.should.raise(TypeError, 'no implicit conversion of Array into String')
end
end
diff --git a/spec/ruby/core/set/add_spec.rb b/spec/ruby/core/set/add_spec.rb
new file mode 100644
index 0000000000..1ce03b1eab
--- /dev/null
+++ b/spec/ruby/core/set/add_spec.rb
@@ -0,0 +1,34 @@
+require_relative '../../spec_helper'
+require_relative 'shared/add'
+
+describe "Set#add" do
+ it_behaves_like :set_add, :add
+end
+
+describe "Set#add?" do
+ before :each do
+ @set = Set.new
+ end
+
+ it "adds the passed Object to self" do
+ @set.add?("cat")
+ @set.should.include?("cat")
+ end
+
+ it "returns self when the Object has not yet been added to self" do
+ @set.add?("cat").should.equal?(@set)
+ end
+
+ it "returns nil when the Object has already been added to self" do
+ @set.add?("cat")
+ @set.add?("cat").should == nil
+ end
+
+ it "raises RuntimeError when called during iteration" do
+ set = Set[:a, :b, :c, :d, :e, :f]
+ set.each do |_m|
+ -> { set << 1 }.should.raise(RuntimeError, /iteration/)
+ end
+ set.should == Set[:a, :b, :c, :d, :e, :f]
+ end
+end
diff --git a/spec/ruby/core/set/append_spec.rb b/spec/ruby/core/set/append_spec.rb
new file mode 100644
index 0000000000..82d34d9130
--- /dev/null
+++ b/spec/ruby/core/set/append_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/add'
+
+describe "Set#<<" do
+ it_behaves_like :set_add, :<<
+end
diff --git a/spec/ruby/core/set/case_compare_spec.rb b/spec/ruby/core/set/case_compare_spec.rb
new file mode 100644
index 0000000000..3781b1b963
--- /dev/null
+++ b/spec/ruby/core/set/case_compare_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../spec_helper'
+require_relative 'shared/include'
+
+describe "Set#===" do
+ it_behaves_like :set_include, :===
+
+ it "is an alias for include?" do
+ set = Set.new
+ set.method(:===).should == set.method(:include?)
+ end
+end
diff --git a/spec/ruby/core/set/case_equality_spec.rb b/spec/ruby/core/set/case_equality_spec.rb
new file mode 100644
index 0000000000..19c1fb6b9c
--- /dev/null
+++ b/spec/ruby/core/set/case_equality_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/include'
+
+describe "Set#===" do
+ it_behaves_like :set_include, :===
+end
diff --git a/spec/ruby/core/set/classify_spec.rb b/spec/ruby/core/set/classify_spec.rb
new file mode 100644
index 0000000000..a225ab7cbb
--- /dev/null
+++ b/spec/ruby/core/set/classify_spec.rb
@@ -0,0 +1,26 @@
+require_relative '../../spec_helper'
+
+describe "Set#classify" do
+ before :each do
+ @set = Set["one", "two", "three", "four"]
+ end
+
+ it "yields each Object in self" do
+ res = []
+ @set.classify { |x| res << x }
+ res.sort.should == ["one", "two", "three", "four"].sort
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.classify
+ enum.should.instance_of?(Enumerator)
+
+ classified = enum.each { |x| x.length }
+ classified.should == { 3 => Set["one", "two"], 4 => Set["four"], 5 => Set["three"] }
+ end
+
+ it "classifies the Objects in self based on the block's return value" do
+ classified = @set.classify { |x| x.length }
+ classified.should == { 3 => Set["one", "two"], 4 => Set["four"], 5 => Set["three"] }
+ end
+end
diff --git a/spec/ruby/core/set/clear_spec.rb b/spec/ruby/core/set/clear_spec.rb
new file mode 100644
index 0000000000..c61a0d78f2
--- /dev/null
+++ b/spec/ruby/core/set/clear_spec.rb
@@ -0,0 +1,16 @@
+require_relative '../../spec_helper'
+
+describe "Set#clear" do
+ before :each do
+ @set = Set["one", "two", "three", "four"]
+ end
+
+ it "removes all elements from self" do
+ @set.clear
+ @set.should.empty?
+ end
+
+ it "returns self" do
+ @set.clear.should.equal?(@set)
+ end
+end
diff --git a/spec/ruby/core/set/collect_spec.rb b/spec/ruby/core/set/collect_spec.rb
new file mode 100644
index 0000000000..d186f1a0d9
--- /dev/null
+++ b/spec/ruby/core/set/collect_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/collect'
+
+describe "Set#collect!" do
+ it_behaves_like :set_collect_bang, :collect!
+end
diff --git a/spec/ruby/core/set/compare_by_identity_spec.rb b/spec/ruby/core/set/compare_by_identity_spec.rb
new file mode 100644
index 0000000000..458e760da0
--- /dev/null
+++ b/spec/ruby/core/set/compare_by_identity_spec.rb
@@ -0,0 +1,153 @@
+require_relative '../../spec_helper'
+
+describe "Set#compare_by_identity" do
+ it "compares its members by identity" do
+ a = "a"
+ b1 = "b"
+ b2 = b1.dup
+
+ 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 == true
+ set.compare_by_identity
+ set.member?(elt.dup).should == 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 == 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.should.compare_by_identity?
+ 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 == 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
+
+ ruby_version_is "4.0" do
+ it "raises a FrozenError on frozen sets" do
+ set = Set.new.freeze
+ -> {
+ set.compare_by_identity
+ }.should.raise(FrozenError, /can't modify frozen Set: (#<)?Set(\[|: {)[\]}]>?/)
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "raises a FrozenError on frozen sets" do
+ set = Set.new.freeze
+ -> {
+ set.compare_by_identity
+ }.should.raise(FrozenError, /frozen Hash/)
+ end
+ 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
+
+describe "Set#compare_by_identity?" do
+ it "returns false by default" do
+ Set.new.should_not.compare_by_identity?
+ end
+
+ it "returns true once #compare_by_identity has been invoked on self" do
+ set = Set.new
+ set.compare_by_identity
+ set.should.compare_by_identity?
+ end
+
+ it "returns true when called multiple times on the same set" do
+ set = Set.new
+ set.compare_by_identity
+ set.should.compare_by_identity?
+ set.should.compare_by_identity?
+ set.should.compare_by_identity?
+ end
+end
diff --git a/spec/ruby/core/set/comparison_spec.rb b/spec/ruby/core/set/comparison_spec.rb
new file mode 100644
index 0000000000..eb18a198e5
--- /dev/null
+++ b/spec/ruby/core/set/comparison_spec.rb
@@ -0,0 +1,26 @@
+require_relative '../../spec_helper'
+
+describe "Set#<=>" do
+ it "returns 0 if the sets are equal" do
+ (Set[] <=> Set[]).should == 0
+ (Set[:a, :b, :c] <=> Set[:a, :b, :c]).should == 0
+ end
+
+ it "returns -1 if the set is a proper subset of the other set" do
+ (Set[] <=> Set[1]).should == -1
+ (Set[1, 2] <=> Set[1, 2, 3]).should == -1
+ end
+
+ it "returns +1 if the set is a proper superset of other set" do
+ (Set[1] <=> Set[]).should == +1
+ (Set[1, 2, 3] <=> Set[1, 2]).should == +1
+ end
+
+ it "returns nil if the set has unique elements" do
+ (Set[1, 2, 3] <=> Set[:a, :b, :c]).should == nil
+ end
+
+ it "returns nil when the argument is not set-like" do
+ (Set[] <=> false).should == nil
+ end
+end
diff --git a/spec/ruby/core/set/constructor_spec.rb b/spec/ruby/core/set/constructor_spec.rb
new file mode 100644
index 0000000000..11138f3a5b
--- /dev/null
+++ b/spec/ruby/core/set/constructor_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "Set[]" do
+ it "returns a new Set populated with the passed Objects" do
+ set = Set[1, 2, 3]
+
+ set.instance_of?(Set).should == true
+ set.size.should.eql?(3)
+
+ set.should.include?(1)
+ set.should.include?(2)
+ set.should.include?(3)
+ end
+end
diff --git a/spec/ruby/core/set/delete_if_spec.rb b/spec/ruby/core/set/delete_if_spec.rb
new file mode 100644
index 0000000000..b231dff50d
--- /dev/null
+++ b/spec/ruby/core/set/delete_if_spec.rb
@@ -0,0 +1,37 @@
+require_relative '../../spec_helper'
+
+describe "Set#delete_if" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.delete_if { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "deletes every element from self for which the passed block returns true" do
+ @set.delete_if { |x| x.size == 3 }
+ @set.size.should.eql?(1)
+
+ @set.should_not.include?("one")
+ @set.should_not.include?("two")
+ @set.should.include?("three")
+ end
+
+ it "returns self" do
+ @set.delete_if { |x| x }.should.equal?(@set)
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.delete_if
+ enum.should.instance_of?(Enumerator)
+
+ enum.each { |x| x.size == 3 }
+
+ @set.should_not.include?("one")
+ @set.should_not.include?("two")
+ @set.should.include?("three")
+ end
+end
diff --git a/spec/ruby/core/set/delete_spec.rb b/spec/ruby/core/set/delete_spec.rb
new file mode 100644
index 0000000000..cdc6dd7b36
--- /dev/null
+++ b/spec/ruby/core/set/delete_spec.rb
@@ -0,0 +1,36 @@
+require_relative '../../spec_helper'
+
+describe "Set#delete" do
+ before :each do
+ @set = Set["a", "b", "c"]
+ end
+
+ it "deletes the passed Object from self" do
+ @set.delete("a")
+ @set.should_not.include?("a")
+ end
+
+ it "returns self" do
+ @set.delete("a").should.equal?(@set)
+ @set.delete("x").should.equal?(@set)
+ end
+end
+
+describe "Set#delete?" do
+ before :each do
+ @set = Set["a", "b", "c"]
+ end
+
+ it "deletes the passed Object from self" do
+ @set.delete?("a")
+ @set.should_not.include?("a")
+ end
+
+ it "returns self when the passed Object is in self" do
+ @set.delete?("a").should.equal?(@set)
+ end
+
+ it "returns nil when the passed Object is not in self" do
+ @set.delete?("x").should == nil
+ end
+end
diff --git a/spec/ruby/core/set/difference_spec.rb b/spec/ruby/core/set/difference_spec.rb
new file mode 100644
index 0000000000..149f946592
--- /dev/null
+++ b/spec/ruby/core/set/difference_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/difference'
+
+describe "Set#difference" do
+ it_behaves_like :set_difference, :difference
+end
diff --git a/spec/ruby/core/set/disjoint_spec.rb b/spec/ruby/core/set/disjoint_spec.rb
new file mode 100644
index 0000000000..d415c21045
--- /dev/null
+++ b/spec/ruby/core/set/disjoint_spec.rb
@@ -0,0 +1,22 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#disjoint?" do
+ it "returns false when two Sets have at least one element in common" do
+ Set[1, 2].disjoint?(Set[2, 3]).should == false
+ end
+
+ it "returns true when two Sets have no element in common" do
+ Set[1, 2].disjoint?(Set[3, 4]).should == true
+ end
+
+ context "when comparing to a Set-like object" do
+ it "returns false when a Set has at least one element in common with a Set-like object" do
+ Set[1, 2].disjoint?(SetSpecs::SetLike.new([2, 3])).should == false
+ end
+
+ it "returns true when a Set has no element in common with a Set-like object" do
+ Set[1, 2].disjoint?(SetSpecs::SetLike.new([3, 4])).should == true
+ end
+ end
+end
diff --git a/spec/ruby/core/set/divide_spec.rb b/spec/ruby/core/set/divide_spec.rb
new file mode 100644
index 0000000000..409a22df75
--- /dev/null
+++ b/spec/ruby/core/set/divide_spec.rb
@@ -0,0 +1,68 @@
+require_relative '../../spec_helper'
+
+describe "Set#divide" do
+ it "divides self into a set of subsets based on the blocks return values" do
+ set = Set["one", "two", "three", "four", "five"].divide { |x| x.length }
+ set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
+ end
+
+ it "yields each Object to the block" do
+ ret = []
+ Set["one", "two", "three", "four", "five"].divide { |x| ret << x }
+ ret.sort.should == ["five", "four", "one", "three", "two"]
+ end
+
+ it "returns an enumerator when not passed a block" do
+ ret = Set[1, 2, 3, 4].divide
+ ret.should.is_a?(Enumerator)
+ ret.each(&:even?).should == Set[Set[1, 3], Set[2, 4]]
+ end
+end
+
+describe "Set#divide when passed a block with an arity of 2" do
+ it "divides self into a set of subsets based on the blocks return values" do
+ set = Set[1, 3, 4, 6, 9, 10, 11].divide { |x, y| (x - y).abs == 1 }
+ set.map{ |x| x.to_a.sort }.sort.should == [[1], [3, 4], [6], [9, 10, 11]]
+ end
+
+ ruby_version_is "4.0" do
+ it "yields each two Object to the block" do
+ ret = []
+ Set[1, 2].divide { |x, y| ret << [x, y] }
+ ret.sort.should == [[1, 2], [2, 1]]
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "yields each two Object to the block" do
+ ret = []
+ Set[1, 2].divide { |x, y| ret << [x, y] }
+ ret.sort.should == [[1, 1], [1, 2], [2, 1], [2, 2]]
+ end
+ end
+
+ it "returns an enumerator when not passed a block" do
+ ret = Set[1, 2, 3, 4].divide
+ ret.should.is_a?(Enumerator)
+ ret.each { |a, b| (a + b).even? }.should == Set[Set[1, 3], Set[2, 4]]
+ end
+end
+
+describe "Set#divide when passed a block with an arity of > 2" do
+ it "only uses the first element if the arity > 2" do
+ set = Set["one", "two", "three", "four", "five"].divide do |x, y, z|
+ y.should == nil
+ z.should == nil
+ x.length
+ end
+ set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
+ end
+
+ it "only uses the first element if the arity = -1" do
+ set = Set["one", "two", "three", "four", "five"].divide do |*xs|
+ xs.size.should == 1
+ xs.first.length
+ end
+ set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
+ end
+end
diff --git a/spec/ruby/core/set/each_spec.rb b/spec/ruby/core/set/each_spec.rb
new file mode 100644
index 0000000000..bdafc99571
--- /dev/null
+++ b/spec/ruby/core/set/each_spec.rb
@@ -0,0 +1,26 @@
+require_relative '../../spec_helper'
+
+describe "Set#each" do
+ before :each do
+ @set = Set[1, 2, 3]
+ end
+
+ it "yields each Object in self" do
+ ret = []
+ @set.each { |x| ret << x }
+ ret.sort.should == [1, 2, 3]
+ end
+
+ it "returns self" do
+ @set.each { |x| x }.should.equal?(@set)
+ end
+
+ it "returns an Enumerator when not passed a block" do
+ enum = @set.each
+ enum.should.instance_of?(Enumerator)
+
+ ret = []
+ enum.each { |x| ret << x }
+ ret.sort.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/core/set/empty_spec.rb b/spec/ruby/core/set/empty_spec.rb
new file mode 100644
index 0000000000..c71f2ce18d
--- /dev/null
+++ b/spec/ruby/core/set/empty_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+
+describe "Set#empty?" do
+ it "returns true if self is empty" do
+ Set[].empty?.should == true
+ Set[1].empty?.should == false
+ Set[1,2,3].empty?.should == false
+ end
+end
diff --git a/spec/ruby/core/set/enumerable/to_set_spec.rb b/spec/ruby/core/set/enumerable/to_set_spec.rb
new file mode 100644
index 0000000000..f139e1c025
--- /dev/null
+++ b/spec/ruby/core/set/enumerable/to_set_spec.rb
@@ -0,0 +1,12 @@
+require_relative '../../../spec_helper'
+
+describe "Enumerable#to_set" do
+ it "returns a new Set created from self" do
+ [1, 2, 3].to_set.should == Set[1, 2, 3]
+ {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]]
+ end
+
+ it "passes down passed blocks" do
+ [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9]
+ end
+end
diff --git a/spec/ruby/core/set/eql_spec.rb b/spec/ruby/core/set/eql_spec.rb
new file mode 100644
index 0000000000..6862ed4eda
--- /dev/null
+++ b/spec/ruby/core/set/eql_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "Set#eql?" do
+ it "returns true when the passed argument is a Set and contains the same elements" do
+ Set[].should.eql?(Set[])
+ Set[1, 2, 3].should.eql?(Set[1, 2, 3])
+ Set[1, 2, 3].should.eql?(Set[3, 2, 1])
+ Set["a", :b, ?c].should.eql?(Set[?c, :b, "a"])
+
+ Set[1, 2, 3].should_not.eql?(Set[1.0, 2, 3])
+ Set[1, 2, 3].should_not.eql?(Set[2, 3])
+ Set[1, 2, 3].should_not.eql?(Set[])
+ end
+end
diff --git a/spec/ruby/core/set/equal_value_spec.rb b/spec/ruby/core/set/equal_value_spec.rb
new file mode 100644
index 0000000000..721a79a3f1
--- /dev/null
+++ b/spec/ruby/core/set/equal_value_spec.rb
@@ -0,0 +1,34 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#==" do
+ it "returns true when the passed Object is a Set and self and the Object contain the same elements" do
+ Set[].should == Set[]
+ Set[1, 2, 3].should == Set[1, 2, 3]
+ Set["1", "2", "3"].should == Set["1", "2", "3"]
+
+ Set[1, 2, 3].should_not == Set[1.0, 2, 3]
+ Set[1, 2, 3].should_not == [1, 2, 3]
+ end
+
+ it "does not depend on the order of the elements" do
+ Set[1, 2, 3].should == Set[3, 2, 1]
+ Set[:a, "b", ?c].should == Set[?c, "b", :a]
+ end
+
+ it "does not depend on the order of nested Sets" do
+ Set[Set[1], Set[2], Set[3]].should == Set[Set[3], Set[2], Set[1]]
+
+ set1 = Set[Set["a", "b"], Set["c", "d"], Set["e", "f"]]
+ set2 = Set[Set["c", "d"], Set["a", "b"], Set["e", "f"]]
+ set1.should == set2
+ end
+
+ ruby_version_is ""..."4.0" do
+ context "when comparing to a Set-like object" do
+ it "returns true when a Set and a Set-like object contain the same elements" do
+ Set[1, 2, 3].should == SetSpecs::SetLike.new([1, 2, 3])
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/set/exclusion_spec.rb b/spec/ruby/core/set/exclusion_spec.rb
new file mode 100644
index 0000000000..52ee34fe78
--- /dev/null
+++ b/spec/ruby/core/set/exclusion_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../spec_helper'
+
+describe "Set#^" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns a new Set containing elements that are not in both self and the passed Enumerable" do
+ (@set ^ Set[3, 4, 5]).should == Set[1, 2, 5]
+ (@set ^ [3, 4, 5]).should == Set[1, 2, 5]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ -> { @set ^ 3 }.should.raise(ArgumentError)
+ -> { @set ^ Object.new }.should.raise(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/filter_spec.rb b/spec/ruby/core/set/filter_spec.rb
index 779254ad68..779254ad68 100644
--- a/spec/ruby/library/set/filter_spec.rb
+++ b/spec/ruby/core/set/filter_spec.rb
diff --git a/spec/ruby/core/set/fixtures/set_like.rb b/spec/ruby/core/set/fixtures/set_like.rb
new file mode 100644
index 0000000000..86dec2ed52
--- /dev/null
+++ b/spec/ruby/core/set/fixtures/set_like.rb
@@ -0,0 +1,30 @@
+
+module SetSpecs
+ # This class is used to test the interaction of "Set-like" objects with real Sets
+ #
+ # These "Set-like" objects reply to is_a?(Set) with true and thus real Set objects are able to transparently
+ # interoperate with them in a duck-typing manner.
+ class SetLike
+ include Enumerable
+
+ def is_a?(klass)
+ super || klass == ::Set
+ end
+
+ def initialize(entries)
+ @entries = entries
+ end
+
+ def each(&block)
+ @entries.each(&block)
+ end
+
+ def inspect
+ "#<#{self.class}: {#{map(&:inspect).join(", ")}}>"
+ end
+
+ def size
+ @entries.size
+ end
+ end
+end
diff --git a/spec/ruby/core/set/flatten_merge_spec.rb b/spec/ruby/core/set/flatten_merge_spec.rb
new file mode 100644
index 0000000000..3904d969ae
--- /dev/null
+++ b/spec/ruby/core/set/flatten_merge_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+
+describe "Set#flatten_merge" do
+ ruby_version_is ""..."4.0" do
+ it "is protected" do
+ Set.protected_instance_methods(false).should.include?(:flatten_merge)
+ end
+
+ it "flattens the passed Set and merges it into self" do
+ set1 = Set[1, 2]
+ set2 = Set[3, 4, Set[5, 6]]
+
+ set1.send(:flatten_merge, set2).should == Set[1, 2, 3, 4, 5, 6]
+ end
+
+ it "raises an ArgumentError when trying to flatten a recursive Set" do
+ set1 = Set[1, 2, 3]
+ set2 = Set[5, 6, 7]
+ set2 << set2
+
+ -> { set1.send(:flatten_merge, set2) }.should.raise(ArgumentError)
+ end
+ end
+end
diff --git a/spec/ruby/core/set/flatten_spec.rb b/spec/ruby/core/set/flatten_spec.rb
new file mode 100644
index 0000000000..ca6323fac8
--- /dev/null
+++ b/spec/ruby/core/set/flatten_spec.rb
@@ -0,0 +1,49 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0'
+
+describe "Set#flatten" do
+ it "returns a copy of self with each included Set flattened" do
+ set = Set[1, 2, Set[3, 4, Set[5, 6, Set[7, 8]]], 9, 10]
+ flattened_set = set.flatten
+
+ flattened_set.should_not.equal?(set)
+ flattened_set.should == Set[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ end
+
+ it "raises an ArgumentError when self is recursive" do
+ (set = Set[]) << set
+ -> { set.flatten }.should.raise(ArgumentError)
+ end
+
+ ruby_version_is ""..."4.0" do
+ context "when Set contains a Set-like object" do
+ it "returns a copy of self with each included Set-like object flattened" do
+ Set[SetSpecs::SetLike.new([1])].flatten.should == Set[1]
+ end
+ end
+ end
+end
+
+describe "Set#flatten!" do
+ it "flattens self" do
+ set = Set[1, 2, Set[3, 4, Set[5, 6, Set[7, 8]]], 9, 10]
+ set.flatten!
+ set.should == Set[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ end
+
+ it "returns self when self was modified" do
+ set = Set[1, 2, Set[3, 4]]
+ set.flatten!.should.equal?(set)
+ end
+
+ it "returns nil when self was not modified" do
+ set = Set[1, 2, 3, 4]
+ set.flatten!.should == nil
+ end
+
+ it "raises an ArgumentError when self is recursive" do
+ (set = Set[]) << set
+ -> { set.flatten! }.should.raise(ArgumentError)
+ end
+end
diff --git a/spec/ruby/core/set/hash_spec.rb b/spec/ruby/core/set/hash_spec.rb
new file mode 100644
index 0000000000..63a0aa66a5
--- /dev/null
+++ b/spec/ruby/core/set/hash_spec.rb
@@ -0,0 +1,19 @@
+require_relative '../../spec_helper'
+
+describe "Set#hash" do
+ it "is static" do
+ Set[].hash.should == Set[].hash
+ Set[1, 2, 3].hash.should == Set[1, 2, 3].hash
+ Set[:a, "b", ?c].hash.should == Set[?c, "b", :a].hash
+
+ Set[].hash.should_not == Set[1, 2, 3].hash
+ Set[1, 2, 3].hash.should_not == Set[:a, "b", ?c].hash
+ end
+
+ ruby_version_is ""..."4.0" do
+ # see https://github.com/jruby/jruby/issues/8393
+ it "is equal to nil.hash for an uninitialized Set" do
+ Set.allocate.hash.should == nil.hash
+ end
+ end
+end
diff --git a/spec/ruby/core/set/include_spec.rb b/spec/ruby/core/set/include_spec.rb
new file mode 100644
index 0000000000..dd33bbc3bd
--- /dev/null
+++ b/spec/ruby/core/set/include_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/include'
+
+describe "Set#include?" do
+ it_behaves_like :set_include, :include?
+end
diff --git a/spec/ruby/core/set/initialize_clone_spec.rb b/spec/ruby/core/set/initialize_clone_spec.rb
new file mode 100644
index 0000000000..13abb7ee4e
--- /dev/null
+++ b/spec/ruby/core/set/initialize_clone_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+describe "Set#initialize_clone" do
+ # See https://bugs.ruby-lang.org/issues/14266
+ it "does not freeze the new Set when called from clone(freeze: false)" do
+ set1 = Set[1, 2]
+ set1.freeze
+ set2 = set1.clone(freeze: false)
+ set1.frozen?.should == true
+ set2.frozen?.should == false
+ set2.add 3
+ set1.should == Set[1, 2]
+ set2.should == Set[1, 2, 3]
+ end
+end
diff --git a/spec/ruby/core/set/initialize_spec.rb b/spec/ruby/core/set/initialize_spec.rb
new file mode 100644
index 0000000000..45538b38fb
--- /dev/null
+++ b/spec/ruby/core/set/initialize_spec.rb
@@ -0,0 +1,88 @@
+require_relative '../../spec_helper'
+
+describe "Set#initialize" do
+ it "is private" do
+ Set.private_instance_methods(false).should.include?(:initialize)
+ end
+
+ it "adds all elements of the passed Enumerable to self" do
+ s = Set.new([1, 2, 3])
+ s.size.should.eql?(3)
+ s.should.include?(1)
+ s.should.include?(2)
+ s.should.include?(3)
+ end
+
+ it "uses #each_entry on the provided Enumerable" do
+ enumerable = MockObject.new('mock-enumerable')
+ enumerable.should_receive(:each_entry).and_yield(1).and_yield(2).and_yield(3)
+ s = Set.new(enumerable)
+ s.size.should.eql?(3)
+ s.should.include?(1)
+ s.should.include?(2)
+ s.should.include?(3)
+ end
+
+ it "uses #each on the provided Enumerable if it does not respond to #each_entry" do
+ enumerable = MockObject.new('mock-enumerable')
+ enumerable.should_receive(:each).and_yield(1).and_yield(2).and_yield(3)
+ s = Set.new(enumerable)
+ s.size.should.eql?(3)
+ s.should.include?(1)
+ s.should.include?(2)
+ s.should.include?(3)
+ end
+
+ it "raises if the provided Enumerable does not respond to #each_entry or #each" do
+ enumerable = MockObject.new('mock-enumerable')
+ -> { Set.new(enumerable) }.should.raise(ArgumentError, "value must be enumerable")
+ end
+
+ it "should initialize with empty array and set" do
+ s = Set.new([])
+ s.size.should.eql?(0)
+
+ s = Set.new({})
+ s.size.should.eql?(0)
+ end
+
+ it "preprocesses all elements by a passed block before adding to self" do
+ s = Set.new([1, 2, 3]) { |x| x * x }
+ s.size.should.eql?(3)
+ s.should.include?(1)
+ s.should.include?(4)
+ s.should.include?(9)
+ end
+
+ it "should initialize with empty array and block" do
+ s = Set.new([]) { |x| x * x }
+ s.size.should.eql?(0)
+ end
+
+ it "should initialize with empty set and block" do
+ s = Set.new(Set.new) { |x| x * x }
+ s.size.should.eql?(0)
+ end
+
+ it "should initialize with set" do
+ o = Set.new([1, 2])
+ s = Set.new(o)
+ s.size.should.eql?(2)
+ s.should.include?(1)
+ s.should.include?(2)
+ end
+
+ it "should initialize with set and block" do
+ o = Set.new([1, 2])
+ s = Set.new(o) { |e| e + 2 }
+ s.size.should.eql?(2)
+ s.should.include?(3)
+ s.should.include?(4)
+ end
+
+ it "should initialize with just block" do
+ s = Set.new { |x| x * x }
+ s.size.should.eql?(0)
+ s.should.eql?(Set.new)
+ end
+end
diff --git a/spec/ruby/core/set/inspect_spec.rb b/spec/ruby/core/set/inspect_spec.rb
new file mode 100644
index 0000000000..0dcce83eb6
--- /dev/null
+++ b/spec/ruby/core/set/inspect_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/inspect'
+
+describe "Set#inspect" do
+ it_behaves_like :set_inspect, :inspect
+end
diff --git a/spec/ruby/core/set/intersect_spec.rb b/spec/ruby/core/set/intersect_spec.rb
new file mode 100644
index 0000000000..d04a1af441
--- /dev/null
+++ b/spec/ruby/core/set/intersect_spec.rb
@@ -0,0 +1,22 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#intersect?" do
+ it "returns true when two Sets have at least one element in common" do
+ Set[1, 2].intersect?(Set[2, 3]).should == true
+ end
+
+ it "returns false when two Sets have no element in common" do
+ Set[1, 2].intersect?(Set[3, 4]).should == false
+ end
+
+ context "when comparing to a Set-like object" do
+ it "returns true when a Set has at least one element in common with a Set-like object" do
+ Set[1, 2].intersect?(SetSpecs::SetLike.new([2, 3])).should == true
+ end
+
+ it "returns false when a Set has no element in common with a Set-like object" do
+ Set[1, 2].intersect?(SetSpecs::SetLike.new([3, 4])).should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/set/intersection_spec.rb b/spec/ruby/core/set/intersection_spec.rb
new file mode 100644
index 0000000000..136b886775
--- /dev/null
+++ b/spec/ruby/core/set/intersection_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../spec_helper'
+require_relative 'shared/intersection'
+
+describe "Set#intersection" do
+ it_behaves_like :set_intersection, :intersection
+end
+
+describe "Set#&" do
+ it_behaves_like :set_intersection, :&
+end
diff --git a/spec/ruby/core/set/join_spec.rb b/spec/ruby/core/set/join_spec.rb
new file mode 100644
index 0000000000..1c1e8a8af8
--- /dev/null
+++ b/spec/ruby/core/set/join_spec.rb
@@ -0,0 +1,30 @@
+require_relative '../../spec_helper'
+
+describe "Set#join" do
+ it "returns an empty string if the Set is empty" do
+ Set[].join.should == ''
+ end
+
+ it "returns a new string formed by joining elements after conversion" do
+ set = Set[:a, :b, :c]
+ set.join.should == "abc"
+ end
+
+ it "does not separate elements when the passed separator is nil" do
+ set = Set[:a, :b, :c]
+ set.join(nil).should == "abc"
+ end
+
+ it "returns a string formed by concatenating each element separated by the separator" do
+ set = Set[:a, :b, :c]
+ set.join(' | ').should == "a | b | c"
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "calls #to_a to convert the Set in to an Array" do
+ set = Set[:a, :b, :c]
+ set.should_receive(:to_a).and_return([:a, :b, :c])
+ set.join.should == "abc"
+ end
+ end
+end
diff --git a/spec/ruby/core/set/keep_if_spec.rb b/spec/ruby/core/set/keep_if_spec.rb
new file mode 100644
index 0000000000..7ca5d0cd43
--- /dev/null
+++ b/spec/ruby/core/set/keep_if_spec.rb
@@ -0,0 +1,37 @@
+require_relative '../../spec_helper'
+
+describe "Set#keep_if" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.keep_if { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "keeps every element from self for which the passed block returns true" do
+ @set.keep_if { |x| x.size != 3 }
+ @set.size.should.eql?(1)
+
+ @set.should_not.include?("one")
+ @set.should_not.include?("two")
+ @set.should.include?("three")
+ end
+
+ it "returns self" do
+ @set.keep_if {}.should.equal?(@set)
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.keep_if
+ enum.should.instance_of?(Enumerator)
+
+ enum.each { |x| x.size != 3 }
+
+ @set.should_not.include?("one")
+ @set.should_not.include?("two")
+ @set.should.include?("three")
+ end
+end
diff --git a/spec/ruby/core/set/length_spec.rb b/spec/ruby/core/set/length_spec.rb
new file mode 100644
index 0000000000..6bb697b4ca
--- /dev/null
+++ b/spec/ruby/core/set/length_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/length'
+
+describe "Set#length" do
+ it_behaves_like :set_length, :length
+end
diff --git a/spec/ruby/core/set/map_spec.rb b/spec/ruby/core/set/map_spec.rb
new file mode 100644
index 0000000000..996191b0a8
--- /dev/null
+++ b/spec/ruby/core/set/map_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/collect'
+
+describe "Set#map!" do
+ it_behaves_like :set_collect_bang, :map!
+end
diff --git a/spec/ruby/core/set/member_spec.rb b/spec/ruby/core/set/member_spec.rb
new file mode 100644
index 0000000000..5c82e8f826
--- /dev/null
+++ b/spec/ruby/core/set/member_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/include'
+
+describe "Set#member?" do
+ it_behaves_like :set_include, :member?
+end
diff --git a/spec/ruby/core/set/merge_spec.rb b/spec/ruby/core/set/merge_spec.rb
new file mode 100644
index 0000000000..a2c1a7e706
--- /dev/null
+++ b/spec/ruby/core/set/merge_spec.rb
@@ -0,0 +1,29 @@
+require_relative '../../spec_helper'
+
+describe "Set#merge" do
+ it "adds the elements of the passed Enumerable to self" do
+ Set[:a, :b].merge(Set[:b, :c, :d]).should == Set[:a, :b, :c, :d]
+ Set[1, 2].merge([3, 4]).should == Set[1, 2, 3, 4]
+ end
+
+ it "returns self" do
+ set = Set[1, 2]
+ set.merge([3, 4]).should.equal?(set)
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ -> { Set[1, 2].merge(1) }.should.raise(ArgumentError)
+ -> { Set[1, 2].merge(Object.new) }.should.raise(ArgumentError)
+ end
+
+ it "raises RuntimeError when called during iteration" do
+ set = Set[:a, :b]
+ set.each do |_m|
+ -> { set.merge([1, 2]) }.should.raise(RuntimeError, /iteration/)
+ end
+ end
+
+ it "accepts multiple arguments" do
+ Set[:a, :b].merge(Set[:b, :c], [:d]).should == Set[:a, :b, :c, :d]
+ end
+end
diff --git a/spec/ruby/core/set/minus_spec.rb b/spec/ruby/core/set/minus_spec.rb
new file mode 100644
index 0000000000..72f98f985e
--- /dev/null
+++ b/spec/ruby/core/set/minus_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/difference'
+
+describe "Set#-" do
+ it_behaves_like :set_difference, :-
+end
diff --git a/spec/ruby/core/set/plus_spec.rb b/spec/ruby/core/set/plus_spec.rb
new file mode 100644
index 0000000000..7e44ff0b7e
--- /dev/null
+++ b/spec/ruby/core/set/plus_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/union'
+
+describe "Set#+" do
+ it_behaves_like :set_union, :+
+end
diff --git a/spec/ruby/core/set/pretty_print_cycle_spec.rb b/spec/ruby/core/set/pretty_print_cycle_spec.rb
new file mode 100644
index 0000000000..7e6017c112
--- /dev/null
+++ b/spec/ruby/core/set/pretty_print_cycle_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "Set#pretty_print_cycle" do
+ it "passes the 'pretty print' representation of a self-referencing Set to the pretty print writer" do
+ pp = mock("PrettyPrint")
+ ruby_version_is(""..."4.0") do
+ pp.should_receive(:text).with("#<Set: {...}>")
+ end
+ ruby_version_is("4.0") do
+ pp.should_receive(:text).with("Set[...]")
+ end
+ Set[1, 2, 3].pretty_print_cycle(pp)
+ end
+end
diff --git a/spec/ruby/core/set/proper_subset_spec.rb b/spec/ruby/core/set/proper_subset_spec.rb
new file mode 100644
index 0000000000..3fd27da131
--- /dev/null
+++ b/spec/ruby/core/set/proper_subset_spec.rb
@@ -0,0 +1,35 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0'
+
+describe "Set#proper_subset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that self is a proper subset of" do
+ Set[].proper_subset?(@set).should == true
+ Set[].proper_subset?(Set[1, 2, 3]).should == true
+ Set[].proper_subset?(Set["a", :b, ?c]).should == true
+
+ Set[1, 2, 3].proper_subset?(@set).should == true
+ Set[1, 3].proper_subset?(@set).should == true
+ Set[1, 2].proper_subset?(@set).should == true
+ Set[1].proper_subset?(@set).should == true
+
+ Set[5].proper_subset?(@set).should == false
+ Set[1, 5].proper_subset?(@set).should == false
+ Set[nil].proper_subset?(@set).should == false
+ Set["test"].proper_subset?(@set).should == false
+
+ @set.proper_subset?(@set).should == false
+ Set[].proper_subset?(Set[]).should == false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ -> { Set[].proper_subset?([]) }.should.raise(ArgumentError)
+ -> { Set[].proper_subset?(1) }.should.raise(ArgumentError)
+ -> { Set[].proper_subset?("test") }.should.raise(ArgumentError)
+ -> { Set[].proper_subset?(Object.new) }.should.raise(ArgumentError)
+ end
+end
diff --git a/spec/ruby/core/set/proper_superset_spec.rb b/spec/ruby/core/set/proper_superset_spec.rb
new file mode 100644
index 0000000000..e95c67ef0e
--- /dev/null
+++ b/spec/ruby/core/set/proper_superset_spec.rb
@@ -0,0 +1,42 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#proper_superset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that self is a proper superset of" do
+ @set.proper_superset?(Set[]).should == true
+ Set[1, 2, 3].proper_superset?(Set[]).should == true
+ Set["a", :b, ?c].proper_superset?(Set[]).should == true
+
+ @set.proper_superset?(Set[1, 2, 3]).should == true
+ @set.proper_superset?(Set[1, 3]).should == true
+ @set.proper_superset?(Set[1, 2]).should == true
+ @set.proper_superset?(Set[1]).should == true
+
+ @set.proper_superset?(Set[5]).should == false
+ @set.proper_superset?(Set[1, 5]).should == false
+ @set.proper_superset?(Set[nil]).should == false
+ @set.proper_superset?(Set["test"]).should == false
+
+ @set.proper_superset?(@set).should == false
+ Set[].proper_superset?(Set[]).should == false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ -> { Set[].proper_superset?([]) }.should.raise(ArgumentError)
+ -> { Set[].proper_superset?(1) }.should.raise(ArgumentError)
+ -> { Set[].proper_superset?("test") }.should.raise(ArgumentError)
+ -> { Set[].proper_superset?(Object.new) }.should.raise(ArgumentError)
+ end
+
+ ruby_version_is ""..."4.0" do
+ context "when comparing to a Set-like object" do
+ it "returns true if passed a Set-like object that self is a proper superset of" do
+ Set[1, 2, 3, 4].proper_superset?(SetSpecs::SetLike.new([1, 2, 3])).should == true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/set/reject_spec.rb b/spec/ruby/core/set/reject_spec.rb
new file mode 100644
index 0000000000..b00a36812b
--- /dev/null
+++ b/spec/ruby/core/set/reject_spec.rb
@@ -0,0 +1,41 @@
+require_relative '../../spec_helper'
+
+describe "Set#reject!" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.reject! { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "deletes every element from self for which the passed block returns true" do
+ @set.reject! { |x| x.size == 3 }
+ @set.size.should.eql?(1)
+
+ @set.should_not.include?("one")
+ @set.should_not.include?("two")
+ @set.should.include?("three")
+ end
+
+ it "returns self when self was modified" do
+ @set.reject! { |x| true }.should.equal?(@set)
+ end
+
+ it "returns nil when self was not modified" do
+ @set.reject! { |x| false }.should == nil
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.reject!
+ enum.should.instance_of?(Enumerator)
+
+ enum.each { |x| x.size == 3 }
+
+ @set.should_not.include?("one")
+ @set.should_not.include?("two")
+ @set.should.include?("three")
+ end
+end
diff --git a/spec/ruby/core/set/replace_spec.rb b/spec/ruby/core/set/replace_spec.rb
new file mode 100644
index 0000000000..2a51a024dc
--- /dev/null
+++ b/spec/ruby/core/set/replace_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+
+describe "Set#replace" do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "replaces the contents with other and returns self" do
+ @set.replace(Set[1, 2, 3]).should == @set
+ @set.should == Set[1, 2, 3]
+ end
+
+ it "raises RuntimeError when called during iteration" do
+ set = Set[:a, :b, :c, :d, :e, :f]
+ set.each do |_m|
+ -> { set.replace(Set[1, 2, 3]) }.should.raise(RuntimeError, /iteration/)
+ end
+ set.should == Set[:a, :b, :c, :d, :e, :f]
+ end
+
+ it "accepts any enumerable as other" do
+ @set.replace([1, 2, 3]).should == Set[1, 2, 3]
+ end
+end
diff --git a/spec/ruby/library/set/select_spec.rb b/spec/ruby/core/set/select_spec.rb
index b458ffacaa..b458ffacaa 100644
--- a/spec/ruby/library/set/select_spec.rb
+++ b/spec/ruby/core/set/select_spec.rb
diff --git a/spec/ruby/core/set/set_spec.rb b/spec/ruby/core/set/set_spec.rb
new file mode 100644
index 0000000000..fd1d2072e3
--- /dev/null
+++ b/spec/ruby/core/set/set_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../spec_helper'
+
+describe 'Set' do
+ it 'is available without explicit requiring' do
+ output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1')
+ puts Set.new([1, 2, 3]).to_a.inspect
+ RUBY
+ output.chomp.should == "[1, 2, 3]"
+ end
+end
diff --git a/spec/ruby/core/set/shared/add.rb b/spec/ruby/core/set/shared/add.rb
new file mode 100644
index 0000000000..8d6d83434f
--- /dev/null
+++ b/spec/ruby/core/set/shared/add.rb
@@ -0,0 +1,14 @@
+describe :set_add, shared: true do
+ before :each do
+ @set = Set.new
+ end
+
+ it "adds the passed Object to self" do
+ @set.send(@method, "dog")
+ @set.should.include?("dog")
+ end
+
+ it "returns self" do
+ @set.send(@method, "dog").should.equal?(@set)
+ end
+end
diff --git a/spec/ruby/core/set/shared/collect.rb b/spec/ruby/core/set/shared/collect.rb
new file mode 100644
index 0000000000..ad5c5afa59
--- /dev/null
+++ b/spec/ruby/core/set/shared/collect.rb
@@ -0,0 +1,20 @@
+describe :set_collect_bang, shared: true do
+ before :each do
+ @set = Set[1, 2, 3, 4, 5]
+ end
+
+ it "yields each Object in self" do
+ res = []
+ @set.send(@method) { |x| res << x }
+ res.sort.should == [1, 2, 3, 4, 5].sort
+ end
+
+ it "returns self" do
+ @set.send(@method) { |x| x }.should.equal?(@set)
+ end
+
+ it "replaces self with the return values of the block" do
+ @set.send(@method) { |x| x * 2 }
+ @set.should == Set[2, 4, 6, 8, 10]
+ end
+end
diff --git a/spec/ruby/core/set/shared/difference.rb b/spec/ruby/core/set/shared/difference.rb
new file mode 100644
index 0000000000..8a17056a82
--- /dev/null
+++ b/spec/ruby/core/set/shared/difference.rb
@@ -0,0 +1,15 @@
+describe :set_difference, shared: true do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "returns a new Set containing self's elements excluding the elements in the passed Enumerable" do
+ @set.send(@method, Set[:a, :b]).should == Set[:c]
+ @set.send(@method, [:b, :c]).should == Set[:a]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ -> { @set.send(@method, 1) }.should.raise(ArgumentError)
+ -> { @set.send(@method, Object.new) }.should.raise(ArgumentError)
+ end
+end
diff --git a/spec/ruby/core/set/shared/include.rb b/spec/ruby/core/set/shared/include.rb
new file mode 100644
index 0000000000..82755ccf59
--- /dev/null
+++ b/spec/ruby/core/set/shared/include.rb
@@ -0,0 +1,29 @@
+describe :set_include, shared: true do
+ it "returns true when self contains the passed Object" do
+ set = Set[:a, :b, :c]
+ set.send(@method, :a).should == true
+ set.send(@method, :e).should == false
+ end
+
+ describe "member equality" do
+ it "is checked using both #hash and #eql?" do
+ obj = Object.new
+ obj_another = Object.new
+
+ def obj.hash; 42 end
+ def obj_another.hash; 42 end
+ def obj_another.eql?(o) hash == o.hash end
+
+ set = Set["a", "b", "c", obj]
+ set.send(@method, obj_another).should == true
+ end
+
+ it "is not checked using #==" do
+ obj = Object.new
+ set = Set["a", "b", "c"]
+
+ obj.should_not_receive(:==)
+ set.send(@method, obj)
+ end
+ end
+end
diff --git a/spec/ruby/core/set/shared/inspect.rb b/spec/ruby/core/set/shared/inspect.rb
new file mode 100644
index 0000000000..31bd8accfd
--- /dev/null
+++ b/spec/ruby/core/set/shared/inspect.rb
@@ -0,0 +1,45 @@
+describe :set_inspect, shared: true do
+ it "returns a String representation of self" do
+ Set[].send(@method).should.is_a?(String)
+ Set[nil, false, true].send(@method).should.is_a?(String)
+ Set[1, 2, 3].send(@method).should.is_a?(String)
+ Set["1", "2", "3"].send(@method).should.is_a?(String)
+ Set[:a, "b", Set[?c]].send(@method).should.is_a?(String)
+ end
+
+ ruby_version_is "4.0" do
+ it "does include the elements of the set" do
+ Set["1"].send(@method).should == 'Set["1"]'
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "does include the elements of the set" do
+ Set["1"].send(@method).should == '#<Set: {"1"}>'
+ end
+ end
+
+ it "puts spaces between the elements" do
+ Set["1", "2"].send(@method).should.include?('", "')
+ end
+
+ ruby_version_is "4.0" do
+ it "correctly handles cyclic-references" do
+ set1 = Set[]
+ set2 = Set[set1]
+ set1 << set2
+ set1.send(@method).should.is_a?(String)
+ set1.send(@method).should.include?("Set[...]")
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "correctly handles cyclic-references" do
+ set1 = Set[]
+ set2 = Set[set1]
+ set1 << set2
+ set1.send(@method).should.is_a?(String)
+ set1.send(@method).should.include?("#<Set: {...}>")
+ end
+ end
+end
diff --git a/spec/ruby/core/set/shared/intersection.rb b/spec/ruby/core/set/shared/intersection.rb
new file mode 100644
index 0000000000..978a4924ef
--- /dev/null
+++ b/spec/ruby/core/set/shared/intersection.rb
@@ -0,0 +1,15 @@
+describe :set_intersection, shared: true do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "returns a new Set containing only elements shared by self and the passed Enumerable" do
+ @set.send(@method, Set[:b, :c, :d, :e]).should == Set[:b, :c]
+ @set.send(@method, [:b, :c, :d]).should == Set[:b, :c]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ -> { @set.send(@method, 1) }.should.raise(ArgumentError)
+ -> { @set.send(@method, Object.new) }.should.raise(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/shared/length.rb b/spec/ruby/core/set/shared/length.rb
index a8fcee9f39..a8fcee9f39 100644
--- a/spec/ruby/library/set/shared/length.rb
+++ b/spec/ruby/core/set/shared/length.rb
diff --git a/spec/ruby/core/set/shared/select.rb b/spec/ruby/core/set/shared/select.rb
new file mode 100644
index 0000000000..0d4a53fffd
--- /dev/null
+++ b/spec/ruby/core/set/shared/select.rb
@@ -0,0 +1,41 @@
+require_relative '../../../spec_helper'
+
+describe :set_select_bang, shared: true do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.send(@method) { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "keeps every element from self for which the passed block returns true" do
+ @set.send(@method) { |x| x.size != 3 }
+ @set.size.should.eql?(1)
+
+ @set.should_not.include?("one")
+ @set.should_not.include?("two")
+ @set.should.include?("three")
+ end
+
+ it "returns self when self was modified" do
+ @set.send(@method) { false }.should.equal?(@set)
+ end
+
+ it "returns nil when self was not modified" do
+ @set.send(@method) { true }.should == nil
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.send(@method)
+ enum.should.instance_of?(Enumerator)
+
+ enum.each { |x| x.size != 3 }
+
+ @set.should_not.include?("one")
+ @set.should_not.include?("two")
+ @set.should.include?("three")
+ end
+end
diff --git a/spec/ruby/core/set/shared/union.rb b/spec/ruby/core/set/shared/union.rb
new file mode 100644
index 0000000000..dddf1716e5
--- /dev/null
+++ b/spec/ruby/core/set/shared/union.rb
@@ -0,0 +1,15 @@
+describe :set_union, shared: true do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "returns a new Set containing all elements of self and the passed Enumerable" do
+ @set.send(@method, Set[:b, :d, :e]).should == Set[:a, :b, :c, :d, :e]
+ @set.send(@method, [:b, :e]).should == Set[:a, :b, :c, :e]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ -> { @set.send(@method, 1) }.should.raise(ArgumentError)
+ -> { @set.send(@method, Object.new) }.should.raise(ArgumentError)
+ end
+end
diff --git a/spec/ruby/core/set/size_spec.rb b/spec/ruby/core/set/size_spec.rb
new file mode 100644
index 0000000000..4ae22c5f0a
--- /dev/null
+++ b/spec/ruby/core/set/size_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/length'
+
+describe "Set#size" do
+ it_behaves_like :set_length, :size
+end
diff --git a/spec/ruby/core/set/sortedset/sortedset_spec.rb b/spec/ruby/core/set/sortedset/sortedset_spec.rb
new file mode 100644
index 0000000000..c8f65f0851
--- /dev/null
+++ b/spec/ruby/core/set/sortedset/sortedset_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../../spec_helper'
+
+describe "SortedSet" do
+ ruby_version_is ""..."4.0" do
+ it "raises error including message that it has been extracted from the set stdlib" do
+ -> {
+ SortedSet
+ }.should.raise(RuntimeError) { |e|
+ e.message.should.include?("The `SortedSet` class has been extracted from the `set` library")
+ }
+ end
+ end
+end
diff --git a/spec/ruby/core/set/subset_spec.rb b/spec/ruby/core/set/subset_spec.rb
new file mode 100644
index 0000000000..81869d4993
--- /dev/null
+++ b/spec/ruby/core/set/subset_spec.rb
@@ -0,0 +1,35 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0'
+
+describe "Set#subset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that is equal to self or self is a subset of" do
+ @set.subset?(@set).should == true
+ Set[].subset?(Set[]).should == true
+
+ Set[].subset?(@set).should == true
+ Set[].subset?(Set[1, 2, 3]).should == true
+ Set[].subset?(Set["a", :b, ?c]).should == true
+
+ Set[1, 2, 3].subset?(@set).should == true
+ Set[1, 3].subset?(@set).should == true
+ Set[1, 2].subset?(@set).should == true
+ Set[1].subset?(@set).should == true
+
+ Set[5].subset?(@set).should == false
+ Set[1, 5].subset?(@set).should == false
+ Set[nil].subset?(@set).should == false
+ Set["test"].subset?(@set).should == false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ -> { Set[].subset?([]) }.should.raise(ArgumentError)
+ -> { Set[].subset?(1) }.should.raise(ArgumentError)
+ -> { Set[].subset?("test") }.should.raise(ArgumentError)
+ -> { Set[].subset?(Object.new) }.should.raise(ArgumentError)
+ end
+end
diff --git a/spec/ruby/core/set/subtract_spec.rb b/spec/ruby/core/set/subtract_spec.rb
new file mode 100644
index 0000000000..ae4bc73d41
--- /dev/null
+++ b/spec/ruby/core/set/subtract_spec.rb
@@ -0,0 +1,16 @@
+require_relative '../../spec_helper'
+
+describe "Set#subtract" do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "deletes any elements contained in other and returns self" do
+ @set.subtract(Set[:b, :c]).should == @set
+ @set.should == Set[:a]
+ end
+
+ it "accepts any enumerable as other" do
+ @set.subtract([:c]).should == Set[:a, :b]
+ end
+end
diff --git a/spec/ruby/core/set/superset_spec.rb b/spec/ruby/core/set/superset_spec.rb
new file mode 100644
index 0000000000..7e7db2b179
--- /dev/null
+++ b/spec/ruby/core/set/superset_spec.rb
@@ -0,0 +1,42 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#superset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that equals self or self is a proper superset of" do
+ @set.superset?(@set).should == true
+ Set[].superset?(Set[]).should == true
+
+ @set.superset?(Set[]).should == true
+ Set[1, 2, 3].superset?(Set[]).should == true
+ Set["a", :b, ?c].superset?(Set[]).should == true
+
+ @set.superset?(Set[1, 2, 3]).should == true
+ @set.superset?(Set[1, 3]).should == true
+ @set.superset?(Set[1, 2]).should == true
+ @set.superset?(Set[1]).should == true
+
+ @set.superset?(Set[5]).should == false
+ @set.superset?(Set[1, 5]).should == false
+ @set.superset?(Set[nil]).should == false
+ @set.superset?(Set["test"]).should == false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ -> { Set[].superset?([]) }.should.raise(ArgumentError)
+ -> { Set[].superset?(1) }.should.raise(ArgumentError)
+ -> { Set[].superset?("test") }.should.raise(ArgumentError)
+ -> { Set[].superset?(Object.new) }.should.raise(ArgumentError)
+ end
+
+ ruby_version_is ""..."4.0" do
+ context "when comparing to a Set-like object" do
+ it "returns true if passed a Set-like object that self is a superset of" do
+ Set[1, 2, 3, 4].superset?(SetSpecs::SetLike.new([1, 2, 3])).should == true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/set/to_a_spec.rb b/spec/ruby/core/set/to_a_spec.rb
new file mode 100644
index 0000000000..1e9800167a
--- /dev/null
+++ b/spec/ruby/core/set/to_a_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../../spec_helper'
+
+describe "Set#to_a" do
+ it "returns an array containing elements of self" do
+ Set[1, 2, 3].to_a.sort.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/core/set/to_s_spec.rb b/spec/ruby/core/set/to_s_spec.rb
new file mode 100644
index 0000000000..55b8bfd9b2
--- /dev/null
+++ b/spec/ruby/core/set/to_s_spec.rb
@@ -0,0 +1,11 @@
+require_relative "../../spec_helper"
+require_relative 'shared/inspect'
+
+describe "Set#to_s" do
+ it_behaves_like :set_inspect, :to_s
+
+ it "is an alias of inspect" do
+ set = Set.new
+ set.method(:to_s).should == set.method(:inspect)
+ end
+end
diff --git a/spec/ruby/core/set/union_spec.rb b/spec/ruby/core/set/union_spec.rb
new file mode 100644
index 0000000000..3e77022d4b
--- /dev/null
+++ b/spec/ruby/core/set/union_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../spec_helper'
+require_relative 'shared/union'
+
+describe "Set#union" do
+ it_behaves_like :set_union, :union
+end
+
+describe "Set#|" do
+ it_behaves_like :set_union, :|
+end
diff --git a/spec/ruby/core/signal/signame_spec.rb b/spec/ruby/core/signal/signame_spec.rb
index b66de9fc85..82f040a6f9 100644
--- a/spec/ruby/core/signal/signame_spec.rb
+++ b/spec/ruby/core/signal/signame_spec.rb
@@ -9,8 +9,20 @@ describe "Signal.signame" do
Signal.signame(-1).should == nil
end
+ it "calls #to_int on an object to convert to an Integer" do
+ obj = mock('signal')
+ obj.should_receive(:to_int).and_return(0)
+ Signal.signame(obj).should == "EXIT"
+ end
+
it "raises a TypeError when the passed argument can't be coerced to Integer" do
- -> { Signal.signame("hello") }.should raise_error(TypeError)
+ -> { Signal.signame("hello") }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError when the passed argument responds to #to_int but does not return an Integer" do
+ obj = mock('signal')
+ obj.should_receive(:to_int).and_return('not an int')
+ -> { Signal.signame(obj) }.should.raise(TypeError)
end
platform_is_not :windows do
diff --git a/spec/ruby/core/signal/trap_spec.rb b/spec/ruby/core/signal/trap_spec.rb
index 2a94a81634..5d3105fee8 100644
--- a/spec/ruby/core/signal/trap_spec.rb
+++ b/spec/ruby/core/signal/trap_spec.rb
@@ -14,7 +14,7 @@ describe "Signal.trap" do
end
it "returns the previous handler" do
- Signal.trap(:HUP, @saved_trap).should equal(@proc)
+ Signal.trap(:HUP, @saved_trap).should.equal?(@proc)
end
it "accepts a block" do
@@ -97,7 +97,7 @@ describe "Signal.trap" do
-> {
Process.kill :HUP, Process.pid
loop { Thread.pass }
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
it "accepts a non-callable that becomes callable when used" do
@@ -134,7 +134,7 @@ describe "Signal.trap" do
Process.kill :HUP, Process.pid
Thread.pass until done
- ScratchPad.recorded.should be_true
+ ScratchPad.recorded.should == true
end
it "registers an handler doing nothing with :IGNORE" do
@@ -158,7 +158,7 @@ describe "Signal.trap" do
it "ignores the signal when passed nil" do
Signal.trap :HUP, nil
- Signal.trap(:HUP, @saved_trap).should be_nil
+ Signal.trap(:HUP, @saved_trap).should == nil
end
it "accepts :DEFAULT in place of a proc" do
@@ -203,22 +203,53 @@ describe "Signal.trap" do
it "accepts long names as Strings" do
Signal.trap "SIGHUP", @proc
- Signal.trap("SIGHUP", @saved_trap).should equal(@proc)
+ Signal.trap("SIGHUP", @saved_trap).should.equal?(@proc)
end
it "accepts short names as Strings" do
Signal.trap "HUP", @proc
- Signal.trap("HUP", @saved_trap).should equal(@proc)
+ Signal.trap("HUP", @saved_trap).should.equal?(@proc)
end
it "accepts long names as Symbols" do
Signal.trap :SIGHUP, @proc
- Signal.trap(:SIGHUP, @saved_trap).should equal(@proc)
+ Signal.trap(:SIGHUP, @saved_trap).should.equal?(@proc)
end
it "accepts short names as Symbols" do
Signal.trap :HUP, @proc
- Signal.trap(:HUP, @saved_trap).should equal(@proc)
+ Signal.trap(:HUP, @saved_trap).should.equal?(@proc)
+ end
+
+ it "calls #to_str on an object to convert to a String" do
+ obj = mock("signal")
+ obj.should_receive(:to_str).exactly(2).times.and_return("HUP")
+ Signal.trap obj, @proc
+ Signal.trap(obj, @saved_trap).should.equal?(@proc)
+ end
+
+ it "accepts Integer values" do
+ hup = Signal.list["HUP"]
+ Signal.trap hup, @proc
+ Signal.trap(hup, @saved_trap).should.equal?(@proc)
+ end
+
+ it "does not call #to_int on an object to convert to an Integer" do
+ obj = mock("signal")
+ obj.should_not_receive(:to_int)
+ -> { Signal.trap obj, @proc }.should.raise(ArgumentError, /bad signal type/)
+ end
+
+ it "raises ArgumentError when passed unknown signal" do
+ -> { Signal.trap(300) { } }.should.raise(ArgumentError, "invalid signal number (300)")
+ -> { Signal.trap("USR10") { } }.should.raise(ArgumentError, /\Aunsupported signal [`']SIGUSR10'\z/)
+ -> { Signal.trap("SIGUSR10") { } }.should.raise(ArgumentError, /\Aunsupported signal [`']SIGUSR10'\z/)
+ end
+
+ it "raises ArgumentError when passed signal is not Integer, String or Symbol" do
+ -> { Signal.trap(nil) { } }.should.raise(ArgumentError, "bad signal type NilClass")
+ -> { Signal.trap(100.0) { } }.should.raise(ArgumentError, "bad signal type Float")
+ -> { Signal.trap(Rational(100)) { } }.should.raise(ArgumentError, "bad signal type Rational")
end
# See man 2 signal
@@ -226,13 +257,21 @@ describe "Signal.trap" do
it "raises ArgumentError or Errno::EINVAL for SIG#{signal}" do
-> {
Signal.trap(signal, -> {})
- }.should raise_error(StandardError) { |e|
- [ArgumentError, Errno::EINVAL].should include(e.class)
+ }.should.raise(StandardError) { |e|
+ [ArgumentError, Errno::EINVAL].should.include?(e.class)
e.message.should =~ /Invalid argument|Signal already used by VM or OS/
}
end
end
+ %w[SEGV BUS ILL FPE VTALRM].each do |signal|
+ it "raises ArgumentError for SIG#{signal} which is reserved by Ruby" do
+ -> {
+ Signal.trap(signal, -> {})
+ }.should.raise(ArgumentError, "can't trap reserved signal: SIG#{signal}")
+ end
+ end
+
it "allows to register a handler for all known signals, except reserved signals for which it raises ArgumentError" do
out = ruby_exe(fixture(__FILE__, "trap_all.rb"), args: "2>&1")
out.should == "OK\n"
diff --git a/spec/ruby/core/sizedqueue/append_spec.rb b/spec/ruby/core/sizedqueue/append_spec.rb
index ca79068930..c52baa3802 100644
--- a/spec/ruby/core/sizedqueue/append_spec.rb
+++ b/spec/ruby/core/sizedqueue/append_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/enque'
require_relative '../../shared/sizedqueue/enque'
+require_relative '../../shared/types/rb_num2dbl_fails'
describe "SizedQueue#<<" do
it_behaves_like :queue_enq, :<<, -> { SizedQueue.new(10) }
@@ -9,3 +10,7 @@ end
describe "SizedQueue#<<" do
it_behaves_like :sizedqueue_enq, :<<, -> n { SizedQueue.new(n) }
end
+
+describe "SizedQueue operations with timeout" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.send(:<<, 1, timeout: v) }
+end
diff --git a/spec/ruby/core/sizedqueue/deq_spec.rb b/spec/ruby/core/sizedqueue/deq_spec.rb
index 5e1bd9f746..2aeb52f8a6 100644
--- a/spec/ruby/core/sizedqueue/deq_spec.rb
+++ b/spec/ruby/core/sizedqueue/deq_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/deque'
+require_relative '../../shared/types/rb_num2dbl_fails'
describe "SizedQueue#deq" do
it_behaves_like :queue_deq, :deq, -> { SizedQueue.new(10) }
end
+
+describe "SizedQueue operations with timeout" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.deq(timeout: v) }
+end
diff --git a/spec/ruby/core/sizedqueue/enq_spec.rb b/spec/ruby/core/sizedqueue/enq_spec.rb
index 3821afac95..b955909475 100644
--- a/spec/ruby/core/sizedqueue/enq_spec.rb
+++ b/spec/ruby/core/sizedqueue/enq_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/enque'
require_relative '../../shared/sizedqueue/enque'
+require_relative '../../shared/types/rb_num2dbl_fails'
describe "SizedQueue#enq" do
it_behaves_like :queue_enq, :enq, -> { SizedQueue.new(10) }
@@ -9,3 +10,7 @@ end
describe "SizedQueue#enq" do
it_behaves_like :sizedqueue_enq, :enq, -> n { SizedQueue.new(n) }
end
+
+describe "SizedQueue operations with timeout" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.enq(1, timeout: v) }
+end
diff --git a/spec/ruby/core/sizedqueue/freeze_spec.rb b/spec/ruby/core/sizedqueue/freeze_spec.rb
new file mode 100644
index 0000000000..98f01cae2f
--- /dev/null
+++ b/spec/ruby/core/sizedqueue/freeze_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative '../../shared/queue/freeze'
+
+describe "SizedQueue#freeze" do
+ it_behaves_like :queue_freeze, :freeze, -> { SizedQueue.new(1) }
+end
diff --git a/spec/ruby/core/sizedqueue/pop_spec.rb b/spec/ruby/core/sizedqueue/pop_spec.rb
index a0cf6f509c..6338ddbaa0 100644
--- a/spec/ruby/core/sizedqueue/pop_spec.rb
+++ b/spec/ruby/core/sizedqueue/pop_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/deque'
+require_relative '../../shared/types/rb_num2dbl_fails'
describe "SizedQueue#pop" do
it_behaves_like :queue_deq, :pop, -> { SizedQueue.new(10) }
end
+
+describe "SizedQueue operations with timeout" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.pop(timeout: v) }
+end
diff --git a/spec/ruby/core/sizedqueue/push_spec.rb b/spec/ruby/core/sizedqueue/push_spec.rb
index bba9be9e3f..9eaa6beca0 100644
--- a/spec/ruby/core/sizedqueue/push_spec.rb
+++ b/spec/ruby/core/sizedqueue/push_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/enque'
require_relative '../../shared/sizedqueue/enque'
+require_relative '../../shared/types/rb_num2dbl_fails'
describe "SizedQueue#push" do
it_behaves_like :queue_enq, :push, -> { SizedQueue.new(10) }
@@ -9,3 +10,7 @@ end
describe "SizedQueue#push" do
it_behaves_like :sizedqueue_enq, :push, -> n { SizedQueue.new(n) }
end
+
+describe "SizedQueue operations with timeout" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.push(1, timeout: v) }
+end
diff --git a/spec/ruby/core/sizedqueue/shift_spec.rb b/spec/ruby/core/sizedqueue/shift_spec.rb
index 5138e68258..52974c1d99 100644
--- a/spec/ruby/core/sizedqueue/shift_spec.rb
+++ b/spec/ruby/core/sizedqueue/shift_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
require_relative '../../shared/queue/deque'
+require_relative '../../shared/types/rb_num2dbl_fails'
describe "SizedQueue#shift" do
it_behaves_like :queue_deq, :shift, -> { SizedQueue.new(10) }
end
+
+describe "SizedQueue operations with timeout" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.shift(timeout: v) }
+end
diff --git a/spec/ruby/core/string/allocate_spec.rb b/spec/ruby/core/string/allocate_spec.rb
index 30d5f60594..00dadaf076 100644
--- a/spec/ruby/core/string/allocate_spec.rb
+++ b/spec/ruby/core/string/allocate_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "String.allocate" do
it "returns an instance of String" do
str = String.allocate
- str.should be_an_instance_of(String)
+ str.should.instance_of?(String)
end
it "returns a fully-formed String" do
diff --git a/spec/ruby/core/string/append_as_bytes_spec.rb b/spec/ruby/core/string/append_as_bytes_spec.rb
new file mode 100644
index 0000000000..feead64615
--- /dev/null
+++ b/spec/ruby/core/string/append_as_bytes_spec.rb
@@ -0,0 +1,60 @@
+require_relative '../../spec_helper'
+
+describe "String#append_bytes" do
+ ruby_version_is "3.4" do
+ it "doesn't allow to mutate frozen strings" do
+ str = "hello".freeze
+ -> { str.append_as_bytes("\xE2\x82") }.should.raise(FrozenError)
+ end
+
+ it "allows creating broken strings in UTF8" do
+ str = +"hello"
+ str.append_as_bytes("\xE2\x82")
+ str.valid_encoding?.should == false
+
+ str.append_as_bytes("\xAC")
+ str.valid_encoding?.should == true
+ end
+
+ it "allows creating broken strings in UTF_32" do
+ str = "abc".encode(Encoding::UTF_32LE)
+ str.append_as_bytes("def")
+ str.encoding.should == Encoding::UTF_32LE
+ str.valid_encoding?.should == false
+ end
+
+ it "never changes the receiver encoding" do
+ str = "".b
+ str.append_as_bytes("€")
+ str.encoding.should == Encoding::BINARY
+ end
+
+ it "accepts variadic String or Integer arguments" do
+ str = "hello".b
+ str.append_as_bytes("\xE2\x82", 12, 43, "\xAC")
+ str.encoding.should == Encoding::BINARY
+ str.should == "hello\xE2\x82\f+\xAC".b
+ end
+
+ it "truncates integers to the least significant byte" do
+ str = +""
+ str.append_as_bytes(0x131, 0x232, 0x333, bignum_value, bignum_value(1))
+ str.bytes.should == [0x31, 0x32, 0x33, 0, 1]
+ end
+
+ it "wraps negative integers" do
+ str = "".b
+ str.append_as_bytes(-1, -bignum_value, -bignum_value(1))
+ str.bytes.should == [0xFF, 0, 0xFF]
+ end
+
+ it "only accepts strings or integers, and doesn't attempt to cast with #to_str or #to_int" do
+ to_str = mock("to_str")
+ to_str.should_not_receive(:to_str)
+ to_str.should_not_receive(:to_int)
+
+ str = +"hello"
+ -> { str.append_as_bytes(to_str) }.should.raise(TypeError, "wrong argument type MockObject (expected String or Integer)")
+ end
+ end
+end
diff --git a/spec/ruby/core/string/append_spec.rb b/spec/ruby/core/string/append_spec.rb
index e001257621..e0f71b7c97 100644
--- a/spec/ruby/core/string/append_spec.rb
+++ b/spec/ruby/core/string/append_spec.rb
@@ -5,9 +5,10 @@ require_relative 'shared/concat'
describe "String#<<" do
it_behaves_like :string_concat, :<<
it_behaves_like :string_concat_encoding, :<<
+ it_behaves_like :string_concat_type_coercion, :<<
it "raises an ArgumentError when given the incorrect number of arguments" do
- -> { "hello".send(:<<) }.should raise_error(ArgumentError)
- -> { "hello".send(:<<, "one", "two") }.should raise_error(ArgumentError)
+ -> { "hello".send(:<<) }.should.raise(ArgumentError)
+ -> { "hello".send(:<<, "one", "two") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/ascii_only_spec.rb b/spec/ruby/core/string/ascii_only_spec.rb
index c7e02fd874..9af663beb8 100644
--- a/spec/ruby/core/string/ascii_only_spec.rb
+++ b/spec/ruby/core/string/ascii_only_spec.rb
@@ -7,18 +7,18 @@ describe "String#ascii_only?" do
it "returns true if the encoding is UTF-8" do
[ ["hello", true],
["hello".encode('UTF-8'), true],
- ["hello".force_encoding('UTF-8'), true],
+ ["hello".dup.force_encoding('UTF-8'), true],
].should be_computed_by(:ascii_only?)
end
it "returns true if the encoding is US-ASCII" do
- "hello".force_encoding(Encoding::US_ASCII).ascii_only?.should be_true
- "hello".encode(Encoding::US_ASCII).ascii_only?.should be_true
+ "hello".dup.force_encoding(Encoding::US_ASCII).ascii_only?.should == true
+ "hello".encode(Encoding::US_ASCII).ascii_only?.should == true
end
it "returns true for all single-character UTF-8 Strings" do
0.upto(127) do |n|
- n.chr.ascii_only?.should be_true
+ n.chr.ascii_only?.should == true
end
end
end
@@ -27,57 +27,56 @@ describe "String#ascii_only?" do
it "returns false if the encoding is BINARY" do
chr = 128.chr
chr.encoding.should == Encoding::BINARY
- chr.ascii_only?.should be_false
+ chr.ascii_only?.should == false
end
it "returns false if the String contains any non-ASCII characters" do
[ ["\u{6666}", false],
["hello, \u{6666}", false],
["\u{6666}".encode('UTF-8'), false],
- ["\u{6666}".force_encoding('UTF-8'), false],
+ ["\u{6666}".dup.force_encoding('UTF-8'), false],
].should be_computed_by(:ascii_only?)
end
it "returns false if the encoding is US-ASCII" do
- [ ["\u{6666}".force_encoding(Encoding::US_ASCII), false],
- ["hello, \u{6666}".force_encoding(Encoding::US_ASCII), false],
+ [ ["\u{6666}".dup.force_encoding(Encoding::US_ASCII), false],
+ ["hello, \u{6666}".dup.force_encoding(Encoding::US_ASCII), false],
].should be_computed_by(:ascii_only?)
end
end
it "returns true for the empty String with an ASCII-compatible encoding" do
- "".ascii_only?.should be_true
- "".encode('UTF-8').ascii_only?.should be_true
+ "".ascii_only?.should == true
+ "".encode('UTF-8').ascii_only?.should == true
end
it "returns false for the empty String with a non-ASCII-compatible encoding" do
- "".force_encoding('UTF-16LE').ascii_only?.should be_false
- "".encode('UTF-16BE').ascii_only?.should be_false
+ "".dup.force_encoding('UTF-16LE').ascii_only?.should == false
+ "".encode('UTF-16BE').ascii_only?.should == false
end
it "returns false for a non-empty String with non-ASCII-compatible encoding" do
- "\x78\x00".force_encoding("UTF-16LE").ascii_only?.should be_false
+ "\x78\x00".dup.force_encoding("UTF-16LE").ascii_only?.should == false
end
it "returns false when interpolating non ascii strings" do
- base = "EU currency is"
- base.force_encoding(Encoding::US_ASCII)
+ base = "EU currency is".dup.force_encoding(Encoding::US_ASCII)
euro = "\u20AC"
interp = "#{base} #{euro}"
- euro.ascii_only?.should be_false
- base.ascii_only?.should be_true
- interp.ascii_only?.should be_false
+ euro.ascii_only?.should == false
+ base.ascii_only?.should == true
+ interp.ascii_only?.should == false
end
it "returns false after appending non ASCII characters to an empty String" do
- ("" << "λ").ascii_only?.should be_false
+ ("".dup << "λ").ascii_only?.should == false
end
it "returns false when concatenating an ASCII and non-ASCII String" do
- "".concat("λ").ascii_only?.should be_false
+ "".dup.concat("λ").ascii_only?.should == false
end
it "returns false when replacing an ASCII String with a non-ASCII String" do
- "".replace("λ").ascii_only?.should be_false
+ "".dup.replace("λ").ascii_only?.should == false
end
end
diff --git a/spec/ruby/core/string/b_spec.rb b/spec/ruby/core/string/b_spec.rb
index 37c7994700..d181447709 100644
--- a/spec/ruby/core/string/b_spec.rb
+++ b/spec/ruby/core/string/b_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe "String#b" do
@@ -9,7 +10,7 @@ describe "String#b" do
it "returns new string without modifying self" do
str = "こんちには"
- str.b.should_not equal(str)
+ str.b.should_not.equal?(str)
str.should == "こんちには"
end
end
diff --git a/spec/ruby/core/string/byteindex_spec.rb b/spec/ruby/core/string/byteindex_spec.rb
new file mode 100644
index 0000000000..f4c6408790
--- /dev/null
+++ b/spec/ruby/core/string/byteindex_spec.rb
@@ -0,0 +1,298 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative 'shared/byte_index_common.rb'
+
+describe "String#byteindex" do
+ it "calls #to_str to convert the first argument" do
+ char = mock("string index char")
+ char.should_receive(:to_str).and_return("b")
+ "abc".byteindex(char).should == 1
+ end
+
+ it "calls #to_int to convert the second argument" do
+ offset = mock("string index offset")
+ offset.should_receive(:to_int).and_return(1)
+ "abc".byteindex("c", offset).should == 2
+ end
+
+ it "does not raise IndexError when byte offset is correct or on string boundary" do
+ "わ".byteindex("").should == 0
+ "わ".byteindex("", 0).should == 0
+ "わ".byteindex("", 3).should == 3
+ end
+
+ it_behaves_like :byte_index_common, :byteindex
+end
+
+describe "String#byteindex with String" do
+ it "behaves the same as String#byteindex(char) for one-character strings" do
+ "blablabla hello cruel world...!".split("").uniq.each do |str|
+ chr = str[0]
+ str.byteindex(str).should == str.byteindex(chr)
+
+ 0.upto(str.size + 1) do |start|
+ str.byteindex(str, start).should == str.byteindex(chr, start)
+ end
+
+ (-str.size - 1).upto(-1) do |start|
+ str.byteindex(str, start).should == str.byteindex(chr, start)
+ end
+ end
+ end
+
+ it "returns the byteindex of the first occurrence of the given substring" do
+ "blablabla".byteindex("").should == 0
+ "blablabla".byteindex("b").should == 0
+ "blablabla".byteindex("bla").should == 0
+ "blablabla".byteindex("blabla").should == 0
+ "blablabla".byteindex("blablabla").should == 0
+
+ "blablabla".byteindex("l").should == 1
+ "blablabla".byteindex("la").should == 1
+ "blablabla".byteindex("labla").should == 1
+ "blablabla".byteindex("lablabla").should == 1
+
+ "blablabla".byteindex("a").should == 2
+ "blablabla".byteindex("abla").should == 2
+ "blablabla".byteindex("ablabla").should == 2
+ end
+
+ it "treats the offset as a byteindex" do
+ "aaaaa".byteindex("a", 0).should == 0
+ "aaaaa".byteindex("a", 2).should == 2
+ "aaaaa".byteindex("a", 4).should == 4
+ end
+
+ it "ignores string subclasses" do
+ "blablabla".byteindex(StringSpecs::MyString.new("bla")).should == 0
+ StringSpecs::MyString.new("blablabla").byteindex("bla").should == 0
+ StringSpecs::MyString.new("blablabla").byteindex(StringSpecs::MyString.new("bla")).should == 0
+ end
+
+ it "starts the search at the given offset" do
+ "blablabla".byteindex("bl", 0).should == 0
+ "blablabla".byteindex("bl", 1).should == 3
+ "blablabla".byteindex("bl", 2).should == 3
+ "blablabla".byteindex("bl", 3).should == 3
+
+ "blablabla".byteindex("bla", 0).should == 0
+ "blablabla".byteindex("bla", 1).should == 3
+ "blablabla".byteindex("bla", 2).should == 3
+ "blablabla".byteindex("bla", 3).should == 3
+
+ "blablabla".byteindex("blab", 0).should == 0
+ "blablabla".byteindex("blab", 1).should == 3
+ "blablabla".byteindex("blab", 2).should == 3
+ "blablabla".byteindex("blab", 3).should == 3
+
+ "blablabla".byteindex("la", 1).should == 1
+ "blablabla".byteindex("la", 2).should == 4
+ "blablabla".byteindex("la", 3).should == 4
+ "blablabla".byteindex("la", 4).should == 4
+
+ "blablabla".byteindex("lab", 1).should == 1
+ "blablabla".byteindex("lab", 2).should == 4
+ "blablabla".byteindex("lab", 3).should == 4
+ "blablabla".byteindex("lab", 4).should == 4
+
+ "blablabla".byteindex("ab", 2).should == 2
+ "blablabla".byteindex("ab", 3).should == 5
+ "blablabla".byteindex("ab", 4).should == 5
+ "blablabla".byteindex("ab", 5).should == 5
+
+ "blablabla".byteindex("", 0).should == 0
+ "blablabla".byteindex("", 1).should == 1
+ "blablabla".byteindex("", 2).should == 2
+ "blablabla".byteindex("", 7).should == 7
+ "blablabla".byteindex("", 8).should == 8
+ "blablabla".byteindex("", 9).should == 9
+ end
+
+ it "starts the search at offset + self.length if offset is negative" do
+ str = "blablabla"
+
+ ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
+ (-str.length .. -1).each do |offset|
+ str.byteindex(needle, offset).should ==
+ str.byteindex(needle, offset + str.length)
+ end
+ end
+ end
+
+ it "returns nil if the substring isn't found" do
+ "blablabla".byteindex("B").should == nil
+ "blablabla".byteindex("z").should == nil
+ "blablabla".byteindex("BLA").should == nil
+ "blablabla".byteindex("blablablabla").should == nil
+ "blablabla".byteindex("", 10).should == nil
+
+ "hello".byteindex("he", 1).should == nil
+ "hello".byteindex("he", 2).should == nil
+ "I’ve got a multibyte character.\n".byteindex("\n\n").should == nil
+ end
+
+ it "returns the character byteindex of a multibyte character" do
+ "ありがとう".byteindex("が").should == 6
+ end
+
+ it "returns the character byteindex after offset" do
+ "われわれ".byteindex("わ", 3).should == 6
+ "ありがとうありがとう".byteindex("が", 9).should == 21
+ end
+
+ it "returns the character byteindex after a partial first match" do
+ "</</h".byteindex("</h").should == 2
+ end
+
+ it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
+ char = "れ".encode Encoding::EUC_JP
+ -> do
+ "あれ".byteindex(char)
+ end.should.raise(Encoding::CompatibilityError)
+ end
+
+ it "handles a substring in a superset encoding" do
+ 'abc'.dup.force_encoding(Encoding::US_ASCII).byteindex('é').should == nil
+ end
+
+ it "handles a substring in a subset encoding" do
+ 'été'.byteindex('t'.dup.force_encoding(Encoding::US_ASCII)).should == 2
+ end
+end
+
+describe "String#byteindex with Regexp" do
+ it "behaves the same as String#byteindex(string) for escaped string regexps" do
+ ["blablabla", "hello cruel world...!"].each do |str|
+ ["", "b", "bla", "lab", "o c", "d."].each do |needle|
+ regexp = Regexp.new(Regexp.escape(needle))
+ str.byteindex(regexp).should == str.byteindex(needle)
+
+ 0.upto(str.size + 1) do |start|
+ str.byteindex(regexp, start).should == str.byteindex(needle, start)
+ end
+
+ (-str.size - 1).upto(-1) do |start|
+ str.byteindex(regexp, start).should == str.byteindex(needle, start)
+ end
+ end
+ end
+ end
+
+ it "returns the byteindex of the first match of regexp" do
+ "blablabla".byteindex(/bla/).should == 0
+ "blablabla".byteindex(/BLA/i).should == 0
+
+ "blablabla".byteindex(/.{0}/).should == 0
+ "blablabla".byteindex(/.{6}/).should == 0
+ "blablabla".byteindex(/.{9}/).should == 0
+
+ "blablabla".byteindex(/.*/).should == 0
+ "blablabla".byteindex(/.+/).should == 0
+
+ "blablabla".byteindex(/lab|b/).should == 0
+
+ not_supported_on :opal do
+ "blablabla".byteindex(/\A/).should == 0
+ "blablabla".byteindex(/\Z/).should == 9
+ "blablabla".byteindex(/\z/).should == 9
+ "blablabla\n".byteindex(/\Z/).should == 9
+ "blablabla\n".byteindex(/\z/).should == 10
+ end
+
+ "blablabla".byteindex(/^/).should == 0
+ "\nblablabla".byteindex(/^/).should == 0
+ "b\nablabla".byteindex(/$/).should == 1
+ "bl\nablabla".byteindex(/$/).should == 2
+
+ "blablabla".byteindex(/.l./).should == 0
+ end
+
+ it "starts the search at the given offset" do
+ "blablabla".byteindex(/.{0}/, 5).should == 5
+ "blablabla".byteindex(/.{1}/, 5).should == 5
+ "blablabla".byteindex(/.{2}/, 5).should == 5
+ "blablabla".byteindex(/.{3}/, 5).should == 5
+ "blablabla".byteindex(/.{4}/, 5).should == 5
+
+ "blablabla".byteindex(/.{0}/, 3).should == 3
+ "blablabla".byteindex(/.{1}/, 3).should == 3
+ "blablabla".byteindex(/.{2}/, 3).should == 3
+ "blablabla".byteindex(/.{5}/, 3).should == 3
+ "blablabla".byteindex(/.{6}/, 3).should == 3
+
+ "blablabla".byteindex(/.l./, 0).should == 0
+ "blablabla".byteindex(/.l./, 1).should == 3
+ "blablabla".byteindex(/.l./, 2).should == 3
+ "blablabla".byteindex(/.l./, 3).should == 3
+
+ "xblaxbla".byteindex(/x./, 0).should == 0
+ "xblaxbla".byteindex(/x./, 1).should == 4
+ "xblaxbla".byteindex(/x./, 2).should == 4
+
+ not_supported_on :opal do
+ "blablabla\n".byteindex(/\Z/, 9).should == 9
+ end
+ end
+
+ it "starts the search at offset + self.length if offset is negative" do
+ str = "blablabla"
+
+ ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
+ (-str.length .. -1).each do |offset|
+ str.byteindex(needle, offset).should ==
+ str.byteindex(needle, offset + str.length)
+ end
+ end
+ end
+
+ it "returns nil if the substring isn't found" do
+ "blablabla".byteindex(/BLA/).should == nil
+
+ "blablabla".byteindex(/.{10}/).should == nil
+ "blaxbla".byteindex(/.x/, 3).should == nil
+ "blaxbla".byteindex(/..x/, 2).should == nil
+ end
+
+ it "returns nil if the Regexp matches the empty string and the offset is out of range" do
+ "ruby".byteindex(//, 12).should == nil
+ end
+
+ it "supports \\G which matches at the given start offset" do
+ "helloYOU.".byteindex(/\GYOU/, 5).should == 5
+ "helloYOU.".byteindex(/\GYOU/).should == nil
+
+ re = /\G.+YOU/
+ # The # marks where \G will match.
+ [
+ ["#hi!YOUall.", 0],
+ ["h#i!YOUall.", 1],
+ ["hi#!YOUall.", 2],
+ ["hi!#YOUall.", nil]
+ ].each do |spec|
+
+ start = spec[0].byteindex("#")
+ str = spec[0].delete("#")
+
+ str.byteindex(re, start).should == spec[1]
+ end
+ end
+
+ it "converts start_offset to an integer via to_int" do
+ obj = mock('1')
+ obj.should_receive(:to_int).and_return(1)
+ "RWOARW".byteindex(/R./, obj).should == 4
+ end
+
+ it "returns the character byteindex of a multibyte character" do
+ "ありがとう".byteindex(/が/).should == 6
+ end
+
+ it "returns the character byteindex after offset" do
+ "われわれ".byteindex(/わ/, 3).should == 6
+ end
+
+ it "treats the offset as a byteindex" do
+ "われわわれ".byteindex(/わ/, 6).should == 6
+ end
+end
diff --git a/spec/ruby/core/string/byterindex_spec.rb b/spec/ruby/core/string/byterindex_spec.rb
new file mode 100644
index 0000000000..569820463d
--- /dev/null
+++ b/spec/ruby/core/string/byterindex_spec.rb
@@ -0,0 +1,353 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative 'shared/byte_index_common.rb'
+
+describe "String#byterindex with object" do
+ it "tries to convert obj to a string via to_str" do
+ obj = mock('lo')
+ def obj.to_str() "lo" end
+ "hello".byterindex(obj).should == "hello".byterindex("lo")
+
+ obj = mock('o')
+ def obj.respond_to?(arg, *) true end
+ def obj.method_missing(*args) "o" end
+ "hello".byterindex(obj).should == "hello".byterindex("o")
+ end
+
+ it "calls #to_int to convert the second argument" do
+ offset = mock("string index offset")
+ offset.should_receive(:to_int).and_return(3)
+ "abc".byterindex("c", offset).should == 2
+ end
+
+ it "does not raise IndexError when byte offset is correct or on string boundary" do
+ "わ".byterindex("", 0).should == 0
+ "わ".byterindex("", 3).should == 3
+ "わ".byterindex("").should == 3
+ end
+
+ it_behaves_like :byte_index_common, :byterindex
+end
+
+describe "String#byterindex with String" do
+ it "behaves the same as String#byterindex(char) for one-character strings" do
+ "blablabla hello cruel world...!".split("").uniq.each do |str|
+ chr = str[0]
+ str.byterindex(str).should == str.byterindex(chr)
+
+ 0.upto(str.size + 1) do |start|
+ str.byterindex(str, start).should == str.byterindex(chr, start)
+ end
+
+ (-str.size - 1).upto(-1) do |start|
+ str.byterindex(str, start).should == str.byterindex(chr, start)
+ end
+ end
+ end
+
+ it "behaves the same as String#byterindex(?char) for one-character strings" do
+ "blablabla hello cruel world...!".split("").uniq.each do |str|
+ chr = str[0] =~ / / ? str[0] : eval("?#{str[0]}")
+ str.byterindex(str).should == str.byterindex(chr)
+
+ 0.upto(str.size + 1) do |start|
+ str.byterindex(str, start).should == str.byterindex(chr, start)
+ end
+
+ (-str.size - 1).upto(-1) do |start|
+ str.byterindex(str, start).should == str.byterindex(chr, start)
+ end
+ end
+ end
+
+ it "returns the index of the last occurrence of the given substring" do
+ "blablabla".byterindex("").should == 9
+ "blablabla".byterindex("a").should == 8
+ "blablabla".byterindex("la").should == 7
+ "blablabla".byterindex("bla").should == 6
+ "blablabla".byterindex("abla").should == 5
+ "blablabla".byterindex("labla").should == 4
+ "blablabla".byterindex("blabla").should == 3
+ "blablabla".byterindex("ablabla").should == 2
+ "blablabla".byterindex("lablabla").should == 1
+ "blablabla".byterindex("blablabla").should == 0
+
+ "blablabla".byterindex("l").should == 7
+ "blablabla".byterindex("bl").should == 6
+ "blablabla".byterindex("abl").should == 5
+ "blablabla".byterindex("labl").should == 4
+ "blablabla".byterindex("blabl").should == 3
+ "blablabla".byterindex("ablabl").should == 2
+ "blablabla".byterindex("lablabl").should == 1
+ "blablabla".byterindex("blablabl").should == 0
+
+ "blablabla".byterindex("b").should == 6
+ "blablabla".byterindex("ab").should == 5
+ "blablabla".byterindex("lab").should == 4
+ "blablabla".byterindex("blab").should == 3
+ "blablabla".byterindex("ablab").should == 2
+ "blablabla".byterindex("lablab").should == 1
+ "blablabla".byterindex("blablab").should == 0
+ end
+
+ it "ignores string subclasses" do
+ "blablabla".byterindex(StringSpecs::MyString.new("bla")).should == 6
+ StringSpecs::MyString.new("blablabla").byterindex("bla").should == 6
+ StringSpecs::MyString.new("blablabla").byterindex(StringSpecs::MyString.new("bla")).should == 6
+ end
+
+ it "starts the search at the given offset" do
+ "blablabla".byterindex("bl", 0).should == 0
+ "blablabla".byterindex("bl", 1).should == 0
+ "blablabla".byterindex("bl", 2).should == 0
+ "blablabla".byterindex("bl", 3).should == 3
+
+ "blablabla".byterindex("bla", 0).should == 0
+ "blablabla".byterindex("bla", 1).should == 0
+ "blablabla".byterindex("bla", 2).should == 0
+ "blablabla".byterindex("bla", 3).should == 3
+
+ "blablabla".byterindex("blab", 0).should == 0
+ "blablabla".byterindex("blab", 1).should == 0
+ "blablabla".byterindex("blab", 2).should == 0
+ "blablabla".byterindex("blab", 3).should == 3
+ "blablabla".byterindex("blab", 6).should == 3
+ "blablablax".byterindex("blab", 6).should == 3
+
+ "blablabla".byterindex("la", 1).should == 1
+ "blablabla".byterindex("la", 2).should == 1
+ "blablabla".byterindex("la", 3).should == 1
+ "blablabla".byterindex("la", 4).should == 4
+
+ "blablabla".byterindex("lab", 1).should == 1
+ "blablabla".byterindex("lab", 2).should == 1
+ "blablabla".byterindex("lab", 3).should == 1
+ "blablabla".byterindex("lab", 4).should == 4
+
+ "blablabla".byterindex("ab", 2).should == 2
+ "blablabla".byterindex("ab", 3).should == 2
+ "blablabla".byterindex("ab", 4).should == 2
+ "blablabla".byterindex("ab", 5).should == 5
+
+ "blablabla".byterindex("", 0).should == 0
+ "blablabla".byterindex("", 1).should == 1
+ "blablabla".byterindex("", 2).should == 2
+ "blablabla".byterindex("", 7).should == 7
+ "blablabla".byterindex("", 8).should == 8
+ "blablabla".byterindex("", 9).should == 9
+ "blablabla".byterindex("", 10).should == 9
+ end
+
+ it "starts the search at offset + self.length if offset is negative" do
+ str = "blablabla"
+
+ ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
+ (-str.length .. -1).each do |offset|
+ str.byterindex(needle, offset).should ==
+ str.byterindex(needle, offset + str.length)
+ end
+ end
+ end
+
+ it "returns nil if the substring isn't found" do
+ "blablabla".byterindex("B").should == nil
+ "blablabla".byterindex("z").should == nil
+ "blablabla".byterindex("BLA").should == nil
+ "blablabla".byterindex("blablablabla").should == nil
+
+ "hello".byterindex("lo", 0).should == nil
+ "hello".byterindex("lo", 1).should == nil
+ "hello".byterindex("lo", 2).should == nil
+
+ "hello".byterindex("llo", 0).should == nil
+ "hello".byterindex("llo", 1).should == nil
+
+ "hello".byterindex("el", 0).should == nil
+ "hello".byterindex("ello", 0).should == nil
+
+ "hello".byterindex("", -6).should == nil
+ "hello".byterindex("", -7).should == nil
+
+ "hello".byterindex("h", -6).should == nil
+ end
+
+ it "tries to convert start_offset to an integer via to_int" do
+ obj = mock('5')
+ def obj.to_int() 5 end
+ "str".byterindex("st", obj).should == 0
+
+ obj = mock('5')
+ def obj.respond_to?(arg, *) true end
+ def obj.method_missing(*args) 5 end
+ "str".byterindex("st", obj).should == 0
+ end
+
+ it "raises a TypeError when given offset is nil" do
+ -> { "str".byterindex("st", nil) }.should.raise(TypeError)
+ end
+
+ it "handles a substring in a superset encoding" do
+ 'abc'.dup.force_encoding(Encoding::US_ASCII).byterindex('é').should == nil
+ end
+
+ it "handles a substring in a subset encoding" do
+ 'été'.byterindex('t'.dup.force_encoding(Encoding::US_ASCII)).should == 2
+ end
+end
+
+describe "String#byterindex with Regexp" do
+ it "behaves the same as String#byterindex(string) for escaped string regexps" do
+ ["blablabla", "hello cruel world...!"].each do |str|
+ ["", "b", "bla", "lab", "o c", "d."].each do |needle|
+ regexp = Regexp.new(Regexp.escape(needle))
+ str.byterindex(regexp).should == str.byterindex(needle)
+
+ 0.upto(str.size + 1) do |start|
+ str.byterindex(regexp, start).should == str.byterindex(needle, start)
+ end
+
+ (-str.size - 1).upto(-1) do |start|
+ str.byterindex(regexp, start).should == str.byterindex(needle, start)
+ end
+ end
+ end
+ end
+
+ it "returns the index of the first match from the end of string of regexp" do
+ "blablabla".byterindex(/bla/).should == 6
+ "blablabla".byterindex(/BLA/i).should == 6
+
+ "blablabla".byterindex(/.{0}/).should == 9
+ "blablabla".byterindex(/.{1}/).should == 8
+ "blablabla".byterindex(/.{2}/).should == 7
+ "blablabla".byterindex(/.{6}/).should == 3
+ "blablabla".byterindex(/.{9}/).should == 0
+
+ "blablabla".byterindex(/.*/).should == 9
+ "blablabla".byterindex(/.+/).should == 8
+
+ "blablabla".byterindex(/bla|a/).should == 8
+
+ not_supported_on :opal do
+ "blablabla".byterindex(/\A/).should == 0
+ "blablabla".byterindex(/\Z/).should == 9
+ "blablabla".byterindex(/\z/).should == 9
+ "blablabla\n".byterindex(/\Z/).should == 10
+ "blablabla\n".byterindex(/\z/).should == 10
+ end
+
+ "blablabla".byterindex(/^/).should == 0
+ not_supported_on :opal do
+ "\nblablabla".byterindex(/^/).should == 1
+ "b\nlablabla".byterindex(/^/).should == 2
+ end
+ "blablabla".byterindex(/$/).should == 9
+
+ "blablabla".byterindex(/.l./).should == 6
+ end
+
+ it "starts the search at the given offset" do
+ "blablabla".byterindex(/.{0}/, 5).should == 5
+ "blablabla".byterindex(/.{1}/, 5).should == 5
+ "blablabla".byterindex(/.{2}/, 5).should == 5
+ "blablabla".byterindex(/.{3}/, 5).should == 5
+ "blablabla".byterindex(/.{4}/, 5).should == 5
+
+ "blablabla".byterindex(/.{0}/, 3).should == 3
+ "blablabla".byterindex(/.{1}/, 3).should == 3
+ "blablabla".byterindex(/.{2}/, 3).should == 3
+ "blablabla".byterindex(/.{5}/, 3).should == 3
+ "blablabla".byterindex(/.{6}/, 3).should == 3
+
+ "blablabla".byterindex(/.l./, 0).should == 0
+ "blablabla".byterindex(/.l./, 1).should == 0
+ "blablabla".byterindex(/.l./, 2).should == 0
+ "blablabla".byterindex(/.l./, 3).should == 3
+
+ "blablablax".byterindex(/.x/, 10).should == 8
+ "blablablax".byterindex(/.x/, 9).should == 8
+ "blablablax".byterindex(/.x/, 8).should == 8
+
+ "blablablax".byterindex(/..x/, 10).should == 7
+ "blablablax".byterindex(/..x/, 9).should == 7
+ "blablablax".byterindex(/..x/, 8).should == 7
+ "blablablax".byterindex(/..x/, 7).should == 7
+
+ not_supported_on :opal do
+ "blablabla\n".byterindex(/\Z/, 9).should == 9
+ end
+ end
+
+ it "starts the search at offset + self.length if offset is negative" do
+ str = "blablabla"
+
+ ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
+ (-str.length .. -1).each do |offset|
+ str.byterindex(needle, offset).should ==
+ str.byterindex(needle, offset + str.length)
+ end
+ end
+ end
+
+ it "returns nil if the substring isn't found" do
+ "blablabla".byterindex(/BLA/).should == nil
+ "blablabla".byterindex(/.{10}/).should == nil
+ "blablablax".byterindex(/.x/, 7).should == nil
+ "blablablax".byterindex(/..x/, 6).should == nil
+
+ not_supported_on :opal do
+ "blablabla".byterindex(/\Z/, 5).should == nil
+ "blablabla".byterindex(/\z/, 5).should == nil
+ "blablabla\n".byterindex(/\z/, 9).should == nil
+ end
+ end
+
+ not_supported_on :opal do
+ it "supports \\G which matches at the given start offset" do
+ "helloYOU.".byterindex(/YOU\G/, 8).should == 5
+ "helloYOU.".byterindex(/YOU\G/).should == nil
+
+ idx = "helloYOUall!".index("YOU")
+ re = /YOU.+\G.+/
+ # The # marks where \G will match.
+ [
+ ["helloYOU#all.", nil],
+ ["helloYOUa#ll.", idx],
+ ["helloYOUal#l.", idx],
+ ["helloYOUall#.", idx],
+ ["helloYOUall.#", nil]
+ ].each do |i|
+ start = i[0].index("#")
+ str = i[0].delete("#")
+
+ str.byterindex(re, start).should == i[1]
+ end
+ end
+ end
+
+ it "tries to convert start_offset to an integer" do
+ obj = mock('5')
+ def obj.to_int() 5 end
+ "str".byterindex(/../, obj).should == 1
+
+ obj = mock('5')
+ def obj.respond_to?(arg, *) true end
+ def obj.method_missing(*args); 5; end
+ "str".byterindex(/../, obj).should == 1
+ end
+
+ it "raises a TypeError when given offset is nil" do
+ -> { "str".byterindex(/../, nil) }.should.raise(TypeError)
+ end
+
+ it "returns the reverse byte index of a multibyte character" do
+ "ありがりがとう".byterindex("が").should == 12
+ "ありがりがとう".byterindex(/が/).should == 12
+ end
+
+ it "returns the character index before the finish" do
+ "ありがりがとう".byterindex("が", 9).should == 6
+ "ありがりがとう".byterindex(/が/, 9).should == 6
+ end
+end
diff --git a/spec/ruby/core/string/bytes_spec.rb b/spec/ruby/core/string/bytes_spec.rb
index 859b346550..e6019fb987 100644
--- a/spec/ruby/core/string/bytes_spec.rb
+++ b/spec/ruby/core/string/bytes_spec.rb
@@ -9,7 +9,7 @@ describe "String#bytes" do
end
it "returns an Array when no block is given" do
- @utf8.bytes.should be_an_instance_of(Array)
+ @utf8.bytes.should.instance_of?(Array)
end
it "yields each byte to a block if one is given, returning self" do
@@ -23,8 +23,8 @@ describe "String#bytes" do
end
it "returns bytes as Integers" do
- @ascii.bytes.to_a.each {|b| b.should be_an_instance_of(Integer)}
- @utf8_ascii.bytes { |b| b.should be_an_instance_of(Integer) }
+ @ascii.bytes.to_a.each {|b| b.should.instance_of?(Integer)}
+ @utf8_ascii.bytes { |b| b.should.instance_of?(Integer) }
end
it "agrees with #unpack('C*')" do
@@ -50,6 +50,6 @@ describe "String#bytes" do
end
it "is unaffected by #force_encoding" do
- @utf8.force_encoding('ASCII').bytes.to_a.should == @utf8.bytes.to_a
+ @utf8.dup.force_encoding('ASCII').bytes.to_a.should == @utf8.bytes.to_a
end
end
diff --git a/spec/ruby/core/string/bytesize_spec.rb b/spec/ruby/core/string/bytesize_spec.rb
index a31f3ae671..2bbefc0820 100644
--- a/spec/ruby/core/string/bytesize_spec.rb
+++ b/spec/ruby/core/string/bytesize_spec.rb
@@ -13,21 +13,21 @@ describe "String#bytesize" do
end
it "works with pseudo-ASCII strings containing single UTF-8 characters" do
- "\u{6666}".force_encoding('ASCII').bytesize.should == 3
+ "\u{6666}".dup.force_encoding('ASCII').bytesize.should == 3
end
it "works with strings containing UTF-8 characters" do
- "c \u{6666}".force_encoding('UTF-8').bytesize.should == 5
+ "c \u{6666}".dup.force_encoding('UTF-8').bytesize.should == 5
"c \u{6666}".bytesize.should == 5
end
it "works with pseudo-ASCII strings containing UTF-8 characters" do
- "c \u{6666}".force_encoding('ASCII').bytesize.should == 5
+ "c \u{6666}".dup.force_encoding('ASCII').bytesize.should == 5
end
it "returns 0 for the empty string" do
"".bytesize.should == 0
- "".force_encoding('ASCII').bytesize.should == 0
- "".force_encoding('UTF-8').bytesize.should == 0
+ "".dup.force_encoding('ASCII').bytesize.should == 0
+ "".dup.force_encoding('UTF-8').bytesize.should == 0
end
end
diff --git a/spec/ruby/core/string/byteslice_spec.rb b/spec/ruby/core/string/byteslice_spec.rb
index a49da040eb..4ad9e8d8f1 100644
--- a/spec/ruby/core/string/byteslice_spec.rb
+++ b/spec/ruby/core/string/byteslice_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/slice'
@@ -17,11 +17,17 @@ describe "String#byteslice with Range" do
it_behaves_like :string_slice_range, :byteslice
end
-describe "String#byteslice on on non ASCII strings" do
+describe "String#byteslice on non ASCII strings" do
it "returns byteslice of unicode strings" do
- "\u3042".byteslice(1).should == "\x81".force_encoding("UTF-8")
- "\u3042".byteslice(1, 2).should == "\x81\x82".force_encoding("UTF-8")
- "\u3042".byteslice(1..2).should == "\x81\x82".force_encoding("UTF-8")
- "\u3042".byteslice(-1).should == "\x82".force_encoding("UTF-8")
+ "\u3042".byteslice(1).should == "\x81".dup.force_encoding("UTF-8")
+ "\u3042".byteslice(1, 2).should == "\x81\x82".dup.force_encoding("UTF-8")
+ "\u3042".byteslice(1..2).should == "\x81\x82".dup.force_encoding("UTF-8")
+ "\u3042".byteslice(-1).should == "\x82".dup.force_encoding("UTF-8")
+ end
+
+ it "returns a String in the same encoding as self" do
+ "ruby".encode("UTF-8").slice(0).encoding.should == Encoding::UTF_8
+ "ruby".encode("US-ASCII").slice(0).encoding.should == Encoding::US_ASCII
+ "ruby".encode("Windows-1251").slice(0).encoding.should == Encoding::Windows_1251
end
end
diff --git a/spec/ruby/core/string/bytesplice_spec.rb b/spec/ruby/core/string/bytesplice_spec.rb
new file mode 100644
index 0000000000..3e5e6fe1ee
--- /dev/null
+++ b/spec/ruby/core/string/bytesplice_spec.rb
@@ -0,0 +1,290 @@
+# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
+require_relative '../../spec_helper'
+
+describe "String#bytesplice" do
+ it "raises IndexError when index is less than -bytesize" do
+ -> { "hello".bytesplice(-6, 0, "xxx") }.should.raise(IndexError, "index -6 out of string")
+ end
+
+ it "raises IndexError when index is greater than bytesize" do
+ -> { "hello".bytesplice(6, 0, "xxx") }.should.raise(IndexError, "index 6 out of string")
+ end
+
+ it "raises IndexError for negative length" do
+ -> { "abc".bytesplice(0, -2, "") }.should.raise(IndexError, "negative length -2")
+ end
+
+ it "replaces with integer indices" do
+ "hello".bytesplice(-5, 0, "xxx").should == "xxxhello"
+ "hello".bytesplice(0, 0, "xxx").should == "xxxhello"
+ "hello".bytesplice(0, 1, "xxx").should == "xxxello"
+ "hello".bytesplice(0, 5, "xxx").should == "xxx"
+ "hello".bytesplice(0, 6, "xxx").should == "xxx"
+ end
+
+ it "raises RangeError when range left boundary is less than -bytesize" do
+ -> { "hello".bytesplice(-6...-6, "xxx") }.should.raise(RangeError, "-6...-6 out of range")
+ end
+
+ it "replaces with ranges" do
+ "hello".bytesplice(-5...-5, "xxx").should == "xxxhello"
+ "hello".bytesplice(0...0, "xxx").should == "xxxhello"
+ "hello".bytesplice(0..0, "xxx").should == "xxxello"
+ "hello".bytesplice(0...1, "xxx").should == "xxxello"
+ "hello".bytesplice(0..1, "xxx").should == "xxxllo"
+ "hello".bytesplice(0..-1, "xxx").should == "xxx"
+ "hello".bytesplice(0...5, "xxx").should == "xxx"
+ "hello".bytesplice(0...6, "xxx").should == "xxx"
+ end
+
+ it "raises TypeError when integer index is provided without length argument" do
+ -> { "hello".bytesplice(0, "xxx") }.should.raise(TypeError, "wrong argument type Integer (expected Range)")
+ end
+
+ it "replaces on an empty string" do
+ "".bytesplice(0, 0, "").should == ""
+ "".bytesplice(0, 0, "xxx").should == "xxx"
+ end
+
+ it "mutates self" do
+ s = "hello"
+ s.bytesplice(2, 1, "xxx").should.equal?(s)
+ end
+
+ it "raises when string is frozen" do
+ s = "hello".freeze
+ -> { s.bytesplice(2, 1, "xxx") }.should.raise(FrozenError, "can't modify frozen String: \"hello\"")
+ end
+
+ it "raises IndexError when str_index is less than -bytesize" do
+ -> { "hello".bytesplice(2, 1, "HELLO", -6, 0) }.should.raise(IndexError, "index -6 out of string")
+ end
+
+ it "raises IndexError when str_index is greater than bytesize" do
+ -> { "hello".bytesplice(2, 1, "HELLO", 6, 0) }.should.raise(IndexError, "index 6 out of string")
+ end
+
+ it "raises IndexError for negative str length" do
+ -> { "abc".bytesplice(0, 1, "", 0, -2) }.should.raise(IndexError, "negative length -2")
+ end
+
+ it "replaces with integer str indices" do
+ "hello".bytesplice(1, 2, "HELLO", -5, 0).should == "hlo"
+ "hello".bytesplice(1, 2, "HELLO", 0, 0).should == "hlo"
+ "hello".bytesplice(1, 2, "HELLO", 0, 1).should == "hHlo"
+ "hello".bytesplice(1, 2, "HELLO", 0, 5).should == "hHELLOlo"
+ "hello".bytesplice(1, 2, "HELLO", 0, 6).should == "hHELLOlo"
+ end
+
+ it "raises RangeError when str range left boundary is less than -bytesize" do
+ -> { "hello".bytesplice(0..1, "HELLO", -6...-6) }.should.raise(RangeError, "-6...-6 out of range")
+ end
+
+ it "replaces with str ranges" do
+ "hello".bytesplice(1..2, "HELLO", -5...-5).should == "hlo"
+ "hello".bytesplice(1..2, "HELLO", 0...0).should == "hlo"
+ "hello".bytesplice(1..2, "HELLO", 0..0).should == "hHlo"
+ "hello".bytesplice(1..2, "HELLO", 0...1).should == "hHlo"
+ "hello".bytesplice(1..2, "HELLO", 0..1).should == "hHElo"
+ "hello".bytesplice(1..2, "HELLO", 0..-1).should == "hHELLOlo"
+ "hello".bytesplice(1..2, "HELLO", 0...5).should == "hHELLOlo"
+ "hello".bytesplice(1..2, "HELLO", 0...6).should == "hHELLOlo"
+ end
+
+ it "raises ArgumentError when integer str index is provided without str length argument" do
+ -> { "hello".bytesplice(0, 1, "xxx", 0) }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 2, 3, or 5)")
+ end
+
+ it "replaces on an empty string with str index/length" do
+ "".bytesplice(0, 0, "", 0, 0).should == ""
+ "".bytesplice(0, 0, "xxx", 0, 1).should == "x"
+ end
+
+ it "mutates self with substring and str index/length" do
+ s = "hello"
+ s.bytesplice(2, 1, "xxx", 1, 2).should.equal?(s)
+ s.should.eql?("hexxlo")
+ end
+
+ it "raises when string is frozen and str index/length" do
+ s = "hello".freeze
+ -> { s.bytesplice(2, 1, "xxx", 0, 1) }.should.raise(FrozenError, "can't modify frozen String: \"hello\"")
+ end
+
+ it "replaces on an empty string with str range" do
+ "".bytesplice(0..0, "", 0..0).should == ""
+ "".bytesplice(0..0, "xyz", 0..1).should == "xy"
+ end
+
+ it "mutates self with substring and str range" do
+ s = "hello"
+ s.bytesplice(2..2, "xyz", 1..2).should.equal?(s)
+ s.should.eql?("heyzlo")
+ end
+
+ it "raises when string is frozen and str range" do
+ s = "hello".freeze
+ -> { s.bytesplice(2..2, "yzx", 0..1) }.should.raise(FrozenError, "can't modify frozen String: \"hello\"")
+ end
+end
+
+describe "String#bytesplice with multibyte characters" do
+ it "raises IndexError when index is out of byte size boundary" do
+ -> { "こんにちは".bytesplice(-16, 0, "xxx") }.should.raise(IndexError, "index -16 out of string")
+ end
+
+ it "raises IndexError when index is not on a codepoint boundary" do
+ -> { "こんにちは".bytesplice(1, 0, "xxx") }.should.raise(IndexError, "offset 1 does not land on character boundary")
+ end
+
+ it "raises IndexError when length is not matching the codepoint boundary" do
+ -> { "こんにちは".bytesplice(0, 1, "xxx") }.should.raise(IndexError, "offset 1 does not land on character boundary")
+ -> { "こんにちは".bytesplice(0, 2, "xxx") }.should.raise(IndexError, "offset 2 does not land on character boundary")
+ end
+
+ it "replaces with integer indices" do
+ "こんにちは".bytesplice(-15, 0, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(0, 0, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(0, 3, "xxx").should == "xxxんにちは"
+ "こんにちは".bytesplice(3, 3, "はは").should == "こははにちは"
+ "こんにちは".bytesplice(15, 0, "xxx").should == "こんにちはxxx"
+ end
+
+ it "replaces with range" do
+ "こんにちは".bytesplice(-15...-16, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(0...0, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(0..2, "xxx").should == "xxxんにちは"
+ "こんにちは".bytesplice(0...3, "xxx").should == "xxxんにちは"
+ "こんにちは".bytesplice(0..5, "xxx").should == "xxxにちは"
+ "こんにちは".bytesplice(0..-1, "xxx").should == "xxx"
+ "こんにちは".bytesplice(0...15, "xxx").should == "xxx"
+ "こんにちは".bytesplice(0...18, "xxx").should == "xxx"
+ end
+
+ it "treats negative length for range as 0" do
+ "こんにちは".bytesplice(0...-100, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(3...-100, "xxx").should == "こxxxんにちは"
+ "こんにちは".bytesplice(-15...-100, "xxx").should == "xxxこんにちは"
+ end
+
+ it "raises when ranges not match codepoint boundaries" do
+ -> { "こんにちは".bytesplice(0..0, "x") }.should.raise(IndexError, "offset 1 does not land on character boundary")
+ -> { "こんにちは".bytesplice(0..1, "x") }.should.raise(IndexError, "offset 2 does not land on character boundary")
+ # Begin is incorrect
+ -> { "こんにちは".bytesplice(-4..-1, "x") }.should.raise(IndexError, "offset 11 does not land on character boundary")
+ -> { "こんにちは".bytesplice(-5..-1, "x") }.should.raise(IndexError, "offset 10 does not land on character boundary")
+ # End is incorrect
+ -> { "こんにちは".bytesplice(-3..-2, "x") }.should.raise(IndexError, "offset 14 does not land on character boundary")
+ -> { "こんにちは".bytesplice(-3..-3, "x") }.should.raise(IndexError, "offset 13 does not land on character boundary")
+ end
+
+ it "deals with a different encoded argument" do
+ s = "こんにちは"
+ s.encoding.should == Encoding::UTF_8
+ sub = "xxxxxx"
+ sub.force_encoding(Encoding::US_ASCII)
+
+ result = s.bytesplice(0, 3, sub)
+ result.should == "xxxxxxんにちは"
+ result.encoding.should == Encoding::UTF_8
+
+ s = "xxxxxx"
+ s.force_encoding(Encoding::US_ASCII)
+ sub = "こんにちは"
+ sub.encoding.should == Encoding::UTF_8
+
+ result = s.bytesplice(0, 3, sub)
+ result.should == "こんにちはxxx"
+ result.encoding.should == Encoding::UTF_8
+ end
+
+ it "raises IndexError when str_index is out of byte size boundary" do
+ -> { "こんにちは".bytesplice(3, 3, "こんにちは", -16, 0) }.should.raise(IndexError, "index -16 out of string")
+ end
+
+ it "raises IndexError when str_index is not on a codepoint boundary" do
+ -> { "こんにちは".bytesplice(3, 3, "こんにちは", 1, 0) }.should.raise(IndexError, "offset 1 does not land on character boundary")
+ end
+
+ it "raises IndexError when str_length is not matching the codepoint boundary" do
+ -> { "こんにちは".bytesplice(3, 3, "こんにちは", 0, 1) }.should.raise(IndexError, "offset 1 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3, 3, "こんにちは", 0, 2) }.should.raise(IndexError, "offset 2 does not land on character boundary")
+ end
+
+ it "replaces with integer str indices" do
+ "こんにちは".bytesplice(3, 3, "こんにちは", -15, 0).should == "こにちは"
+ "こんにちは".bytesplice(3, 3, "こんにちは", 0, 0).should == "こにちは"
+ "こんにちは".bytesplice(3, 3, "こんにちは", 0, 3).should == "ここにちは"
+ "こんにちは".bytesplice(3, 3, "はは", 3, 3).should == "こはにちは"
+ "こんにちは".bytesplice(3, 3, "こんにちは", 15, 0).should == "こにちは"
+ end
+
+ it "replaces with str range" do
+ "こんにちは".bytesplice(0..2, "こんにちは", -15...-16).should == "んにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 0...0).should == "んにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 3..5).should == "んんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 3...6).should == "んんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 3..8).should == "んにんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 0..-1).should == "こんにちはんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 0...15).should == "こんにちはんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 0...18).should == "こんにちはんにちは"
+ end
+
+ it "treats negative length for str range as 0" do
+ "こんにちは".bytesplice(0..2, "こんにちは", 0...-100).should == "んにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 3...-100).should == "んにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", -15...-100).should == "んにちは"
+ end
+
+ it "raises when ranges not match codepoint boundaries in str" do
+ -> { "こんにちは".bytesplice(3...3, "こ", 0..0) }.should.raise(IndexError, "offset 1 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3...3, "こ", 0..1) }.should.raise(IndexError, "offset 2 does not land on character boundary")
+ # Begin is incorrect
+ -> { "こんにちは".bytesplice(3...3, "こんにちは", -4..-1) }.should.raise(IndexError, "offset 11 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3...3, "こんにちは", -5..-1) }.should.raise(IndexError, "offset 10 does not land on character boundary")
+ # End is incorrect
+ -> { "こんにちは".bytesplice(3...3, "こんにちは", -3..-2) }.should.raise(IndexError, "offset 14 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3...3, "こんにちは", -3..-3) }.should.raise(IndexError, "offset 13 does not land on character boundary")
+ end
+
+ it "deals with a different encoded argument with str index/length" do
+ s = "こんにちは"
+ s.encoding.should == Encoding::UTF_8
+ sub = "goodbye"
+ sub.force_encoding(Encoding::US_ASCII)
+
+ result = s.bytesplice(3, 3, sub, 0, 3)
+ result.should == "こgooにちは"
+ result.encoding.should == Encoding::UTF_8
+
+ s = "hello"
+ s.force_encoding(Encoding::US_ASCII)
+ sub = "こんにちは"
+ sub.encoding.should == Encoding::UTF_8
+
+ result = s.bytesplice(1, 2, sub, 3, 3)
+ result.should == "hんlo"
+ result.encoding.should == Encoding::UTF_8
+ end
+
+ it "deals with a different encoded argument with str range" do
+ s = "こんにちは"
+ s.encoding.should == Encoding::UTF_8
+ sub = "goodbye"
+ sub.force_encoding(Encoding::US_ASCII)
+
+ result = s.bytesplice(3..5, sub, 0..2)
+ result.should == "こgooにちは"
+ result.encoding.should == Encoding::UTF_8
+
+ s = "hello"
+ s.force_encoding(Encoding::US_ASCII)
+ sub = "こんにちは"
+ sub.encoding.should == Encoding::UTF_8
+
+ result = s.bytesplice(1..2, sub, 3..5)
+ result.should == "hんlo"
+ result.encoding.should == Encoding::UTF_8
+ end
+end
diff --git a/spec/ruby/core/string/capitalize_spec.rb b/spec/ruby/core/string/capitalize_spec.rb
index 751f4160a6..12b1675c2e 100644
--- a/spec/ruby/core/string/capitalize_spec.rb
+++ b/spec/ruby/core/string/capitalize_spec.rb
@@ -28,7 +28,7 @@ describe "String#capitalize" do
capitalized.should == "Sset"
capitalized.size.should == 4
capitalized.bytesize.should == 4
- capitalized.ascii_only?.should be_true
+ capitalized.ascii_only?.should == true
end
end
@@ -52,7 +52,7 @@ describe "String#capitalize" do
end
it "does not allow any other additional option" do
- -> { "iSa".capitalize(:turkic, :ascii) }.should raise_error(ArgumentError)
+ -> { "iSa".capitalize(:turkic, :ascii) }.should.raise(ArgumentError)
end
end
@@ -66,37 +66,32 @@ describe "String#capitalize" do
end
it "does not allow any other additional option" do
- -> { "iß".capitalize(:lithuanian, :ascii) }.should raise_error(ArgumentError)
+ -> { "iß".capitalize(:lithuanian, :ascii) }.should.raise(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
- -> { "abc".capitalize(:fold) }.should raise_error(ArgumentError)
+ -> { "abc".capitalize(:fold) }.should.raise(ArgumentError)
end
it "does not allow invalid options" do
- -> { "abc".capitalize(:invalid_option) }.should raise_error(ArgumentError)
+ -> { "abc".capitalize(:invalid_option) }.should.raise(ArgumentError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").capitalize.should.instance_of?(String)
+ StringSpecs::MyString.new("Hello").capitalize.should.instance_of?(String)
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(String)
- StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(String)
- end
+ it "returns a String in the same encoding as self" do
+ "h".encode("US-ASCII").capitalize.encoding.should == Encoding::US_ASCII
end
end
describe "String#capitalize!" do
it "capitalizes self in place" do
- a = "hello"
- a.capitalize!.should equal(a)
+ a = +"hello"
+ a.capitalize!.should.equal?(a)
a.should == "Hello"
end
@@ -108,13 +103,13 @@ describe "String#capitalize!" do
describe "full Unicode case mapping" do
it "modifies self in place for all of Unicode with no option" do
- a = "äöÜ"
+ a = +"äöÜ"
a.capitalize!
a.should == "Äöü"
end
it "only capitalizes the first resulting character when upcasing a character produces a multi-character sequence" do
- a = "ß"
+ a = +"ß"
a.capitalize!
a.should == "Ss"
end
@@ -126,19 +121,19 @@ describe "String#capitalize!" do
end
it "updates string metadata" do
- capitalized = "ßeT"
+ capitalized = +"ßeT"
capitalized.capitalize!
capitalized.should == "Sset"
capitalized.size.should == 4
capitalized.bytesize.should == 4
- capitalized.ascii_only?.should be_true
+ capitalized.ascii_only?.should == true
end
end
describe "modifies self in place for ASCII-only case mapping" do
it "does not capitalize non-ASCII characters" do
- a = "ßet"
+ a = +"ßet"
a.capitalize!(:ascii)
a.should == "ßet"
end
@@ -152,61 +147,61 @@ describe "String#capitalize!" do
describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do
it "capitalizes ASCII characters according to Turkic semantics" do
- a = "iSa"
+ a = +"iSa"
a.capitalize!(:turkic)
a.should == "İsa"
end
it "allows Lithuanian as an extra option" do
- a = "iSa"
+ a = +"iSa"
a.capitalize!(:turkic, :lithuanian)
a.should == "İsa"
end
it "does not allow any other additional option" do
- -> { a = "iSa"; a.capitalize!(:turkic, :ascii) }.should raise_error(ArgumentError)
+ -> { a = "iSa"; a.capitalize!(:turkic, :ascii) }.should.raise(ArgumentError)
end
end
describe "modifies self in place for full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
- a = "iß"
+ a = +"iß"
a.capitalize!(:lithuanian)
a.should == "Iß"
end
it "allows Turkic as an extra option (and applies Turkic semantics)" do
- a = "iß"
+ a = +"iß"
a.capitalize!(:lithuanian, :turkic)
a.should == "İß"
end
it "does not allow any other additional option" do
- -> { a = "iß"; a.capitalize!(:lithuanian, :ascii) }.should raise_error(ArgumentError)
+ -> { a = "iß"; a.capitalize!(:lithuanian, :ascii) }.should.raise(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
- -> { a = "abc"; a.capitalize!(:fold) }.should raise_error(ArgumentError)
+ -> { a = "abc"; a.capitalize!(:fold) }.should.raise(ArgumentError)
end
it "does not allow invalid options" do
- -> { a = "abc"; a.capitalize!(:invalid_option) }.should raise_error(ArgumentError)
+ -> { a = "abc"; a.capitalize!(:invalid_option) }.should.raise(ArgumentError)
end
it "returns nil when no changes are made" do
- a = "Hello"
+ a = +"Hello"
a.capitalize!.should == nil
a.should == "Hello"
- "".capitalize!.should == nil
- "H".capitalize!.should == nil
+ (+"").capitalize!.should == nil
+ (+"H").capitalize!.should == nil
end
it "raises a FrozenError when self is frozen" do
["", "Hello", "hello"].each do |a|
a.freeze
- -> { a.capitalize! }.should raise_error(FrozenError)
+ -> { a.capitalize! }.should.raise(FrozenError)
end
end
end
diff --git a/spec/ruby/core/string/casecmp_spec.rb b/spec/ruby/core/string/casecmp_spec.rb
index 986fbc8718..90577aaac0 100644
--- a/spec/ruby/core/string/casecmp_spec.rb
+++ b/spec/ruby/core/string/casecmp_spec.rb
@@ -26,11 +26,11 @@ describe "String#casecmp independent of case" do
end
it "returns nil if other can't be converted to a string" do
- "abc".casecmp(mock('abc')).should be_nil
+ "abc".casecmp(mock('abc')).should == nil
end
it "returns nil if incompatible encodings" do
- "あれ".casecmp("れ".encode(Encoding::EUC_JP)).should be_nil
+ "あれ".casecmp("れ".encode(Encoding::EUC_JP)).should == nil
end
describe "in UTF-8 mode" do
@@ -117,6 +117,11 @@ describe "String#casecmp independent of case" do
"B".casecmp(a).should == 1
end
end
+
+ it "returns 0 for empty strings in different encodings" do
+ ''.b.casecmp('').should == 0
+ ''.b.casecmp(''.encode("UTF-32LE")).should == 0
+ end
end
describe 'String#casecmp? independent of case' do
@@ -138,7 +143,7 @@ describe 'String#casecmp? independent of case' do
end
it "returns nil if incompatible encodings" do
- "あれ".casecmp?("れ".encode(Encoding::EUC_JP)).should be_nil
+ "あれ".casecmp?("れ".encode(Encoding::EUC_JP)).should == nil
end
describe 'for UNICODE characters' do
@@ -185,10 +190,15 @@ describe 'String#casecmp? independent of case' do
end
it "case folds" do
- "ß".casecmp?("ss").should be_true
+ "ß".casecmp?("ss").should == true
end
it "returns nil if other can't be converted to a string" do
- "abc".casecmp?(mock('abc')).should be_nil
+ "abc".casecmp?(mock('abc')).should == nil
+ end
+
+ it "returns true for empty strings in different encodings" do
+ ''.b.should.casecmp?('')
+ ''.b.should.casecmp?(''.encode("UTF-32LE"))
end
end
diff --git a/spec/ruby/core/string/center_spec.rb b/spec/ruby/core/string/center_spec.rb
index 76da6e1e09..ac5b8a2ff3 100644
--- a/spec/ruby/core/string/center_spec.rb
+++ b/spec/ruby/core/string/center_spec.rb
@@ -57,10 +57,10 @@ describe "String#center with length, padding" do
end
it "raises a TypeError when length can't be converted to an integer" do
- -> { "hello".center("x") }.should raise_error(TypeError)
- -> { "hello".center("x", "y") }.should raise_error(TypeError)
- -> { "hello".center([]) }.should raise_error(TypeError)
- -> { "hello".center(mock('x')) }.should raise_error(TypeError)
+ -> { "hello".center("x") }.should.raise(TypeError)
+ -> { "hello".center("x", "y") }.should.raise(TypeError)
+ -> { "hello".center([]) }.should.raise(TypeError)
+ -> { "hello".center(mock('x')) }.should.raise(TypeError)
end
it "calls #to_str to convert padstr to a String" do
@@ -71,60 +71,47 @@ describe "String#center with length, padding" do
end
it "raises a TypeError when padstr can't be converted to a string" do
- -> { "hello".center(20, 100) }.should raise_error(TypeError)
- -> { "hello".center(20, []) }.should raise_error(TypeError)
- -> { "hello".center(20, mock('x')) }.should raise_error(TypeError)
+ -> { "hello".center(20, 100) }.should.raise(TypeError)
+ -> { "hello".center(20, []) }.should.raise(TypeError)
+ -> { "hello".center(20, mock('x')) }.should.raise(TypeError)
end
it "raises an ArgumentError if padstr is empty" do
- -> { "hello".center(10, "") }.should raise_error(ArgumentError)
- -> { "hello".center(0, "") }.should raise_error(ArgumentError)
+ -> { "hello".center(10, "") }.should.raise(ArgumentError)
+ -> { "hello".center(0, "") }.should.raise(ArgumentError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on subclasses" do
- StringSpecs::MyString.new("").center(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString)
+ it "returns String instances when called on subclasses" do
+ StringSpecs::MyString.new("").center(10).should.instance_of?(String)
+ StringSpecs::MyString.new("foo").center(10).should.instance_of?(String)
+ StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should.instance_of?(String)
- "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances when called on subclasses" do
- StringSpecs::MyString.new("").center(10).should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
-
- "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- end
+ "".center(10, StringSpecs::MyString.new("x")).should.instance_of?(String)
+ "foo".center(10, StringSpecs::MyString.new("x")).should.instance_of?(String)
end
describe "with width" do
it "returns a String in the same encoding as the original" do
- str = "abc".force_encoding Encoding::IBM437
+ str = "abc".dup.force_encoding Encoding::IBM437
result = str.center 6
result.should == " abc "
- result.encoding.should equal(Encoding::IBM437)
+ result.encoding.should.equal?(Encoding::IBM437)
end
end
describe "with width, pattern" do
it "returns a String in the compatible encoding" do
- str = "abc".force_encoding Encoding::IBM437
+ str = "abc".dup.force_encoding Encoding::IBM437
result = str.center 6, "あ"
result.should == "あabcああ"
- result.encoding.should equal(Encoding::UTF_8)
+ result.encoding.should.equal?(Encoding::UTF_8)
end
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
pat = "ア".encode Encoding::EUC_JP
-> do
"あれ".center 5, pat
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError)
end
end
end
diff --git a/spec/ruby/core/string/chars_spec.rb b/spec/ruby/core/string/chars_spec.rb
index e4f26bc0cc..ee85430574 100644
--- a/spec/ruby/core/string/chars_spec.rb
+++ b/spec/ruby/core/string/chars_spec.rb
@@ -1,5 +1,5 @@
+require_relative "../../spec_helper"
require_relative 'shared/chars'
-require_relative 'shared/each_char_without_block'
describe "String#chars" do
it_behaves_like :string_chars, :chars
@@ -7,4 +7,10 @@ describe "String#chars" do
it "returns an array when no block given" do
"hello".chars.should == ['h', 'e', 'l', 'l', 'o']
end
+
+ it "returns Strings in the same encoding as self" do
+ "hello".encode("US-ASCII").chars.each do |c|
+ c.encoding.should == Encoding::US_ASCII
+ end
+ end
end
diff --git a/spec/ruby/core/string/chilled_string_spec.rb b/spec/ruby/core/string/chilled_string_spec.rb
new file mode 100644
index 0000000000..6a5e846db2
--- /dev/null
+++ b/spec/ruby/core/string/chilled_string_spec.rb
@@ -0,0 +1,151 @@
+require_relative '../../spec_helper'
+
+describe "chilled String" do
+ guard -> { ruby_version_is "3.4" and !"test".equal?("test") } do
+ describe "chilled string literals" do
+
+ describe "#frozen?" do
+ it "returns false" do
+ "chilled".frozen?.should == false
+ end
+ end
+
+ describe "#-@" do
+ it "returns a different instance" do
+ input = "chilled"
+ interned = (-input)
+ interned.frozen?.should == true
+ interned.object_id.should_not == input.object_id
+ end
+ end
+
+ describe "#+@" do
+ it "returns a different instance" do
+ input = "chilled"
+ duped = (+input)
+ duped.frozen?.should == false
+ duped.object_id.should_not == input.object_id
+ end
+ end
+
+ describe "#clone" do
+ it "preserves chilled status" do
+ input = "chilled".clone
+ -> {
+ input << "-mutated"
+ }.should complain(/literal string will be frozen in the future/)
+ input.should == "chilled-mutated"
+ end
+ end
+
+ describe "mutation" do
+ it "emits a warning" do
+ input = "chilled"
+ -> {
+ input << "-mutated"
+ }.should complain(/literal string will be frozen in the future/)
+ input.should == "chilled-mutated"
+ end
+
+ it "emits a warning for concatenated strings" do
+ input = "still" "+chilled"
+ -> {
+ input << "-mutated"
+ }.should complain(/literal string will be frozen in the future/)
+ input.should == "still+chilled-mutated"
+ end
+
+ it "emits a warning on singleton_class creation" do
+ -> {
+ "chilled".singleton_class
+ }.should complain(/literal string will be frozen in the future/)
+ end
+
+ it "emits a warning on instance variable assignment" do
+ -> {
+ "chilled".instance_variable_set(:@ivar, 42)
+ }.should complain(/literal string will be frozen in the future/)
+ end
+
+ it "raises FrozenError after the string was explicitly frozen" do
+ input = "chilled"
+ input.freeze
+ -> {
+ -> {
+ input << "mutated"
+ }.should.raise(FrozenError)
+ }.should_not complain(/literal string will be frozen in the future/)
+ end
+ end
+ end
+
+ describe "chilled strings returned by Symbol#to_s" do
+
+ describe "#frozen?" do
+ it "returns false" do
+ :chilled.to_s.frozen?.should == false
+ end
+ end
+
+ describe "#-@" do
+ it "returns a different instance" do
+ input = :chilled.to_s
+ interned = (-input)
+ interned.frozen?.should == true
+ interned.object_id.should_not == input.object_id
+ end
+ end
+
+ describe "#+@" do
+ it "returns a different instance" do
+ input = :chilled.to_s
+ duped = (+input)
+ duped.frozen?.should == false
+ duped.object_id.should_not == input.object_id
+ end
+ end
+
+ describe "#clone" do
+ it "preserves chilled status" do
+ input = :chilled.to_s.clone
+ -> {
+ input << "-mutated"
+ }.should complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ input.should == "chilled-mutated"
+ end
+ end
+
+ describe "mutation" do
+ it "emits a warning" do
+ input = :chilled.to_s
+ -> {
+ input << "-mutated"
+ }.should complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ input.should == "chilled-mutated"
+ end
+
+ it "emits a warning on singleton_class creation" do
+ -> {
+ :chilled.to_s.singleton_class
+ }.should complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ end
+
+ it "emits a warning on instance variable assignment" do
+ -> {
+ :chilled.to_s.instance_variable_set(:@ivar, 42)
+ }.should complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ end
+
+ it "raises FrozenError after the string was explicitly frozen" do
+ input = :chilled.to_s
+ input.freeze
+ -> {
+ -> {
+ input << "mutated"
+ }.should.raise(FrozenError)
+ }.should_not complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/string/chomp_spec.rb b/spec/ruby/core/string/chomp_spec.rb
index c03bfc7951..3a8550892f 100644
--- a/spec/ruby/core/string/chomp_spec.rb
+++ b/spec/ruby/core/string/chomp_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -21,7 +22,7 @@ describe "String#chomp" do
it "returns a copy of the String when it is not modified" do
str = "abc"
- str.chomp.should_not equal(str)
+ str.chomp.should_not.equal?(str)
end
it "removes one trailing newline" do
@@ -40,18 +41,13 @@ describe "String#chomp" do
"".chomp.should == ""
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- str = StringSpecs::MyString.new("hello\n").chomp
- str.should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns a String in the same encoding as self" do
+ "abc\n\n".encode("US-ASCII").chomp.encoding.should == Encoding::US_ASCII
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- str = StringSpecs::MyString.new("hello\n").chomp
- str.should be_an_instance_of(String)
- end
+ it "returns String instances when called on a subclass" do
+ str = StringSpecs::MyString.new("hello\n").chomp
+ str.should.instance_of?(String)
end
it "removes trailing characters that match $/ when it has been assigned a value" do
@@ -71,7 +67,7 @@ describe "String#chomp" do
it "returns a copy of the String" do
str = "abc"
- str.chomp(nil).should_not equal(str)
+ str.chomp(nil).should_not.equal?(str)
end
it "returns an empty String when self is empty" do
@@ -137,7 +133,7 @@ describe "String#chomp" do
it "raises a TypeError if #to_str does not return a String" do
arg = mock("string chomp")
arg.should_receive(:to_str).and_return(1)
- -> { "abc".chomp(arg) }.should raise_error(TypeError)
+ -> { "abc".chomp(arg) }.should.raise(TypeError)
end
end
@@ -175,11 +171,11 @@ describe "String#chomp!" do
it "modifies self" do
str = "abc\n"
- str.chomp!.should equal(str)
+ str.chomp!.should.equal?(str)
end
it "returns nil if self is not modified" do
- "abc".chomp!.should be_nil
+ "abc".chomp!.should == nil
end
it "removes one trailing newline" do
@@ -195,12 +191,12 @@ describe "String#chomp!" do
end
it "returns nil when self is empty" do
- "".chomp!.should be_nil
+ "".chomp!.should == nil
end
it "returns subclass instances when called on a subclass" do
str = StringSpecs::MyString.new("hello\n").chomp!
- str.should be_an_instance_of(StringSpecs::MyString)
+ str.should.instance_of?(StringSpecs::MyString)
end
it "removes trailing characters that match $/ when it has been assigned a value" do
@@ -211,11 +207,11 @@ describe "String#chomp!" do
describe "when passed nil" do
it "returns nil" do
- "abc\r\n".chomp!(nil).should be_nil
+ "abc\r\n".chomp!(nil).should == nil
end
it "returns nil when self is empty" do
- "".chomp!(nil).should be_nil
+ "".chomp!(nil).should == nil
end
end
@@ -229,7 +225,7 @@ describe "String#chomp!" do
end
it "does not remove a final carriage return" do
- "abc\r".chomp!("").should be_nil
+ "abc\r".chomp!("").should == nil
end
it "removes more than one trailing newlines" do
@@ -241,7 +237,7 @@ describe "String#chomp!" do
end
it "returns nil when self is empty" do
- "".chomp!("").should be_nil
+ "".chomp!("").should == nil
end
end
@@ -259,7 +255,7 @@ describe "String#chomp!" do
end
it "returns nil when self is empty" do
- "".chomp!("\n").should be_nil
+ "".chomp!("\n").should == nil
end
end
@@ -273,7 +269,7 @@ describe "String#chomp!" do
it "raises a TypeError if #to_str does not return a String" do
arg = mock("string chomp")
arg.should_receive(:to_str).and_return(1)
- -> { "abc".chomp!(arg) }.should raise_error(TypeError)
+ -> { "abc".chomp!(arg) }.should.raise(TypeError)
end
end
@@ -283,11 +279,11 @@ describe "String#chomp!" do
end
it "returns nil if the argument does not match the trailing characters" do
- "abc".chomp!("def").should be_nil
+ "abc".chomp!("def").should == nil
end
it "returns nil when self is empty" do
- "".chomp!("abc").should be_nil
+ "".chomp!("abc").should == nil
end
end
@@ -295,15 +291,15 @@ describe "String#chomp!" do
a = "string\n\r"
a.freeze
- -> { a.chomp! }.should raise_error(FrozenError)
+ -> { a.chomp! }.should.raise(FrozenError)
end
# see [ruby-core:23666]
it "raises a FrozenError on a frozen instance when it would not be modified" do
a = "string\n\r"
a.freeze
- -> { a.chomp!(nil) }.should raise_error(FrozenError)
- -> { a.chomp!("x") }.should raise_error(FrozenError)
+ -> { a.chomp!(nil) }.should.raise(FrozenError)
+ -> { a.chomp!("x") }.should.raise(FrozenError)
end
end
@@ -350,7 +346,7 @@ describe "String#chomp!" do
end
it "returns nil when the String is not modified" do
- "あれ".chomp!.should be_nil
+ "あれ".chomp!.should == nil
end
it "removes the final carriage return, newline from a multibyte String" do
diff --git a/spec/ruby/core/string/chop_spec.rb b/spec/ruby/core/string/chop_spec.rb
index 266d973f67..2113da543b 100644
--- a/spec/ruby/core/string/chop_spec.rb
+++ b/spec/ruby/core/string/chop_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -46,19 +47,15 @@ describe "String#chop" do
it "returns a new string when applied to an empty string" do
s = ""
- s.chop.should_not equal(s)
+ s.chop.should_not.equal?(s)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("hello\n").chop.should.instance_of?(String)
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(String)
- end
+ it "returns a String in the same encoding as self" do
+ "abc\n\n".encode("US-ASCII").chop.encoding.should == Encoding::US_ASCII
end
end
@@ -102,21 +99,21 @@ describe "String#chop!" do
it "returns self if modifications were made" do
str = "hello"
- str.chop!.should equal(str)
+ str.chop!.should.equal?(str)
end
it "returns nil when called on an empty string" do
- "".chop!.should be_nil
+ "".chop!.should == nil
end
it "raises a FrozenError on a frozen instance that is modified" do
- -> { "string\n\r".freeze.chop! }.should raise_error(FrozenError)
+ -> { "string\n\r".freeze.chop! }.should.raise(FrozenError)
end
# see [ruby-core:23666]
it "raises a FrozenError on a frozen instance that would not be modified" do
a = ""
a.freeze
- -> { a.chop! }.should raise_error(FrozenError)
+ -> { a.chop! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/chr_spec.rb b/spec/ruby/core/string/chr_spec.rb
index 9ed29542e6..26c7d51202 100644
--- a/spec/ruby/core/string/chr_spec.rb
+++ b/spec/ruby/core/string/chr_spec.rb
@@ -3,11 +3,11 @@ require_relative '../../spec_helper'
describe "String#chr" do
it "returns a copy of self" do
s = 'e'
- s.should_not equal s.chr
+ s.should_not.equal? s.chr
end
it "returns a String" do
- 'glark'.chr.should be_an_instance_of(String)
+ 'glark'.chr.should.instance_of?(String)
end
it "returns an empty String if self is an empty String" do
diff --git a/spec/ruby/core/string/clear_spec.rb b/spec/ruby/core/string/clear_spec.rb
index e1d68e03bd..d4688d3689 100644
--- a/spec/ruby/core/string/clear_spec.rb
+++ b/spec/ruby/core/string/clear_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe "String#clear" do
@@ -13,7 +14,7 @@ describe "String#clear" do
it "returns self after emptying it" do
cleared = @s.clear
cleared.should == ""
- cleared.should equal @s
+ cleared.should.equal? @s
end
it "preserves its encoding" do
@@ -31,7 +32,7 @@ describe "String#clear" do
it "raises a FrozenError if self is frozen" do
@s.freeze
- -> { @s.clear }.should raise_error(FrozenError)
- -> { "".freeze.clear }.should raise_error(FrozenError)
+ -> { @s.clear }.should.raise(FrozenError)
+ -> { "".freeze.clear }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/clone_spec.rb b/spec/ruby/core/string/clone_spec.rb
index f8d40423f0..2cb289d2c1 100644
--- a/spec/ruby/core/string/clone_spec.rb
+++ b/spec/ruby/core/string/clone_spec.rb
@@ -43,8 +43,8 @@ describe "String#clone" do
end
it "copies frozen state" do
- @obj.freeze.clone.frozen?.should be_true
- "".freeze.clone.frozen?.should be_true
+ @obj.freeze.clone.frozen?.should == true
+ "".freeze.clone.frozen?.should == true
end
it "does not modify the original string when changing cloned string" do
@@ -54,4 +54,8 @@ describe "String#clone" do
orig.should == "xtring"
clone.should == "string"
end
+
+ it "returns a String in the same encoding as self" do
+ "a".encode("US-ASCII").clone.encoding.should == Encoding::US_ASCII
+ end
end
diff --git a/spec/ruby/core/string/codepoints_spec.rb b/spec/ruby/core/string/codepoints_spec.rb
index 0b6cde82f7..51bd57d127 100644
--- a/spec/ruby/core/string/codepoints_spec.rb
+++ b/spec/ruby/core/string/codepoints_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/codepoints'
require_relative 'shared/each_codepoint_without_block'
@@ -11,8 +11,8 @@ describe "String#codepoints" do
end
it "raises an ArgumentError when no block is given if self has an invalid encoding" do
- s = "\xDF".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.codepoints }.should raise_error(ArgumentError)
+ s = "\xDF".dup.force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should == false
+ -> { s.codepoints }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/comparison_spec.rb b/spec/ruby/core/string/comparison_spec.rb
index 91cfdca25a..0737c131bb 100644
--- a/spec/ruby/core/string/comparison_spec.rb
+++ b/spec/ruby/core/string/comparison_spec.rb
@@ -61,12 +61,12 @@ describe "String#<=> with String" do
end
it "ignores encoding difference" do
- ("ÄÖÛ".force_encoding("utf-8") <=> "ÄÖÜ".force_encoding("iso-8859-1")).should == -1
- ("ÄÖÜ".force_encoding("utf-8") <=> "ÄÖÛ".force_encoding("iso-8859-1")).should == 1
+ ("ÄÖÛ".dup.force_encoding("utf-8") <=> "ÄÖÜ".dup.force_encoding("iso-8859-1")).should == -1
+ ("ÄÖÜ".dup.force_encoding("utf-8") <=> "ÄÖÛ".dup.force_encoding("iso-8859-1")).should == 1
end
it "returns 0 with identical ASCII-compatible bytes of different encodings" do
- ("abc".force_encoding("utf-8") <=> "abc".force_encoding("iso-8859-1")).should == 0
+ ("abc".dup.force_encoding("utf-8") <=> "abc".dup.force_encoding("iso-8859-1")).should == 0
end
it "compares the indices of the encodings when the strings have identical non-ASCII-compatible bytes" do
@@ -77,7 +77,7 @@ describe "String#<=> with String" do
end
it "returns 0 when comparing 2 empty strings but one is not ASCII-compatible" do
- ("" <=> "".force_encoding('iso-2022-jp')).should == 0
+ ("" <=> "".dup.force_encoding('iso-2022-jp')).should == 0
end
end
@@ -85,7 +85,7 @@ end
# just using it as an indicator.
describe "String#<=>" do
it "returns nil if its argument provides neither #to_str nor #<=>" do
- ("abc" <=> mock('x')).should be_nil
+ ("abc" <=> mock('x')).should == nil
end
it "uses the result of calling #to_str for comparison when #to_str is defined" do
@@ -107,6 +107,6 @@ describe "String#<=>" do
def obj.<=>(other); other <=> self; end
obj.should_receive(:<=>).once
- ("abc" <=> obj).should be_nil
+ ("abc" <=> obj).should == nil
end
end
diff --git a/spec/ruby/core/string/concat_spec.rb b/spec/ruby/core/string/concat_spec.rb
index 5f6daadad7..0194a357a0 100644
--- a/spec/ruby/core/string/concat_spec.rb
+++ b/spec/ruby/core/string/concat_spec.rb
@@ -5,22 +5,23 @@ require_relative 'shared/concat'
describe "String#concat" do
it_behaves_like :string_concat, :concat
it_behaves_like :string_concat_encoding, :concat
+ it_behaves_like :string_concat_type_coercion, :concat
it "takes multiple arguments" do
- str = "hello "
+ str = +"hello "
str.concat "wo", "", "rld"
str.should == "hello world"
end
it "concatenates the initial value when given arguments contain 2 self" do
- str = "hello"
+ str = +"hello"
str.concat str, str
str.should == "hellohellohello"
end
it "returns self when given no arguments" do
- str = "hello"
- str.concat.should equal(str)
+ str = +"hello"
+ str.concat.should.equal?(str)
str.should == "hello"
end
end
diff --git a/spec/ruby/core/string/count_spec.rb b/spec/ruby/core/string/count_spec.rb
index 06ba5a4f0e..fd127c6ff2 100644
--- a/spec/ruby/core/string/count_spec.rb
+++ b/spec/ruby/core/string/count_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -23,7 +23,7 @@ describe "String#count" do
end
it "raises an ArgumentError when given no arguments" do
- -> { "hell yeah".count }.should raise_error(ArgumentError)
+ -> { "hell yeah".count }.should.raise(ArgumentError)
end
it "negates sets starting with ^" do
@@ -76,8 +76,8 @@ describe "String#count" do
it "raises if the given sequences are invalid" do
s = "hel-[()]-lo012^"
- -> { s.count("h-e") }.should raise_error(ArgumentError)
- -> { s.count("^h-e") }.should raise_error(ArgumentError)
+ -> { s.count("h-e") }.should.raise(ArgumentError)
+ -> { s.count("^h-e") }.should.raise(ArgumentError)
end
it 'returns the number of occurrences of a multi-byte character' do
@@ -98,8 +98,8 @@ describe "String#count" do
end
it "raises a TypeError when a set arg can't be converted to a string" do
- -> { "hello world".count(100) }.should raise_error(TypeError)
- -> { "hello world".count([]) }.should raise_error(TypeError)
- -> { "hello world".count(mock('x')) }.should raise_error(TypeError)
+ -> { "hello world".count(100) }.should.raise(TypeError)
+ -> { "hello world".count([]) }.should.raise(TypeError)
+ -> { "hello world".count(mock('x')) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/string/crypt_spec.rb b/spec/ruby/core/string/crypt_spec.rb
index 06f84c70a4..924b4d48cf 100644
--- a/spec/ruby/core/string/crypt_spec.rb
+++ b/spec/ruby/core/string/crypt_spec.rb
@@ -15,7 +15,7 @@ describe "String#crypt" do
end
it "raises Errno::EINVAL when the salt is shorter than 29 characters" do
- -> { "mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHW") }.should raise_error(Errno::EINVAL)
+ -> { "mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHW") }.should.raise(Errno::EINVAL)
end
it "calls #to_str to converts the salt arg to a String" do
@@ -26,9 +26,9 @@ describe "String#crypt" do
end
it "doesn't return subclass instances" do
- StringSpecs::MyString.new("mypassword").crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should be_an_instance_of(String)
- "mypassword".crypt(StringSpecs::MyString.new("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu")).should be_an_instance_of(String)
- StringSpecs::MyString.new("mypassword").crypt(StringSpecs::MyString.new("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu")).should be_an_instance_of(String)
+ StringSpecs::MyString.new("mypassword").crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should.instance_of?(String)
+ "mypassword".crypt(StringSpecs::MyString.new("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu")).should.instance_of?(String)
+ StringSpecs::MyString.new("mypassword").crypt(StringSpecs::MyString.new("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu")).should.instance_of?(String)
end
end
@@ -60,7 +60,7 @@ describe "String#crypt" do
end
it "raises an ArgumentError when the string contains NUL character" do
- -> { "poison\0null".crypt("aa") }.should raise_error(ArgumentError)
+ -> { "poison\0null".crypt("aa") }.should.raise(ArgumentError)
end
it "calls #to_str to converts the salt arg to a String" do
@@ -71,22 +71,22 @@ describe "String#crypt" do
end
it "doesn't return subclass instances" do
- StringSpecs::MyString.new("hello").crypt("aa").should be_an_instance_of(String)
- "hello".crypt(StringSpecs::MyString.new("aa")).should be_an_instance_of(String)
- StringSpecs::MyString.new("hello").crypt(StringSpecs::MyString.new("aa")).should be_an_instance_of(String)
+ StringSpecs::MyString.new("hello").crypt("aa").should.instance_of?(String)
+ "hello".crypt(StringSpecs::MyString.new("aa")).should.instance_of?(String)
+ StringSpecs::MyString.new("hello").crypt(StringSpecs::MyString.new("aa")).should.instance_of?(String)
end
it "raises an ArgumentError when the salt is shorter than two characters" do
- -> { "hello".crypt("") }.should raise_error(ArgumentError)
- -> { "hello".crypt("f") }.should raise_error(ArgumentError)
- -> { "hello".crypt("\x00\x00") }.should raise_error(ArgumentError)
- -> { "hello".crypt("\x00a") }.should raise_error(ArgumentError)
- -> { "hello".crypt("a\x00") }.should raise_error(ArgumentError)
+ -> { "hello".crypt("") }.should.raise(ArgumentError)
+ -> { "hello".crypt("f") }.should.raise(ArgumentError)
+ -> { "hello".crypt("\x00\x00") }.should.raise(ArgumentError)
+ -> { "hello".crypt("\x00a") }.should.raise(ArgumentError)
+ -> { "hello".crypt("a\x00") }.should.raise(ArgumentError)
end
end
it "raises a type error when the salt arg can't be converted to a string" do
- -> { "".crypt(5) }.should raise_error(TypeError)
- -> { "".crypt(mock('x')) }.should raise_error(TypeError)
+ -> { "".crypt(5) }.should.raise(TypeError)
+ -> { "".crypt(mock('x')) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/string/dedup_spec.rb b/spec/ruby/core/string/dedup_spec.rb
index 919d440c51..2b31d80708 100644
--- a/spec/ruby/core/string/dedup_spec.rb
+++ b/spec/ruby/core/string/dedup_spec.rb
@@ -2,7 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/dedup'
describe 'String#dedup' do
- ruby_version_is '3.2'do
- it_behaves_like :string_dedup, :dedup
- end
+ it_behaves_like :string_dedup, :dedup
end
diff --git a/spec/ruby/core/string/delete_prefix_spec.rb b/spec/ruby/core/string/delete_prefix_spec.rb
index 17ce18bcca..fc69adcbad 100644
--- a/spec/ruby/core/string/delete_prefix_spec.rb
+++ b/spec/ruby/core/string/delete_prefix_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -11,13 +12,13 @@ describe "String#delete_prefix" do
it "returns a copy of the string, when the prefix isn't found" do
s = 'hello'
r = s.delete_prefix('hello!')
- r.should_not equal s
+ r.should_not.equal? s
r.should == s
r = s.delete_prefix('ell')
- r.should_not equal s
+ r.should_not.equal? s
r.should == s
r = s.delete_prefix('')
- r.should_not equal s
+ r.should_not.equal? s
r.should == s
end
@@ -38,25 +39,20 @@ describe "String#delete_prefix" do
'hello'.delete_prefix(o).should == 'o'
end
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance when called on a subclass instance" do
- s = StringSpecs::MyString.new('hello')
- s.delete_prefix('hell').should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns a String instance when called on a subclass instance" do
+ s = StringSpecs::MyString.new('hello')
+ s.delete_prefix('hell').should.instance_of?(String)
end
- ruby_version_is '3.0' do
- it "returns a String instance when called on a subclass instance" do
- s = StringSpecs::MyString.new('hello')
- s.delete_prefix('hell').should be_an_instance_of(String)
- end
+ it "returns a String in the same encoding as self" do
+ 'hello'.encode("US-ASCII").delete_prefix('hell').encoding.should == Encoding::US_ASCII
end
end
describe "String#delete_prefix!" do
it "removes the found prefix" do
s = 'hello'
- s.delete_prefix!('hell').should equal(s)
+ s.delete_prefix!('hell').should.equal?(s)
s.should == 'o'
end
@@ -80,8 +76,8 @@ describe "String#delete_prefix!" do
end
it "raises a FrozenError when self is frozen" do
- -> { 'hello'.freeze.delete_prefix!('hell') }.should raise_error(FrozenError)
- -> { 'hello'.freeze.delete_prefix!('') }.should raise_error(FrozenError)
- -> { ''.freeze.delete_prefix!('') }.should raise_error(FrozenError)
+ -> { 'hello'.freeze.delete_prefix!('hell') }.should.raise(FrozenError)
+ -> { 'hello'.freeze.delete_prefix!('') }.should.raise(FrozenError)
+ -> { ''.freeze.delete_prefix!('') }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/delete_spec.rb b/spec/ruby/core/string/delete_spec.rb
index b91e88b76f..adb5150cff 100644
--- a/spec/ruby/core/string/delete_spec.rb
+++ b/spec/ruby/core/string/delete_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -14,7 +15,7 @@ describe "String#delete" do
end
it "raises an ArgumentError when given no arguments" do
- -> { "hell yeah".delete }.should raise_error(ArgumentError)
+ -> { "hell yeah".delete }.should.raise(ArgumentError)
end
it "negates sets starting with ^" do
@@ -62,10 +63,10 @@ describe "String#delete" do
not_supported_on :opal do
xFF = [0xFF].pack('C')
range = "\x00 - #{xFF}".force_encoding('utf-8')
- -> { "hello".delete(range).should == "" }.should raise_error(ArgumentError)
+ -> { "hello".delete(range).should == "" }.should.raise(ArgumentError)
end
- -> { "hello".delete("h-e") }.should raise_error(ArgumentError)
- -> { "hello".delete("^h-e") }.should raise_error(ArgumentError)
+ -> { "hello".delete("h-e") }.should.raise(ArgumentError)
+ -> { "hello".delete("^h-e") }.should.raise(ArgumentError)
end
it "tries to convert each set arg to a string using to_str" do
@@ -79,28 +80,24 @@ describe "String#delete" do
end
it "raises a TypeError when one set arg can't be converted to a string" do
- -> { "hello world".delete(100) }.should raise_error(TypeError)
- -> { "hello world".delete([]) }.should raise_error(TypeError)
- -> { "hello world".delete(mock('x')) }.should raise_error(TypeError)
+ -> { "hello world".delete(100) }.should.raise(TypeError)
+ -> { "hello world".delete([]) }.should.raise(TypeError)
+ -> { "hello world".delete(mock('x')) }.should.raise(TypeError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("oh no!!!").delete("!").should.instance_of?(String)
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(String)
- end
+ it "returns a String in the same encoding as self" do
+ "hello".encode("US-ASCII").delete("lo").encoding.should == Encoding::US_ASCII
end
end
describe "String#delete!" do
it "modifies self in place and returns self" do
a = "hello"
- a.delete!("aeiou", "^e").should equal(a)
+ a.delete!("aeiou", "^e").should.equal?(a)
a.should == "hell"
end
@@ -114,7 +111,7 @@ describe "String#delete!" do
a = "hello"
a.freeze
- -> { a.delete!("") }.should raise_error(FrozenError)
- -> { a.delete!("aeiou", "^e") }.should raise_error(FrozenError)
+ -> { a.delete!("") }.should.raise(FrozenError)
+ -> { a.delete!("aeiou", "^e") }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/delete_suffix_spec.rb b/spec/ruby/core/string/delete_suffix_spec.rb
index 0705c73246..11d8fbbac1 100644
--- a/spec/ruby/core/string/delete_suffix_spec.rb
+++ b/spec/ruby/core/string/delete_suffix_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -11,13 +12,13 @@ describe "String#delete_suffix" do
it "returns a copy of the string, when the suffix isn't found" do
s = 'hello'
r = s.delete_suffix('!hello')
- r.should_not equal s
+ r.should_not.equal? s
r.should == s
r = s.delete_suffix('ell')
- r.should_not equal s
+ r.should_not.equal? s
r.should == s
r = s.delete_suffix('')
- r.should_not equal s
+ r.should_not.equal? s
r.should == s
end
@@ -38,25 +39,20 @@ describe "String#delete_suffix" do
'hello'.delete_suffix(o).should == 'h'
end
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance when called on a subclass instance" do
- s = StringSpecs::MyString.new('hello')
- s.delete_suffix('ello').should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns a String instance when called on a subclass instance" do
+ s = StringSpecs::MyString.new('hello')
+ s.delete_suffix('ello').should.instance_of?(String)
end
- ruby_version_is '3.0' do
- it "returns a String instance when called on a subclass instance" do
- s = StringSpecs::MyString.new('hello')
- s.delete_suffix('ello').should be_an_instance_of(String)
- end
+ it "returns a String in the same encoding as self" do
+ "hello".encode("US-ASCII").delete_suffix("ello").encoding.should == Encoding::US_ASCII
end
end
describe "String#delete_suffix!" do
it "removes the found prefix" do
s = 'hello'
- s.delete_suffix!('ello').should equal(s)
+ s.delete_suffix!('ello').should.equal?(s)
s.should == 'h'
end
@@ -80,8 +76,8 @@ describe "String#delete_suffix!" do
end
it "raises a FrozenError when self is frozen" do
- -> { 'hello'.freeze.delete_suffix!('ello') }.should raise_error(FrozenError)
- -> { 'hello'.freeze.delete_suffix!('') }.should raise_error(FrozenError)
- -> { ''.freeze.delete_suffix!('') }.should raise_error(FrozenError)
+ -> { 'hello'.freeze.delete_suffix!('ello') }.should.raise(FrozenError)
+ -> { 'hello'.freeze.delete_suffix!('') }.should.raise(FrozenError)
+ -> { ''.freeze.delete_suffix!('') }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/downcase_spec.rb b/spec/ruby/core/string/downcase_spec.rb
index f0a15f1e25..4f7f44e5d4 100644
--- a/spec/ruby/core/string/downcase_spec.rb
+++ b/spec/ruby/core/string/downcase_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -8,6 +9,10 @@ describe "String#downcase" do
"hello".downcase.should == "hello"
end
+ it "returns a String in the same encoding as self" do
+ "hELLO".encode("US-ASCII").downcase.encoding.should == Encoding::US_ASCII
+ end
+
describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do
"ÄÖÜ".downcase.should == "äöü"
@@ -19,7 +24,7 @@ describe "String#downcase" do
downcased.should == "king"
downcased.size.should == 4
downcased.bytesize.should == 4
- downcased.ascii_only?.should be_true
+ downcased.ascii_only?.should == true
end
end
@@ -43,7 +48,7 @@ describe "String#downcase" do
end
it "does not allow any other additional option" do
- -> { "İ".downcase(:turkic, :ascii) }.should raise_error(ArgumentError)
+ -> { "İ".downcase(:turkic, :ascii) }.should.raise(ArgumentError)
end
end
@@ -57,7 +62,7 @@ describe "String#downcase" do
end
it "does not allow any other additional option" do
- -> { "İS".downcase(:lithuanian, :ascii) }.should raise_error(ArgumentError)
+ -> { "İS".downcase(:lithuanian, :ascii) }.should.raise(ArgumentError)
end
end
@@ -69,26 +74,18 @@ describe "String#downcase" do
end
it "does not allow invalid options" do
- -> { "ABC".downcase(:invalid_option) }.should raise_error(ArgumentError)
- end
-
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance for subclasses" do
- StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(StringSpecs::MyString)
- end
+ -> { "ABC".downcase(:invalid_option) }.should.raise(ArgumentError)
end
- ruby_version_is '3.0' do
- it "returns a String instance for subclasses" do
- StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(String)
- end
+ it "returns a String instance for subclasses" do
+ StringSpecs::MyString.new("FOObar").downcase.should.instance_of?(String)
end
end
describe "String#downcase!" do
it "modifies self in place" do
a = "HeLlO"
- a.downcase!.should equal(a)
+ a.downcase!.should.equal?(a)
a.should == "hello"
end
@@ -112,7 +109,7 @@ describe "String#downcase!" do
downcased.should == "king"
downcased.size.should == 4
downcased.bytesize.should == 4
- downcased.ascii_only?.should be_true
+ downcased.ascii_only?.should == true
end
end
@@ -144,7 +141,7 @@ describe "String#downcase!" do
end
it "does not allow any other additional option" do
- -> { a = "İ"; a.downcase!(:turkic, :ascii) }.should raise_error(ArgumentError)
+ -> { a = "İ"; a.downcase!(:turkic, :ascii) }.should.raise(ArgumentError)
end
end
@@ -162,7 +159,7 @@ describe "String#downcase!" do
end
it "does not allow any other additional option" do
- -> { a = "İS"; a.downcase!(:lithuanian, :ascii) }.should raise_error(ArgumentError)
+ -> { a = "İS"; a.downcase!(:lithuanian, :ascii) }.should.raise(ArgumentError)
end
end
@@ -178,7 +175,7 @@ describe "String#downcase!" do
end
it "does not allow invalid options" do
- -> { a = "ABC"; a.downcase!(:invalid_option) }.should raise_error(ArgumentError)
+ -> { a = "ABC"; a.downcase!(:invalid_option) }.should.raise(ArgumentError)
end
it "returns nil if no modifications were made" do
@@ -188,11 +185,11 @@ describe "String#downcase!" do
end
it "raises a FrozenError when self is frozen" do
- -> { "HeLlo".freeze.downcase! }.should raise_error(FrozenError)
- -> { "hello".freeze.downcase! }.should raise_error(FrozenError)
+ -> { "HeLlo".freeze.downcase! }.should.raise(FrozenError)
+ -> { "hello".freeze.downcase! }.should.raise(FrozenError)
end
it "sets the result String encoding to the source String encoding" do
- "ABC".downcase.encoding.should equal(Encoding::UTF_8)
+ "ABC".downcase.encoding.should.equal?(Encoding::UTF_8)
end
end
diff --git a/spec/ruby/core/string/dump_spec.rb b/spec/ruby/core/string/dump_spec.rb
index 79a8b55e6d..176be79db2 100644
--- a/spec/ruby/core/string/dump_spec.rb
+++ b/spec/ruby/core/string/dump_spec.rb
@@ -7,16 +7,8 @@ describe "String#dump" do
"foo".freeze.dump.should_not.frozen?
end
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance" do
- StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns a String instance" do
- StringSpecs::MyString.new.dump.should be_an_instance_of(String)
- end
+ it "returns a String instance" do
+ StringSpecs::MyString.new.dump.should.instance_of?(String)
end
it "wraps string with \"" do
@@ -350,7 +342,7 @@ describe "String#dump" do
].should be_computed_by(:dump)
end
- it "returns a string with multi-byte UTF-8 characters replaced by \\u{} notation with upper-case hex digits" do
+ it "returns a string with multi-byte UTF-8 characters less than or equal 0xFFFF replaced by \\uXXXX notation with upper-case hex digits" do
[ [0200.chr('utf-8'), '"\u0080"'],
[0201.chr('utf-8'), '"\u0081"'],
[0202.chr('utf-8'), '"\u0082"'],
@@ -382,15 +374,21 @@ describe "String#dump" do
[0235.chr('utf-8'), '"\u009D"'],
[0236.chr('utf-8'), '"\u009E"'],
[0237.chr('utf-8'), '"\u009F"'],
+ [0177777.chr('utf-8'), '"\uFFFF"'],
].should be_computed_by(:dump)
end
+ it "returns a string with multi-byte UTF-8 characters greater than 0xFFFF replaced by \\u{XXXXXX} notation with upper-case hex digits" do
+ 0x10000.chr('utf-8').dump.should == '"\u{10000}"'
+ 0x10FFFF.chr('utf-8').dump.should == '"\u{10FFFF}"'
+ end
+
it "includes .force_encoding(name) if the encoding isn't ASCII compatible" do
"\u{876}".encode('utf-16be').dump.should.end_with?(".force_encoding(\"UTF-16BE\")")
"\u{876}".encode('utf-16le').dump.should.end_with?(".force_encoding(\"UTF-16LE\")")
end
- it "keeps origin encoding" do
+ it "returns a String in the same encoding as self" do
"foo".encode("ISO-8859-1").dump.encoding.should == Encoding::ISO_8859_1
"foo".encode('windows-1251').dump.encoding.should == Encoding::Windows_1251
1.chr.dump.encoding.should == Encoding::US_ASCII
diff --git a/spec/ruby/core/string/dup_spec.rb b/spec/ruby/core/string/dup_spec.rb
index eec3cf0a70..e367f7a311 100644
--- a/spec/ruby/core/string/dup_spec.rb
+++ b/spec/ruby/core/string/dup_spec.rb
@@ -21,7 +21,7 @@ describe "String#dup" do
it "does not copy singleton methods" do
def @obj.special() :the_one end
dup = @obj.dup
- -> { dup.special }.should raise_error(NameError)
+ -> { dup.special }.should.raise(NameError)
end
it "does not copy modules included in the singleton class" do
@@ -30,7 +30,7 @@ describe "String#dup" do
end
dup = @obj.dup
- -> { dup.repr }.should raise_error(NameError)
+ -> { dup.repr }.should.raise(NameError)
end
it "does not copy constants defined in the singleton class" do
@@ -39,7 +39,7 @@ describe "String#dup" do
end
dup = @obj.dup
- -> { class << dup; CLONE; end }.should raise_error(NameError)
+ -> { class << dup; CLONE; end }.should.raise(NameError)
end
it "does not modify the original string when changing dupped string" do
@@ -51,11 +51,15 @@ describe "String#dup" do
end
it "does not modify the original setbyte-mutated string when changing dupped string" do
- orig = "a"
+ orig = +"a"
orig.setbyte 0, "b".ord
copy = orig.dup
orig.setbyte 0, "c".ord
orig.should == "c"
copy.should == "b"
end
+
+ it "returns a String in the same encoding as self" do
+ "hello".encode("US-ASCII").dup.encoding.should == Encoding::US_ASCII
+ end
end
diff --git a/spec/ruby/core/string/each_byte_spec.rb b/spec/ruby/core/string/each_byte_spec.rb
index e04dca807f..1884df416b 100644
--- a/spec/ruby/core/string/each_byte_spec.rb
+++ b/spec/ruby/core/string/each_byte_spec.rb
@@ -9,39 +9,39 @@ describe "String#each_byte" do
end
it "keeps iterating from the old position (to new string end) when self changes" do
- r = ""
- s = "hello world"
+ r = +""
+ s = +"hello world"
s.each_byte do |c|
r << c
s.insert(0, "<>") if r.size < 3
end
r.should == "h><>hello world"
- r = ""
- s = "hello world"
+ r = +""
+ s = +"hello world"
s.each_byte { |c| s.slice!(-1); r << c }
r.should == "hello "
- r = ""
- s = "hello world"
+ r = +""
+ s = +"hello world"
s.each_byte { |c| s.slice!(0); r << c }
r.should == "hlowrd"
- r = ""
- s = "hello world"
+ r = +""
+ s = +"hello world"
s.each_byte { |c| s.slice!(0..-1); r << c }
r.should == "h"
end
it "returns self" do
s = "hello"
- (s.each_byte {}).should equal(s)
+ (s.each_byte {}).should.equal?(s)
end
describe "when no block is given" do
it "returns an enumerator" do
enum = "hello".each_byte
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.should == [104, 101, 108, 108, 111]
end
diff --git a/spec/ruby/core/string/each_char_spec.rb b/spec/ruby/core/string/each_char_spec.rb
index aff98c0a5c..36219f79db 100644
--- a/spec/ruby/core/string/each_char_spec.rb
+++ b/spec/ruby/core/string/each_char_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../spec_helper"
require_relative 'shared/chars'
require_relative 'shared/each_char_without_block'
diff --git a/spec/ruby/core/string/each_grapheme_cluster_spec.rb b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
index b45d89ecb0..e1fa4ae67b 100644
--- a/spec/ruby/core/string/each_grapheme_cluster_spec.rb
+++ b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../spec_helper"
require_relative 'shared/chars'
require_relative 'shared/grapheme_clusters'
require_relative 'shared/each_char_without_block'
@@ -7,11 +8,9 @@ describe "String#each_grapheme_cluster" do
it_behaves_like :string_grapheme_clusters, :each_grapheme_cluster
it_behaves_like :string_each_char_without_block, :each_grapheme_cluster
- ruby_version_is '3.0' do
- it "yields String instances for subclasses" do
- a = []
- StringSpecs::MyString.new("abc").each_grapheme_cluster { |s| a << s.class }
- a.should == [String, String, String]
- end
+ it "yields String instances for subclasses" do
+ a = []
+ StringSpecs::MyString.new("abc").each_grapheme_cluster { |s| a << s.class }
+ a.should == [String, String, String]
end
end
diff --git a/spec/ruby/core/string/element_set_spec.rb b/spec/ruby/core/string/element_set_spec.rb
index 881b4343d4..2abc5117aa 100644
--- a/spec/ruby/core/string/element_set_spec.rb
+++ b/spec/ruby/core/string/element_set_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -17,13 +18,13 @@ describe "String#[]= with Integer index" do
it "raises an IndexError without changing self if idx is outside of self" do
str = "hello"
- -> { str[20] = "bam" }.should raise_error(IndexError)
+ -> { str[20] = "bam" }.should.raise(IndexError)
str.should == "hello"
- -> { str[-20] = "bam" }.should raise_error(IndexError)
+ -> { str[-20] = "bam" }.should.raise(IndexError)
str.should == "hello"
- -> { ""[-1] = "bam" }.should raise_error(IndexError)
+ -> { ""[-1] = "bam" }.should.raise(IndexError)
end
# Behaviour is verified by matz in
@@ -36,7 +37,7 @@ describe "String#[]= with Integer index" do
it "raises IndexError if the string index doesn't match a position in the string" do
str = "hello"
- -> { str['y'] = "bam" }.should raise_error(IndexError)
+ -> { str['y'] = "bam" }.should.raise(IndexError)
str.should == "hello"
end
@@ -44,7 +45,7 @@ describe "String#[]= with Integer index" do
a = "hello"
a.freeze
- -> { a[0] = "bam" }.should raise_error(FrozenError)
+ -> { a[0] = "bam" }.should.raise(FrozenError)
end
it "calls to_int on index" do
@@ -68,17 +69,17 @@ describe "String#[]= with Integer index" do
end
it "raises a TypeError if other_str can't be converted to a String" do
- -> { "test"[1] = [] }.should raise_error(TypeError)
- -> { "test"[1] = mock('x') }.should raise_error(TypeError)
- -> { "test"[1] = nil }.should raise_error(TypeError)
+ -> { "test"[1] = [] }.should.raise(TypeError)
+ -> { "test"[1] = mock('x') }.should.raise(TypeError)
+ -> { "test"[1] = nil }.should.raise(TypeError)
end
it "raises a TypeError if passed an Integer replacement" do
- -> { "abc"[1] = 65 }.should raise_error(TypeError)
+ -> { "abc"[1] = 65 }.should.raise(TypeError)
end
it "raises an IndexError if the index is greater than character size" do
- -> { "あれ"[4] = "a" }.should raise_error(IndexError)
+ -> { "あれ"[4] = "a" }.should.raise(IndexError)
end
it "calls #to_int to convert the index" do
@@ -94,14 +95,14 @@ describe "String#[]= with Integer index" do
index = mock("string element set")
index.should_receive(:to_int).and_return('1')
- -> { "abc"[index] = "d" }.should raise_error(TypeError)
+ -> { "abc"[index] = "d" }.should.raise(TypeError)
end
it "raises an IndexError if #to_int returns a value out of range" do
index = mock("string element set")
index.should_receive(:to_int).and_return(4)
- -> { "ab"[index] = "c" }.should raise_error(IndexError)
+ -> { "ab"[index] = "c" }.should.raise(IndexError)
end
it "replaces a character with a multibyte character" do
@@ -126,7 +127,7 @@ describe "String#[]= with Integer index" do
str = " ".force_encoding Encoding::US_ASCII
rep = [160].pack('C').force_encoding Encoding::BINARY
str[0] = rep
- str.encoding.should equal(Encoding::BINARY)
+ str.encoding.should.equal?(Encoding::BINARY)
end
it "updates the string to a compatible encoding" do
@@ -138,7 +139,7 @@ describe "String#[]= with Integer index" do
it "raises an Encoding::CompatibilityError if the replacement encoding is incompatible" do
str = "あれ"
rep = "が".encode Encoding::EUC_JP
- -> { str[0] = rep }.should raise_error(Encoding::CompatibilityError)
+ -> { str[0] = rep }.should.raise(Encoding::CompatibilityError)
end
end
@@ -163,7 +164,7 @@ describe "String#[]= with String index" do
it "raises an IndexError if the search String is not found" do
str = "abcde"
- -> { str["g"] = "h" }.should raise_error(IndexError)
+ -> { str["g"] = "h" }.should.raise(IndexError)
end
it "replaces characters with a multibyte character" do
@@ -188,13 +189,13 @@ describe "String#[]= with String index" do
str = " ".force_encoding Encoding::US_ASCII
rep = [160].pack('C').force_encoding Encoding::BINARY
str[" "] = rep
- str.encoding.should equal(Encoding::BINARY)
+ str.encoding.should.equal?(Encoding::BINARY)
end
it "raises an Encoding::CompatibilityError if the replacement encoding is incompatible" do
str = "あれ"
rep = "が".encode Encoding::EUC_JP
- -> { str["れ"] = rep }.should raise_error(Encoding::CompatibilityError)
+ -> { str["れ"] = rep }.should.raise(Encoding::CompatibilityError)
end
end
@@ -207,7 +208,7 @@ describe "String#[]= with a Regexp index" do
it "raises IndexError if the regexp index doesn't match a position in the string" do
str = "hello"
- -> { str[/y/] = "bam" }.should raise_error(IndexError)
+ -> { str[/y/] = "bam" }.should.raise(IndexError)
str.should == "hello"
end
@@ -224,7 +225,7 @@ describe "String#[]= with a Regexp index" do
rep = mock("string element set regexp")
rep.should_not_receive(:to_str)
- -> { "abc"[/def/] = rep }.should raise_error(IndexError)
+ -> { "abc"[/def/] = rep }.should.raise(IndexError)
end
describe "with 3 arguments" do
@@ -241,7 +242,7 @@ describe "String#[]= with a Regexp index" do
ref = mock("string element set regexp ref")
ref.should_receive(:to_int).and_return(nil)
- -> { "abc"[/a(b)/, ref] = "x" }.should raise_error(TypeError)
+ -> { "abc"[/a(b)/, ref] = "x" }.should.raise(TypeError)
end
it "uses the 2nd of 3 arguments as which capture should be replaced" do
@@ -260,20 +261,20 @@ describe "String#[]= with a Regexp index" do
rep = mock("string element set regexp")
rep.should_not_receive(:to_str)
- -> { "abc"[/a(b)/, 2] = rep }.should raise_error(IndexError)
+ -> { "abc"[/a(b)/, 2] = rep }.should.raise(IndexError)
end
it "raises IndexError if the specified capture isn't available" do
str = "aaa bbb ccc"
- -> { str[/a (bbb) c/, 2] = "ddd" }.should raise_error(IndexError)
- -> { str[/a (bbb) c/, -2] = "ddd" }.should raise_error(IndexError)
+ -> { str[/a (bbb) c/, 2] = "ddd" }.should.raise(IndexError)
+ -> { str[/a (bbb) c/, -2] = "ddd" }.should.raise(IndexError)
end
describe "when the optional capture does not match" do
it "raises an IndexError before setting the replacement" do
str1 = "a b c"
str2 = str1.dup
- -> { str2[/a (b) (Z)?/, 2] = "d" }.should raise_error(IndexError)
+ -> { str2[/a (b) (Z)?/, 2] = "d" }.should.raise(IndexError)
str2.should == str1
end
end
@@ -301,13 +302,13 @@ describe "String#[]= with a Regexp index" do
str = " ".force_encoding Encoding::US_ASCII
rep = [160].pack('C').force_encoding Encoding::BINARY
str[/ /] = rep
- str.encoding.should equal(Encoding::BINARY)
+ str.encoding.should.equal?(Encoding::BINARY)
end
it "raises an Encoding::CompatibilityError if the replacement encoding is incompatible" do
str = "あれ"
rep = "が".encode Encoding::EUC_JP
- -> { str[/れ/] = rep }.should raise_error(Encoding::CompatibilityError)
+ -> { str[/れ/] = rep }.should.raise(Encoding::CompatibilityError)
end
end
@@ -357,11 +358,11 @@ describe "String#[]= with a Range index" do
end
it "raises a RangeError if negative Range begin is out of range" do
- -> { "abc"[-4..-2] = "x" }.should raise_error(RangeError)
+ -> { "abc"[-4..-2] = "x" }.should.raise(RangeError, "-4..-2 out of range")
end
it "raises a RangeError if positive Range begin is greater than String size" do
- -> { "abc"[4..2] = "x" }.should raise_error(RangeError)
+ -> { "abc"[4..2] = "x" }.should.raise(RangeError, "4..2 out of range")
end
it "uses the Range end as an index rather than a count" do
@@ -422,13 +423,13 @@ describe "String#[]= with a Range index" do
str = " ".force_encoding Encoding::US_ASCII
rep = [160].pack('C').force_encoding Encoding::BINARY
str[0..1] = rep
- str.encoding.should equal(Encoding::BINARY)
+ str.encoding.should.equal?(Encoding::BINARY)
end
it "raises an Encoding::CompatibilityError if the replacement encoding is incompatible" do
str = "あれ"
rep = "が".encode Encoding::EUC_JP
- -> { str[0..1] = rep }.should raise_error(Encoding::CompatibilityError)
+ -> { str[0..1] = rep }.should.raise(Encoding::CompatibilityError)
end
end
@@ -497,14 +498,14 @@ describe "String#[]= with Integer index, count" do
index = mock("string element set index")
index.should_receive(:to_int).and_return("1")
- -> { "abc"[index, 2] = "xyz" }.should raise_error(TypeError)
+ -> { "abc"[index, 2] = "xyz" }.should.raise(TypeError)
end
it "raises a TypeError if #to_int for count does not return an Integer" do
count = mock("string element set count")
count.should_receive(:to_int).and_return("1")
- -> { "abc"[1, count] = "xyz" }.should raise_error(TypeError)
+ -> { "abc"[1, count] = "xyz" }.should.raise(TypeError)
end
it "calls #to_str to convert the replacement object" do
@@ -520,23 +521,23 @@ describe "String#[]= with Integer index, count" do
r = mock("string element set replacement")
r.should_receive(:to_str).and_return(nil)
- -> { "abc"[1, 1] = r }.should raise_error(TypeError)
+ -> { "abc"[1, 1] = r }.should.raise(TypeError)
end
it "raises an IndexError if |idx| is greater than the length of the string" do
- -> { "hello"[6, 0] = "bob" }.should raise_error(IndexError)
- -> { "hello"[-6, 0] = "bob" }.should raise_error(IndexError)
+ -> { "hello"[6, 0] = "bob" }.should.raise(IndexError)
+ -> { "hello"[-6, 0] = "bob" }.should.raise(IndexError)
end
it "raises an IndexError if count < 0" do
- -> { "hello"[0, -1] = "bob" }.should raise_error(IndexError)
- -> { "hello"[1, -1] = "bob" }.should raise_error(IndexError)
+ -> { "hello"[0, -1] = "bob" }.should.raise(IndexError)
+ -> { "hello"[1, -1] = "bob" }.should.raise(IndexError)
end
it "raises a TypeError if other_str is a type other than String" do
- -> { "hello"[0, 2] = nil }.should raise_error(TypeError)
- -> { "hello"[0, 2] = [] }.should raise_error(TypeError)
- -> { "hello"[0, 2] = 33 }.should raise_error(TypeError)
+ -> { "hello"[0, 2] = nil }.should.raise(TypeError)
+ -> { "hello"[0, 2] = [] }.should.raise(TypeError)
+ -> { "hello"[0, 2] = 33 }.should.raise(TypeError)
end
it "replaces characters with a multibyte character" do
@@ -570,19 +571,19 @@ describe "String#[]= with Integer index, count" do
end
it "raises an IndexError if the character index is out of range of a multibyte String" do
- -> { "あれ"[3, 0] = "り" }.should raise_error(IndexError)
+ -> { "あれ"[3, 0] = "り" }.should.raise(IndexError)
end
it "encodes the String in an encoding compatible with the replacement" do
str = " ".force_encoding Encoding::US_ASCII
rep = [160].pack('C').force_encoding Encoding::BINARY
str[0, 1] = rep
- str.encoding.should equal(Encoding::BINARY)
+ str.encoding.should.equal?(Encoding::BINARY)
end
it "raises an Encoding::CompatibilityError if the replacement encoding is incompatible" do
str = "あれ"
rep = "が".encode Encoding::EUC_JP
- -> { str[0, 1] = rep }.should raise_error(Encoding::CompatibilityError)
+ -> { str[0, 1] = rep }.should.raise(Encoding::CompatibilityError)
end
end
diff --git a/spec/ruby/core/string/encode_spec.rb b/spec/ruby/core/string/encode_spec.rb
index 5604ab7210..ab096f4041 100644
--- a/spec/ruby/core/string/encode_spec.rb
+++ b/spec/ruby/core/string/encode_spec.rb
@@ -20,7 +20,7 @@ describe "String#encode" do
Encoding.default_internal = nil
str = "あ"
encoded = str.encode
- encoded.should_not equal(str)
+ encoded.should_not.equal?(str)
encoded.should == str
end
@@ -28,15 +28,15 @@ describe "String#encode" do
Encoding.default_internal = nil
str = "abc"
encoded = str.encode
- encoded.should_not equal(str)
+ encoded.should_not.equal?(str)
encoded.should == str
end
it "encodes an ascii substring of a binary string to UTF-8" do
x82 = [0x82].pack('C')
- str = "#{x82}foo".force_encoding("binary")[1..-1].encode("utf-8")
- str.should == "foo".force_encoding("utf-8")
- str.encoding.should equal(Encoding::UTF_8)
+ str = "#{x82}foo".dup.force_encoding("binary")[1..-1].encode("utf-8")
+ str.should == "foo".dup.force_encoding("utf-8")
+ str.encoding.should.equal?(Encoding::UTF_8)
end
end
@@ -44,12 +44,12 @@ describe "String#encode" do
it "returns a copy when passed the same encoding as the String" do
str = "あ"
encoded = str.encode(Encoding::UTF_8)
- encoded.should_not equal(str)
+ encoded.should_not.equal?(str)
encoded.should == str
end
it "round trips a String" do
- str = "abc def".force_encoding Encoding::US_ASCII
+ str = "abc def".dup.force_encoding Encoding::US_ASCII
str.encode("utf-32be").encode("ascii").should == "abc def"
end
end
@@ -58,13 +58,25 @@ describe "String#encode" do
it "returns a copy when Encoding.default_internal is nil" do
Encoding.default_internal = nil
str = "あ"
- str.encode(invalid: :replace).should_not equal(str)
+ str.encode(invalid: :replace).should_not.equal?(str)
end
- it "normalizes newlines" do
- "\r\nfoo".encode(universal_newline: true).should == "\nfoo"
+ it "normalizes newlines with cr_newline option" do
+ "\r\nfoo".encode(cr_newline: true).should == "\r\rfoo"
+ "\rfoo".encode(cr_newline: true).should == "\rfoo"
+ "\nfoo".encode(cr_newline: true).should == "\rfoo"
+ end
+
+ it "normalizes newlines with crlf_newline option" do
+ "\r\nfoo".encode(crlf_newline: true).should == "\r\r\nfoo"
+ "\rfoo".encode(crlf_newline: true).should == "\rfoo"
+ "\nfoo".encode(crlf_newline: true).should == "\r\nfoo"
+ end
+ it "normalizes newlines with universal_newline option" do
+ "\r\nfoo".encode(universal_newline: true).should == "\nfoo"
"\rfoo".encode(universal_newline: true).should == "\nfoo"
+ "\nfoo".encode(universal_newline: true).should == "\nfoo"
end
it "replaces invalid encoding in source with default replacement" do
@@ -79,6 +91,10 @@ describe "String#encode" do
encoded.encode("UTF-8").should == "ちfoofoo"
end
+ it "replace multiple invalid bytes at the end with a single replacement character" do
+ "\xE3\x81\x93\xE3\x81".encode("UTF-8", invalid: :replace).should == "\u3053\ufffd"
+ end
+
it "replaces invalid encoding in source using a specified replacement even when a fallback is given" do
encoded = "ち\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace, replace: "foo", fallback: -> c { "bar" })
encoded.should == "\u3061foofoo".encode("UTF-16LE")
@@ -118,11 +134,10 @@ describe "String#encode" do
describe "when passed to, from" do
it "returns a copy in the destination encoding when both encodings are the same" do
- str = "あ"
- str.force_encoding("binary")
+ str = "あ".dup.force_encoding("binary")
encoded = str.encode("utf-8", "utf-8")
- encoded.should_not equal(str)
+ encoded.should_not.equal?(str)
encoded.should == str.force_encoding("utf-8")
encoded.encoding.should == Encoding::UTF_8
end
@@ -137,7 +152,7 @@ describe "String#encode" do
it "returns a copy when the destination encoding is the same as the String encoding" do
str = "あ"
encoded = str.encode(Encoding::UTF_8, undef: :replace)
- encoded.should_not equal(str)
+ encoded.should_not.equal?(str)
encoded.should == str
end
end
@@ -146,16 +161,15 @@ describe "String#encode" do
it "returns a copy when both encodings are the same" do
str = "あ"
encoded = str.encode("utf-8", "utf-8", invalid: :replace)
- encoded.should_not equal(str)
+ encoded.should_not.equal?(str)
encoded.should == str
end
it "returns a copy in the destination encoding when both encodings are the same" do
- str = "あ"
- str.force_encoding("binary")
+ str = "あ".dup.force_encoding("binary")
encoded = str.encode("utf-8", "utf-8", invalid: :replace)
- encoded.should_not equal(str)
+ encoded.should_not.equal?(str)
encoded.should == str.force_encoding("utf-8")
encoded.encoding.should == Encoding::UTF_8
end
@@ -176,51 +190,51 @@ describe "String#encode!" do
it_behaves_like :string_encode, :encode!
it "raises a FrozenError when called on a frozen String" do
- -> { "foo".freeze.encode!("euc-jp") }.should raise_error(FrozenError)
+ -> { "foo".freeze.encode!("euc-jp") }.should.raise(FrozenError)
end
# http://redmine.ruby-lang.org/issues/show/1836
it "raises a FrozenError when called on a frozen String when it's a no-op" do
- -> { "foo".freeze.encode!("utf-8") }.should raise_error(FrozenError)
+ -> { "foo".freeze.encode!("utf-8") }.should.raise(FrozenError)
end
describe "when passed no options" do
it "returns self when Encoding.default_internal is nil" do
Encoding.default_internal = nil
- str = "あ"
- str.encode!.should equal(str)
+ str = +"あ"
+ str.encode!.should.equal?(str)
end
it "returns self for a ASCII-only String when Encoding.default_internal is nil" do
Encoding.default_internal = nil
- str = "abc"
- str.encode!.should equal(str)
+ str = +"abc"
+ str.encode!.should.equal?(str)
end
end
describe "when passed options" do
it "returns self for ASCII-only String when Encoding.default_internal is nil" do
Encoding.default_internal = nil
- str = "abc"
- str.encode!(invalid: :replace).should equal(str)
+ str = +"abc"
+ str.encode!(invalid: :replace).should.equal?(str)
end
end
describe "when passed to encoding" do
it "returns self" do
- str = "abc"
+ str = +"abc"
result = str.encode!(Encoding::BINARY)
- result.encoding.should equal(Encoding::BINARY)
- result.should equal(str)
+ result.encoding.should.equal?(Encoding::BINARY)
+ result.should.equal?(str)
end
end
describe "when passed to, from" do
it "returns self" do
- str = "ああ"
+ str = +"ああ"
result = str.encode!("euc-jp", "utf-8")
- result.encoding.should equal(Encoding::EUC_JP)
- result.should equal(str)
+ result.encoding.should.equal?(Encoding::EUC_JP)
+ result.should.equal?(str)
end
end
end
diff --git a/spec/ruby/core/string/encoding_spec.rb b/spec/ruby/core/string/encoding_spec.rb
index 574a1e2f92..aa0e4765ed 100644
--- a/spec/ruby/core/string/encoding_spec.rb
+++ b/spec/ruby/core/string/encoding_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/iso-8859-9-encoding'
describe "String#encoding" do
it "returns an Encoding object" do
- String.new.encoding.should be_an_instance_of(Encoding)
+ String.new.encoding.should.instance_of?(Encoding)
end
it "is equal to the source encoding by default" do
@@ -14,11 +14,11 @@ describe "String#encoding" do
end
it "returns the given encoding if #force_encoding has been called" do
- "a".force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
+ "a".dup.force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
end
it "returns the given encoding if #encode!has been called" do
- "a".encode!(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
+ "a".dup.encode!(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
end
end
@@ -70,13 +70,13 @@ describe "String#encoding for Strings with \\u escapes" do
it "returns US-ASCII if self is US-ASCII only" do
s = "\u{40}"
- s.ascii_only?.should be_true
+ s.ascii_only?.should == true
s.encoding.should == Encoding::US_ASCII
end
it "returns UTF-8 if self isn't US-ASCII only" do
s = "\u{4076}\u{619}"
- s.ascii_only?.should be_false
+ s.ascii_only?.should == false
s.encoding.should == Encoding::UTF_8
end
@@ -108,13 +108,13 @@ describe "String#encoding for Strings with \\u escapes" do
end
it "returns the given encoding if #force_encoding has been called" do
- "\u{20}".force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
- "\u{2020}".force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
+ "\u{20}".dup.force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
+ "\u{2020}".dup.force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
end
it "returns the given encoding if #encode!has been called" do
- "\u{20}".encode!(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
- "\u{2020}".encode!(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
+ "\u{20}".dup.encode!(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
+ "\u{2020}".dup.encode!(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
end
end
@@ -122,7 +122,7 @@ describe "String#encoding for Strings with \\x escapes" do
it "returns US-ASCII if self is US-ASCII only" do
s = "\x61"
- s.ascii_only?.should be_true
+ s.ascii_only?.should == true
s.encoding.should == Encoding::US_ASCII
end
@@ -131,7 +131,7 @@ describe "String#encoding for Strings with \\x escapes" do
str = " "
str.encoding.should == Encoding::US_ASCII
str += [0xDF].pack('C')
- str.ascii_only?.should be_false
+ str.ascii_only?.should == false
str.encoding.should == Encoding::BINARY
end
@@ -140,7 +140,7 @@ describe "String#encoding for Strings with \\x escapes" do
it "returns the source encoding when an escape creates a byte with the 8th bit set if the source encoding isn't US-ASCII" do
fixture = StringSpecs::ISO88599Encoding.new
fixture.source_encoding.should == Encoding::ISO8859_9
- fixture.x_escape.ascii_only?.should be_false
+ fixture.x_escape.ascii_only?.should == false
fixture.x_escape.encoding.should == Encoding::ISO8859_9
end
@@ -173,16 +173,12 @@ describe "String#encoding for Strings with \\x escapes" do
end
it "returns the given encoding if #force_encoding has been called" do
- x50 = "\x50"
- x50.force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
- xD4 = [212].pack('C')
- xD4.force_encoding(Encoding::ISO_8859_9).encoding.should == Encoding::ISO_8859_9
+ "\x50".dup.force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
+ [212].pack('C').force_encoding(Encoding::ISO_8859_9).encoding.should == Encoding::ISO_8859_9
end
it "returns the given encoding if #encode!has been called" do
- x50 = "\x50"
- x50.encode!(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
- x00 = "x\00"
- x00.encode!(Encoding::UTF_8).encoding.should == Encoding::UTF_8
+ "\x50".dup.encode!(Encoding::SHIFT_JIS).encoding.should == Encoding::SHIFT_JIS
+ "x\00".dup.encode!(Encoding::UTF_8).encoding.should == Encoding::UTF_8
end
end
diff --git a/spec/ruby/core/string/eql_spec.rb b/spec/ruby/core/string/eql_spec.rb
index 397974d9fb..46ebeda509 100644
--- a/spec/ruby/core/string/eql_spec.rb
+++ b/spec/ruby/core/string/eql_spec.rb
@@ -6,16 +6,16 @@ describe "String#eql?" do
describe "when given a non-String" do
it "returns false" do
- 'hello'.should_not eql(5)
+ 'hello'.should_not.eql?(5)
not_supported_on :opal do
- 'hello'.should_not eql(:hello)
+ 'hello'.should_not.eql?(:hello)
end
- 'hello'.should_not eql(mock('x'))
+ 'hello'.should_not.eql?(mock('x'))
end
it "does not try to call #to_str on the given argument" do
(obj = mock('x')).should_not_receive(:to_str)
- 'hello'.should_not eql(obj)
+ 'hello'.should_not.eql?(obj)
end
end
end
diff --git a/spec/ruby/core/string/fixtures/to_c.rb b/spec/ruby/core/string/fixtures/to_c.rb
new file mode 100644
index 0000000000..7776933263
--- /dev/null
+++ b/spec/ruby/core/string/fixtures/to_c.rb
@@ -0,0 +1,5 @@
+module StringSpecs
+ def self.to_c_method(string)
+ string.to_c
+ end
+end
diff --git a/spec/ruby/core/string/fixtures/utf-8-encoding.rb b/spec/ruby/core/string/fixtures/utf-8-encoding.rb
deleted file mode 100644
index fd243ec522..0000000000
--- a/spec/ruby/core/string/fixtures/utf-8-encoding.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- encoding: utf-8 -*-
-module StringSpecs
- class UTF8Encoding
- def self.source_encoding; __ENCODING__; end
- def self.egrave; "é"; end
- end
-end
diff --git a/spec/ruby/core/string/force_encoding_spec.rb b/spec/ruby/core/string/force_encoding_spec.rb
index f37aaf9eb4..fc6914213f 100644
--- a/spec/ruby/core/string/force_encoding_spec.rb
+++ b/spec/ruby/core/string/force_encoding_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe "String#force_encoding" do
@@ -40,23 +41,23 @@ describe "String#force_encoding" do
obj = mock("force_encoding")
obj.should_receive(:to_str).and_return(1)
- -> { "abc".force_encoding(obj) }.should raise_error(TypeError)
+ -> { "abc".force_encoding(obj) }.should.raise(TypeError)
end
it "raises a TypeError if passed nil" do
- -> { "abc".force_encoding(nil) }.should raise_error(TypeError)
+ -> { "abc".force_encoding(nil) }.should.raise(TypeError)
end
it "returns self" do
str = "abc"
- str.force_encoding('utf-8').should equal(str)
+ str.force_encoding('utf-8').should.equal?(str)
end
it "sets the encoding even if the String contents are invalid in that encoding" do
str = "\u{9765}"
str.force_encoding('euc-jp')
str.encoding.should == Encoding::EUC_JP
- str.valid_encoding?.should be_false
+ str.valid_encoding?.should == false
end
it "does not transcode self" do
@@ -66,6 +67,6 @@ describe "String#force_encoding" do
it "raises a FrozenError if self is frozen" do
str = "abcd".freeze
- -> { str.force_encoding(str.encoding) }.should raise_error(FrozenError)
+ -> { str.force_encoding(str.encoding) }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/freeze_spec.rb b/spec/ruby/core/string/freeze_spec.rb
index 04d1e9513c..8485e8de21 100644
--- a/spec/ruby/core/string/freeze_spec.rb
+++ b/spec/ruby/core/string/freeze_spec.rb
@@ -1,13 +1,14 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe "String#freeze" do
it "produces the same object whenever called on an instance of a literal in the source" do
- "abc".freeze.should equal "abc".freeze
+ "abc".freeze.should.equal? "abc".freeze
end
it "doesn't produce the same object for different instances of literals in the source" do
- "abc".should_not equal "abc"
+ "abc".should_not.equal? "abc"
end
it "being a special form doesn't change the value of defined?" do
diff --git a/spec/ruby/core/string/getbyte_spec.rb b/spec/ruby/core/string/getbyte_spec.rb
index 27b7d826ea..d4619dca61 100644
--- a/spec/ruby/core/string/getbyte_spec.rb
+++ b/spec/ruby/core/string/getbyte_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "String#getbyte" do
it "returns an Integer if given a valid index" do
- "a".getbyte(0).should be_kind_of(Integer)
+ "a".getbyte(0).should.is_a?(Integer)
end
it "starts indexing at 0" do
@@ -51,19 +51,19 @@ describe "String#getbyte" do
end
it "returns nil for out-of-bound indexes" do
- "g".getbyte(1).should be_nil
+ "g".getbyte(1).should == nil
end
it "regards the empty String as containing no bytes" do
- "".getbyte(0).should be_nil
+ "".getbyte(0).should == nil
end
it "raises an ArgumentError unless given one argument" do
- -> { "glark".getbyte }.should raise_error(ArgumentError)
- -> { "food".getbyte(0,0) }.should raise_error(ArgumentError)
+ -> { "glark".getbyte }.should.raise(ArgumentError)
+ -> { "food".getbyte(0,0) }.should.raise(ArgumentError)
end
it "raises a TypeError unless its argument can be coerced into an Integer" do
- -> { "a".getbyte('a') }.should raise_error(TypeError)
+ -> { "a".getbyte('a') }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/string/grapheme_clusters_spec.rb b/spec/ruby/core/string/grapheme_clusters_spec.rb
index 3046265a12..380a245083 100644
--- a/spec/ruby/core/string/grapheme_clusters_spec.rb
+++ b/spec/ruby/core/string/grapheme_clusters_spec.rb
@@ -1,3 +1,4 @@
+require_relative "../../spec_helper"
require_relative 'shared/chars'
require_relative 'shared/grapheme_clusters'
diff --git a/spec/ruby/core/string/gsub_spec.rb b/spec/ruby/core/string/gsub_spec.rb
index 3211ebbd0a..d0e1c30bd2 100644
--- a/spec/ruby/core/string/gsub_spec.rb
+++ b/spec/ruby/core/string/gsub_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -174,9 +175,9 @@ describe "String#gsub with pattern and replacement" do
end
it "raises a TypeError when pattern can't be converted to a string" do
- -> { "hello".gsub([], "x") }.should raise_error(TypeError)
- -> { "hello".gsub(Object.new, "x") }.should raise_error(TypeError)
- -> { "hello".gsub(nil, "x") }.should raise_error(TypeError)
+ -> { "hello".gsub([], "x") }.should.raise(TypeError)
+ -> { "hello".gsub(Object.new, "x") }.should.raise(TypeError)
+ -> { "hello".gsub(nil, "x") }.should.raise(TypeError)
end
it "tries to convert replacement to a string using to_str" do
@@ -187,31 +188,18 @@ describe "String#gsub with pattern and replacement" do
end
it "raises a TypeError when replacement can't be converted to a string" do
- -> { "hello".gsub(/[aeiou]/, []) }.should raise_error(TypeError)
- -> { "hello".gsub(/[aeiou]/, Object.new) }.should raise_error(TypeError)
- -> { "hello".gsub(/[aeiou]/, nil) }.should raise_error(TypeError)
+ -> { "hello".gsub(/[aeiou]/, []) }.should.raise(TypeError)
+ -> { "hello".gsub(/[aeiou]/, Object.new) }.should.raise(TypeError)
+ -> { "hello".gsub(/[aeiou]/, nil) }.should.raise(TypeError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("").gsub(//, "").should.instance_of?(String)
+ StringSpecs::MyString.new("").gsub(/foo/, "").should.instance_of?(String)
+ StringSpecs::MyString.new("foo").gsub(/foo/, "").should.instance_of?(String)
+ StringSpecs::MyString.new("foo").gsub("foo", "").should.instance_of?(String)
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(String)
- StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(String)
- end
- end
-
- # Note: $~ cannot be tested because mspec messes with it
-
it "sets $~ to MatchData of last match and nil when there's none" do
'hello.'.gsub('hello', 'x')
$~[0].should == 'hello'
@@ -225,6 +213,18 @@ describe "String#gsub with pattern and replacement" do
'hello.'.gsub(/not/, 'x')
$~.should == nil
end
+
+ it "handles a pattern in a superset encoding" do
+ result = 'abc'.force_encoding(Encoding::US_ASCII).gsub('é', 'è')
+ result.should == 'abc'
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ result = 'été'.gsub('t'.force_encoding(Encoding::US_ASCII), 'u')
+ result.should == 'éué'
+ result.encoding.should == Encoding::UTF_8
+ end
end
describe "String#gsub with pattern and Hash" do
@@ -450,8 +450,8 @@ describe "String#gsub with pattern and block" do
s = "hllëllo"
s2 = "hellö"
- -> { s.gsub(/l/) { |bar| "Русский".force_encoding("iso-8859-5") } }.should raise_error(Encoding::CompatibilityError)
- -> { s2.gsub(/l/) { |bar| "Русский".force_encoding("iso-8859-5") } }.should raise_error(Encoding::CompatibilityError)
+ -> { s.gsub(/l/) { |bar| "Русский".force_encoding("iso-8859-5") } }.should.raise(Encoding::CompatibilityError)
+ -> { s2.gsub(/l/) { |bar| "Русский".force_encoding("iso-8859-5") } }.should.raise(Encoding::CompatibilityError)
end
it "replaces the incompatible part properly even if the encodings are not compatible" do
@@ -463,7 +463,7 @@ describe "String#gsub with pattern and block" do
not_supported_on :opal do
it "raises an ArgumentError if encoding is not valid" do
x92 = [0x92].pack('C').force_encoding('utf-8')
- -> { "a#{x92}b".gsub(/[^\x00-\x7f]/u, '') }.should raise_error(ArgumentError)
+ -> { "a#{x92}b".gsub(/[^\x00-\x7f]/u, '') }.should.raise(ArgumentError)
end
end
end
@@ -471,7 +471,7 @@ end
describe "String#gsub with pattern and without replacement and block" do
it "returns an enumerator" do
enum = "abca".gsub(/a/)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.should == ["a", "a"]
end
@@ -495,13 +495,13 @@ end
describe "String#gsub! with pattern and replacement" do
it "modifies self in place and returns self" do
a = "hello"
- a.gsub!(/[aeiou]/, '*').should equal(a)
+ a.gsub!(/[aeiou]/, '*').should.equal?(a)
a.should == "h*ll*"
end
it "modifies self in place with multi-byte characters and returns self" do
a = "¿por qué?"
- a.gsub!(/([a-z\d]*)/, "*").should equal(a)
+ a.gsub!(/([a-z\d]*)/, "*").should.equal?(a)
a.should == "*¿** **é*?*"
end
@@ -517,16 +517,37 @@ describe "String#gsub! with pattern and replacement" do
s = "hello"
s.freeze
- -> { s.gsub!(/ROAR/, "x") }.should raise_error(FrozenError)
- -> { s.gsub!(/e/, "e") }.should raise_error(FrozenError)
- -> { s.gsub!(/[aeiou]/, '*') }.should raise_error(FrozenError)
+ -> { s.gsub!(/ROAR/, "x") }.should.raise(FrozenError)
+ -> { s.gsub!(/e/, "e") }.should.raise(FrozenError)
+ -> { s.gsub!(/[aeiou]/, '*') }.should.raise(FrozenError)
+ end
+
+ it "handles a pattern in a superset encoding" do
+ string = 'abc'.force_encoding(Encoding::US_ASCII)
+
+ result = string.gsub!('é', 'è')
+
+ result.should == nil
+ string.should == 'abc'
+ string.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ string = 'été'
+ pattern = 't'.force_encoding(Encoding::US_ASCII)
+
+ result = string.gsub!(pattern, 'u')
+
+ result.should == string
+ string.should == 'éué'
+ string.encoding.should == Encoding::UTF_8
end
end
describe "String#gsub! with pattern and block" do
it "modifies self in place and returns self" do
a = "hello"
- a.gsub!(/[aeiou]/) { '*' }.should equal(a)
+ a.gsub!(/[aeiou]/) { '*' }.should.equal?(a)
a.should == "h*ll*"
end
@@ -542,9 +563,9 @@ describe "String#gsub! with pattern and block" do
s = "hello"
s.freeze
- -> { s.gsub!(/ROAR/) { "x" } }.should raise_error(FrozenError)
- -> { s.gsub!(/e/) { "e" } }.should raise_error(FrozenError)
- -> { s.gsub!(/[aeiou]/) { '*' } }.should raise_error(FrozenError)
+ -> { s.gsub!(/ROAR/) { "x" } }.should.raise(FrozenError)
+ -> { s.gsub!(/e/) { "e" } }.should.raise(FrozenError)
+ -> { s.gsub!(/[aeiou]/) { '*' } }.should.raise(FrozenError)
end
it "uses the compatible encoding if they are compatible" do
@@ -559,8 +580,8 @@ describe "String#gsub! with pattern and block" do
s = "hllëllo"
s2 = "hellö"
- -> { s.gsub!(/l/) { |bar| "Русский".force_encoding("iso-8859-5") } }.should raise_error(Encoding::CompatibilityError)
- -> { s2.gsub!(/l/) { |bar| "Русский".force_encoding("iso-8859-5") } }.should raise_error(Encoding::CompatibilityError)
+ -> { s.gsub!(/l/) { |bar| "Русский".force_encoding("iso-8859-5") } }.should.raise(Encoding::CompatibilityError)
+ -> { s2.gsub!(/l/) { |bar| "Русский".force_encoding("iso-8859-5") } }.should.raise(Encoding::CompatibilityError)
end
it "replaces the incompatible part properly even if the encodings are not compatible" do
@@ -572,7 +593,7 @@ describe "String#gsub! with pattern and block" do
not_supported_on :opal do
it "raises an ArgumentError if encoding is not valid" do
x92 = [0x92].pack('C').force_encoding('utf-8')
- -> { "a#{x92}b".gsub!(/[^\x00-\x7f]/u, '') }.should raise_error(ArgumentError)
+ -> { "a#{x92}b".gsub!(/[^\x00-\x7f]/u, '') }.should.raise(ArgumentError)
end
end
end
@@ -580,7 +601,7 @@ end
describe "String#gsub! with pattern and without replacement and block" do
it "returns an enumerator" do
enum = "abca".gsub!(/a/)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.should == ["a", "a"]
end
diff --git a/spec/ruby/core/string/include_spec.rb b/spec/ruby/core/string/include_spec.rb
index 23e1e134ec..d943430335 100644
--- a/spec/ruby/core/string/include_spec.rb
+++ b/spec/ruby/core/string/include_spec.rb
@@ -15,16 +15,16 @@ describe "String#include? with String" do
it "returns true if both strings are empty" do
"".should.include?("")
- "".force_encoding("EUC-JP").should.include?("")
- "".should.include?("".force_encoding("EUC-JP"))
- "".force_encoding("EUC-JP").should.include?("".force_encoding("EUC-JP"))
+ "".dup.force_encoding("EUC-JP").should.include?("")
+ "".should.include?("".dup.force_encoding("EUC-JP"))
+ "".dup.force_encoding("EUC-JP").should.include?("".dup.force_encoding("EUC-JP"))
end
it "returns true if the RHS is empty" do
"a".should.include?("")
- "a".force_encoding("EUC-JP").should.include?("")
- "a".should.include?("".force_encoding("EUC-JP"))
- "a".force_encoding("EUC-JP").should.include?("".force_encoding("EUC-JP"))
+ "a".dup.force_encoding("EUC-JP").should.include?("")
+ "a".should.include?("".dup.force_encoding("EUC-JP"))
+ "a".dup.force_encoding("EUC-JP").should.include?("".dup.force_encoding("EUC-JP"))
end
it "tries to convert other to string using to_str" do
@@ -35,15 +35,15 @@ describe "String#include? with String" do
end
it "raises a TypeError if other can't be converted to string" do
- -> { "hello".include?([]) }.should raise_error(TypeError)
- -> { "hello".include?('h'.ord) }.should raise_error(TypeError)
- -> { "hello".include?(mock('x')) }.should raise_error(TypeError)
+ -> { "hello".include?([]) }.should.raise(TypeError)
+ -> { "hello".include?('h'.ord) }.should.raise(TypeError)
+ -> { "hello".include?(mock('x')) }.should.raise(TypeError)
end
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
pat = "ア".encode Encoding::EUC_JP
-> do
"あれ".include?(pat)
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError)
end
end
diff --git a/spec/ruby/core/string/index_spec.rb b/spec/ruby/core/string/index_spec.rb
index 5d77a88e4e..3f82181b98 100644
--- a/spec/ruby/core/string/index_spec.rb
+++ b/spec/ruby/core/string/index_spec.rb
@@ -4,15 +4,15 @@ require_relative 'fixtures/classes'
describe "String#index" do
it "raises a TypeError if passed nil" do
- -> { "abc".index nil }.should raise_error(TypeError)
+ -> { "abc".index nil }.should.raise(TypeError)
end
it "raises a TypeError if passed a boolean" do
- -> { "abc".index true }.should raise_error(TypeError)
+ -> { "abc".index true }.should.raise(TypeError)
end
it "raises a TypeError if passed a Symbol" do
- -> { "abc".index :a }.should raise_error(TypeError)
+ -> { "abc".index :a }.should.raise(TypeError)
end
it "calls #to_str to convert the first argument" do
@@ -28,7 +28,7 @@ describe "String#index" do
end
it "raises a TypeError if passed an Integer" do
- -> { "abc".index 97 }.should raise_error(TypeError)
+ -> { "abc".index 97 }.should.raise(TypeError)
end
end
@@ -157,7 +157,22 @@ describe "String#index with String" do
char = "れ".encode Encoding::EUC_JP
-> do
"あれ".index char
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError)
+ end
+
+ it "handles a substring in a superset encoding" do
+ 'abc'.dup.force_encoding(Encoding::US_ASCII).index('é').should == nil
+ end
+
+ it "handles a substring in a subset encoding" do
+ 'été'.index('t'.dup.force_encoding(Encoding::US_ASCII)).should == 1
+ end
+
+ it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
+ str = 'abc'.dup.force_encoding("ISO-2022-JP")
+ pattern = 'b'.dup.force_encoding("EUC-JP")
+
+ -> { str.index(pattern) }.should.raise(Encoding::CompatibilityError, "incompatible character encodings: ISO-2022-JP and EUC-JP")
end
end
@@ -216,6 +231,15 @@ describe "String#index with Regexp" do
$~.should == nil
end
+ it "always clear $~" do
+ "a".index(/a/)
+ $~.should_not == nil
+
+ string = "blablabla"
+ string.index(/bla/, string.length + 1)
+ $~.should == nil
+ end
+
it "starts the search at the given offset" do
"blablabla".index(/.{0}/, 5).should == 5
"blablabla".index(/.{1}/, 5).should == 5
@@ -263,7 +287,7 @@ describe "String#index with Regexp" do
end
it "returns nil if the Regexp matches the empty string and the offset is out of range" do
- "ruby".index(//,12).should be_nil
+ "ruby".index(//,12).should == nil
end
it "supports \\G which matches at the given start offset" do
@@ -308,6 +332,6 @@ describe "String#index with Regexp" do
re = Regexp.new "れ".encode(Encoding::EUC_JP)
-> do
"あれ".index re
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError, "incompatible encoding regexp match (EUC-JP regexp with UTF-8 string)")
end
end
diff --git a/spec/ruby/core/string/initialize_spec.rb b/spec/ruby/core/string/initialize_spec.rb
index 08734cc916..b0c1e2e573 100644
--- a/spec/ruby/core/string/initialize_spec.rb
+++ b/spec/ruby/core/string/initialize_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/replace'
describe "String#initialize" do
it "is a private method" do
- String.should have_private_instance_method(:initialize)
+ String.private_instance_methods(false).should.include?(:initialize)
end
describe "with no arguments" do
@@ -16,7 +16,7 @@ describe "String#initialize" do
it "does not raise an exception when frozen" do
a = "hello".freeze
- a.send(:initialize).should equal(a)
+ a.send(:initialize).should.equal?(a)
end
end
diff --git a/spec/ruby/core/string/insert_spec.rb b/spec/ruby/core/string/insert_spec.rb
index 0c87df3a95..c89793a8ca 100644
--- a/spec/ruby/core/string/insert_spec.rb
+++ b/spec/ruby/core/string/insert_spec.rb
@@ -1,5 +1,5 @@
# -*- encoding: utf-8 -*-
-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -23,8 +23,8 @@ describe "String#insert with index, other" do
end
it "raises an IndexError if the index is beyond string" do
- -> { "abcd".insert(5, 'X') }.should raise_error(IndexError)
- -> { "abcd".insert(-6, 'X') }.should raise_error(IndexError)
+ -> { "abcd".insert(5, 'X') }.should.raise(IndexError)
+ -> { "abcd".insert(-6, 'X') }.should.raise(IndexError)
end
it "converts index to an integer using to_int" do
@@ -42,15 +42,15 @@ describe "String#insert with index, other" do
end
it "raises a TypeError if other can't be converted to string" do
- -> { "abcd".insert(-6, Object.new)}.should raise_error(TypeError)
- -> { "abcd".insert(-6, []) }.should raise_error(TypeError)
- -> { "abcd".insert(-6, mock('x')) }.should raise_error(TypeError)
+ -> { "abcd".insert(-6, Object.new)}.should.raise(TypeError)
+ -> { "abcd".insert(-6, []) }.should.raise(TypeError)
+ -> { "abcd".insert(-6, mock('x')) }.should.raise(TypeError)
end
it "raises a FrozenError if self is frozen" do
str = "abcd".freeze
- -> { str.insert(4, '') }.should raise_error(FrozenError)
- -> { str.insert(4, 'X') }.should raise_error(FrozenError)
+ -> { str.insert(4, '') }.should.raise(FrozenError)
+ -> { str.insert(4, 'X') }.should.raise(FrozenError)
end
it "inserts a character into a multibyte encoded string" do
@@ -67,7 +67,7 @@ describe "String#insert with index, other" do
pat = "ア".encode Encoding::EUC_JP
-> do
"あれ".insert 0, pat
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError)
end
it "should not call subclassed string methods" do
diff --git a/spec/ruby/core/string/inspect_spec.rb b/spec/ruby/core/string/inspect_spec.rb
index 8bf3d3161f..8b91ce2f84 100644
--- a/spec/ruby/core/string/inspect_spec.rb
+++ b/spec/ruby/core/string/inspect_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
describe "String#inspect" do
it "does not return a subclass instance" do
- StringSpecs::MyString.new.inspect.should be_an_instance_of(String)
+ StringSpecs::MyString.new.inspect.should.instance_of?(String)
end
it "returns a string with special characters replaced with \\<char> notation" do
@@ -327,7 +327,7 @@ describe "String#inspect" do
end
it "works for broken US-ASCII strings" do
- s = "©".force_encoding("US-ASCII")
+ s = "©".dup.force_encoding("US-ASCII")
s.inspect.should == '"\xC2\xA9"'
end
diff --git a/spec/ruby/core/string/lines_spec.rb b/spec/ruby/core/string/lines_spec.rb
index ad4b119074..40ab5f71d8 100644
--- a/spec/ruby/core/string/lines_spec.rb
+++ b/spec/ruby/core/string/lines_spec.rb
@@ -1,7 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/each_line'
-require_relative 'shared/each_line_without_block'
describe "String#lines" do
it_behaves_like :string_each_line, :lines
diff --git a/spec/ruby/core/string/ljust_spec.rb b/spec/ruby/core/string/ljust_spec.rb
index 9a25d3abd4..0b2aab2638 100644
--- a/spec/ruby/core/string/ljust_spec.rb
+++ b/spec/ruby/core/string/ljust_spec.rb
@@ -41,10 +41,10 @@ describe "String#ljust with length, padding" do
end
it "raises a TypeError when length can't be converted to an integer" do
- -> { "hello".ljust("x") }.should raise_error(TypeError)
- -> { "hello".ljust("x", "y") }.should raise_error(TypeError)
- -> { "hello".ljust([]) }.should raise_error(TypeError)
- -> { "hello".ljust(mock('x')) }.should raise_error(TypeError)
+ -> { "hello".ljust("x") }.should.raise(TypeError)
+ -> { "hello".ljust("x", "y") }.should.raise(TypeError)
+ -> { "hello".ljust([]) }.should.raise(TypeError)
+ -> { "hello".ljust(mock('x')) }.should.raise(TypeError)
end
it "tries to convert padstr to a string using to_str" do
@@ -55,59 +55,46 @@ describe "String#ljust with length, padding" do
end
it "raises a TypeError when padstr can't be converted" do
- -> { "hello".ljust(20, []) }.should raise_error(TypeError)
- -> { "hello".ljust(20, Object.new)}.should raise_error(TypeError)
- -> { "hello".ljust(20, mock('x')) }.should raise_error(TypeError)
+ -> { "hello".ljust(20, []) }.should.raise(TypeError)
+ -> { "hello".ljust(20, Object.new)}.should.raise(TypeError)
+ -> { "hello".ljust(20, mock('x')) }.should.raise(TypeError)
end
it "raises an ArgumentError when padstr is empty" do
- -> { "hello".ljust(10, '') }.should raise_error(ArgumentError)
+ -> { "hello".ljust(10, '') }.should.raise(ArgumentError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on subclasses" do
- StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString)
+ it "returns String instances when called on subclasses" do
+ StringSpecs::MyString.new("").ljust(10).should.instance_of?(String)
+ StringSpecs::MyString.new("foo").ljust(10).should.instance_of?(String)
+ StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should.instance_of?(String)
- "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances when called on subclasses" do
- StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
-
- "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- end
+ "".ljust(10, StringSpecs::MyString.new("x")).should.instance_of?(String)
+ "foo".ljust(10, StringSpecs::MyString.new("x")).should.instance_of?(String)
end
describe "with width" do
it "returns a String in the same encoding as the original" do
- str = "abc".force_encoding Encoding::IBM437
+ str = "abc".dup.force_encoding Encoding::IBM437
result = str.ljust 5
result.should == "abc "
- result.encoding.should equal(Encoding::IBM437)
+ result.encoding.should.equal?(Encoding::IBM437)
end
end
describe "with width, pattern" do
it "returns a String in the compatible encoding" do
- str = "abc".force_encoding Encoding::IBM437
+ str = "abc".dup.force_encoding Encoding::IBM437
result = str.ljust 5, "あ"
result.should == "abcああ"
- result.encoding.should equal(Encoding::UTF_8)
+ result.encoding.should.equal?(Encoding::UTF_8)
end
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
pat = "ア".encode Encoding::EUC_JP
-> do
"あれ".ljust 5, pat
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError)
end
end
end
diff --git a/spec/ruby/core/string/lstrip_spec.rb b/spec/ruby/core/string/lstrip_spec.rb
index 75434613f1..5896f8d7da 100644
--- a/spec/ruby/core/string/lstrip_spec.rb
+++ b/spec/ruby/core/string/lstrip_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/strip'
@@ -6,11 +7,11 @@ describe "String#lstrip" do
it_behaves_like :string_strip, :lstrip
it "returns a copy of self with leading whitespace removed" do
- " hello ".lstrip.should == "hello "
- " hello world ".lstrip.should == "hello world "
- "\n\r\t\n\v\r hello world ".lstrip.should == "hello world "
- "hello".lstrip.should == "hello"
- " こにちわ".lstrip.should == "こにちわ"
+ " hello ".lstrip.should == "hello "
+ " hello world ".lstrip.should == "hello world "
+ "\n\r\t\n\v\r hello world ".lstrip.should == "hello world "
+ "hello".lstrip.should == "hello"
+ " こにちわ".lstrip.should == "こにちわ"
end
it "works with lazy substrings" do
@@ -20,18 +21,16 @@ describe "String#lstrip" do
" こにちわ "[1...-1].lstrip.should == "こにちわ"
end
- ruby_version_is '3.0' do
- it "strips leading \\0" do
- "\x00hello".lstrip.should == "hello"
- "\000 \000hello\000 \000".lstrip.should == "hello\000 \000"
- end
+ it "strips leading \\0" do
+ "\x00hello".lstrip.should == "hello"
+ "\000 \000hello\000 \000".lstrip.should == "hello\000 \000"
end
end
describe "String#lstrip!" do
it "modifies self in place and returns self" do
a = " hello "
- a.lstrip!.should equal(a)
+ a.lstrip!.should.equal?(a)
a.should == "hello "
end
@@ -47,31 +46,29 @@ describe "String#lstrip!" do
" ".lstrip.should == ""
end
- ruby_version_is '3.0' do
- it "removes leading NULL bytes and whitespace" do
- a = "\000 \000hello\000 \000"
- a.lstrip!
- a.should == "hello\000 \000"
- end
+ it "removes leading NULL bytes and whitespace" do
+ a = "\000 \000hello\000 \000"
+ a.lstrip!
+ a.should == "hello\000 \000"
end
it "raises a FrozenError on a frozen instance that is modified" do
- -> { " hello ".freeze.lstrip! }.should raise_error(FrozenError)
+ -> { " hello ".freeze.lstrip! }.should.raise(FrozenError)
end
# see [ruby-core:23657]
it "raises a FrozenError on a frozen instance that would not be modified" do
- -> { "hello".freeze.lstrip! }.should raise_error(FrozenError)
- -> { "".freeze.lstrip! }.should raise_error(FrozenError)
+ -> { "hello".freeze.lstrip! }.should.raise(FrozenError)
+ -> { "".freeze.lstrip! }.should.raise(FrozenError)
end
it "raises an ArgumentError if the first non-space codepoint is invalid" do
s = "\xDFabc".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.lstrip! }.should raise_error(ArgumentError)
+ s.valid_encoding?.should == false
+ -> { s.lstrip! }.should.raise(ArgumentError)
s = " \xDFabc".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.lstrip! }.should raise_error(ArgumentError)
+ s.valid_encoding?.should == false
+ -> { s.lstrip! }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/match_spec.rb b/spec/ruby/core/string/match_spec.rb
index 5e988f34ca..3ea8d90aa8 100644
--- a/spec/ruby/core/string/match_spec.rb
+++ b/spec/ruby/core/string/match_spec.rb
@@ -19,8 +19,8 @@ describe "String#=~" do
end
it "raises a TypeError if a obj is a string" do
- -> { "some string" =~ "another string" }.should raise_error(TypeError)
- -> { "a" =~ StringSpecs::MyString.new("b") }.should raise_error(TypeError)
+ -> { "some string" =~ "another string" }.should.raise(TypeError)
+ -> { "a" =~ StringSpecs::MyString.new("b") }.should.raise(TypeError)
end
it "invokes obj.=~ with self if obj is neither a string nor regexp" do
@@ -81,7 +81,7 @@ describe "String#match" do
describe "when passed a block" do
it "yields the MatchData" do
"abc".match(/./) {|m| ScratchPad.record m }
- ScratchPad.recorded.should be_kind_of(MatchData)
+ ScratchPad.recorded.should.is_a?(MatchData)
end
it "returns the block result" do
@@ -107,9 +107,9 @@ describe "String#match" do
end
it "raises a TypeError if pattern is not a regexp or a string" do
- -> { 'hello'.match(10) }.should raise_error(TypeError)
+ -> { 'hello'.match(10) }.should.raise(TypeError)
not_supported_on :opal do
- -> { 'hello'.match(:ell) }.should raise_error(TypeError)
+ -> { 'hello'.match(:ell) }.should.raise(TypeError)
end
end
@@ -137,9 +137,17 @@ describe "String#match" do
end
it "calls match on the regular expression" do
- regexp = /./.dup
- regexp.should_receive(:match).and_return(:foo)
- 'hello'.match(regexp).should == :foo
+ # Can't use regexp.should_receive(:match).and_return(:foo) since regexps are frozen
+ ScratchPad.clear
+ regexp = Class.new(Regexp) {
+ def match(*args)
+ ScratchPad.record [:match, *args]
+ super(*args)
+ end
+ }.new('.')
+
+ 'hello'.match(regexp)
+ ScratchPad.recorded.should == [:match, 'hello']
end
end
@@ -151,17 +159,17 @@ describe "String#match?" do
context "when matches the given regex" do
it "returns true but does not set Regexp.last_match" do
- 'string'.match?(/string/i).should be_true
- Regexp.last_match.should be_nil
+ 'string'.match?(/string/i).should == true
+ Regexp.last_match.should == nil
end
end
it "returns false when does not match the given regex" do
- 'string'.match?(/STRING/).should be_false
+ 'string'.match?(/STRING/).should == false
end
it "takes matching position as the 2nd argument" do
- 'string'.match?(/str/i, 0).should be_true
- 'string'.match?(/str/i, 1).should be_false
+ 'string'.match?(/str/i, 0).should == true
+ 'string'.match?(/str/i, 1).should == false
end
end
diff --git a/spec/ruby/core/string/modulo_spec.rb b/spec/ruby/core/string/modulo_spec.rb
index 99c1694417..f93ec4bcf8 100644
--- a/spec/ruby/core/string/modulo_spec.rb
+++ b/spec/ruby/core/string/modulo_spec.rb
@@ -46,42 +46,57 @@ describe "String#%" do
end
it "raises if a compatible encoding can't be found" do
- -> { "hello %s".encode("utf-8") % "world".encode("UTF-16LE") }.should raise_error(Encoding::CompatibilityError)
+ -> { "hello %s".encode("utf-8") % "world".encode("UTF-16LE") }.should.raise(Encoding::CompatibilityError)
end
end
it "raises an error if single % appears at the end" do
- -> { ("%" % []) }.should raise_error(ArgumentError)
- -> { ("foo%" % [])}.should raise_error(ArgumentError)
+ -> { ("%" % []) }.should.raise(ArgumentError)
+ -> { ("foo%" % [])}.should.raise(ArgumentError)
end
- it "formats single % character before a newline as literal %" do
- ("%\n" % []).should == "%\n"
- ("foo%\n" % []).should == "foo%\n"
- ("%\n.3f" % 1.2).should == "%\n.3f"
- end
+ ruby_version_is ""..."3.4" do
+ it "formats single % character before a newline as literal %" do
+ ("%\n" % []).should == "%\n"
+ ("foo%\n" % []).should == "foo%\n"
+ ("%\n.3f" % 1.2).should == "%\n.3f"
+ end
- it "formats single % character before a NUL as literal %" do
- ("%\0" % []).should == "%\0"
- ("foo%\0" % []).should == "foo%\0"
- ("%\0.3f" % 1.2).should == "%\0.3f"
- end
+ it "formats single % character before a NUL as literal %" do
+ ("%\0" % []).should == "%\0"
+ ("foo%\0" % []).should == "foo%\0"
+ ("%\0.3f" % 1.2).should == "%\0.3f"
+ end
- it "raises an error if single % appears anywhere else" do
- -> { (" % " % []) }.should raise_error(ArgumentError)
- -> { ("foo%quux" % []) }.should raise_error(ArgumentError)
- end
+ it "raises an error if single % appears anywhere else" do
+ -> { (" % " % []) }.should.raise(ArgumentError)
+ -> { ("foo%quux" % []) }.should.raise(ArgumentError)
+ end
- it "raises an error if NULL or \\n appear anywhere else in the format string" do
- begin
- old_debug, $DEBUG = $DEBUG, false
+ it "raises an error if NULL or \\n appear anywhere else in the format string" do
+ begin
+ old_debug, $DEBUG = $DEBUG, false
- -> { "%.\n3f" % 1.2 }.should raise_error(ArgumentError)
- -> { "%.3\nf" % 1.2 }.should raise_error(ArgumentError)
- -> { "%.\03f" % 1.2 }.should raise_error(ArgumentError)
- -> { "%.3\0f" % 1.2 }.should raise_error(ArgumentError)
- ensure
- $DEBUG = old_debug
+ -> { "%.\n3f" % 1.2 }.should.raise(ArgumentError)
+ -> { "%.3\nf" % 1.2 }.should.raise(ArgumentError)
+ -> { "%.\03f" % 1.2 }.should.raise(ArgumentError)
+ -> { "%.3\0f" % 1.2 }.should.raise(ArgumentError)
+ ensure
+ $DEBUG = old_debug
+ end
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError if % is not followed by a conversion specifier" do
+ -> { "%" % [] }.should.raise(ArgumentError)
+ -> { "%\n" % [] }.should.raise(ArgumentError)
+ -> { "%\0" % [] }.should.raise(ArgumentError)
+ -> { " % " % [] }.should.raise(ArgumentError)
+ -> { "%.\n3f" % 1.2 }.should.raise(ArgumentError)
+ -> { "%.3\nf" % 1.2 }.should.raise(ArgumentError)
+ -> { "%.\03f" % 1.2 }.should.raise(ArgumentError)
+ -> { "%.3\0f" % 1.2 }.should.raise(ArgumentError)
end
end
@@ -104,8 +119,8 @@ describe "String#%" do
s = $stderr
$stderr = IOStub.new
- -> { "" % [1, 2, 3] }.should raise_error(ArgumentError)
- -> { "%s" % [1, 2, 3] }.should raise_error(ArgumentError)
+ -> { "" % [1, 2, 3] }.should.raise(ArgumentError)
+ -> { "%s" % [1, 2, 3] }.should.raise(ArgumentError)
ensure
$DEBUG = old_debug
$stderr = s
@@ -125,26 +140,34 @@ describe "String#%" do
end
end
- it "replaces trailing absolute argument specifier without type with percent sign" do
- ("hello %1$" % "foo").should == "hello %"
+ ruby_version_is ""..."3.4" do
+ it "replaces trailing absolute argument specifier without type with percent sign" do
+ ("hello %1$" % "foo").should == "hello %"
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError if absolute argument specifier is followed by a conversion specifier" do
+ -> { "hello %1$" % "foo" }.should.raise(ArgumentError)
+ end
end
it "raises an ArgumentError when given invalid argument specifiers" do
- -> { "%1" % [] }.should raise_error(ArgumentError)
- -> { "%+" % [] }.should raise_error(ArgumentError)
- -> { "%-" % [] }.should raise_error(ArgumentError)
- -> { "%#" % [] }.should raise_error(ArgumentError)
- -> { "%0" % [] }.should raise_error(ArgumentError)
- -> { "%*" % [] }.should raise_error(ArgumentError)
- -> { "%." % [] }.should raise_error(ArgumentError)
- -> { "%_" % [] }.should raise_error(ArgumentError)
- -> { "%0$s" % "x" }.should raise_error(ArgumentError)
- -> { "%*0$s" % [5, "x"] }.should raise_error(ArgumentError)
- -> { "%*1$.*0$1$s" % [1, 2, 3] }.should raise_error(ArgumentError)
+ -> { "%1" % [] }.should.raise(ArgumentError)
+ -> { "%+" % [] }.should.raise(ArgumentError)
+ -> { "%-" % [] }.should.raise(ArgumentError)
+ -> { "%#" % [] }.should.raise(ArgumentError)
+ -> { "%0" % [] }.should.raise(ArgumentError)
+ -> { "%*" % [] }.should.raise(ArgumentError)
+ -> { "%." % [] }.should.raise(ArgumentError)
+ -> { "%_" % [] }.should.raise(ArgumentError)
+ -> { "%0$s" % "x" }.should.raise(ArgumentError)
+ -> { "%*0$s" % [5, "x"] }.should.raise(ArgumentError)
+ -> { "%*1$.*0$1$s" % [1, 2, 3] }.should.raise(ArgumentError)
end
it "raises an ArgumentError when multiple positional argument tokens are given for one format specifier" do
- -> { "%1$1$s" % "foo" }.should raise_error(ArgumentError)
+ -> { "%1$1$s" % "foo" }.should.raise(ArgumentError)
end
it "respects positional arguments and precision tokens given for one format specifier" do
@@ -160,36 +183,36 @@ describe "String#%" do
end
it "raises an ArgumentError when multiple width star tokens are given for one format specifier" do
- -> { "%**s" % [5, 5, 5] }.should raise_error(ArgumentError)
+ -> { "%**s" % [5, 5, 5] }.should.raise(ArgumentError)
end
it "raises an ArgumentError when a width star token is seen after a width token" do
- -> { "%5*s" % [5, 5] }.should raise_error(ArgumentError)
+ -> { "%5*s" % [5, 5] }.should.raise(ArgumentError)
end
it "raises an ArgumentError when multiple precision tokens are given" do
- -> { "%.5.5s" % 5 }.should raise_error(ArgumentError)
- -> { "%.5.*s" % [5, 5] }.should raise_error(ArgumentError)
- -> { "%.*.5s" % [5, 5] }.should raise_error(ArgumentError)
+ -> { "%.5.5s" % 5 }.should.raise(ArgumentError)
+ -> { "%.5.*s" % [5, 5] }.should.raise(ArgumentError)
+ -> { "%.*.5s" % [5, 5] }.should.raise(ArgumentError)
end
it "raises an ArgumentError when there are less arguments than format specifiers" do
("foo" % []).should == "foo"
- -> { "%s" % [] }.should raise_error(ArgumentError)
- -> { "%s %s" % [1] }.should raise_error(ArgumentError)
+ -> { "%s" % [] }.should.raise(ArgumentError)
+ -> { "%s %s" % [1] }.should.raise(ArgumentError)
end
it "raises an ArgumentError when absolute and relative argument numbers are mixed" do
- -> { "%s %1$s" % "foo" }.should raise_error(ArgumentError)
- -> { "%1$s %s" % "foo" }.should raise_error(ArgumentError)
+ -> { "%s %1$s" % "foo" }.should.raise(ArgumentError)
+ -> { "%1$s %s" % "foo" }.should.raise(ArgumentError)
- -> { "%s %2$s" % ["foo", "bar"] }.should raise_error(ArgumentError)
- -> { "%2$s %s" % ["foo", "bar"] }.should raise_error(ArgumentError)
+ -> { "%s %2$s" % ["foo", "bar"] }.should.raise(ArgumentError)
+ -> { "%2$s %s" % ["foo", "bar"] }.should.raise(ArgumentError)
- -> { "%*2$s" % [5, 5, 5] }.should raise_error(ArgumentError)
- -> { "%*.*2$s" % [5, 5, 5] }.should raise_error(ArgumentError)
- -> { "%*2$.*2$s" % [5, 5, 5] }.should raise_error(ArgumentError)
- -> { "%*.*2$s" % [5, 5, 5] }.should raise_error(ArgumentError)
+ -> { "%*2$s" % [5, 5, 5] }.should.raise(ArgumentError)
+ -> { "%*.*2$s" % [5, 5, 5] }.should.raise(ArgumentError)
+ -> { "%*2$.*2$s" % [5, 5, 5] }.should.raise(ArgumentError)
+ -> { "%*.*2$s" % [5, 5, 5] }.should.raise(ArgumentError)
end
it "allows reuse of the one argument multiple via absolute argument numbers" do
@@ -198,13 +221,13 @@ describe "String#%" do
end
it "always interprets an array argument as a list of argument parameters" do
- -> { "%p" % [] }.should raise_error(ArgumentError)
+ -> { "%p" % [] }.should.raise(ArgumentError)
("%p" % [1]).should == "1"
("%p %p" % [1, 2]).should == "1 2"
end
it "always interprets an array subclass argument as a list of argument parameters" do
- -> { "%p" % StringSpecs::MyArray[] }.should raise_error(ArgumentError)
+ -> { "%p" % StringSpecs::MyArray[] }.should.raise(ArgumentError)
("%p" % StringSpecs::MyArray[1]).should == "1"
("%p %p" % StringSpecs::MyArray[1, 2]).should == "1 2"
end
@@ -275,7 +298,7 @@ describe "String#%" do
x = mock("string modulo to_ary")
x.should_receive(:to_ary).and_return("x")
- -> { "%s" % x }.should raise_error(TypeError)
+ -> { "%s" % x }.should.raise(TypeError)
end
it "tries to convert the argument to Array by calling #to_ary" do
@@ -298,7 +321,7 @@ describe "String#%" do
"%f", "%g", "%G", "%i", "%o", "%p",
"%s", "%u", "%x", "%X"
].each do |format|
- (StringSpecs::MyString.new(format) % universal).should be_an_instance_of(String)
+ (StringSpecs::MyString.new(format) % universal).should.instance_of?(String)
end
end
@@ -361,15 +384,15 @@ describe "String#%" do
("%*c" % [10, 3]).should == " \003"
("%c" % 42).should == "*"
- -> { "%c" % Object }.should raise_error(TypeError)
+ -> { "%c" % Object }.should.raise(TypeError)
end
it "supports single character strings as argument for %c" do
("%c" % 'A').should == "A"
end
- it "raises an exception for multiple character strings as argument for %c" do
- -> { "%c" % 'AA' }.should raise_error(ArgumentError)
+ it "supports only the first character as argument for %c" do
+ ("%c" % 'AA').should == "A"
end
it "calls to_str on argument for %c formats" do
@@ -539,7 +562,7 @@ describe "String#%" do
("%1$p" % [10, 5]).should == "10"
("%-22p" % 10).should == "10 "
("%*p" % [10, 10]).should == " 10"
- ("%p" % {capture: 1}).should == "{:capture=>1}"
+ ("%p" % {capture: 1}).should == {capture: 1}.inspect
("%p" % "str").should == "\"str\""
end
@@ -587,7 +610,7 @@ describe "String#%" do
# See http://groups.google.com/group/ruby-core-google/t/c285c18cd94c216d
it "raises an ArgumentError for huge precisions for %s" do
block = -> { "%.25555555555555555555555555555555555555s" % "hello world" }
- block.should raise_error(ArgumentError)
+ block.should.raise(ArgumentError)
end
# Note: %u has been changed to an alias for %d in 1.9.
@@ -682,16 +705,16 @@ describe "String#%" do
-> {
# see [ruby-core:14139] for more details
(format % "0777").should == (format % Kernel.Integer("0777"))
- }.should_not raise_error(ArgumentError)
+ }.should_not.raise(ArgumentError)
- -> { format % "0__7_7_7" }.should raise_error(ArgumentError)
+ -> { format % "0__7_7_7" }.should.raise(ArgumentError)
- -> { format % "" }.should raise_error(ArgumentError)
- -> { format % "x" }.should raise_error(ArgumentError)
- -> { format % "5x" }.should raise_error(ArgumentError)
- -> { format % "08" }.should raise_error(ArgumentError)
- -> { format % "0b2" }.should raise_error(ArgumentError)
- -> { format % "123__456" }.should raise_error(ArgumentError)
+ -> { format % "" }.should.raise(ArgumentError)
+ -> { format % "x" }.should.raise(ArgumentError)
+ -> { format % "5x" }.should.raise(ArgumentError)
+ -> { format % "08" }.should.raise(ArgumentError)
+ -> { format % "0b2" }.should.raise(ArgumentError)
+ -> { format % "123__456" }.should.raise(ArgumentError)
obj = mock('5')
obj.should_receive(:to_i).and_return(5)
@@ -718,21 +741,25 @@ describe "String#%" do
(format % "-10.4e-20").should == (format % -10.4e-20)
(format % ".5").should == (format % 0.5)
(format % "-.5").should == (format % -0.5)
+
+ ruby_version_is "3.4" do
+ (format % "10.").should == (format % 10)
+ end
+
# Something's strange with this spec:
# it works just fine in individual mode, but not when run as part of a group
(format % "10_1_0.5_5_5").should == (format % 1010.555)
(format % "0777").should == (format % 777)
- -> { format % "" }.should raise_error(ArgumentError)
- -> { format % "x" }.should raise_error(ArgumentError)
- -> { format % "." }.should raise_error(ArgumentError)
- -> { format % "10." }.should raise_error(ArgumentError)
- -> { format % "5x" }.should raise_error(ArgumentError)
- -> { format % "0b1" }.should raise_error(ArgumentError)
- -> { format % "10e10.5" }.should raise_error(ArgumentError)
- -> { format % "10__10" }.should raise_error(ArgumentError)
- -> { format % "10.10__10" }.should raise_error(ArgumentError)
+ -> { format % "" }.should.raise(ArgumentError)
+ -> { format % "x" }.should.raise(ArgumentError)
+ -> { format % "." }.should.raise(ArgumentError)
+ -> { format % "5x" }.should.raise(ArgumentError)
+ -> { format % "0b1" }.should.raise(ArgumentError)
+ -> { format % "10e10.5" }.should.raise(ArgumentError)
+ -> { format % "10__10" }.should.raise(ArgumentError)
+ -> { format % "10.10__10" }.should.raise(ArgumentError)
obj = mock('5.0')
obj.should_receive(:to_f).and_return(5.0)
@@ -750,7 +777,7 @@ describe "String#%" do
end
it "should raise ArgumentError if no hash given" do
- -> {"%{foo}" % []}.should raise_error(ArgumentError)
+ -> {"%{foo}" % []}.should.raise(ArgumentError)
end
end
@@ -760,11 +787,11 @@ describe "String#%" do
end
it "raises KeyError if key is missing from passed-in hash" do
- -> {"%<foo>d" % {}}.should raise_error(KeyError)
+ -> {"%<foo>d" % {}}.should.raise(KeyError)
end
it "should raise ArgumentError if no hash given" do
- -> {"%<foo>" % []}.should raise_error(ArgumentError)
+ -> {"%<foo>" % []}.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/string/new_spec.rb b/spec/ruby/core/string/new_spec.rb
index ca678f5323..aadf1e0e46 100644
--- a/spec/ruby/core/string/new_spec.rb
+++ b/spec/ruby/core/string/new_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
describe "String.new" do
it "returns an instance of String" do
str = String.new
- str.should be_an_instance_of(String)
+ str.should.instance_of?(String)
end
it "accepts an encoding argument" do
@@ -28,7 +28,7 @@ describe "String.new" do
it "returns a new string given a string argument" do
str1 = "test"
str = String.new(str1)
- str.should be_an_instance_of(String)
+ str.should.instance_of?(String)
str.should == str1
str << "more"
str.should == "testmore"
@@ -36,7 +36,7 @@ describe "String.new" do
it "returns an instance of a subclass" do
a = StringSpecs::MyString.new("blah")
- a.should be_an_instance_of(StringSpecs::MyString)
+ a.should.instance_of?(StringSpecs::MyString)
a.should == "blah"
end
@@ -51,8 +51,8 @@ describe "String.new" do
end
it "raises TypeError on inconvertible object" do
- -> { String.new 5 }.should raise_error(TypeError)
- -> { String.new nil }.should raise_error(TypeError)
+ -> { String.new 5 }.should.raise(TypeError)
+ -> { String.new nil }.should.raise(TypeError)
end
it "returns a binary String" do
diff --git a/spec/ruby/core/string/ord_spec.rb b/spec/ruby/core/string/ord_spec.rb
index 4cf26990fe..5a17fc1d87 100644
--- a/spec/ruby/core/string/ord_spec.rb
+++ b/spec/ruby/core/string/ord_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "String#ord" do
it "returns an Integer" do
- 'a'.ord.should be_an_instance_of(Integer)
+ 'a'.ord.should.instance_of?(Integer)
end
it "returns the codepoint of the first character in the String" do
@@ -23,11 +23,11 @@ describe "String#ord" do
end
it "raises an ArgumentError if called on an empty String" do
- -> { ''.ord }.should raise_error(ArgumentError)
+ -> { ''.ord }.should.raise(ArgumentError)
end
it "raises ArgumentError if the character is broken" do
- s = "©".force_encoding("US-ASCII")
- -> { s.ord }.should raise_error(ArgumentError, "invalid byte sequence in US-ASCII")
+ s = "©".dup.force_encoding("US-ASCII")
+ -> { s.ord }.should.raise(ArgumentError, "invalid byte sequence in US-ASCII")
end
end
diff --git a/spec/ruby/core/string/partition_spec.rb b/spec/ruby/core/string/partition_spec.rb
index 98311f2be4..29fe910b39 100644
--- a/spec/ruby/core/string/partition_spec.rb
+++ b/spec/ruby/core/string/partition_spec.rb
@@ -31,11 +31,33 @@ describe "String#partition with String" do
end
it "raises an error if not convertible to string" do
- ->{ "hello".partition(5) }.should raise_error(TypeError)
- ->{ "hello".partition(nil) }.should raise_error(TypeError)
+ ->{ "hello".partition(5) }.should.raise(TypeError)
+ ->{ "hello".partition(nil) }.should.raise(TypeError)
end
it "takes precedence over a given block" do
"hello world".partition("o") { true }.should == ["hell", "o", " world"]
end
+
+ it "handles a pattern in a superset encoding" do
+ string = "hello".dup.force_encoding(Encoding::US_ASCII)
+
+ result = string.partition("é")
+
+ result.should == ["hello", "", ""]
+ result[0].encoding.should == Encoding::US_ASCII
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ pattern = "o".dup.force_encoding(Encoding::US_ASCII)
+
+ result = "héllo world".partition(pattern)
+
+ result.should == ["héll", "o", " world"]
+ result[0].encoding.should == Encoding::UTF_8
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::UTF_8
+ end
end
diff --git a/spec/ruby/core/string/plus_spec.rb b/spec/ruby/core/string/plus_spec.rb
index 5ff198f07e..0464141c37 100644
--- a/spec/ruby/core/string/plus_spec.rb
+++ b/spec/ruby/core/string/plus_spec.rb
@@ -3,6 +3,9 @@ require_relative 'fixtures/classes'
require_relative 'shared/concat'
describe "String#+" do
+ it_behaves_like :string_concat_encoding, :+
+ it_behaves_like :string_concat_type_coercion, :+
+
it "returns a new string containing the given string concatenated to self" do
("" + "").should == ""
("" + "Hello").should == "Hello"
@@ -18,19 +21,17 @@ describe "String#+" do
end
it "raises a TypeError when given any object that fails #to_str" do
- -> { "" + Object.new }.should raise_error(TypeError)
- -> { "" + 65 }.should raise_error(TypeError)
+ -> { "" + Object.new }.should.raise(TypeError)
+ -> { "" + 65 }.should.raise(TypeError)
end
it "doesn't return subclass instances" do
- (StringSpecs::MyString.new("hello") + "").should be_an_instance_of(String)
- (StringSpecs::MyString.new("hello") + "foo").should be_an_instance_of(String)
- (StringSpecs::MyString.new("hello") + StringSpecs::MyString.new("foo")).should be_an_instance_of(String)
- (StringSpecs::MyString.new("hello") + StringSpecs::MyString.new("")).should be_an_instance_of(String)
- (StringSpecs::MyString.new("") + StringSpecs::MyString.new("")).should be_an_instance_of(String)
- ("hello" + StringSpecs::MyString.new("foo")).should be_an_instance_of(String)
- ("hello" + StringSpecs::MyString.new("")).should be_an_instance_of(String)
+ (StringSpecs::MyString.new("hello") + "").should.instance_of?(String)
+ (StringSpecs::MyString.new("hello") + "foo").should.instance_of?(String)
+ (StringSpecs::MyString.new("hello") + StringSpecs::MyString.new("foo")).should.instance_of?(String)
+ (StringSpecs::MyString.new("hello") + StringSpecs::MyString.new("")).should.instance_of?(String)
+ (StringSpecs::MyString.new("") + StringSpecs::MyString.new("")).should.instance_of?(String)
+ ("hello" + StringSpecs::MyString.new("foo")).should.instance_of?(String)
+ ("hello" + StringSpecs::MyString.new("")).should.instance_of?(String)
end
-
- it_behaves_like :string_concat_encoding, :+
end
diff --git a/spec/ruby/core/string/prepend_spec.rb b/spec/ruby/core/string/prepend_spec.rb
index a0393d4760..a8da4e62cb 100644
--- a/spec/ruby/core/string/prepend_spec.rb
+++ b/spec/ruby/core/string/prepend_spec.rb
@@ -1,10 +1,11 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "String#prepend" do
it "prepends the given argument to self and returns self" do
str = "world"
- str.prepend("hello ").should equal(str)
+ str.prepend("hello ").should.equal?(str)
str.should == "hello world"
end
@@ -16,16 +17,16 @@ describe "String#prepend" do
end
it "raises a TypeError if the given argument can't be converted to a String" do
- -> { "hello ".prepend [] }.should raise_error(TypeError)
- -> { 'hello '.prepend mock('x') }.should raise_error(TypeError)
+ -> { "hello ".prepend [] }.should.raise(TypeError)
+ -> { 'hello '.prepend mock('x') }.should.raise(TypeError)
end
it "raises a FrozenError when self is frozen" do
a = "hello"
a.freeze
- -> { a.prepend "" }.should raise_error(FrozenError)
- -> { a.prepend "test" }.should raise_error(FrozenError)
+ -> { a.prepend "" }.should.raise(FrozenError)
+ -> { a.prepend "test" }.should.raise(FrozenError)
end
it "works when given a subclass instance" do
@@ -48,7 +49,7 @@ describe "String#prepend" do
it "returns self when given no arguments" do
str = "hello"
- str.prepend.should equal(str)
+ str.prepend.should.equal?(str)
str.should == "hello"
end
end
diff --git a/spec/ruby/core/string/reverse_spec.rb b/spec/ruby/core/string/reverse_spec.rb
index 4206b8af90..e37c1125db 100644
--- a/spec/ruby/core/string/reverse_spec.rb
+++ b/spec/ruby/core/string/reverse_spec.rb
@@ -1,4 +1,5 @@
# encoding: utf-8
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -10,20 +11,10 @@ describe "String#reverse" do
"".reverse.should == ""
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("stressed").reverse.should be_an_instance_of(String)
- StringSpecs::MyString.new("m").reverse.should be_an_instance_of(String)
- StringSpecs::MyString.new("").reverse.should be_an_instance_of(String)
- end
- end
-
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("stressed").reverse.should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("m").reverse.should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("").reverse.should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("stressed").reverse.should.instance_of?(String)
+ StringSpecs::MyString.new("m").reverse.should.instance_of?(String)
+ StringSpecs::MyString.new("").reverse.should.instance_of?(String)
end
it "reverses a string with multi byte characters" do
@@ -33,29 +24,33 @@ describe "String#reverse" do
it "works with a broken string" do
str = "微軟\xDF\xDE正黑體".force_encoding(Encoding::UTF_8)
- str.valid_encoding?.should be_false
+ str.valid_encoding?.should == false
str.reverse.should == "體黑正\xDE\xDF軟微"
end
+
+ it "returns a String in the same encoding as self" do
+ "stressed".encode("US-ASCII").reverse.encoding.should == Encoding::US_ASCII
+ end
end
describe "String#reverse!" do
it "reverses self in place and always returns self" do
a = "stressed"
- a.reverse!.should equal(a)
+ a.reverse!.should.equal?(a)
a.should == "desserts"
"".reverse!.should == ""
end
it "raises a FrozenError on a frozen instance that is modified" do
- -> { "anna".freeze.reverse! }.should raise_error(FrozenError)
- -> { "hello".freeze.reverse! }.should raise_error(FrozenError)
+ -> { "anna".freeze.reverse! }.should.raise(FrozenError)
+ -> { "hello".freeze.reverse! }.should.raise(FrozenError)
end
# see [ruby-core:23666]
it "raises a FrozenError on a frozen instance that would not be modified" do
- -> { "".freeze.reverse! }.should raise_error(FrozenError)
+ -> { "".freeze.reverse! }.should.raise(FrozenError)
end
it "reverses a string with multi byte characters" do
@@ -67,7 +62,7 @@ describe "String#reverse!" do
it "works with a broken string" do
str = "微軟\xDF\xDE正黑體".force_encoding(Encoding::UTF_8)
- str.valid_encoding?.should be_false
+ str.valid_encoding?.should == false
str.reverse!
str.should == "體黑正\xDE\xDF軟微"
diff --git a/spec/ruby/core/string/rindex_spec.rb b/spec/ruby/core/string/rindex_spec.rb
index a3b437a1e4..acecec224f 100644
--- a/spec/ruby/core/string/rindex_spec.rb
+++ b/spec/ruby/core/string/rindex_spec.rb
@@ -1,24 +1,23 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'fixtures/utf-8-encoding'
describe "String#rindex with object" do
it "raises a TypeError if obj isn't a String or Regexp" do
not_supported_on :opal do
- -> { "hello".rindex(:sym) }.should raise_error(TypeError)
+ -> { "hello".rindex(:sym) }.should.raise(TypeError)
end
- -> { "hello".rindex(mock('x')) }.should raise_error(TypeError)
+ -> { "hello".rindex(mock('x')) }.should.raise(TypeError)
end
it "raises a TypeError if obj is an Integer" do
- -> { "hello".rindex(42) }.should raise_error(TypeError)
+ -> { "hello".rindex(42) }.should.raise(TypeError)
end
it "doesn't try to convert obj to an integer via to_int" do
obj = mock('x')
obj.should_not_receive(:to_int)
- -> { "hello".rindex(obj) }.should raise_error(TypeError)
+ -> { "hello".rindex(obj) }.should.raise(TypeError)
end
it "tries to convert obj to a string via to_str" do
@@ -194,7 +193,22 @@ describe "String#rindex with String" do
end
it "raises a TypeError when given offset is nil" do
- -> { "str".rindex("st", nil) }.should raise_error(TypeError)
+ -> { "str".rindex("st", nil) }.should.raise(TypeError)
+ end
+
+ it "handles a substring in a superset encoding" do
+ 'abc'.dup.force_encoding(Encoding::US_ASCII).rindex('é').should == nil
+ end
+
+ it "handles a substring in a subset encoding" do
+ 'été'.rindex('t'.dup.force_encoding(Encoding::US_ASCII)).should == 1
+ end
+
+ it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
+ str = 'abc'.dup.force_encoding("ISO-2022-JP")
+ pattern = 'b'.dup.force_encoding("EUC-JP")
+
+ -> { str.rindex(pattern) }.should.raise(Encoding::CompatibilityError, "incompatible character encodings: ISO-2022-JP and EUC-JP")
end
end
@@ -348,7 +362,7 @@ describe "String#rindex with Regexp" do
end
it "raises a TypeError when given offset is nil" do
- -> { "str".rindex(/../, nil) }.should raise_error(TypeError)
+ -> { "str".rindex(/../, nil) }.should.raise(TypeError)
end
it "returns the reverse character index of a multibyte character" do
@@ -357,14 +371,14 @@ describe "String#rindex with Regexp" do
end
it "returns the character index before the finish" do
- "ありがりがとう".rindex("が", 3).should == 2
- "ありがりがとう".rindex(/が/, 3).should == 2
+ "ありがりがとう".rindex("が", 3).should == 2
+ "ありがりがとう".rindex(/が/, 3).should == 2
end
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
re = Regexp.new "れ".encode(Encoding::EUC_JP)
-> do
"あれ".rindex re
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError, "incompatible encoding regexp match (EUC-JP regexp with UTF-8 string)")
end
end
diff --git a/spec/ruby/core/string/rjust_spec.rb b/spec/ruby/core/string/rjust_spec.rb
index d067b7bdb3..9f9c369745 100644
--- a/spec/ruby/core/string/rjust_spec.rb
+++ b/spec/ruby/core/string/rjust_spec.rb
@@ -41,10 +41,10 @@ describe "String#rjust with length, padding" do
end
it "raises a TypeError when length can't be converted to an integer" do
- -> { "hello".rjust("x") }.should raise_error(TypeError)
- -> { "hello".rjust("x", "y") }.should raise_error(TypeError)
- -> { "hello".rjust([]) }.should raise_error(TypeError)
- -> { "hello".rjust(mock('x')) }.should raise_error(TypeError)
+ -> { "hello".rjust("x") }.should.raise(TypeError)
+ -> { "hello".rjust("x", "y") }.should.raise(TypeError)
+ -> { "hello".rjust([]) }.should.raise(TypeError)
+ -> { "hello".rjust(mock('x')) }.should.raise(TypeError)
end
it "tries to convert padstr to a string using to_str" do
@@ -55,59 +55,46 @@ describe "String#rjust with length, padding" do
end
it "raises a TypeError when padstr can't be converted" do
- -> { "hello".rjust(20, []) }.should raise_error(TypeError)
- -> { "hello".rjust(20, Object.new)}.should raise_error(TypeError)
- -> { "hello".rjust(20, mock('x')) }.should raise_error(TypeError)
+ -> { "hello".rjust(20, []) }.should.raise(TypeError)
+ -> { "hello".rjust(20, Object.new)}.should.raise(TypeError)
+ -> { "hello".rjust(20, mock('x')) }.should.raise(TypeError)
end
it "raises an ArgumentError when padstr is empty" do
- -> { "hello".rjust(10, '') }.should raise_error(ArgumentError)
+ -> { "hello".rjust(10, '') }.should.raise(ArgumentError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on subclasses" do
- StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString)
+ it "returns String instances when called on subclasses" do
+ StringSpecs::MyString.new("").rjust(10).should.instance_of?(String)
+ StringSpecs::MyString.new("foo").rjust(10).should.instance_of?(String)
+ StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should.instance_of?(String)
- "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances when called on subclasses" do
- StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
-
- "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- end
+ "".rjust(10, StringSpecs::MyString.new("x")).should.instance_of?(String)
+ "foo".rjust(10, StringSpecs::MyString.new("x")).should.instance_of?(String)
end
describe "with width" do
it "returns a String in the same encoding as the original" do
- str = "abc".force_encoding Encoding::IBM437
+ str = "abc".dup.force_encoding Encoding::IBM437
result = str.rjust 5
result.should == " abc"
- result.encoding.should equal(Encoding::IBM437)
+ result.encoding.should.equal?(Encoding::IBM437)
end
end
describe "with width, pattern" do
it "returns a String in the compatible encoding" do
- str = "abc".force_encoding Encoding::IBM437
+ str = "abc".dup.force_encoding Encoding::IBM437
result = str.rjust 5, "あ"
result.should == "ああabc"
- result.encoding.should equal(Encoding::UTF_8)
+ result.encoding.should.equal?(Encoding::UTF_8)
end
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
pat = "ア".encode Encoding::EUC_JP
-> do
"あれ".rjust 5, pat
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError)
end
end
end
diff --git a/spec/ruby/core/string/rpartition_spec.rb b/spec/ruby/core/string/rpartition_spec.rb
index c8f9afaee9..a7dd7430b7 100644
--- a/spec/ruby/core/string/rpartition_spec.rb
+++ b/spec/ruby/core/string/rpartition_spec.rb
@@ -43,7 +43,29 @@ describe "String#rpartition with String" do
end
it "raises an error if not convertible to string" do
- ->{ "hello".rpartition(5) }.should raise_error(TypeError)
- ->{ "hello".rpartition(nil) }.should raise_error(TypeError)
+ ->{ "hello".rpartition(5) }.should.raise(TypeError)
+ ->{ "hello".rpartition(nil) }.should.raise(TypeError)
+ end
+
+ it "handles a pattern in a superset encoding" do
+ string = "hello".dup.force_encoding(Encoding::US_ASCII)
+
+ result = string.rpartition("é")
+
+ result.should == ["", "", "hello"]
+ result[0].encoding.should == Encoding::US_ASCII
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ pattern = "o".dup.force_encoding(Encoding::US_ASCII)
+
+ result = "héllo world".rpartition(pattern)
+
+ result.should == ["héllo w", "o", "rld"]
+ result[0].encoding.should == Encoding::UTF_8
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::UTF_8
end
end
diff --git a/spec/ruby/core/string/rstrip_spec.rb b/spec/ruby/core/string/rstrip_spec.rb
index 4332b33b20..1638ea375d 100644
--- a/spec/ruby/core/string/rstrip_spec.rb
+++ b/spec/ruby/core/string/rstrip_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/strip'
@@ -29,7 +30,7 @@ end
describe "String#rstrip!" do
it "modifies self in place and returns self" do
a = " hello "
- a.rstrip!.should equal(a)
+ a.rstrip!.should.equal?(a)
a.should == " hello"
end
@@ -51,31 +52,29 @@ describe "String#rstrip!" do
" ".rstrip.should == ""
end
- ruby_version_is '3.0' do
- it "removes trailing NULL bytes and whitespace" do
- a = "\000 goodbye \000"
- a.rstrip!
- a.should == "\000 goodbye"
- end
+ it "removes trailing NULL bytes and whitespace" do
+ a = "\000 goodbye \000"
+ a.rstrip!
+ a.should == "\000 goodbye"
end
it "raises a FrozenError on a frozen instance that is modified" do
- -> { " hello ".freeze.rstrip! }.should raise_error(FrozenError)
+ -> { " hello ".freeze.rstrip! }.should.raise(FrozenError)
end
# see [ruby-core:23666]
it "raises a FrozenError on a frozen instance that would not be modified" do
- -> { "hello".freeze.rstrip! }.should raise_error(FrozenError)
- -> { "".freeze.rstrip! }.should raise_error(FrozenError)
+ -> { "hello".freeze.rstrip! }.should.raise(FrozenError)
+ -> { "".freeze.rstrip! }.should.raise(FrozenError)
end
- it "raises an ArgumentError if the last non-space codepoint is invalid" do
+ it "raises an Encoding::CompatibilityError if the last non-space codepoint is invalid" do
s = "abc\xDF".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.rstrip! }.should raise_error(ArgumentError)
+ s.valid_encoding?.should == false
+ -> { s.rstrip! }.should.raise(Encoding::CompatibilityError)
s = "abc\xDF ".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.rstrip! }.should raise_error(ArgumentError)
+ s.valid_encoding?.should == false
+ -> { s.rstrip! }.should.raise(Encoding::CompatibilityError)
end
end
diff --git a/spec/ruby/core/string/scan_spec.rb b/spec/ruby/core/string/scan_spec.rb
index ab73f5747b..47fa7214c2 100644
--- a/spec/ruby/core/string/scan_spec.rb
+++ b/spec/ruby/core/string/scan_spec.rb
@@ -58,24 +58,30 @@ describe "String#scan" do
end
it "raises a TypeError if pattern isn't a Regexp and can't be converted to a String" do
- -> { "cruel world".scan(5) }.should raise_error(TypeError)
+ -> { "cruel world".scan(5) }.should.raise(TypeError)
not_supported_on :opal do
- -> { "cruel world".scan(:test) }.should raise_error(TypeError)
+ -> { "cruel world".scan(:test) }.should.raise(TypeError)
end
- -> { "cruel world".scan(mock('x')) }.should raise_error(TypeError)
+ -> { "cruel world".scan(mock('x')) }.should.raise(TypeError)
end
# jruby/jruby#5513
it "does not raise any errors when passed a multi-byte string" do
"あああaaaあああ".scan("あああ").should == ["あああ", "あああ"]
end
+
+ it "returns Strings in the same encoding as self" do
+ "cruel world".encode("US-ASCII").scan(/\w+/).each do |s|
+ s.encoding.should == Encoding::US_ASCII
+ end
+ end
end
describe "String#scan with pattern and block" do
it "returns self" do
s = "foo"
- s.scan(/./) {}.should equal(s)
- s.scan(/roar/) {}.should equal(s)
+ s.scan(/./) {}.should.equal?(s)
+ s.scan(/roar/) {}.should.equal?(s)
end
it "passes each match to the block as one argument: an array" do
@@ -97,11 +103,11 @@ describe "String#scan with pattern and block" do
offsets = []
str.scan(/([aeiou])/) do
- md = $~
- md.string.should == str
- matches << md.to_a
- offsets << md.offset(0)
- str
+ md = $~
+ md.string.should == str
+ matches << md.to_a
+ offsets << md.offset(0)
+ str
end
matches.should == [["e", "e"], ["o", "o"]]
@@ -111,11 +117,11 @@ describe "String#scan with pattern and block" do
offsets = []
str.scan("l") do
- md = $~
- md.string.should == str
- matches << md.to_a
- offsets << md.offset(0)
- str
+ md = $~
+ md.string.should == str
+ matches << md.to_a
+ offsets << md.offset(0)
+ str
end
matches.should == [["l"], ["l"]]
@@ -159,11 +165,9 @@ describe "String#scan with pattern and block" do
end
end
- ruby_version_is '3.0' do
- it "yields String instances for subclasses" do
- a = []
- StringSpecs::MyString.new("abc").scan(/./) { |s| a << s.class }
- a.should == [String, String, String]
- end
+ it "yields String instances for subclasses" do
+ a = []
+ StringSpecs::MyString.new("abc").scan(/./) { |s| a << s.class }
+ a.should == [String, String, String]
end
end
diff --git a/spec/ruby/core/string/scrub_spec.rb b/spec/ruby/core/string/scrub_spec.rb
index 66755bcc7b..9dc55dbef7 100644
--- a/spec/ruby/core/string/scrub_spec.rb
+++ b/spec/ruby/core/string/scrub_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -31,18 +32,15 @@ describe "String#scrub with a default replacement" do
input.scrub.should == "abc?????"
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(String)
- input = [0x81].pack('C').force_encoding('utf-8')
- StringSpecs::MyString.new(input).scrub.should be_an_instance_of(String)
- end
+ it "returns a String in the same encoding as self" do
+ x81 = [0x81].pack('C').force_encoding('utf-8')
+ "abc\u3042#{x81}".scrub.encoding.should == Encoding::UTF_8
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("foo").scrub.should.instance_of?(String)
+ input = [0x81].pack('C').force_encoding('utf-8')
+ StringSpecs::MyString.new(input).scrub.should.instance_of?(String)
end
end
@@ -77,22 +75,25 @@ describe "String#scrub with a custom replacement" do
xE4 = [0xE4].pack('C').force_encoding('utf-8')
block = -> { "foo#{x81}".scrub(xE4) }
- block.should raise_error(ArgumentError)
+ block.should.raise(ArgumentError)
+ end
+
+ it "returns a String in the same encoding as self" do
+ x81 = [0x81].pack('C').force_encoding('utf-8')
+ "abc\u3042#{x81}".scrub("*").encoding.should == Encoding::UTF_8
end
it "raises TypeError when a non String replacement is given" do
x81 = [0x81].pack('C').force_encoding('utf-8')
block = -> { "foo#{x81}".scrub(1) }
- block.should raise_error(TypeError)
+ block.should.raise(TypeError)
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("foo").scrub("*").should be_an_instance_of(String)
- input = [0x81].pack('C').force_encoding('utf-8')
- StringSpecs::MyString.new(input).scrub("*").should be_an_instance_of(String)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("foo").scrub("*").should.instance_of?(String)
+ input = [0x81].pack('C').force_encoding('utf-8')
+ StringSpecs::MyString.new(input).scrub("*").should.instance_of?(String)
end
end
@@ -119,12 +120,10 @@ describe "String#scrub with a block" do
replaced.should == "€€"
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("foo").scrub { |b| "*" }.should be_an_instance_of(String)
- input = [0x81].pack('C').force_encoding('utf-8')
- StringSpecs::MyString.new(input).scrub { |b| "<#{b.unpack("H*")[0]}>" }.should be_an_instance_of(String)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("foo").scrub { |b| "*" }.should.instance_of?(String)
+ input = [0x81].pack('C').force_encoding('utf-8')
+ StringSpecs::MyString.new(input).scrub { |b| "<#{b.unpack("H*")[0]}>" }.should.instance_of?(String)
end
end
@@ -147,7 +146,7 @@ describe "String#scrub!" do
input = "a"
input.freeze
input.scrub!
- input.frozen?.should be_true
+ input.frozen?.should == true
end
it "preserves the instance variables of already valid strings" do
diff --git a/spec/ruby/core/string/setbyte_spec.rb b/spec/ruby/core/string/setbyte_spec.rb
index 77bff64038..d9fcc279c0 100644
--- a/spec/ruby/core/string/setbyte_spec.rb
+++ b/spec/ruby/core/string/setbyte_spec.rb
@@ -1,9 +1,10 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe "String#setbyte" do
it "returns an Integer" do
- "a".setbyte(0,1).should be_kind_of(Integer)
+ "a".setbyte(0,1).should.is_a?(Integer)
end
it "modifies the receiver" do
@@ -33,9 +34,9 @@ describe "String#setbyte" do
it "can invalidate a String's encoding" do
str = "glark"
- str.valid_encoding?.should be_true
+ str.valid_encoding?.should == true
str.setbyte(2,253)
- str.valid_encoding?.should be_false
+ str.valid_encoding?.should == false
str = "ABC"
str.setbyte(0, 0x20) # ' '
@@ -57,11 +58,11 @@ describe "String#setbyte" do
end
it "raises an IndexError if the index is greater than the String bytesize" do
- -> { "?".setbyte(1, 97) }.should raise_error(IndexError)
+ -> { "?".setbyte(1, 97) }.should.raise(IndexError)
end
it "raises an IndexError if the negative index is greater magnitude than the String bytesize" do
- -> { "???".setbyte(-5, 97) }.should raise_error(IndexError)
+ -> { "???".setbyte(-5, 97) }.should.raise(IndexError)
end
it "sets a byte at an index greater than String size" do
@@ -83,12 +84,12 @@ describe "String#setbyte" do
it "raises a FrozenError if self is frozen" do
str = "cold".freeze
- str.frozen?.should be_true
- -> { str.setbyte(3,96) }.should raise_error(FrozenError)
+ str.frozen?.should == true
+ -> { str.setbyte(3,96) }.should.raise(FrozenError)
end
it "raises a TypeError unless the second argument is an Integer" do
- -> { "a".setbyte(0,'a') }.should raise_error(TypeError)
+ -> { "a".setbyte(0,'a') }.should.raise(TypeError)
end
it "calls #to_int to convert the index" do
diff --git a/spec/ruby/core/string/shared/byte_index_common.rb b/spec/ruby/core/string/shared/byte_index_common.rb
new file mode 100644
index 0000000000..bae6cff49f
--- /dev/null
+++ b/spec/ruby/core/string/shared/byte_index_common.rb
@@ -0,0 +1,63 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../../spec_helper'
+
+describe :byte_index_common, shared: true do
+ describe "raises on type errors" do
+ it "raises a TypeError if passed nil" do
+ -> { "abc".send(@method, nil) }.should.raise(TypeError, "no implicit conversion of nil into String")
+ end
+
+ it "raises a TypeError if passed a boolean" do
+ -> { "abc".send(@method, true) }.should.raise(TypeError, "no implicit conversion of true into String")
+ end
+
+ it "raises a TypeError if passed a Symbol" do
+ not_supported_on :opal do
+ -> { "abc".send(@method, :a) }.should.raise(TypeError, "no implicit conversion of Symbol into String")
+ end
+ end
+
+ it "raises a TypeError if passed a Symbol" do
+ obj = mock('x')
+ obj.should_not_receive(:to_int)
+ -> { "hello".send(@method, obj) }.should.raise(TypeError, "no implicit conversion of MockObject into String")
+ end
+
+ it "raises a TypeError if passed an Integer" do
+ -> { "abc".send(@method, 97) }.should.raise(TypeError, "no implicit conversion of Integer into String")
+ end
+ end
+
+ describe "with multibyte codepoints" do
+ it "raises an IndexError when byte offset lands in the middle of a multibyte character" do
+ -> { "わ".send(@method, "", 1) }.should.raise(IndexError, "offset 1 does not land on character boundary")
+ -> { "わ".send(@method, "", 2) }.should.raise(IndexError, "offset 2 does not land on character boundary")
+ -> { "わ".send(@method, "", -1) }.should.raise(IndexError, "offset 2 does not land on character boundary")
+ -> { "わ".send(@method, "", -2) }.should.raise(IndexError, "offset 1 does not land on character boundary")
+ end
+
+ it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
+ re = Regexp.new "れ".encode(Encoding::EUC_JP)
+ -> do
+ "あれ".send(@method, re)
+ end.should.raise(Encoding::CompatibilityError, "incompatible encoding regexp match (EUC-JP regexp with UTF-8 string)")
+ end
+ end
+
+ describe "with global variables" do
+ it "doesn't set $~ for non regex search" do
+ $~ = nil
+
+ 'hello.'.send(@method, 'll')
+ $~.should == nil
+ end
+
+ it "sets $~ to MatchData of match and nil when there's none" do
+ 'hello.'.send(@method, /.e./)
+ $~[0].should == 'hel'
+
+ 'hello.'.send(@method, /not/)
+ $~.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/string/shared/chars.rb b/spec/ruby/core/string/shared/chars.rb
index e9fdf89fd6..826d403589 100644
--- a/spec/ruby/core/string/shared/chars.rb
+++ b/spec/ruby/core/string/shared/chars.rb
@@ -11,22 +11,21 @@ describe :string_chars, shared: true do
it "returns self" do
s = StringSpecs::MyString.new "hello"
- s.send(@method){}.should equal(s)
+ s.send(@method){}.should.equal?(s)
end
-
it "is unicode aware" do
"\303\207\342\210\202\303\251\306\222g".send(@method).to_a.should ==
["\303\207", "\342\210\202", "\303\251", "\306\222", "g"]
end
it "returns characters in the same encoding as self" do
- "&%".force_encoding('Shift_JIS').send(@method).to_a.all? {|c| c.encoding.name.should == 'Shift_JIS'}
+ "&%".dup.force_encoding('Shift_JIS').send(@method).to_a.all? {|c| c.encoding.name.should == 'Shift_JIS'}
"&%".encode('BINARY').send(@method).to_a.all? {|c| c.encoding.should == Encoding::BINARY }
end
it "works with multibyte characters" do
- s = "\u{8987}".force_encoding("UTF-8")
+ s = "\u{8987}".dup.force_encoding("UTF-8")
s.bytesize.should == 3
s.send(@method).to_a.should == [s]
end
@@ -34,19 +33,19 @@ describe :string_chars, shared: true do
it "works if the String's contents is invalid for its encoding" do
xA4 = [0xA4].pack('C')
xA4.force_encoding('UTF-8')
- xA4.valid_encoding?.should be_false
+ xA4.valid_encoding?.should == false
xA4.send(@method).to_a.should == [xA4.force_encoding("UTF-8")]
end
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 = "\u{20AC}".dup.force_encoding('UTF-8')
+ s.encode('UTF-8').send(@method).to_a.should == ["\u{20AC}".dup.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').encode('UTF-8').send(@method).to_a.should == ["\u{20AC}".dup.force_encoding('UTF-8')]
end
it "uses the String's encoding to determine what characters it contains" do
- s = "\u{24B62}"
+ s = +"\u{24B62}"
s.force_encoding('UTF-8').send(@method).to_a.should == [
s.force_encoding('UTF-8')
@@ -63,4 +62,25 @@ describe :string_chars, shared: true do
[0xA2].pack('C').force_encoding('SJIS')
]
end
+
+ it "returns individual chars for dummy encodings" do
+ "ab".dup.force_encoding(Encoding::UTF_7).send(@method).to_a.should == [
+ "\x61".dup.force_encoding(Encoding::UTF_7),
+ "\x62".dup.force_encoding(Encoding::UTF_7)
+ ]
+
+ "abcd".dup.force_encoding(Encoding::UTF_16).send(@method).to_a.should == [
+ "\x61".dup.force_encoding(Encoding::UTF_16),
+ "\x62".dup.force_encoding(Encoding::UTF_16),
+ "\x63".dup.force_encoding(Encoding::UTF_16),
+ "\x64".dup.force_encoding(Encoding::UTF_16)
+ ]
+
+ "abcd".dup.force_encoding(Encoding::UTF_32).send(@method).to_a.should == [
+ "\x61".dup.force_encoding(Encoding::UTF_32),
+ "\x62".dup.force_encoding(Encoding::UTF_32),
+ "\x63".dup.force_encoding(Encoding::UTF_32),
+ "\x64".dup.force_encoding(Encoding::UTF_32)
+ ]
+ end
end
diff --git a/spec/ruby/core/string/shared/codepoints.rb b/spec/ruby/core/string/shared/codepoints.rb
index 0b2e078e0a..b6abf6a3ff 100644
--- a/spec/ruby/core/string/shared/codepoints.rb
+++ b/spec/ruby/core/string/shared/codepoints.rb
@@ -1,15 +1,15 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_codepoints, shared: true do
it "returns self" do
s = "foo"
result = s.send(@method) {}
- result.should equal s
+ result.should.equal? s
end
it "raises an ArgumentError when self has an invalid encoding and a method is called on the returned Enumerator" do
- s = "\xDF".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.send(@method).to_a }.should raise_error(ArgumentError)
+ s = "\xDF".dup.force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should == false
+ -> { s.send(@method).to_a }.should.raise(ArgumentError)
end
it "yields each codepoint to the block if one is given" do
@@ -21,14 +21,14 @@ describe :string_codepoints, shared: true do
end
it "raises an ArgumentError if self's encoding is invalid and a block is given" do
- s = "\xDF".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.send(@method) { } }.should raise_error(ArgumentError)
+ s = "\xDF".dup.force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should == false
+ -> { s.send(@method) { } }.should.raise(ArgumentError)
end
it "yields codepoints as Integers" do
"glark\u{20}".send(@method).to_a.each do |codepoint|
- codepoint.should be_an_instance_of(Integer)
+ codepoint.should.instance_of?(Integer)
end
end
@@ -49,14 +49,19 @@ describe :string_codepoints, shared: true do
it "round-trips to the original String using Integer#chr" do
s = "\u{13}\u{7711}\u{1010}"
- s2 = ""
+ s2 = +""
s.send(@method) {|n| s2 << n.chr(Encoding::UTF_8)}
s.should == s2
end
it "is synonymous with #bytes for Strings which are single-byte optimizable" do
s = "(){}".encode('ascii')
- s.ascii_only?.should be_true
+ s.ascii_only?.should == true
s.send(@method).to_a.should == s.bytes.to_a
end
+
+ it "returns individual bytes for dummy encodings UTF-16 and UTF-32" do
+ "abcd".dup.force_encoding(Encoding::UTF_16).send(@method).to_a.should == [97, 98, 99, 100]
+ "abcd".dup.force_encoding(Encoding::UTF_32).send(@method).to_a.should == [97, 98, 99, 100]
+ end
end
diff --git a/spec/ruby/core/string/shared/concat.rb b/spec/ruby/core/string/shared/concat.rb
index 54ac1035d3..60cd0e12d4 100644
--- a/spec/ruby/core/string/shared/concat.rb
+++ b/spec/ruby/core/string/shared/concat.rb
@@ -1,42 +1,31 @@
+# frozen_string_literal: false
describe :string_concat, shared: true do
it "concatenates the given argument to self and returns self" do
str = 'hello '
- str.send(@method, 'world').should equal(str)
+ str.send(@method, 'world').should.equal?(str)
str.should == "hello world"
end
- it "converts the given argument to a String using to_str" do
- obj = mock('world!')
- obj.should_receive(:to_str).and_return("world!")
- a = 'hello '.send(@method, obj)
- a.should == 'hello world!'
- end
-
- it "raises a TypeError if the given argument can't be converted to a String" do
- -> { 'hello '.send(@method, []) }.should raise_error(TypeError)
- -> { 'hello '.send(@method, mock('x')) }.should raise_error(TypeError)
- end
-
it "raises a FrozenError when self is frozen" do
a = "hello"
a.freeze
- -> { a.send(@method, "") }.should raise_error(FrozenError)
- -> { a.send(@method, "test") }.should raise_error(FrozenError)
+ -> { a.send(@method, "") }.should.raise(FrozenError)
+ -> { a.send(@method, "test") }.should.raise(FrozenError)
end
it "returns a String when given a subclass instance" do
a = "hello"
a.send(@method, StringSpecs::MyString.new(" world"))
a.should == "hello world"
- a.should be_an_instance_of(String)
+ a.should.instance_of?(String)
end
it "returns an instance of same class when called on a subclass" do
str = StringSpecs::MyString.new("hello")
str.send(@method, " world")
str.should == "hello world"
- str.should be_an_instance_of(StringSpecs::MyString)
+ str.should.instance_of?(StringSpecs::MyString)
end
describe "with Integer" do
@@ -61,28 +50,28 @@ describe :string_concat, shared: true do
end
it "raises RangeError if the argument is an invalid codepoint for self's encoding" do
- -> { "".encode(Encoding::US_ASCII).send(@method, 256) }.should raise_error(RangeError)
- -> { "".encode(Encoding::EUC_JP).send(@method, 0x81) }.should raise_error(RangeError)
+ -> { "".encode(Encoding::US_ASCII).send(@method, 256) }.should.raise(RangeError)
+ -> { "".encode(Encoding::EUC_JP).send(@method, 0x81) }.should.raise(RangeError)
end
it "raises RangeError if the argument is negative" do
- -> { "".send(@method, -200) }.should raise_error(RangeError)
- -> { "".send(@method, -bignum_value) }.should raise_error(RangeError)
+ -> { "".send(@method, -200) }.should.raise(RangeError)
+ -> { "".send(@method, -bignum_value) }.should.raise(RangeError)
end
it "doesn't call to_int on its argument" do
x = mock('x')
x.should_not_receive(:to_int)
- -> { "".send(@method, x) }.should raise_error(TypeError)
+ -> { "".send(@method, x) }.should.raise(TypeError)
end
it "raises a FrozenError when self is frozen" do
a = "hello"
a.freeze
- -> { a.send(@method, 0) }.should raise_error(FrozenError)
- -> { a.send(@method, 33) }.should raise_error(FrozenError)
+ -> { a.send(@method, 0) }.should.raise(FrozenError)
+ -> { a.send(@method, 33) }.should.raise(FrozenError)
end
end
end
@@ -102,7 +91,7 @@ describe :string_concat_encoding, shared: true do
end
it "raises Encoding::CompatibilityError if neither are empty" do
- -> { "x".encode("UTF-16LE").send(@method, "y".encode("UTF-8")) }.should raise_error(Encoding::CompatibilityError)
+ -> { "x".encode("UTF-16LE").send(@method, "y".encode("UTF-8")) }.should.raise(Encoding::CompatibilityError)
end
end
@@ -120,7 +109,7 @@ describe :string_concat_encoding, shared: true do
end
it "raises Encoding::CompatibilityError if neither are empty" do
- -> { "x".encode("UTF-8").send(@method, "y".encode("UTF-16LE")) }.should raise_error(Encoding::CompatibilityError)
+ -> { "x".encode("UTF-8").send(@method, "y".encode("UTF-16LE")) }.should.raise(Encoding::CompatibilityError)
end
end
@@ -138,7 +127,7 @@ describe :string_concat_encoding, shared: true do
end
it "raises Encoding::CompatibilityError if neither are ASCII-only" do
- -> { "\u00E9".encode("UTF-8").send(@method, "\u00E9".encode("ISO-8859-1")) }.should raise_error(Encoding::CompatibilityError)
+ -> { "\u00E9".encode("UTF-8").send(@method, "\u00E9".encode("ISO-8859-1")) }.should.raise(Encoding::CompatibilityError)
end
end
@@ -148,3 +137,23 @@ describe :string_concat_encoding, shared: true do
end
end
end
+
+describe :string_concat_type_coercion, shared: true do
+ it "converts the given argument to a String using to_str" do
+ obj = mock('world!')
+ obj.should_receive(:to_str).and_return("world!")
+ a = 'hello '.send(@method, obj)
+ a.should == 'hello world!'
+ end
+
+ it "raises a TypeError if the given argument can't be converted to a String" do
+ -> { 'hello '.send(@method, []) }.should.raise(TypeError)
+ -> { 'hello '.send(@method, mock('x')) }.should.raise(TypeError)
+ end
+
+ it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to a String" do
+ obj = mock('world!')
+ obj.should_receive(:to_str).and_raise(NoMethodError)
+ -> { 'hello '.send(@method, obj) }.should.raise(NoMethodError)
+ end
+end
diff --git a/spec/ruby/core/string/shared/dedup.rb b/spec/ruby/core/string/shared/dedup.rb
index 6ffcb9b045..59506c2901 100644
--- a/spec/ruby/core/string/shared/dedup.rb
+++ b/spec/ruby/core/string/shared/dedup.rb
@@ -1,9 +1,10 @@
+# frozen_string_literal: false
describe :string_dedup, shared: true do
it 'returns self if the String is frozen' do
input = 'foo'.freeze
output = input.send(@method)
- output.should equal(input)
+ output.should.equal?(input)
output.should.frozen?
end
@@ -12,7 +13,7 @@ describe :string_dedup, shared: true do
output = input.send(@method)
output.should.frozen?
- output.should_not equal(input)
+ output.should_not.equal?(input)
output.should == 'foo'
end
@@ -20,22 +21,22 @@ describe :string_dedup, shared: true do
origin = "this is a string"
dynamic = %w(this is a string).join(' ')
- origin.should_not equal(dynamic)
- origin.send(@method).should equal(dynamic.send(@method))
+ origin.should_not.equal?(dynamic)
+ origin.send(@method).should.equal?(dynamic.send(@method))
end
it "returns the same object when it's called on the same String literal" do
- "unfrozen string".send(@method).should equal("unfrozen string".send(@method))
- "unfrozen string".send(@method).should_not equal("another unfrozen string".send(@method))
+ "unfrozen string".send(@method).should.equal?("unfrozen string".send(@method))
+ "unfrozen string".send(@method).should_not.equal?("another unfrozen string".send(@method))
end
it "deduplicates frozen strings" do
dynamic = %w(this string is frozen).join(' ').freeze
- dynamic.should_not equal("this string is frozen".freeze)
+ dynamic.should_not.equal?("this string is frozen".freeze)
- dynamic.send(@method).should equal("this string is frozen".freeze)
- dynamic.send(@method).should equal("this string is frozen".send(@method).freeze)
+ dynamic.send(@method).should.equal?("this string is frozen".freeze)
+ dynamic.send(@method).should.equal?("this string is frozen".send(@method).freeze)
end
it "does not deduplicate a frozen string when it has instance variables" do
@@ -43,15 +44,8 @@ describe :string_dedup, shared: true do
dynamic.instance_variable_set(:@a, 1)
dynamic.freeze
- dynamic.send(@method).should_not equal("this string is frozen".freeze)
- dynamic.send(@method).should_not equal("this string is frozen".send(@method).freeze)
- dynamic.send(@method).should equal(dynamic)
- end
-
- ruby_version_is "3.0" do
- it "interns the provided string if it is frozen" do
- dynamic = "this string is unique and frozen #{rand}".freeze
- dynamic.send(@method).should equal(dynamic)
- end
+ dynamic.send(@method).should_not.equal?("this string is frozen".freeze)
+ dynamic.send(@method).should_not.equal?("this string is frozen".send(@method).freeze)
+ dynamic.send(@method).should.equal?(dynamic)
end
end
diff --git a/spec/ruby/core/string/shared/each_char_without_block.rb b/spec/ruby/core/string/shared/each_char_without_block.rb
index 397100ce0e..3c32bae42b 100644
--- a/spec/ruby/core/string/shared/each_char_without_block.rb
+++ b/spec/ruby/core/string/shared/each_char_without_block.rb
@@ -6,7 +6,7 @@ describe :string_each_char_without_block, shared: true do
describe "when no block is given" do
it "returns an enumerator" do
enum = "hello".send(@method)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.should == ['h', 'e', 'l', 'l', 'o']
end
diff --git a/spec/ruby/core/string/shared/each_codepoint_without_block.rb b/spec/ruby/core/string/shared/each_codepoint_without_block.rb
index 92b7f76032..60d603954c 100644
--- a/spec/ruby/core/string/shared/each_codepoint_without_block.rb
+++ b/spec/ruby/core/string/shared/each_codepoint_without_block.rb
@@ -1,14 +1,14 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_each_codepoint_without_block, shared: true do
describe "when no block is given" do
it "returns an Enumerator" do
- "".send(@method).should be_an_instance_of(Enumerator)
+ "".send(@method).should.instance_of?(Enumerator)
end
it "returns an Enumerator even when self has an invalid encoding" do
- s = "\xDF".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- s.send(@method).should be_an_instance_of(Enumerator)
+ s = "\xDF".dup.force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should == false
+ s.send(@method).should.instance_of?(Enumerator)
end
describe "returned Enumerator" do
@@ -23,8 +23,8 @@ describe :string_each_codepoint_without_block, shared: true do
end
it "should return the size of the string even when the string has an invalid encoding" do
- s = "\xDF".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
+ s = "\xDF".dup.force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should == false
s.send(@method).size.should == 1
end
end
diff --git a/spec/ruby/core/string/shared/each_line.rb b/spec/ruby/core/string/shared/each_line.rb
index bfedf8f35a..127db876ad 100644
--- a/spec/ruby/core/string/shared/each_line.rb
+++ b/spec/ruby/core/string/shared/each_line.rb
@@ -46,14 +46,36 @@ describe :string_each_line, shared: true do
a.should == ["one\ntwo\r\nthree"]
end
- it "yields paragraphs (broken by 2 or more successive newlines) when passed '' and replaces multiple newlines with only two ones" do
- a = []
- "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s }
- a.should == ["hello\nworld\n\n", "and\nuniverse\n\n"]
+ context "when passed '' (paragraph mode, broken by 2 or more successive newlines)" do
+ it "replaces multiple newlines with only two ones" do
+ a = []
+ "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s }
+ a.should == ["hello\nworld\n\n", "and\nuniverse\n\n"]
- a = []
- "hello\nworld\n\n\nand\nuniverse\n\n\n\n\ndog".send(@method, '') { |s| a << s }
- a.should == ["hello\nworld\n\n", "and\nuniverse\n\n", "dog"]
+ a = []
+ "hello\nworld\n\n\nand\nuniverse\n\n\n\n\ndog".send(@method, '') { |s| a << s }
+ a.should == ["hello\nworld\n\n", "and\nuniverse\n\n", "dog"]
+ end
+
+ it 'handles \r\n-style newlines' do
+ a = []
+ "hello\nworld\r\n\r\n\nand\nuniverse\n\r\n\n\n\n".send(@method, '') { |s| a << s }
+ a.should == ["hello\nworld\r\n\r\n", "and\nuniverse\n\r\n"]
+
+ a = []
+ "hello\r\nworld\n\n\nand\nuniverse\n\n\n\r\n\r\ndog".send(@method, '') { |s| a << s }
+ a.should == ["hello\r\nworld\n\n", "and\nuniverse\n\n", "dog"]
+ end
+
+ it "removes trailing newlines with `chomp: true`" do
+ a = []
+ "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '', chomp: true) { |s| a << s }
+ a.should == ["hello\nworld", "and\nuniverse"]
+
+ a = []
+ "hello\nworld\n\n\nand\nuniverse\n\n\n\n\ndog".send(@method, '', chomp: true) { |s| a << s }
+ a.should == ["hello\nworld", "and\nuniverse", "dog"]
+ end
end
describe "uses $/" do
@@ -85,25 +107,15 @@ describe :string_each_line, shared: true do
end
end
- ruby_version_is ''...'3.0' do
- it "yields subclass instances for subclasses" do
- a = []
- StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class }
- a.should == [StringSpecs::MyString, StringSpecs::MyString]
- end
- end
-
- ruby_version_is '3.0' do
- it "yields String instances for subclasses" do
- a = []
- StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class }
- a.should == [String, String]
- end
+ it "yields String instances for subclasses" do
+ a = []
+ StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class }
+ a.should == [String, String]
end
it "returns self" do
s = "hello\nworld"
- (s.send(@method) {}).should equal(s)
+ (s.send(@method) {}).should.equal?(s)
end
it "tries to convert the separator to a string using to_str" do
@@ -116,15 +128,21 @@ describe :string_each_line, shared: true do
end
it "does not care if the string is modified while substituting" do
- str = "hello\nworld."
+ str = +"hello\nworld."
out = []
str.send(@method){|x| out << x; str[-1] = '!' }.should == "hello\nworld!"
out.should == ["hello\n", "world."]
end
+ it "returns Strings in the same encoding as self" do
+ "one\ntwo\r\nthree".encode("US-ASCII").send(@method) do |s|
+ s.encoding.should == Encoding::US_ASCII
+ end
+ end
+
it "raises a TypeError when the separator can't be converted to a string" do
- -> { "hello world".send(@method, false) {} }.should raise_error(TypeError)
- -> { "hello world".send(@method, mock('x')) {} }.should raise_error(TypeError)
+ -> { "hello world".send(@method, false) {} }.should.raise(TypeError)
+ -> { "hello world".send(@method, mock('x')) {} }.should.raise(TypeError)
end
it "accepts a string separator" do
@@ -132,7 +150,7 @@ describe :string_each_line, shared: true do
end
it "raises a TypeError when the separator is a symbol" do
- -> { "hello world".send(@method, :o).to_a }.should raise_error(TypeError)
+ -> { "hello world".send(@method, :o).to_a }.should.raise(TypeError)
end
context "when `chomp` keyword argument is passed" do
@@ -163,4 +181,18 @@ describe :string_each_line, shared: true do
a.should == ["hello\r\n", "world\r\n"]
end
end
+
+ it "does not split lines for dummy UTF-16" do
+ "a\nb".encode(Encoding::UTF_16).lines.should == [
+ "\xFE\xFF\x00\x61\x00\n\x00\x62".dup.force_encoding(Encoding::UTF_16)
+ ]
+
+ str = "\x00\n\n\x00".dup.force_encoding(Encoding::UTF_16)
+ str.lines.should == [str]
+ end
+
+ it "raises Encoding::ConverterNotFoundError for dummy UTF-7" do
+ str = "a\nb".dup.force_encoding(Encoding::UTF_7)
+ -> { str.lines }.should.raise(Encoding::ConverterNotFoundError)
+ end
end
diff --git a/spec/ruby/core/string/shared/each_line_without_block.rb b/spec/ruby/core/string/shared/each_line_without_block.rb
index 8e08b0390c..af0ab69c00 100644
--- a/spec/ruby/core/string/shared/each_line_without_block.rb
+++ b/spec/ruby/core/string/shared/each_line_without_block.rb
@@ -2,7 +2,7 @@ describe :string_each_line_without_block, shared: true do
describe "when no block is given" do
it "returns an enumerator" do
enum = "hello world".send(@method, ' ')
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.to_a.should == ["hello ", "world"]
end
diff --git a/spec/ruby/core/string/shared/encode.rb b/spec/ruby/core/string/shared/encode.rb
index a73de5b943..7f644c26d9 100644
--- a/spec/ruby/core/string/shared/encode.rb
+++ b/spec/ruby/core/string/shared/encode.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
describe :string_encode, shared: true do
describe "when passed no options" do
it "transcodes to Encoding.default_internal when set" do
@@ -10,7 +11,7 @@ describe :string_encode, shared: true do
it "transcodes a 7-bit String despite no generic converting being available" do
-> do
Encoding::Converter.new Encoding::Emacs_Mule, Encoding::BINARY
- end.should raise_error(Encoding::ConverterNotFoundError)
+ end.should.raise(Encoding::ConverterNotFoundError)
Encoding.default_internal = Encoding::Emacs_Mule
str = "\x79".force_encoding Encoding::BINARY
@@ -21,7 +22,7 @@ describe :string_encode, shared: true do
it "raises an Encoding::ConverterNotFoundError when no conversion is possible" do
Encoding.default_internal = Encoding::Emacs_Mule
str = [0x80].pack('C').force_encoding Encoding::BINARY
- -> { str.send(@method) }.should raise_error(Encoding::ConverterNotFoundError)
+ -> { str.send(@method) }.should.raise(Encoding::ConverterNotFoundError)
end
end
@@ -53,7 +54,7 @@ describe :string_encode, shared: true do
it "transcodes a 7-bit String despite no generic converting being available" do
-> do
Encoding::Converter.new Encoding::Emacs_Mule, Encoding::BINARY
- end.should raise_error(Encoding::ConverterNotFoundError)
+ end.should.raise(Encoding::ConverterNotFoundError)
str = "\x79".force_encoding Encoding::BINARY
str.send(@method, Encoding::Emacs_Mule).should == "y".force_encoding(Encoding::BINARY)
@@ -63,13 +64,21 @@ describe :string_encode, shared: true do
str = [0x80].pack('C').force_encoding Encoding::BINARY
-> do
str.send(@method, Encoding::Emacs_Mule)
- end.should raise_error(Encoding::ConverterNotFoundError)
+ end.should.raise(Encoding::ConverterNotFoundError)
end
it "raises an Encoding::ConverterNotFoundError for an invalid encoding" do
-> do
"abc".send(@method, "xyz")
- end.should raise_error(Encoding::ConverterNotFoundError)
+ end.should.raise(Encoding::ConverterNotFoundError)
+ end
+
+ it "raises an Encoding::UndefinedConversionError when a character cannot be represented in the destination encoding" do
+ # U+0100 (Ā) is valid UTF-8 but not representable in windows-1252
+ str = "test\u0100".force_encoding('utf-8')
+ -> {
+ str.send(@method, Encoding::Windows_1252)
+ }.should.raise(Encoding::UndefinedConversionError)
end
end
@@ -98,7 +107,7 @@ describe :string_encode, shared: true do
str = [0x80].pack('C').force_encoding Encoding::BINARY
-> do
str.send(@method, invalid: :replace, undef: :replace)
- end.should raise_error(Encoding::ConverterNotFoundError)
+ end.should.raise(Encoding::ConverterNotFoundError)
end
it "replaces invalid characters when replacing Emacs-Mule encoded strings" do
@@ -141,6 +150,14 @@ describe :string_encode, shared: true do
"ab#{xFF}c".send(@method, Encoding::ISO_8859_1, invalid: :replace).should == "ab?c"
end
+ it "raises UndefinedConversionError for characters not representable in destination encoding with only invalid: :replace" do
+ # U+0100 (Ā) is valid UTF-8 but not representable in windows-1252
+ str = "test\u0100".force_encoding('utf-8')
+ -> {
+ str.send(@method, Encoding::Windows_1252, invalid: :replace, replace: "")
+ }.should.raise(Encoding::UndefinedConversionError)
+ end
+
it "calls #to_hash to convert the options object" do
options = mock("string encode options")
options.should_receive(:to_hash).and_return({ undef: :replace })
@@ -193,6 +210,190 @@ describe :string_encode, shared: true do
end
end
+ describe "given the fallback option" do
+ context "given a hash" do
+ it "looks up the replacement value from the hash" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => "bar" })
+ encoded.should == "Bbar"
+ end
+
+ it "calls to_str on the returned value" do
+ obj = Object.new
+ obj.should_receive(:to_str).and_return("bar")
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => obj })
+ encoded.should == "Bbar"
+ end
+
+ it "does not call to_s on the returned value" do
+ obj = Object.new
+ obj.should_not_receive(:to_s)
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => obj })
+ }.should.raise(TypeError, "no implicit conversion of Object into String")
+ end
+
+ it "raises an error if the key is not present in the hash" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: { "foo" => "bar" })
+ }.should.raise(Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII")
+ end
+
+ it "raises an error if the value is itself invalid" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => "\uffee" })
+ }.should.raise(ArgumentError, "too big fallback string")
+ end
+
+ it "uses the hash's default value if set" do
+ hash = {}
+ hash.default = "bar"
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: hash)
+ encoded.should == "Bbar"
+ end
+
+ it "uses the result of calling default_proc if set" do
+ hash = {}
+ hash.default_proc = -> _, _ { "bar" }
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: hash)
+ encoded.should == "Bbar"
+ end
+ end
+
+ context "given an object inheriting from Hash" do
+ before do
+ klass = Class.new(Hash)
+ @hash_like = klass.new
+ @hash_like["\ufffd"] = "bar"
+ end
+
+ it "looks up the replacement value from the object" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: @hash_like)
+ encoded.should == "Bbar"
+ end
+ end
+
+ context "given an object responding to []" do
+ before do
+ klass = Class.new do
+ def [](c) = c.bytes.inspect
+ end
+ @hash_like = klass.new
+ end
+
+ it "calls [] on the object, passing the invalid character" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: @hash_like)
+ encoded.should == "B[239, 191, 189]"
+ end
+ end
+
+ context "given an object not responding to []" do
+ before do
+ @non_hash_like = Object.new
+ end
+
+ it "raises an error" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: @non_hash_like)
+ }.should.raise(Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII")
+ end
+ end
+
+ context "given a proc" do
+ it "calls the proc to get the replacement value, passing in the invalid character" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| c.bytes.inspect })
+ encoded.should == "B[239, 191, 189]"
+ end
+
+ it "calls to_str on the returned value" do
+ obj = Object.new
+ obj.should_receive(:to_str).and_return("bar")
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| obj })
+ encoded.should == "Bbar"
+ end
+
+ it "does not call to_s on the returned value" do
+ obj = Object.new
+ obj.should_not_receive(:to_s)
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| obj })
+ }.should.raise(TypeError, "no implicit conversion of Object into String")
+ end
+
+ it "raises an error if the returned value is itself invalid" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { "\uffee" })
+ }.should.raise(ArgumentError, "too big fallback string")
+ end
+ end
+
+ context "given a lambda" do
+ it "calls the lambda to get the replacement value, passing in the invalid character" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { c.bytes.inspect })
+ encoded.should == "B[239, 191, 189]"
+ end
+
+ it "calls to_str on the returned value" do
+ obj = Object.new
+ obj.should_receive(:to_str).and_return("bar")
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { obj })
+ encoded.should == "Bbar"
+ end
+
+ it "does not call to_s on the returned value" do
+ obj = Object.new
+ obj.should_not_receive(:to_s)
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { obj })
+ }.should.raise(TypeError, "no implicit conversion of Object into String")
+ end
+
+ it "raises an error if the returned value is itself invalid" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { "\uffee" })
+ }.should.raise(ArgumentError, "too big fallback string")
+ end
+ end
+
+ context "given a method" do
+ def replace(c) = c.bytes.inspect
+ def replace_bad(c) = "\uffee"
+
+ def replace_to_str(c)
+ obj = Object.new
+ obj.should_receive(:to_str).and_return("bar")
+ obj
+ end
+
+ def replace_to_s(c)
+ obj = Object.new
+ obj.should_not_receive(:to_s)
+ obj
+ end
+
+ it "calls the method to get the replacement value, passing in the invalid character" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace))
+ encoded.should == "B[239, 191, 189]"
+ end
+
+ it "calls to_str on the returned value" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_to_str))
+ encoded.should == "Bbar"
+ end
+
+ it "does not call to_s on the returned value" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_to_s))
+ }.should.raise(TypeError, "no implicit conversion of Object into String")
+ end
+
+ it "raises an error if the returned value is itself invalid" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_bad))
+ }.should.raise(ArgumentError, "too big fallback string")
+ end
+ end
+ end
+
describe "given the xml: :text option" do
it "replaces all instances of '&' with '&amp;'" do
'& and &'.send(@method, "UTF-8", xml: :text).should == '&amp; and &amp;'
@@ -242,6 +443,6 @@ describe :string_encode, shared: true do
end
it "raises ArgumentError if the value of the :xml option is not :text or :attr" do
- -> { ''.send(@method, "UTF-8", xml: :other) }.should raise_error(ArgumentError)
+ -> { ''.send(@method, "UTF-8", xml: :other) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/shared/eql.rb b/spec/ruby/core/string/shared/eql.rb
index 6f268c929c..0e356c69e8 100644
--- a/spec/ruby/core/string/shared/eql.rb
+++ b/spec/ruby/core/string/shared/eql.rb
@@ -1,38 +1,38 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
describe :string_eql_value, shared: true do
it "returns true if self <=> string returns 0" do
- 'hello'.send(@method, 'hello').should be_true
+ 'hello'.send(@method, 'hello').should == true
end
it "returns false if self <=> string does not return 0" do
- "more".send(@method, "MORE").should be_false
- "less".send(@method, "greater").should be_false
+ "more".send(@method, "MORE").should == false
+ "less".send(@method, "greater").should == false
end
it "ignores encoding difference of compatible string" do
- "hello".force_encoding("utf-8").send(@method, "hello".force_encoding("iso-8859-1")).should be_true
+ "hello".dup.force_encoding("utf-8").send(@method, "hello".dup.force_encoding("iso-8859-1")).should == true
end
it "considers encoding difference of incompatible string" do
- "\xff".force_encoding("utf-8").send(@method, "\xff".force_encoding("iso-8859-1")).should be_false
+ "\xff".dup.force_encoding("utf-8").send(@method, "\xff".dup.force_encoding("iso-8859-1")).should == false
end
it "considers encoding compatibility" do
- "abcd".force_encoding("utf-8").send(@method, "abcd".force_encoding("utf-32le")).should be_false
+ "abcd".dup.force_encoding("utf-8").send(@method, "abcd".dup.force_encoding("utf-32le")).should == false
end
it "ignores subclass differences" do
a = "hello"
b = StringSpecs::MyString.new("hello")
- a.send(@method, b).should be_true
- b.send(@method, a).should be_true
+ a.send(@method, b).should == true
+ b.send(@method, a).should == true
end
it "returns true when comparing 2 empty strings but one is not ASCII-compatible" do
- "".send(@method, "".force_encoding('iso-2022-jp')).should == true
+ "".send(@method, "".dup.force_encoding('iso-2022-jp')).should == true
end
end
diff --git a/spec/ruby/core/string/shared/equal_value.rb b/spec/ruby/core/string/shared/equal_value.rb
index fccafb5821..dfc5c7cd29 100644
--- a/spec/ruby/core/string/shared/equal_value.rb
+++ b/spec/ruby/core/string/shared/equal_value.rb
@@ -3,11 +3,11 @@ require_relative '../fixtures/classes'
describe :string_equal_value, shared: true do
it "returns false if obj does not respond to to_str" do
- 'hello'.send(@method, 5).should be_false
+ 'hello'.send(@method, 5).should == false
not_supported_on :opal do
- 'hello'.send(@method, :hello).should be_false
+ 'hello'.send(@method, :hello).should == false
end
- 'hello'.send(@method, mock('x')).should be_false
+ 'hello'.send(@method, mock('x')).should == false
end
it "returns obj == self if obj responds to to_str" do
@@ -20,10 +20,10 @@ describe :string_equal_value, shared: true do
# Don't use @method for :== in `obj.should_receive(:==)`
obj.should_receive(:==).and_return(true)
- 'hello'.send(@method, obj).should be_true
+ 'hello'.send(@method, obj).should == true
end
it "is not fooled by NUL characters" do
- "abc\0def".send(@method, "abc\0xyz").should be_false
+ "abc\0def".send(@method, "abc\0xyz").should == false
end
end
diff --git a/spec/ruby/core/string/shared/grapheme_clusters.rb b/spec/ruby/core/string/shared/grapheme_clusters.rb
index 8b666868b1..dd8c7ed5fe 100644
--- a/spec/ruby/core/string/shared/grapheme_clusters.rb
+++ b/spec/ruby/core/string/shared/grapheme_clusters.rb
@@ -9,8 +9,17 @@ describe :string_grapheme_clusters, shared: true do
a.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"]
end
+ it "returns grapheme clusters for various UTF encodings" do
+ [Encoding::UTF_16LE, Encoding::UTF_16BE, Encoding::UTF_32LE, Encoding::UTF_32BE].each do |enc|
+ a = []
+ # test string: abc[rainbow flag emoji][paw prints]
+ "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}".encode(enc).send(@method) { |c| a << c }
+ a.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"].map { |s| s.encode(enc) }
+ end
+ end
+
it "returns self" do
s = StringSpecs::MyString.new "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}"
- s.send(@method) {}.should equal(s)
+ s.send(@method) {}.should.equal?(s)
end
end
diff --git a/spec/ruby/core/string/shared/length.rb b/spec/ruby/core/string/shared/length.rb
index 94e5ec135b..ae572ba755 100644
--- a/spec/ruby/core/string/shared/length.rb
+++ b/spec/ruby/core/string/shared/length.rb
@@ -18,7 +18,7 @@ describe :string_length, shared: true do
end
it "returns the length of the new self after encoding is changed" do
- str = 'こにちわ'
+ str = +'こにちわ'
str.send(@method)
str.force_encoding('BINARY').send(@method).should == 12
@@ -44,12 +44,12 @@ describe :string_length, shared: true do
end
it "adds 1 (and not 2) for a incomplete surrogate in UTF-16" do
- "\x00\xd8".force_encoding("UTF-16LE").send(@method).should == 1
- "\xd8\x00".force_encoding("UTF-16BE").send(@method).should == 1
+ "\x00\xd8".dup.force_encoding("UTF-16LE").send(@method).should == 1
+ "\xd8\x00".dup.force_encoding("UTF-16BE").send(@method).should == 1
end
it "adds 1 for a broken sequence in UTF-32" do
- "\x04\x03\x02\x01".force_encoding("UTF-32LE").send(@method).should == 1
- "\x01\x02\x03\x04".force_encoding("UTF-32BE").send(@method).should == 1
+ "\x04\x03\x02\x01".dup.force_encoding("UTF-32LE").send(@method).should == 1
+ "\x01\x02\x03\x04".dup.force_encoding("UTF-32BE").send(@method).should == 1
end
end
diff --git a/spec/ruby/core/string/shared/partition.rb b/spec/ruby/core/string/shared/partition.rb
index 7dc3d9cc0b..3f7e606eb3 100644
--- a/spec/ruby/core/string/shared/partition.rb
+++ b/spec/ruby/core/string/shared/partition.rb
@@ -2,35 +2,32 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
describe :string_partition, shared: true do
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("hello").send(@method, "l").each do |item|
- item.should be_an_instance_of(String)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").send(@method, "l").each do |item|
+ item.should.instance_of?(String)
+ end
- StringSpecs::MyString.new("hello").send(@method, "x").each do |item|
- item.should be_an_instance_of(String)
- end
+ StringSpecs::MyString.new("hello").send(@method, "x").each do |item|
+ item.should.instance_of?(String)
+ end
- StringSpecs::MyString.new("hello").send(@method, /l./).each do |item|
- item.should be_an_instance_of(String)
- end
+ StringSpecs::MyString.new("hello").send(@method, /l./).each do |item|
+ item.should.instance_of?(String)
end
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("hello").send(@method, StringSpecs::MyString.new("l")).each do |item|
- item.should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns before- and after- parts in the same encoding as self" do
+ strings = "hello".encode("US-ASCII").send(@method, "ello")
+ strings[0].encoding.should == Encoding::US_ASCII
+ strings[2].encoding.should == Encoding::US_ASCII
- StringSpecs::MyString.new("hello").send(@method, "x").each do |item|
- item.should be_an_instance_of(StringSpecs::MyString)
- end
+ strings = "hello".encode("US-ASCII").send(@method, /ello/)
+ strings[0].encoding.should == Encoding::US_ASCII
+ strings[2].encoding.should == Encoding::US_ASCII
+ end
- StringSpecs::MyString.new("hello").send(@method, /l./).each do |item|
- item.should be_an_instance_of(StringSpecs::MyString)
- end
- end
+ it "returns the matching part in the separator's encoding" do
+ strings = "hello".encode("US-ASCII").send(@method, "ello")
+ strings[1].encoding.should == Encoding::UTF_8
end
end
diff --git a/spec/ruby/core/string/shared/replace.rb b/spec/ruby/core/string/shared/replace.rb
index a5108d9e7c..73b26351f1 100644
--- a/spec/ruby/core/string/shared/replace.rb
+++ b/spec/ruby/core/string/shared/replace.rb
@@ -1,7 +1,8 @@
+# frozen_string_literal: false
describe :string_replace, shared: true do
it "returns self" do
a = "a"
- a.send(@method, "b").should equal(a)
+ a.send(@method, "b").should.equal?(a)
end
it "replaces the content of self with other" do
@@ -19,7 +20,7 @@ describe :string_replace, shared: true do
it "carries over the encoding invalidity" do
a = "\u{8765}".force_encoding('ascii')
- "".send(@method, a).valid_encoding?.should be_false
+ "".send(@method, a).valid_encoding?.should == false
end
it "tries to convert other to string using to_str" do
@@ -29,19 +30,19 @@ describe :string_replace, shared: true do
end
it "raises a TypeError if other can't be converted to string" do
- -> { "hello".send(@method, 123) }.should raise_error(TypeError)
- -> { "hello".send(@method, []) }.should raise_error(TypeError)
- -> { "hello".send(@method, mock('x')) }.should raise_error(TypeError)
+ -> { "hello".send(@method, 123) }.should.raise(TypeError)
+ -> { "hello".send(@method, []) }.should.raise(TypeError)
+ -> { "hello".send(@method, mock('x')) }.should.raise(TypeError)
end
it "raises a FrozenError on a frozen instance that is modified" do
a = "hello".freeze
- -> { a.send(@method, "world") }.should raise_error(FrozenError)
+ -> { a.send(@method, "world") }.should.raise(FrozenError)
end
# see [ruby-core:23666]
it "raises a FrozenError on a frozen instance when self-replacing" do
a = "hello".freeze
- -> { a.send(@method, a) }.should raise_error(FrozenError)
+ -> { a.send(@method, a) }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/shared/slice.rb b/spec/ruby/core/string/shared/slice.rb
index 713234fffd..d296ab6680 100644
--- a/spec/ruby/core/string/shared/slice.rb
+++ b/spec/ruby/core/string/shared/slice.rb
@@ -21,17 +21,17 @@ describe :string_slice, shared: true do
end
it "raises a TypeError if the given index is nil" do
- -> { "hello".send(@method, nil) }.should raise_error(TypeError)
+ -> { "hello".send(@method, nil) }.should.raise(TypeError)
end
it "raises a TypeError if the given index can't be converted to an Integer" do
- -> { "hello".send(@method, mock('x')) }.should raise_error(TypeError)
- -> { "hello".send(@method, {}) }.should raise_error(TypeError)
- -> { "hello".send(@method, []) }.should raise_error(TypeError)
+ -> { "hello".send(@method, mock('x')) }.should.raise(TypeError)
+ -> { "hello".send(@method, {}) }.should.raise(TypeError)
+ -> { "hello".send(@method, []) }.should.raise(TypeError)
end
it "raises a RangeError if the index is too big" do
- -> { "hello".send(@method, bignum_value) }.should raise_error(RangeError)
+ -> { "hello".send(@method, bignum_value) }.should.raise(RangeError)
end
end
@@ -80,12 +80,12 @@ describe :string_slice_index_length, shared: true do
"hello there".send(@method, -3,2).should == "er"
end
- it "returns a string with the same encoding" do
+ it "returns a string with the same encoding as self" do
s = "hello there"
s.send(@method, 1, 9).encoding.should == s.encoding
- a = "hello".force_encoding("binary")
- b = " there".force_encoding("ISO-8859-1")
+ a = "hello".dup.force_encoding("binary")
+ b = " there".dup.force_encoding("ISO-8859-1")
c = (a + b).force_encoding(Encoding::US_ASCII)
c.send(@method, 0, 5).encoding.should == Encoding::US_ASCII
@@ -119,6 +119,18 @@ describe :string_slice_index_length, shared: true do
"hello there".send(@method, -4,-3).should == nil
end
+ platform_is pointer_size: 64 do
+ it "returns nil if the length is negative big value" do
+ "hello there".send(@method, 4, -(1 << 31)).should == nil
+
+ # by some reason length < -(1 << 31) on CI on Windows leads to
+ # 'RangeError: bignum too big to convert into `long'' error
+ platform_is_not :windows do
+ "hello there".send(@method, 4, -(1 << 63)).should == nil
+ end
+ end
+ end
+
it "calls to_int on the given index and the given length" do
"hello".send(@method, 0.5, 1).should == "h"
"hello".send(@method, 0.5, 2.5).should == "he"
@@ -133,41 +145,35 @@ describe :string_slice_index_length, shared: true do
end
it "raises a TypeError when idx or length can't be converted to an integer" do
- -> { "hello".send(@method, mock('x'), 0) }.should raise_error(TypeError)
- -> { "hello".send(@method, 0, mock('x')) }.should raise_error(TypeError)
+ -> { "hello".send(@method, mock('x'), 0) }.should.raise(TypeError)
+ -> { "hello".send(@method, 0, mock('x')) }.should.raise(TypeError)
# I'm deliberately including this here.
# It means that str.send(@method, other, idx) isn't supported.
- -> { "hello".send(@method, "", 0) }.should raise_error(TypeError)
+ -> { "hello".send(@method, "", 0) }.should.raise(TypeError)
end
it "raises a TypeError when the given index or the given length is nil" do
- -> { "hello".send(@method, 1, nil) }.should raise_error(TypeError)
- -> { "hello".send(@method, nil, 1) }.should raise_error(TypeError)
- -> { "hello".send(@method, nil, nil) }.should raise_error(TypeError)
+ -> { "hello".send(@method, 1, nil) }.should.raise(TypeError)
+ -> { "hello".send(@method, nil, 1) }.should.raise(TypeError)
+ -> { "hello".send(@method, nil, nil) }.should.raise(TypeError)
end
it "raises a RangeError if the index or length is too big" do
- -> { "hello".send(@method, bignum_value, 1) }.should raise_error(RangeError)
- -> { "hello".send(@method, 0, bignum_value) }.should raise_error(RangeError)
+ -> { "hello".send(@method, bignum_value, 1) }.should.raise(RangeError)
+ -> { "hello".send(@method, 0, bignum_value) }.should.raise(RangeError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, 0,0).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, 0,4).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, 1,4).should be_an_instance_of(StringSpecs::MyString)
- end
+ it "raises a RangeError if the index or length is too small" do
+ -> { "hello".send(@method, -bignum_value, 1) }.should.raise(RangeError)
+ -> { "hello".send(@method, 0, -bignum_value) }.should.raise(RangeError)
end
- ruby_version_is '3.0' do
- it "returns String instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, 0,0).should be_an_instance_of(String)
- s.send(@method, 0,4).should be_an_instance_of(String)
- s.send(@method, 1,4).should be_an_instance_of(String)
- end
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, 0,0).should.instance_of?(String)
+ s.send(@method, 0,4).should.instance_of?(String)
+ s.send(@method, 1,4).should.instance_of?(String)
end
it "handles repeated application" do
@@ -206,6 +212,10 @@ describe :string_slice_range, shared: true do
"x".send(@method, 1..-1).should == ""
end
+ it "returns a String in the same encoding as self" do
+ "hello there".encode("US-ASCII").send(@method, 1..1).encoding.should == Encoding::US_ASCII
+ end
+
it "returns nil if the beginning of the range falls outside of self" do
"hello there".send(@method, 12..-1).should == nil
"hello there".send(@method, 20..25).should == nil
@@ -238,22 +248,11 @@ describe :string_slice_range, shared: true do
"x".send(@method, 1...-1).should == ""
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, 0...0).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, 0..4).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, 1..4).should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, 0...0).should be_an_instance_of(String)
- s.send(@method, 0..4).should be_an_instance_of(String)
- s.send(@method, 1..4).should be_an_instance_of(String)
- end
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, 0...0).should.instance_of?(String)
+ s.send(@method, 0..4).should.instance_of?(String)
+ s.send(@method, 1..4).should.instance_of?(String)
end
it "calls to_int on range arguments" do
@@ -294,12 +293,12 @@ describe :string_slice_range, shared: true do
end
it "raises a type error if a range is passed with a length" do
- ->{ "hello".send(@method, 1..2, 1) }.should raise_error(TypeError)
+ ->{ "hello".send(@method, 1..2, 1) }.should.raise(TypeError)
end
it "raises a RangeError if one of the bound is too big" do
- -> { "hello".send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError)
- -> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError)
+ -> { "hello".send(@method, bignum_value..(bignum_value + 1)) }.should.raise(RangeError)
+ -> { "hello".send(@method, 0..bignum_value) }.should.raise(RangeError)
end
it "works with endless ranges" do
@@ -328,23 +327,14 @@ describe :string_slice_regexp, shared: true do
"hello there".send(@method, /xyz/).should == nil
end
- not_supported_on :opal do
- end
-
- ruby_version_is ''...'3.0' do
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, //).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, /../).should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns a String in the same encoding as self" do
+ "hello there".encode("US-ASCII").send(@method, /[aeiou](.)\1/).encoding.should == Encoding::US_ASCII
end
- ruby_version_is '3.0' do
- it "returns String instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, //).should be_an_instance_of(String)
- s.send(@method, /../).should be_an_instance_of(String)
- end
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, //).should.instance_of?(String)
+ s.send(@method, /../).should.instance_of?(String)
end
it "sets $~ to MatchData when there is a match and nil when there's none" do
@@ -391,6 +381,10 @@ describe :string_slice_regexp_index, shared: true do
$~[1].should == nil
end
+ it "returns a String in the same encoding as self" do
+ "hello there".encode("US-ASCII").send(@method, /[aeiou](.)\1/, 0).encoding.should == Encoding::US_ASCII
+ end
+
it "calls to_int on the given index" do
obj = mock('2')
obj.should_receive(:to_int).and_return(2)
@@ -400,29 +394,19 @@ describe :string_slice_regexp_index, shared: true do
end
it "raises a TypeError when the given index can't be converted to Integer" do
- -> { "hello".send(@method, /(.)(.)(.)/, mock('x')) }.should raise_error(TypeError)
- -> { "hello".send(@method, /(.)(.)(.)/, {}) }.should raise_error(TypeError)
- -> { "hello".send(@method, /(.)(.)(.)/, []) }.should raise_error(TypeError)
+ -> { "hello".send(@method, /(.)(.)(.)/, mock('x')) }.should.raise(TypeError)
+ -> { "hello".send(@method, /(.)(.)(.)/, {}) }.should.raise(TypeError)
+ -> { "hello".send(@method, /(.)(.)(.)/, []) }.should.raise(TypeError)
end
it "raises a TypeError when the given index is nil" do
- -> { "hello".send(@method, /(.)(.)(.)/, nil) }.should raise_error(TypeError)
+ -> { "hello".send(@method, /(.)(.)(.)/, nil) }.should.raise(TypeError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, /(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, /(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, /(.)(.)/, 0).should be_an_instance_of(String)
- s.send(@method, /(.)(.)/, 1).should be_an_instance_of(String)
- end
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, /(.)(.)/, 0).should.instance_of?(String)
+ s.send(@method, /(.)(.)/, 1).should.instance_of?(String)
end
it "sets $~ to MatchData when there is a match and nil when there's none" do
@@ -458,25 +442,14 @@ describe :string_slice_string, shared: true do
o = mock('x')
o.should_not_receive(:to_str)
- -> { "hello".send(@method, o) }.should raise_error(TypeError)
- end
-
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance when given a subclass instance" do
- s = StringSpecs::MyString.new("el")
- r = "hello".send(@method, s)
- r.should == "el"
- r.should be_an_instance_of(StringSpecs::MyString)
- end
+ -> { "hello".send(@method, o) }.should.raise(TypeError)
end
- ruby_version_is '3.0' do
- it "returns a String instance when given a subclass instance" do
- s = StringSpecs::MyString.new("el")
- r = "hello".send(@method, s)
- r.should == "el"
- r.should be_an_instance_of(String)
- end
+ it "returns a String instance when given a subclass instance" do
+ s = StringSpecs::MyString.new("el")
+ r = "hello".send(@method, s)
+ r.should == "el"
+ r.should.instance_of?(String)
end
end
@@ -503,37 +476,28 @@ describe :string_slice_regexp_group, shared: true do
end
it "returns nil if there is no match" do
- "hello there".send(@method, /(?<whut>what?)/, 'whut').should be_nil
+ "hello there".send(@method, /(?<whut>what?)/, 'whut').should == nil
end
it "raises an IndexError if there is no capture for the given name" do
-> do
"hello there".send(@method, /[aeiou](.)\1/, 'non')
- end.should raise_error(IndexError)
+ end.should.raise(IndexError)
end
it "raises a TypeError when the given name is not a String" do
- -> { "hello".send(@method, /(?<q>.)/, mock('x')) }.should raise_error(TypeError)
- -> { "hello".send(@method, /(?<q>.)/, {}) }.should raise_error(TypeError)
- -> { "hello".send(@method, /(?<q>.)/, []) }.should raise_error(TypeError)
+ -> { "hello".send(@method, /(?<q>.)/, mock('x')) }.should.raise(TypeError)
+ -> { "hello".send(@method, /(?<q>.)/, {}) }.should.raise(TypeError)
+ -> { "hello".send(@method, /(?<q>.)/, []) }.should.raise(TypeError)
end
it "raises an IndexError when given the empty String as a group name" do
- -> { "hello".send(@method, /(?<q>)/, '') }.should raise_error(IndexError)
+ -> { "hello".send(@method, /(?<q>)/, '') }.should.raise(IndexError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, /(?<q>.)/, 'q').should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, /(?<q>.)/, 'q').should be_an_instance_of(String)
- end
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, /(?<q>.)/, 'q').should.instance_of?(String)
end
it "sets $~ to MatchData when there is a match and nil when there's none" do
@@ -541,13 +505,13 @@ describe :string_slice_regexp_group, shared: true do
$~[0].should == 'he'
'hello'.send(@method, /(?<non>not)/, 'non')
- $~.should be_nil
+ $~.should == nil
end
end
end
describe :string_slice_symbol, shared: true do
it "raises TypeError" do
- -> { 'hello'.send(@method, :hello) }.should raise_error(TypeError)
+ -> { 'hello'.send(@method, :hello) }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/string/shared/strip.rb b/spec/ruby/core/string/shared/strip.rb
index 9c232b4694..39c7232ff9 100644
--- a/spec/ruby/core/string/shared/strip.rb
+++ b/spec/ruby/core/string/shared/strip.rb
@@ -2,19 +2,13 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
describe :string_strip, shared: true do
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(String)
- StringSpecs::MyString.new(" ").send(@method).should be_an_instance_of(String)
- StringSpecs::MyString.new("").send(@method).should be_an_instance_of(String)
- end
+ it "returns a String in the same encoding as self" do
+ " hello ".encode("US-ASCII").send(@method).encoding.should == Encoding::US_ASCII
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new(" ").send(@method).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new(" hello ").send(@method).should.instance_of?(String)
+ StringSpecs::MyString.new(" ").send(@method).should.instance_of?(String)
+ StringSpecs::MyString.new("").send(@method).should.instance_of?(String)
end
end
diff --git a/spec/ruby/core/string/shared/succ.rb b/spec/ruby/core/string/shared/succ.rb
index 66edf6dc82..8f1d327741 100644
--- a/spec/ruby/core/string/shared/succ.rb
+++ b/spec/ruby/core/string/shared/succ.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_succ, shared: true do
it "returns an empty string for empty strings" do
"".send(@method).should == ""
@@ -59,34 +59,29 @@ describe :string_succ, shared: true do
"\xFF\xFF".send(@method).should == "\x01\x00\x00"
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("").send(@method).should.instance_of?(String)
+ StringSpecs::MyString.new("a").send(@method).should.instance_of?(String)
+ StringSpecs::MyString.new("z").send(@method).should.instance_of?(String)
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("").send(@method).should be_an_instance_of(String)
- StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(String)
- StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(String)
- end
+ it "returns a String in the same encoding as self" do
+ "z".encode("US-ASCII").send(@method).encoding.should == Encoding::US_ASCII
end
end
describe :string_succ_bang, shared: true do
it "is equivalent to succ, but modifies self in place (still returns self)" do
["", "abcd", "THX1138"].each do |s|
+ s = +s
r = s.dup.send(@method)
- s.send(@method).should equal(s)
+ s.send(@method).should.equal?(s)
s.should == r
end
end
it "raises a FrozenError if self is frozen" do
- -> { "".freeze.send(@method) }.should raise_error(FrozenError)
- -> { "abcd".freeze.send(@method) }.should raise_error(FrozenError)
+ -> { "".freeze.send(@method) }.should.raise(FrozenError)
+ -> { "abcd".freeze.send(@method) }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/shared/to_a.rb b/spec/ruby/core/string/shared/to_a.rb
deleted file mode 100644
index bad3ea6584..0000000000
--- a/spec/ruby/core/string/shared/to_a.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-describe :string_to_a, shared: true do
- it "returns an empty array for empty strings" do
- "".send(@method).should == []
- end
-
- it "returns an array containing the string for non-empty strings" do
- "hello".send(@method).should == ["hello"]
- end
-end
diff --git a/spec/ruby/core/string/shared/to_s.rb b/spec/ruby/core/string/shared/to_s.rb
index 4b87a6cbe1..96c59470d6 100644
--- a/spec/ruby/core/string/shared/to_s.rb
+++ b/spec/ruby/core/string/shared/to_s.rb
@@ -1,13 +1,13 @@
describe :string_to_s, shared: true do
it "returns self when self.class == String" do
a = "a string"
- a.should equal(a.send(@method))
+ a.should.equal?(a.send(@method))
end
it "returns a new instance of String when called on a subclass" do
a = StringSpecs::MyString.new("a string")
s = a.send(@method)
s.should == "a string"
- s.should be_an_instance_of(String)
+ s.should.instance_of?(String)
end
end
diff --git a/spec/ruby/core/string/shared/to_sym.rb b/spec/ruby/core/string/shared/to_sym.rb
index ef7c22bb6a..2a8a2e3182 100644
--- a/spec/ruby/core/string/shared/to_sym.rb
+++ b/spec/ruby/core/string/shared/to_sym.rb
@@ -1,42 +1,42 @@
describe :string_to_sym, shared: true do
it "returns the symbol corresponding to self" do
- "Koala".send(@method).should equal :Koala
- 'cat'.send(@method).should equal :cat
- '@cat'.send(@method).should equal :@cat
- 'cat and dog'.send(@method).should equal :"cat and dog"
- "abc=".send(@method).should equal :abc=
+ "Koala".send(@method).should.equal? :Koala
+ 'cat'.send(@method).should.equal? :cat
+ '@cat'.send(@method).should.equal? :@cat
+ 'cat and dog'.send(@method).should.equal? :"cat and dog"
+ "abc=".send(@method).should.equal? :abc=
end
it "does not special case +(binary) and -(binary)" do
- "+(binary)".send(@method).should equal :"+(binary)"
- "-(binary)".send(@method).should equal :"-(binary)"
+ "+(binary)".send(@method).should.equal? :"+(binary)"
+ "-(binary)".send(@method).should.equal? :"-(binary)"
end
it "does not special case certain operators" do
- "!@".send(@method).should equal :"!@"
- "~@".send(@method).should equal :"~@"
- "!(unary)".send(@method).should equal :"!(unary)"
- "~(unary)".send(@method).should equal :"~(unary)"
- "+(unary)".send(@method).should equal :"+(unary)"
- "-(unary)".send(@method).should equal :"-(unary)"
+ "!@".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"
+ 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"
+ 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'}"
+ 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
@@ -56,9 +56,9 @@ describe :string_to_sym, shared: true do
it "ignores existing symbols with different encoding" do
source = "fée"
- iso_symbol = source.force_encoding(Encoding::ISO_8859_1).send(@method)
+ iso_symbol = source.dup.force_encoding(Encoding::ISO_8859_1).send(@method)
iso_symbol.encoding.should == Encoding::ISO_8859_1
- binary_symbol = source.force_encoding(Encoding::BINARY).send(@method)
+ binary_symbol = source.dup.force_encoding(Encoding::BINARY).send(@method)
binary_symbol.encoding.should == Encoding::BINARY
end
@@ -67,6 +67,6 @@ describe :string_to_sym, shared: true do
invalid_utf8.should_not.valid_encoding?
-> {
invalid_utf8.send(@method)
- }.should raise_error(EncodingError, /invalid/)
+ }.should.raise(EncodingError, 'invalid symbol in encoding UTF-8 :"\xC3"')
end
end
diff --git a/spec/ruby/core/string/slice_spec.rb b/spec/ruby/core/string/slice_spec.rb
index c9e13ed1bc..14e2251b3f 100644
--- a/spec/ruby/core/string/slice_spec.rb
+++ b/spec/ruby/core/string/slice_spec.rb
@@ -1,5 +1,5 @@
# -*- encoding: utf-8 -*-
-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/slice'
@@ -54,9 +54,9 @@ describe "String#slice! with index" do
end
it "raises a FrozenError if self is frozen" do
- -> { "hello".freeze.slice!(1) }.should raise_error(FrozenError)
- -> { "hello".freeze.slice!(10) }.should raise_error(FrozenError)
- -> { "".freeze.slice!(0) }.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(1) }.should.raise(FrozenError)
+ -> { "hello".freeze.slice!(10) }.should.raise(FrozenError)
+ -> { "".freeze.slice!(0) }.should.raise(FrozenError)
end
it "calls to_int on index" do
@@ -110,13 +110,13 @@ describe "String#slice! with index, length" do
end
it "raises a FrozenError if self is frozen" do
- -> { "hello".freeze.slice!(1, 2) }.should raise_error(FrozenError)
- -> { "hello".freeze.slice!(10, 3) }.should raise_error(FrozenError)
- -> { "hello".freeze.slice!(-10, 3)}.should raise_error(FrozenError)
- -> { "hello".freeze.slice!(4, -3) }.should raise_error(FrozenError)
- -> { "hello".freeze.slice!(10, 3) }.should raise_error(FrozenError)
- -> { "hello".freeze.slice!(-10, 3)}.should raise_error(FrozenError)
- -> { "hello".freeze.slice!(4, -3) }.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(1, 2) }.should.raise(FrozenError)
+ -> { "hello".freeze.slice!(10, 3) }.should.raise(FrozenError)
+ -> { "hello".freeze.slice!(-10, 3)}.should.raise(FrozenError)
+ -> { "hello".freeze.slice!(4, -3) }.should.raise(FrozenError)
+ -> { "hello".freeze.slice!(10, 3) }.should.raise(FrozenError)
+ -> { "hello".freeze.slice!(-10, 3)}.should.raise(FrozenError)
+ -> { "hello".freeze.slice!(4, -3) }.should.raise(FrozenError)
end
it "calls to_int on idx and length" do
@@ -132,20 +132,10 @@ describe "String#slice! with index, length" do
"hello".slice!(obj, obj).should == "ll"
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(0, 0).should be_an_instance_of(StringSpecs::MyString)
- s.slice!(0, 4).should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(0, 0).should be_an_instance_of(String)
- s.slice!(0, 4).should be_an_instance_of(String)
- end
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(0, 0).should.instance_of?(String)
+ s.slice!(0, 4).should.instance_of?(String)
end
it "returns the substring given by the character offsets" do
@@ -185,20 +175,10 @@ describe "String#slice! Range" do
b.should == "hello"
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(0...0).should be_an_instance_of(StringSpecs::MyString)
- s.slice!(0..4).should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(0...0).should be_an_instance_of(String)
- s.slice!(0..4).should be_an_instance_of(String)
- end
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(0...0).should.instance_of?(String)
+ s.slice!(0..4).should.instance_of?(String)
end
it "calls to_int on range arguments" do
@@ -248,12 +228,12 @@ describe "String#slice! Range" do
it "raises a FrozenError on a frozen instance that is modified" do
- -> { "hello".freeze.slice!(1..3) }.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(1..3) }.should.raise(FrozenError)
end
# see redmine #1551
it "raises a FrozenError on a frozen instance that would not be modified" do
- -> { "hello".freeze.slice!(10..20)}.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(10..20)}.should.raise(FrozenError)
end
end
@@ -274,20 +254,10 @@ describe "String#slice! with Regexp" do
s.should == "this is a string"
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(//).should be_an_instance_of(StringSpecs::MyString)
- s.slice!(/../).should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(//).should be_an_instance_of(String)
- s.slice!(/../).should be_an_instance_of(String)
- end
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(//).should.instance_of?(String)
+ s.slice!(/../).should.instance_of?(String)
end
it "returns the matching portion of self with a multi byte character" do
@@ -304,11 +274,11 @@ describe "String#slice! with Regexp" do
end
it "raises a FrozenError on a frozen instance that is modified" do
- -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(FrozenError)
+ -> { "this is a string".freeze.slice!(/s.*t/) }.should.raise(FrozenError)
end
it "raises a FrozenError on a frozen instance that would not be modified" do
- -> { "this is a string".freeze.slice!(/zzz/) }.should raise_error(FrozenError)
+ -> { "this is a string".freeze.slice!(/zzz/) }.should.raise(FrozenError)
end
end
@@ -344,20 +314,10 @@ describe "String#slice! with Regexp, index" do
"har".slice!(/(.)(.)(.)/, obj).should == "a"
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(/(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString)
- s.slice!(/(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(/(.)(.)/, 0).should be_an_instance_of(String)
- s.slice!(/(.)(.)/, 1).should be_an_instance_of(String)
- end
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(/(.)(.)/, 0).should.instance_of?(String)
+ s.slice!(/(.)(.)/, 1).should.instance_of?(String)
end
it "returns the encoding aware capture for the given index" do
@@ -382,9 +342,9 @@ describe "String#slice! with Regexp, index" do
end
it "raises a FrozenError if self is frozen" do
- -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(FrozenError)
- -> { "this is a string".freeze.slice!(/zzz/, 0)}.should raise_error(FrozenError)
- -> { "this is a string".freeze.slice!(/(.)/, 2)}.should raise_error(FrozenError)
+ -> { "this is a string".freeze.slice!(/s.*t/) }.should.raise(FrozenError)
+ -> { "this is a string".freeze.slice!(/zzz/, 0)}.should.raise(FrozenError)
+ -> { "this is a string".freeze.slice!(/(.)/, 2)}.should.raise(FrozenError)
end
end
@@ -412,30 +372,19 @@ describe "String#slice! with String" do
o = mock('x')
o.should_not_receive(:to_str)
- -> { "hello".slice!(o) }.should raise_error(TypeError)
- end
-
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance when given a subclass instance" do
- s = StringSpecs::MyString.new("el")
- r = "hello".slice!(s)
- r.should == "el"
- r.should be_an_instance_of(StringSpecs::MyString)
- end
+ -> { "hello".slice!(o) }.should.raise(TypeError)
end
- ruby_version_is '3.0' do
- it "returns a subclass instance when given a subclass instance" do
- s = StringSpecs::MyString.new("el")
- r = "hello".slice!(s)
- r.should == "el"
- r.should be_an_instance_of(String)
- end
+ it "returns a subclass instance when given a subclass instance" do
+ s = StringSpecs::MyString.new("el")
+ r = "hello".slice!(s)
+ r.should == "el"
+ r.should.instance_of?(String)
end
it "raises a FrozenError if self is frozen" do
- -> { "hello hello".freeze.slice!('llo') }.should raise_error(FrozenError)
- -> { "this is a string".freeze.slice!('zzz')}.should raise_error(FrozenError)
- -> { "this is a string".freeze.slice!('zzz')}.should raise_error(FrozenError)
+ -> { "hello hello".freeze.slice!('llo') }.should.raise(FrozenError)
+ -> { "this is a string".freeze.slice!('zzz')}.should.raise(FrozenError)
+ -> { "this is a string".freeze.slice!('zzz')}.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb
index b57f660816..6e8c1c6219 100644
--- a/spec/ruby/core/string/split_spec.rb
+++ b/spec/ruby/core/string/split_spec.rb
@@ -4,17 +4,17 @@ require_relative 'fixtures/classes'
describe "String#split with String" do
it "throws an ArgumentError if the string is not a valid" do
- s = "\xDF".force_encoding(Encoding::UTF_8)
+ s = "\xDF".dup.force_encoding(Encoding::UTF_8)
- -> { s.split }.should raise_error(ArgumentError)
- -> { s.split(':') }.should raise_error(ArgumentError)
+ -> { s.split }.should.raise(ArgumentError)
+ -> { s.split(':') }.should.raise(ArgumentError)
end
it "throws an ArgumentError if the pattern is not a valid string" do
str = 'проверка'
- broken_str = "\xDF".force_encoding(Encoding::UTF_8)
+ broken_str = "\xDF".dup.force_encoding(Encoding::UTF_8)
- -> { str.split(broken_str) }.should raise_error(ArgumentError)
+ -> { str.split(broken_str) }.should.raise(ArgumentError)
end
it "splits on multibyte characters" do
@@ -29,9 +29,35 @@ describe "String#split with String" do
"1,2,,3,4,,".split(',').should == ["1", "2", "", "3", "4"]
"1,2,,3,4,,".split(',', 0).should == ["1", "2", "", "3", "4"]
" a b c\nd ".split(" ").should == ["", "a", "b", "c\nd"]
+ " a あ c\nd ".split(" ").should == ["", "a", "あ", "c\nd"]
"hai".split("hai").should == []
",".split(",").should == []
",".split(",", 0).should == []
+ "あ".split("あ").should == []
+ "あ".split("あ", 0).should == []
+ end
+
+ it "does not suppress trailing empty fields when a positive limit is given" do
+ " 1 2 ".split(" ", 2).should == ["1", "2 "]
+ " 1 2 ".split(" ", 3).should == ["1", "2", ""]
+ " 1 2 ".split(" ", 4).should == ["1", "2", ""]
+ " 1 あ ".split(" ", 2).should == ["1", "あ "]
+ " 1 あ ".split(" ", 3).should == ["1", "あ", ""]
+ " 1 あ ".split(" ", 4).should == ["1", "あ", ""]
+
+ "1,2,".split(',', 2).should == ["1", "2,"]
+ "1,2,".split(',', 3).should == ["1", "2", ""]
+ "1,2,".split(',', 4).should == ["1", "2", ""]
+ "1,あ,".split(',', 2).should == ["1", "あ,"]
+ "1,あ,".split(',', 3).should == ["1", "あ", ""]
+ "1,あ,".split(',', 4).should == ["1", "あ", ""]
+
+ "1 2 ".split(/ /, 2).should == ["1", "2 "]
+ "1 2 ".split(/ /, 3).should == ["1", "2", ""]
+ "1 2 ".split(/ /, 4).should == ["1", "2", ""]
+ "1 あ ".split(/ /, 2).should == ["1", "あ "]
+ "1 あ ".split(/ /, 3).should == ["1", "あ", ""]
+ "1 あ ".split(/ /, 4).should == ["1", "あ", ""]
end
it "returns an array with one entry if limit is 1: the original string" do
@@ -68,7 +94,7 @@ describe "String#split with String" do
end
it "raises a RangeError when the limit is larger than int" do
- -> { "a,b".split(" ", 2147483649) }.should raise_error(RangeError)
+ -> { "a,b".split(" ", 2147483649) }.should.raise(RangeError)
end
it "defaults to $; when string isn't given or nil" do
@@ -93,21 +119,21 @@ describe "String#split with String" do
$; = old_fs
end
end
+ end
- context "when $; is not nil" do
- before do
- suppress_warning do
- @old_value, $; = $;, 'foobar'
- end
+ context "when $; is not nil" do
+ before do
+ suppress_warning do
+ @old_value, $; = $;, 'foobar'
end
+ end
- after do
- $; = @old_value
- end
+ after do
+ $; = @old_value
+ end
- it "warns" do
- -> { "".split }.should complain(/warning: \$; is set to non-nil value/)
- end
+ it "warns" do
+ -> { "".split }.should complain(/warning: \$; is set to non-nil value/)
end
end
@@ -166,44 +192,16 @@ describe "String#split with String" do
"foo".split("bar", 3).should == ["foo"]
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances based on self" do
- ["", "x.y.z.", " x y "].each do |str|
- ["", ".", " "].each do |pat|
- [-1, 0, 1, 2].each do |limit|
- StringSpecs::MyString.new(str).split(pat, limit).each do |x|
- x.should be_an_instance_of(StringSpecs::MyString)
- end
-
- str.split(StringSpecs::MyString.new(pat), limit).each do |x|
- x.should be_an_instance_of(String)
- end
+ it "returns String instances based on self" do
+ ["", "x.y.z.", " x y "].each do |str|
+ ["", ".", " "].each do |pat|
+ [-1, 0, 1, 2].each do |limit|
+ StringSpecs::MyString.new(str).split(pat, limit).each do |x|
+ x.should.instance_of?(String)
end
- end
- end
- end
-
- it "does not call constructor on created subclass instances" do
- # can't call should_not_receive on an object that doesn't yet exist
- # so failure here is signalled by exception, not expectation failure
-
- s = StringSpecs::StringWithRaisingConstructor.new('silly:string')
- s.split(':').first.should == 'silly'
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances based on self" do
- ["", "x.y.z.", " x y "].each do |str|
- ["", ".", " "].each do |pat|
- [-1, 0, 1, 2].each do |limit|
- StringSpecs::MyString.new(str).split(pat, limit).each do |x|
- x.should be_an_instance_of(String)
- end
- str.split(StringSpecs::MyString.new(pat), limit).each do |x|
- x.should be_an_instance_of(String)
- end
+ str.split(StringSpecs::MyString.new(pat), limit).each do |x|
+ x.should.instance_of?(String)
end
end
end
@@ -220,13 +218,20 @@ describe "String#split with String" do
it "doesn't split on non-ascii whitespace" do
"a\u{2008}b".split(" ").should == ["a\u{2008}b"]
end
+
+ it "returns Strings in the same encoding as self" do
+ strings = "hello world".encode("US-ASCII").split(" ")
+
+ strings[0].encoding.should == Encoding::US_ASCII
+ strings[1].encoding.should == Encoding::US_ASCII
+ end
end
describe "String#split with Regexp" do
it "throws an ArgumentError if the string is not a valid" do
- s = "\xDF".force_encoding(Encoding::UTF_8)
+ s = "\xDF".dup.force_encoding(Encoding::UTF_8)
- -> { s.split(/./) }.should raise_error(ArgumentError)
+ -> { s.split(/./) }.should.raise(ArgumentError)
end
it "divides self on regexp matches" do
@@ -362,8 +367,8 @@ describe "String#split with Regexp" do
end
it "returns a type error if limit can't be converted to an integer" do
- -> {"1.2.3.4".split(".", "three")}.should raise_error(TypeError)
- -> {"1.2.3.4".split(".", nil) }.should raise_error(TypeError)
+ -> {"1.2.3.4".split(".", "three")}.should.raise(TypeError)
+ -> {"1.2.3.4".split(".", nil) }.should.raise(TypeError)
end
it "doesn't set $~" do
@@ -381,59 +386,34 @@ describe "String#split with Regexp" do
"foo".split(/bar/, 3).should == ["foo"]
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances based on self" do
- ["", "x:y:z:", " x y "].each do |str|
- [//, /:/, /\s+/].each do |pat|
- [-1, 0, 1, 2].each do |limit|
- StringSpecs::MyString.new(str).split(pat, limit).each do |x|
- x.should be_an_instance_of(StringSpecs::MyString)
- end
+ it "returns String instances based on self" do
+ ["", "x:y:z:", " x y "].each do |str|
+ [//, /:/, /\s+/].each do |pat|
+ [-1, 0, 1, 2].each do |limit|
+ StringSpecs::MyString.new(str).split(pat, limit).each do |x|
+ x.should.instance_of?(String)
end
end
end
end
-
- it "does not call constructor on created subclass instances" do
- # can't call should_not_receive on an object that doesn't yet exist
- # so failure here is signalled by exception, not expectation failure
-
- s = StringSpecs::StringWithRaisingConstructor.new('silly:string')
- s.split(/:/).first.should == 'silly'
- end
end
- ruby_version_is '3.0' do
- it "returns String instances based on self" do
- ["", "x:y:z:", " x y "].each do |str|
- [//, /:/, /\s+/].each do |pat|
- [-1, 0, 1, 2].each do |limit|
- StringSpecs::MyString.new(str).split(pat, limit).each do |x|
- x.should be_an_instance_of(String)
- end
- end
- end
- end
- end
- end
-
- it "retains the encoding of the source string" do
+ it "returns Strings in the same encoding as self" do
ary = "а б в".split
encodings = ary.map { |s| s.encoding }
encodings.should == [Encoding::UTF_8, Encoding::UTF_8, Encoding::UTF_8]
end
-
it "splits a string on each character for a multibyte encoding and empty split" do
"That's why efficiency could not be helped".split("").size.should == 39
end
it "returns an ArgumentError if an invalid UTF-8 string is supplied" do
- broken_str = 'проверка' # in russian, means "test"
+ broken_str = +'проверка' # in russian, means "test"
broken_str.force_encoding('binary')
broken_str.chop!
broken_str.force_encoding('utf-8')
- ->{ broken_str.split(/\r\n|\r|\n/) }.should raise_error(ArgumentError)
+ ->{ broken_str.split(/\r\n|\r|\n/) }.should.raise(ArgumentError)
end
# See https://bugs.ruby-lang.org/issues/12689 and https://github.com/jruby/jruby/issues/4868
@@ -537,39 +517,30 @@ describe "String#split with Regexp" do
end
describe "for a String subclass" do
- ruby_version_is ''...'3.0' do
- it "yields instances of the same subclass" do
- a = []
- StringSpecs::MyString.new("a|b").split("|") { |str| a << str }
- first, last = a
-
- first.should be_an_instance_of(StringSpecs::MyString)
- first.should == "a"
-
- last.should be_an_instance_of(StringSpecs::MyString)
- last.should == "b"
- end
- end
-
- ruby_version_is '3.0' do
- it "yields instances of String" do
- a = []
- StringSpecs::MyString.new("a|b").split("|") { |str| a << str }
- first, last = a
+ it "yields instances of String" do
+ a = []
+ StringSpecs::MyString.new("a|b").split("|") { |str| a << str }
+ first, last = a
- first.should be_an_instance_of(String)
- first.should == "a"
+ first.should.instance_of?(String)
+ first.should == "a"
- last.should be_an_instance_of(String)
- last.should == "b"
- end
+ last.should.instance_of?(String)
+ last.should == "b"
end
end
it "raises a TypeError when not called with nil, String, or Regexp" do
- -> { "hello".split(42) }.should raise_error(TypeError)
- -> { "hello".split(:ll) }.should raise_error(TypeError)
- -> { "hello".split(false) }.should raise_error(TypeError)
- -> { "hello".split(Object.new) }.should raise_error(TypeError)
+ -> { "hello".split(42) }.should.raise(TypeError)
+ -> { "hello".split(:ll) }.should.raise(TypeError)
+ -> { "hello".split(false) }.should.raise(TypeError)
+ -> { "hello".split(Object.new) }.should.raise(TypeError)
+ end
+
+ it "returns Strings in the same encoding as self" do
+ strings = "hello world".encode("US-ASCII").split(/ /)
+
+ strings[0].encoding.should == Encoding::US_ASCII
+ strings[1].encoding.should == Encoding::US_ASCII
end
end
diff --git a/spec/ruby/core/string/squeeze_spec.rb b/spec/ruby/core/string/squeeze_spec.rb
index 5dc12a4247..52b6e1eed4 100644
--- a/spec/ruby/core/string/squeeze_spec.rb
+++ b/spec/ruby/core/string/squeeze_spec.rb
@@ -1,4 +1,5 @@
-# -*- encoding: binary -*-
+# encoding: binary
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -50,8 +51,8 @@ describe "String#squeeze" do
it "raises an ArgumentError when the parameter is out of sequence" do
s = "--subbookkeeper--"
- -> { s.squeeze("e-b") }.should raise_error(ArgumentError)
- -> { s.squeeze("^e-b") }.should raise_error(ArgumentError)
+ -> { s.squeeze("e-b") }.should.raise(ArgumentError)
+ -> { s.squeeze("^e-b") }.should.raise(ArgumentError)
end
it "tries to convert each set arg to a string using to_str" do
@@ -64,29 +65,26 @@ describe "String#squeeze" do
"hello room".squeeze(other_string, other_string2).should == "hello rom"
end
- it "raises a TypeError when one set arg can't be converted to a string" do
- -> { "hello world".squeeze([]) }.should raise_error(TypeError)
- -> { "hello world".squeeze(Object.new)}.should raise_error(TypeError)
- -> { "hello world".squeeze(mock('x')) }.should raise_error(TypeError)
+ it "returns a String in the same encoding as self" do
+ "yellow moon".encode("US-ASCII").squeeze.encoding.should == Encoding::US_ASCII
+ "yellow moon".encode("US-ASCII").squeeze("a").encoding.should == Encoding::US_ASCII
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(StringSpecs::MyString)
- end
+ it "raises a TypeError when one set arg can't be converted to a string" do
+ -> { "hello world".squeeze([]) }.should.raise(TypeError)
+ -> { "hello world".squeeze(Object.new)}.should.raise(TypeError)
+ -> { "hello world".squeeze(mock('x')) }.should.raise(TypeError)
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(String)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("oh no!!!").squeeze("!").should.instance_of?(String)
end
end
describe "String#squeeze!" do
it "modifies self in place and returns self" do
a = "yellow moon"
- a.squeeze!.should equal(a)
+ a.squeeze!.should.equal?(a)
a.should == "yelow mon"
end
@@ -99,15 +97,15 @@ describe "String#squeeze!" do
it "raises an ArgumentError when the parameter is out of sequence" do
s = "--subbookkeeper--"
- -> { s.squeeze!("e-b") }.should raise_error(ArgumentError)
- -> { s.squeeze!("^e-b") }.should raise_error(ArgumentError)
+ -> { s.squeeze!("e-b") }.should.raise(ArgumentError)
+ -> { s.squeeze!("^e-b") }.should.raise(ArgumentError)
end
it "raises a FrozenError when self is frozen" do
a = "yellow moon"
a.freeze
- -> { a.squeeze!("") }.should raise_error(FrozenError)
- -> { a.squeeze! }.should raise_error(FrozenError)
+ -> { a.squeeze!("") }.should.raise(FrozenError)
+ -> { a.squeeze! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/start_with_spec.rb b/spec/ruby/core/string/start_with_spec.rb
index 3833289f96..8b0ba6b5a7 100644
--- a/spec/ruby/core/string/start_with_spec.rb
+++ b/spec/ruby/core/string/start_with_spec.rb
@@ -7,12 +7,12 @@ describe "String#start_with?" do
it_behaves_like :start_with, :to_s
# Here and not in the shared examples because this is invalid as a Symbol
- it "does not check that we are not starting to match at the head of a character" do
+ it "matches part of a character with the same part" do
"\xA9".should.start_with?("\xA9") # A9 is not a character head for UTF-8
end
- it "does not check we are matching only part of a character" do
+ it "checks we are matching only part of a character" do
"\xe3\x81\x82".size.should == 1
- "\xe3\x81\x82".should.start_with?("\xe3")
+ "\xe3\x81\x82".should_not.start_with?("\xe3")
end
end
diff --git a/spec/ruby/core/string/strip_spec.rb b/spec/ruby/core/string/strip_spec.rb
index 662f13b032..81994a7f2e 100644
--- a/spec/ruby/core/string/strip_spec.rb
+++ b/spec/ruby/core/string/strip_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/strip'
@@ -11,17 +12,15 @@ describe "String#strip" do
"\tgoodbye\r\v\n".strip.should == "goodbye"
end
- ruby_version_is '3.0' do
- it "returns a copy of self without leading and trailing NULL bytes and whitespace" do
- " \x00 goodbye \x00 ".strip.should == "goodbye"
- end
+ it "returns a copy of self without leading and trailing NULL bytes and whitespace" do
+ " \x00 goodbye \x00 ".strip.should == "goodbye"
end
end
describe "String#strip!" do
it "modifies self in place and returns self" do
a = " hello "
- a.strip!.should equal(a)
+ a.strip!.should.equal?(a)
a.should == "hello"
a = "\tgoodbye\r\v\n"
@@ -41,21 +40,19 @@ describe "String#strip!" do
" ".strip.should == ""
end
- ruby_version_is '3.0' do
- it "removes leading and trailing NULL bytes and whitespace" do
- a = "\000 goodbye \000"
- a.strip!
- a.should == "goodbye"
- end
+ it "removes leading and trailing NULL bytes and whitespace" do
+ a = "\000 goodbye \000"
+ a.strip!
+ a.should == "goodbye"
end
it "raises a FrozenError on a frozen instance that is modified" do
- -> { " hello ".freeze.strip! }.should raise_error(FrozenError)
+ -> { " hello ".freeze.strip! }.should.raise(FrozenError)
end
# see #1552
it "raises a FrozenError on a frozen instance that would not be modified" do
- -> {"hello".freeze.strip! }.should raise_error(FrozenError)
- -> {"".freeze.strip! }.should raise_error(FrozenError)
+ -> {"hello".freeze.strip! }.should.raise(FrozenError)
+ -> {"".freeze.strip! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/sub_spec.rb b/spec/ruby/core/string/sub_spec.rb
index 9effe88c27..f0082fba59 100644
--- a/spec/ruby/core/string/sub_spec.rb
+++ b/spec/ruby/core/string/sub_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -6,7 +7,7 @@ describe "String#sub with pattern, replacement" do
a = "hello"
b = a.sub(/w.*$/, "*")
- b.should_not equal(a)
+ b.should_not.equal?(a)
b.should == "hello"
end
@@ -146,16 +147,16 @@ describe "String#sub with pattern, replacement" do
not_supported_on :opal do
it "raises a TypeError when pattern is a Symbol" do
- -> { "hello".sub(:woot, "x") }.should raise_error(TypeError)
+ -> { "hello".sub(:woot, "x") }.should.raise(TypeError)
end
end
it "raises a TypeError when pattern is an Array" do
- -> { "hello".sub([], "x") }.should raise_error(TypeError)
+ -> { "hello".sub([], "x") }.should.raise(TypeError)
end
it "raises a TypeError when pattern can't be converted to a string" do
- -> { "hello".sub(Object.new, nil) }.should raise_error(TypeError)
+ -> { "hello".sub(Object.new, nil) }.should.raise(TypeError)
end
it "tries to convert replacement to a string using to_str" do
@@ -166,26 +167,15 @@ describe "String#sub with pattern, replacement" do
end
it "raises a TypeError when replacement can't be converted to a string" do
- -> { "hello".sub(/[aeiou]/, []) }.should raise_error(TypeError)
- -> { "hello".sub(/[aeiou]/, 99) }.should raise_error(TypeError)
+ -> { "hello".sub(/[aeiou]/, []) }.should.raise(TypeError)
+ -> { "hello".sub(/[aeiou]/, 99) }.should.raise(TypeError)
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(String)
- StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(String)
- StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(String)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("").sub(//, "").should.instance_of?(String)
+ StringSpecs::MyString.new("").sub(/foo/, "").should.instance_of?(String)
+ StringSpecs::MyString.new("foo").sub(/foo/, "").should.instance_of?(String)
+ StringSpecs::MyString.new("foo").sub("foo", "").should.instance_of?(String)
end
it "sets $~ to MatchData of match and nil when there's none" do
@@ -214,6 +204,17 @@ describe "String#sub with pattern, replacement" do
"ababa".sub(/(b)/, '\\\\\1').should == "a\\baba"
end
+ it "handles a pattern in a superset encoding" do
+ result = 'abc'.force_encoding(Encoding::US_ASCII).sub('é', 'è')
+ result.should == 'abc'
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ result = 'été'.sub('t'.force_encoding(Encoding::US_ASCII), 'u')
+ result.should == 'éué'
+ result.encoding.should == Encoding::UTF_8
+ end
end
describe "String#sub with pattern and block" do
@@ -231,10 +232,10 @@ describe "String#sub with pattern and block" do
offsets = []
str.sub(/([aeiou])/) do
- md = $~
- md.string.should == str
- offsets << md.offset(0)
- str
+ md = $~
+ md.string.should == str
+ offsets << md.offset(0)
+ str
end.should == "hhellollo"
offsets.should == [[1, 2]]
@@ -280,7 +281,7 @@ end
describe "String#sub! with pattern, replacement" do
it "modifies self in place and returns self" do
a = "hello"
- a.sub!(/[aeiou]/, '*').should equal(a)
+ a.sub!(/[aeiou]/, '*').should.equal?(a)
a.should == "h*llo"
end
@@ -295,16 +296,37 @@ describe "String#sub! with pattern, replacement" do
s = "hello"
s.freeze
- -> { s.sub!(/ROAR/, "x") }.should raise_error(FrozenError)
- -> { s.sub!(/e/, "e") }.should raise_error(FrozenError)
- -> { s.sub!(/[aeiou]/, '*') }.should raise_error(FrozenError)
+ -> { s.sub!(/ROAR/, "x") }.should.raise(FrozenError)
+ -> { s.sub!(/e/, "e") }.should.raise(FrozenError)
+ -> { s.sub!(/[aeiou]/, '*') }.should.raise(FrozenError)
+ end
+
+ it "handles a pattern in a superset encoding" do
+ string = 'abc'.force_encoding(Encoding::US_ASCII)
+
+ result = string.sub!('é', 'è')
+
+ result.should == nil
+ string.should == 'abc'
+ string.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ string = 'été'
+ pattern = 't'.force_encoding(Encoding::US_ASCII)
+
+ result = string.sub!(pattern, 'u')
+
+ result.should == string
+ string.should == 'éué'
+ string.encoding.should == Encoding::UTF_8
end
end
describe "String#sub! with pattern and block" do
it "modifies self in place and returns self" do
a = "hello"
- a.sub!(/[aeiou]/) { '*' }.should equal(a)
+ a.sub!(/[aeiou]/) { '*' }.should.equal?(a)
a.should == "h*llo"
end
@@ -317,10 +339,10 @@ describe "String#sub! with pattern and block" do
offsets = []
str.dup.sub!(/([aeiou])/) do
- md = $~
- md.string.should == str
- offsets << md.offset(0)
- str
+ md = $~
+ md.string.should == str
+ offsets << md.offset(0)
+ str
end.should == "hhellollo"
offsets.should == [[1, 2]]
@@ -335,16 +357,16 @@ describe "String#sub! with pattern and block" do
it "raises a RuntimeError if the string is modified while substituting" do
str = "hello"
- -> { str.sub!(//) { str << 'x' } }.should raise_error(RuntimeError)
+ -> { str.sub!(//) { str << 'x' } }.should.raise(RuntimeError)
end
it "raises a FrozenError when self is frozen" do
s = "hello"
s.freeze
- -> { s.sub!(/ROAR/) { "x" } }.should raise_error(FrozenError)
- -> { s.sub!(/e/) { "e" } }.should raise_error(FrozenError)
- -> { s.sub!(/[aeiou]/) { '*' } }.should raise_error(FrozenError)
+ -> { s.sub!(/ROAR/) { "x" } }.should.raise(FrozenError)
+ -> { s.sub!(/e/) { "e" } }.should.raise(FrozenError)
+ -> { s.sub!(/[aeiou]/) { '*' } }.should.raise(FrozenError)
end
end
@@ -479,12 +501,12 @@ end
describe "String#sub with pattern and without replacement and block" do
it "raises a ArgumentError" do
- -> { "abca".sub(/a/) }.should raise_error(ArgumentError)
+ -> { "abca".sub(/a/) }.should.raise(ArgumentError)
end
end
describe "String#sub! with pattern and without replacement and block" do
it "raises a ArgumentError" do
- -> { "abca".sub!(/a/) }.should raise_error(ArgumentError)
+ -> { "abca".sub!(/a/) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/swapcase_spec.rb b/spec/ruby/core/string/swapcase_spec.rb
index 6307a1eaaf..f0e6e0182c 100644
--- a/spec/ruby/core/string/swapcase_spec.rb
+++ b/spec/ruby/core/string/swapcase_spec.rb
@@ -1,12 +1,17 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "String#swapcase" do
it "returns a new string with all uppercase chars from self converted to lowercase and vice versa" do
- "Hello".swapcase.should == "hELLO"
- "cYbEr_PuNk11".swapcase.should == "CyBeR_pUnK11"
- "+++---111222???".swapcase.should == "+++---111222???"
+ "Hello".swapcase.should == "hELLO"
+ "cYbEr_PuNk11".swapcase.should == "CyBeR_pUnK11"
+ "+++---111222???".swapcase.should == "+++---111222???"
+ end
+
+ it "returns a String in the same encoding as self" do
+ "Hello".encode("US-ASCII").swapcase.encoding.should == Encoding::US_ASCII
end
describe "full Unicode case mapping" do
@@ -20,7 +25,7 @@ describe "String#swapcase" do
swapcased.should == "aSSET"
swapcased.size.should == 5
swapcased.bytesize.should == 5
- swapcased.ascii_only?.should be_true
+ swapcased.ascii_only?.should == true
end
end
@@ -44,7 +49,7 @@ describe "String#swapcase" do
end
it "does not allow any other additional option" do
- -> { "aiS".swapcase(:turkic, :ascii) }.should raise_error(ArgumentError)
+ -> { "aiS".swapcase(:turkic, :ascii) }.should.raise(ArgumentError)
end
end
@@ -58,37 +63,28 @@ describe "String#swapcase" do
end
it "does not allow any other additional option" do
- -> { "aiS".swapcase(:lithuanian, :ascii) }.should raise_error(ArgumentError)
+ -> { "aiS".swapcase(:lithuanian, :ascii) }.should.raise(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
- -> { "abc".swapcase(:fold) }.should raise_error(ArgumentError)
+ -> { "abc".swapcase(:fold) }.should.raise(ArgumentError)
end
it "does not allow invalid options" do
- -> { "abc".swapcase(:invalid_option) }.should raise_error(ArgumentError)
- end
-
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("").swapcase.should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(StringSpecs::MyString)
- end
+ -> { "abc".swapcase(:invalid_option) }.should.raise(ArgumentError)
end
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("").swapcase.should be_an_instance_of(String)
- StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(String)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("").swapcase.should.instance_of?(String)
+ StringSpecs::MyString.new("hello").swapcase.should.instance_of?(String)
end
end
describe "String#swapcase!" do
it "modifies self in place" do
a = "cYbEr_PuNk11"
- a.swapcase!.should equal(a)
+ a.swapcase!.should.equal?(a)
a.should == "CyBeR_pUnK11"
end
@@ -118,7 +114,7 @@ describe "String#swapcase!" do
swapcased.should == "aSSET"
swapcased.size.should == 5
swapcased.bytesize.should == 5
- swapcased.ascii_only?.should be_true
+ swapcased.ascii_only?.should == true
end
end
@@ -150,7 +146,7 @@ describe "String#swapcase!" do
end
it "does not allow any other additional option" do
- -> { a = "aiS"; a.swapcase!(:turkic, :ascii) }.should raise_error(ArgumentError)
+ -> { a = "aiS"; a.swapcase!(:turkic, :ascii) }.should.raise(ArgumentError)
end
end
@@ -168,16 +164,16 @@ describe "String#swapcase!" do
end
it "does not allow any other additional option" do
- -> { a = "aiS"; a.swapcase!(:lithuanian, :ascii) }.should raise_error(ArgumentError)
+ -> { a = "aiS"; a.swapcase!(:lithuanian, :ascii) }.should.raise(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
- -> { a = "abc"; a.swapcase!(:fold) }.should raise_error(ArgumentError)
+ -> { a = "abc"; a.swapcase!(:fold) }.should.raise(ArgumentError)
end
it "does not allow invalid options" do
- -> { a = "abc"; a.swapcase!(:invalid_option) }.should raise_error(ArgumentError)
+ -> { a = "abc"; a.swapcase!(:invalid_option) }.should.raise(ArgumentError)
end
it "returns nil if no modifications were made" do
@@ -191,7 +187,7 @@ describe "String#swapcase!" do
it "raises a FrozenError when self is frozen" do
["", "hello"].each do |a|
a.freeze
- -> { a.swapcase! }.should raise_error(FrozenError)
+ -> { a.swapcase! }.should.raise(FrozenError)
end
end
end
diff --git a/spec/ruby/core/string/to_c_spec.rb b/spec/ruby/core/string/to_c_spec.rb
index 9c84b14f4d..9cd0ed4401 100644
--- a/spec/ruby/core/string/to_c_spec.rb
+++ b/spec/ruby/core/string/to_c_spec.rb
@@ -1,99 +1,53 @@
require_relative '../../spec_helper'
+require_relative '../../shared/kernel/complex'
+require_relative 'fixtures/to_c'
describe "String#to_c" do
- it "returns a Complex object" do
- '9'.to_c.should be_an_instance_of(Complex)
- end
-
- it "understands integers" do
- '20'.to_c.should == Complex(20)
- end
-
- it "understands negative integers" do
- '-3'.to_c.should == Complex(-3)
- end
-
- it "understands fractions (numerator/denominator) for the real part" do
- '2/3'.to_c.should == Complex(Rational(2, 3))
- end
-
- it "understands fractions (numerator/denominator) for the imaginary part" do
- '4+2/3i'.to_c.should == Complex(4, Rational(2, 3))
- end
-
- it "understands negative fractions (-numerator/denominator) for the real part" do
- '-2/3'.to_c.should == Complex(Rational(-2, 3))
- end
-
- it "understands negative fractions (-numerator/denominator) for the imaginary part" do
- '7-2/3i'.to_c.should == Complex(7, Rational(-2, 3))
- end
-
- it "understands floats (a.b) for the real part" do
- '2.3'.to_c.should == Complex(2.3)
- end
-
- it "understands floats (a.b) for the imaginary part" do
- '4+2.3i'.to_c.should == Complex(4, 2.3)
- end
-
- it "understands negative floats (-a.b) for the real part" do
- '-2.33'.to_c.should == Complex(-2.33)
- end
-
- it "understands negative floats (-a.b) for the imaginary part" do
- '7-28.771i'.to_c.should == Complex(7, -28.771)
- end
-
- it "understands an integer followed by 'i' to mean that integer is the imaginary part" do
- '35i'.to_c.should == Complex(0,35)
- end
-
- it "understands a negative integer followed by 'i' to mean that negative integer is the imaginary part" do
- '-29i'.to_c.should == Complex(0,-29)
- end
-
- it "understands an 'i' by itself as denoting a complex number with an imaginary part of 1" do
- 'i'.to_c.should == Complex(0,1)
- end
-
- it "understands a '-i' by itself as denoting a complex number with an imaginary part of -1" do
- '-i'.to_c.should == Complex(0,-1)
- end
-
- it "understands 'a+bi' to mean a complex number with 'a' as the real part, 'b' as the imaginary" do
- '79+4i'.to_c.should == Complex(79,4)
- end
+ it_behaves_like :kernel_complex, :to_c_method, StringSpecs
+end
- it "understands 'a-bi' to mean a complex number with 'a' as the real part, '-b' as the imaginary" do
- '79-4i'.to_c.should == Complex(79,-4)
+describe "String#to_c" do
+ it "returns a complex number with 0 as the real part, 0 as the imaginary part for unrecognised Strings" do
+ 'ruby'.to_c.should == Complex(0, 0)
end
- it "understands scientific notation for the real part" do
- '2e3+4i'.to_c.should == Complex(2e3,4)
+ it "ignores trailing garbage" do
+ '79+4iruby'.to_c.should == Complex(79, 4)
+ '7__9+4__0i'.to_c.should == Complex(7, 0)
end
- it "understands negative scientific notation for the real part" do
- '-2e3+4i'.to_c.should == Complex(-2e3,4)
- end
+ context "it treats special float value strings as characters" do
+ it "parses any string that starts with 'I' as 1i" do
+ 'Infinity'.to_c.should == Complex(0, 1)
+ '-Infinity'.to_c.should == Complex(0, -1)
+ 'Insecure'.to_c.should == Complex(0, 1)
+ '-Insecure'.to_c.should == Complex(0, -1)
+ end
- it "understands scientific notation for the imaginary part" do
- '4+2e3i'.to_c.should == Complex(4, 2e3)
+ it "does not parse any numeric information in 'NaN'" do
+ 'NaN'.to_c.should == Complex(0, 0)
+ end
end
- it "understands negative scientific notation for the imaginary part" do
- '4-2e3i'.to_c.should == Complex(4, -2e3)
+ it "allows null-byte" do
+ "1-2i\0".to_c.should == Complex(1, -2)
+ "1\0-2i".to_c.should == Complex(1, 0)
+ "\01-2i".to_c.should == Complex(0, 0)
end
- it "understands scientific notation for the real and imaginary part in the same String" do
- '2e3+2e4i'.to_c.should == Complex(2e3,2e4)
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ '79+4i'.encode("UTF-16").to_c
+ }.should.raise(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
end
- it "understands negative scientific notation for the real and imaginary part in the same String" do
- '-2e3-2e4i'.to_c.should == Complex(-2e3,-2e4)
- end
+ it "treats a sequence of underscores as an end of Complex string" do
+ "5+3_1i".to_c.should == Complex(5, 31)
+ "5+3__1i".to_c.should == Complex(5)
+ "5+3___1i".to_c.should == Complex(5)
- it "returns a complex number with 0 as the real part, 0 as the imaginary part for unrecognised Strings" do
- 'ruby'.to_c.should == Complex(0,0)
+ "12_3".to_c.should == Complex(123)
+ "12__3".to_c.should == Complex(12)
+ "12___3".to_c.should == Complex(12)
end
end
diff --git a/spec/ruby/core/string/to_f_spec.rb b/spec/ruby/core/string/to_f_spec.rb
index cf64ecfc5d..bb09e4f2f3 100644
--- a/spec/ruby/core/string/to_f_spec.rb
+++ b/spec/ruby/core/string/to_f_spec.rb
@@ -5,16 +5,15 @@ require_relative 'fixtures/classes'
describe "String#to_f" do
it "treats leading characters of self as a floating point number" do
- "123.45e1".to_f.should == 1234.5
- "45.67 degrees".to_f.should == 45.67
- "0".to_f.should == 0.0
- "123.45e1".to_f.should == 1234.5
+ "123.45e1".to_f.should == 1234.5
+ "45.67 degrees".to_f.should == 45.67
+ "0".to_f.should == 0.0
- ".5".to_f.should == 0.5
- ".5e1".to_f.should == 5.0
- "5.".to_f.should == 5.0
- "5e".to_f.should == 5.0
- "5E".to_f.should == 5.0
+ ".5".to_f.should == 0.5
+ ".5e1".to_f.should == 5.0
+ "5.".to_f.should == 5.0
+ "5e".to_f.should == 5.0
+ "5E".to_f.should == 5.0
end
it "treats special float value strings as characters" do
@@ -43,18 +42,39 @@ describe "String#to_f" do
"1_234_567.890_1".to_f.should == 1_234_567.890_1
end
- it "returns 0 for strings with any non-digit in them" do
- "blah".to_f.should == 0
- "0b5".to_f.should == 0
- "0d5".to_f.should == 0
- "0o5".to_f.should == 0
- "0xx5".to_f.should == 0
- end
-
it "returns 0 for strings with leading underscores" do
"_9".to_f.should == 0
end
+ it "stops if the underscore is not followed or preceded by a number" do
+ "1__2".to_f.should == 1.0
+ "1_.2".to_f.should == 1.0
+ "1._2".to_f.should == 1.0
+ "1.2_e2".to_f.should == 1.2
+ "1.2e_2".to_f.should == 1.2
+ "1_x2".to_f.should == 1.0
+ "1x_2".to_f.should == 1.0
+ "+_1".to_f.should == 0.0
+ "-_1".to_f.should == 0.0
+ end
+
+ it "does not allow prefixes to autodetect the base" do
+ "0b10".to_f.should == 0
+ "010".to_f.should == 10
+ "0o10".to_f.should == 0
+ "0d10".to_f.should == 0
+ "0x10".to_f.should == 0
+ end
+
+ it "treats any non-numeric character other than '.', 'e' and '_' as terminals" do
+ "blah".to_f.should == 0
+ "1b5".to_f.should == 1
+ "1d5".to_f.should == 1
+ "1o5".to_f.should == 1
+ "1xx5".to_f.should == 1
+ "x5".to_f.should == 0
+ end
+
it "takes an optional sign" do
"-45.67 degrees".to_f.should == -45.67
"+45.67 degrees".to_f.should == 45.67
@@ -63,8 +83,58 @@ describe "String#to_f" do
(1.0 / "-0".to_f).to_s.should == "-Infinity"
end
+ it "treats a second 'e' as terminal" do
+ "1.234e1e2".to_f.should == 1.234e1
+ end
+
+ it "treats a second '.' as terminal" do
+ "1.2.3".to_f.should == 1.2
+ end
+
+ it "treats a '.' after an 'e' as terminal" do
+ "1.234e1.9".to_f.should == 1.234e1
+ end
+
it "returns 0.0 if the conversion fails" do
"bad".to_f.should == 0.0
"thx1138".to_f.should == 0.0
end
+
+ it "ignores leading and trailing whitespace" do
+ " 1.2".to_f.should == 1.2
+ "1.2 ".to_f.should == 1.2
+ " 1.2 ".to_f.should == 1.2
+ "\t1.2".to_f.should == 1.2
+ "\n1.2".to_f.should == 1.2
+ "\v1.2".to_f.should == 1.2
+ "\f1.2".to_f.should == 1.2
+ "\r1.2".to_f.should == 1.2
+ end
+
+ it "treats non-printable ASCII characters as terminals" do
+ "\0001.2".to_f.should == 0
+ "\0011.2".to_f.should == 0
+ "\0371.2".to_f.should == 0
+ "\1771.2".to_f.should == 0
+ "\2001.2".b.to_f.should == 0
+ "\3771.2".b.to_f.should == 0
+ end
+
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ '1.2'.encode("UTF-16").to_f
+ }.should.raise(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
+ end
+
+ it "allows String representation without a fractional part" do
+ "1.".to_f.should == 1.0
+ "+1.".to_f.should == 1.0
+ "-1.".to_f.should == -1.0
+ "1.e+0".to_f.should == 1.0
+ "1.e+0".to_f.should == 1.0
+
+ ruby_bug "#20705", ""..."3.4" do
+ "1.e-2".to_f.should be_close(0.01, TOLERANCE)
+ end
+ end
end
diff --git a/spec/ruby/core/string/to_i_spec.rb b/spec/ruby/core/string/to_i_spec.rb
index e4fa89aab3..629750bd73 100644
--- a/spec/ruby/core/string/to_i_spec.rb
+++ b/spec/ruby/core/string/to_i_spec.rb
@@ -10,6 +10,18 @@ describe "String#to_i" do
"1_2_3asdf".to_i.should == 123
end
+ it "ignores multiple non-consecutive underscores when the first digit is 0" do
+ (2..16).each do |base|
+ "0_0_010".to_i(base).should == base;
+ end
+ end
+
+ it "bails out at the first double underscore if the first digit is 0" do
+ (2..16).each do |base|
+ "010__1".to_i(base).should == base;
+ end
+ end
+
it "ignores leading whitespaces" do
[ " 123", " 123", "\r\n\r\n123", "\t\t123",
"\r\n\t\n123", " \t\n\r\t 123"].each do |str|
@@ -126,31 +138,31 @@ describe "String#to_i" do
end
it "raises an ArgumentError for illegal bases (1, < 0 or > 36)" do
- -> { "".to_i(1) }.should raise_error(ArgumentError)
- -> { "".to_i(-1) }.should raise_error(ArgumentError)
- -> { "".to_i(37) }.should raise_error(ArgumentError)
+ -> { "".to_i(1) }.should.raise(ArgumentError)
+ -> { "".to_i(-1) }.should.raise(ArgumentError)
+ -> { "".to_i(37) }.should.raise(ArgumentError)
end
it "returns an Integer for long strings with trailing spaces" do
"0 ".to_i.should == 0
- "0 ".to_i.should be_an_instance_of(Integer)
+ "0 ".to_i.should.instance_of?(Integer)
"10 ".to_i.should == 10
- "10 ".to_i.should be_an_instance_of(Integer)
+ "10 ".to_i.should.instance_of?(Integer)
"-10 ".to_i.should == -10
- "-10 ".to_i.should be_an_instance_of(Integer)
+ "-10 ".to_i.should.instance_of?(Integer)
end
it "returns an Integer for long strings with leading spaces" do
" 0".to_i.should == 0
- " 0".to_i.should be_an_instance_of(Integer)
+ " 0".to_i.should.instance_of?(Integer)
" 10".to_i.should == 10
- " 10".to_i.should be_an_instance_of(Integer)
+ " 10".to_i.should.instance_of?(Integer)
" -10".to_i.should == -10
- " -10".to_i.should be_an_instance_of(Integer)
+ " -10".to_i.should.instance_of?(Integer)
end
it "returns the correct Integer for long strings" do
diff --git a/spec/ruby/core/string/to_r_spec.rb b/spec/ruby/core/string/to_r_spec.rb
index 7e1d635d3b..fb7c9d108e 100644
--- a/spec/ruby/core/string/to_r_spec.rb
+++ b/spec/ruby/core/string/to_r_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "String#to_r" do
it "returns a Rational object" do
- String.new.to_r.should be_an_instance_of(Rational)
+ String.new.to_r.should.instance_of?(Rational)
end
it "returns (0/1) for the empty String" do
@@ -33,6 +33,10 @@ describe "String#to_r" do
"-20".to_r.should == Rational(-20, 1)
end
+ it "accepts leading plus signs" do
+ "+20".to_r.should == Rational(20, 1)
+ end
+
it "does not treat a leading period without a numeric prefix as a decimal point" do
".9".to_r.should_not == Rational(8106479329266893, 9007199254740992)
end
diff --git a/spec/ruby/core/string/tr_s_spec.rb b/spec/ruby/core/string/tr_s_spec.rb
index e1bb20ce35..22a193ec4b 100644
--- a/spec/ruby/core/string/tr_s_spec.rb
+++ b/spec/ruby/core/string/tr_s_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -17,6 +18,13 @@ describe "String#tr_s" do
"hello ^--^".tr_s("---", "_").should == "hello ^_^"
end
+ it "accepts c1-c1 notation to denote range of one character" do
+ "hello".tr_s('e-e', 'x').should == "hxllo"
+ "123456789".tr_s("2-23","xy").should == "1xy456789"
+ "hello ^-^".tr_s("e-", "a-a_").should == "hallo ^_^"
+ "hello ^-^".tr_s("---o", "_a").should == "hella ^_^"
+ end
+
it "pads to_str with its last char if it is shorter than from_string" do
"this".tr_s("this", "x").should == "x"
end
@@ -45,16 +53,8 @@ describe "String#tr_s" do
"bla".tr_s(from_str, to_str).should == "BlA"
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns String instances when called on a subclass" do
- StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(String)
- end
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").tr_s("e", "a").should.instance_of?(String)
end
# http://redmine.ruby-lang.org/issues/show/1839
@@ -124,8 +124,8 @@ describe "String#tr_s!" do
it "raises a FrozenError if self is frozen" do
s = "hello".freeze
- -> { s.tr_s!("el", "ar") }.should raise_error(FrozenError)
- -> { s.tr_s!("l", "r") }.should raise_error(FrozenError)
- -> { s.tr_s!("", "") }.should raise_error(FrozenError)
+ -> { s.tr_s!("el", "ar") }.should.raise(FrozenError)
+ -> { s.tr_s!("l", "r") }.should.raise(FrozenError)
+ -> { s.tr_s!("", "") }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/tr_spec.rb b/spec/ruby/core/string/tr_spec.rb
index 72adb9f2eb..cb57c3851e 100644
--- a/spec/ruby/core/string/tr_spec.rb
+++ b/spec/ruby/core/string/tr_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -16,17 +17,24 @@ describe "String#tr" do
"hello ^-^".tr("---", "_").should == "hello ^_^"
end
+ it "accepts c1-c1 notation to denote range of one character" do
+ "hello".tr('e-e', 'x').should == "hxllo"
+ "123456789".tr("2-23","xy").should == "1xy456789"
+ "hello ^-^".tr("e-", "a-a_").should == "hallo ^_^"
+ "hello ^-^".tr("---o", "_a").should == "hella ^_^"
+ end
+
it "pads to_str with its last char if it is shorter than from_string" do
"this".tr("this", "x").should == "xxxx"
"hello".tr("a-z", "A-H.").should == "HE..."
end
it "raises an ArgumentError a descending range in the replacement as containing just the start character" do
- -> { "hello".tr("a-y", "z-b") }.should raise_error(ArgumentError)
+ -> { "hello".tr("a-y", "z-b") }.should.raise(ArgumentError)
end
it "raises an ArgumentError a descending range in the source as empty" do
- -> { "hello".tr("l-a", "z") }.should raise_error(ArgumentError)
+ -> { "hello".tr("l-a", "z") }.should.raise(ArgumentError)
end
it "translates chars not in from_string when it starts with a ^" do
@@ -57,16 +65,8 @@ describe "String#tr" do
"bla".tr(from_str, to_str).should == "BlA"
end
- ruby_version_is ''...'3.0' do
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(StringSpecs::MyString)
- end
- end
-
- ruby_version_is '3.0' do
- it "returns Stringinstances when called on a subclass" do
- StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(String)
- end
+ it "returns Stringinstances when called on a subclass" do
+ StringSpecs::MyString.new("hello").tr("e", "a").should.instance_of?(String)
end
# http://redmine.ruby-lang.org/issues/show/1839
@@ -119,8 +119,8 @@ describe "String#tr!" do
it "raises a FrozenError if self is frozen" do
s = "abcdefghijklmnopqR".freeze
- -> { s.tr!("cdefg", "12") }.should raise_error(FrozenError)
- -> { s.tr!("R", "S") }.should raise_error(FrozenError)
- -> { s.tr!("", "") }.should raise_error(FrozenError)
+ -> { s.tr!("cdefg", "12") }.should.raise(FrozenError)
+ -> { s.tr!("R", "S") }.should.raise(FrozenError)
+ -> { s.tr!("", "") }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/try_convert_spec.rb b/spec/ruby/core/string/try_convert_spec.rb
index 84415c4a75..0c0219cd2e 100644
--- a/spec/ruby/core/string/try_convert_spec.rb
+++ b/spec/ruby/core/string/try_convert_spec.rb
@@ -4,47 +4,47 @@ require_relative 'fixtures/classes'
describe "String.try_convert" do
it "returns the argument if it's a String" do
x = String.new
- String.try_convert(x).should equal(x)
+ String.try_convert(x).should.equal?(x)
end
it "returns the argument if it's a kind of String" do
x = StringSpecs::MyString.new
- String.try_convert(x).should equal(x)
+ String.try_convert(x).should.equal?(x)
end
it "returns nil when the argument does not respond to #to_str" do
- String.try_convert(Object.new).should be_nil
+ String.try_convert(Object.new).should == nil
end
it "sends #to_str to the argument and returns the result if it's nil" do
obj = mock("to_str")
obj.should_receive(:to_str).and_return(nil)
- String.try_convert(obj).should be_nil
+ String.try_convert(obj).should == nil
end
it "sends #to_str to the argument and returns the result if it's a String" do
x = String.new
obj = mock("to_str")
obj.should_receive(:to_str).and_return(x)
- String.try_convert(obj).should equal(x)
+ String.try_convert(obj).should.equal?(x)
end
it "sends #to_str to the argument and returns the result if it's a kind of String" do
x = StringSpecs::MyString.new
obj = mock("to_str")
obj.should_receive(:to_str).and_return(x)
- String.try_convert(obj).should equal(x)
+ String.try_convert(obj).should.equal?(x)
end
it "sends #to_str to the argument and raises TypeError if it's not a kind of String" do
obj = mock("to_str")
obj.should_receive(:to_str).and_return(Object.new)
- -> { String.try_convert obj }.should raise_error(TypeError)
+ -> { String.try_convert obj }.should raise_consistent_error(TypeError, "can't convert MockObject into String (MockObject#to_str gives Object)")
end
it "does not rescue exceptions raised by #to_str" do
obj = mock("to_str")
obj.should_receive(:to_str).and_raise(RuntimeError)
- -> { String.try_convert obj }.should raise_error(RuntimeError)
+ -> { String.try_convert obj }.should.raise(RuntimeError)
end
end
diff --git a/spec/ruby/core/string/undump_spec.rb b/spec/ruby/core/string/undump_spec.rb
index 08058d9bd1..8516e24b3b 100644
--- a/spec/ruby/core/string/undump_spec.rb
+++ b/spec/ruby/core/string/undump_spec.rb
@@ -8,7 +8,7 @@ describe "String#undump" do
end
it "always returns String instance" do
- StringSpecs::MyString.new('"foo"').undump.should be_an_instance_of(String)
+ StringSpecs::MyString.new('"foo"').undump.should.instance_of?(String)
end
it "strips outer \"" do
@@ -389,53 +389,53 @@ describe "String#undump" do
'"\\bv".force_encoding("UTF-16BE")'.undump.should == "\u0876".encode('utf-16be')
end
- it "keeps origin encoding" do
+ it "returns a String in the same encoding as self" do
'"foo"'.encode("ISO-8859-1").undump.encoding.should == Encoding::ISO_8859_1
'"foo"'.encode('windows-1251').undump.encoding.should == Encoding::Windows_1251
end
describe "Limitations" do
it "cannot undump non ASCII-compatible string" do
- -> { '"foo"'.encode('utf-16le').undump }.should raise_error(Encoding::CompatibilityError)
+ -> { '"foo"'.encode('utf-16le').undump }.should.raise(Encoding::CompatibilityError)
end
end
describe "invalid dump" do
it "raises RuntimeError exception if wrapping \" are missing" do
- -> { 'foo'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
- -> { '"foo'.undump }.should raise_error(RuntimeError, /unterminated dumped string/)
- -> { 'foo"'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
- -> { "'foo'".undump }.should raise_error(RuntimeError, /invalid dumped string/)
+ -> { 'foo'.undump }.should.raise(RuntimeError, /invalid dumped string/)
+ -> { '"foo'.undump }.should.raise(RuntimeError, /unterminated dumped string/)
+ -> { 'foo"'.undump }.should.raise(RuntimeError, /invalid dumped string/)
+ -> { "'foo'".undump }.should.raise(RuntimeError, /invalid dumped string/)
end
it "raises RuntimeError if there is incorrect \\x sequence" do
- -> { '"\x"'.undump }.should raise_error(RuntimeError, /invalid hex escape/)
- -> { '"\\x3y"'.undump }.should raise_error(RuntimeError, /invalid hex escape/)
+ -> { '"\x"'.undump }.should.raise(RuntimeError, /invalid hex escape/)
+ -> { '"\\x3y"'.undump }.should.raise(RuntimeError, /invalid hex escape/)
end
it "raises RuntimeError in there is incorrect \\u sequence" do
- -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
- -> { '"\\u{"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
- -> { '"\\u{3042"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
- -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
+ -> { '"\\u"'.undump }.should.raise(RuntimeError, /invalid Unicode escape/)
+ -> { '"\\u{"'.undump }.should.raise(RuntimeError, /invalid Unicode escape/)
+ -> { '"\\u{3042"'.undump }.should.raise(RuntimeError, /invalid Unicode escape/)
+ -> { '"\\u"'.undump }.should.raise(RuntimeError, /invalid Unicode escape/)
end
it "raises RuntimeError if there is malformed dump of non ASCII-compatible string" do
- -> { '"".force_encoding("BINARY"'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
- -> { '"".force_encoding("Unknown")'.undump }.should raise_error(RuntimeError, /dumped string has unknown encoding name/)
- -> { '"".force_encoding()'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
+ -> { '"".force_encoding("BINARY"'.undump }.should.raise(RuntimeError, /invalid dumped string/)
+ -> { '"".force_encoding("Unknown")'.undump }.should.raise(RuntimeError, /dumped string has unknown encoding name/)
+ -> { '"".force_encoding()'.undump }.should.raise(RuntimeError, /invalid dumped string/)
end
it "raises RuntimeError if string contains \0 character" do
- -> { "\"foo\0\"".undump }.should raise_error(RuntimeError, /string contains null byte/)
+ -> { "\"foo\0\"".undump }.should.raise(RuntimeError, /string contains null byte/)
end
it "raises RuntimeError if string contains non ASCII character" do
- -> { "\"\u3042\"".undump }.should raise_error(RuntimeError, /non-ASCII character detected/)
+ -> { "\"\u3042\"".undump }.should.raise(RuntimeError, /non-ASCII character detected/)
end
it "raises RuntimeError if there are some excessive \"" do
- -> { '" "" "'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
+ -> { '" "" "'.undump }.should.raise(RuntimeError, /invalid dumped string/)
end
end
end
diff --git a/spec/ruby/core/string/unicode_normalize_spec.rb b/spec/ruby/core/string/unicode_normalize_spec.rb
index 6de7533fc7..92b3a46b43 100644
--- a/spec/ruby/core/string/unicode_normalize_spec.rb
+++ b/spec/ruby/core/string/unicode_normalize_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
# Examples taken from http://www.unicode.org/reports/tr15/#Norm_Forms
@@ -50,13 +51,13 @@ describe "String#unicode_normalize" do
it "raises an Encoding::CompatibilityError if string is not in an unicode encoding" do
-> do
[0xE0].pack('C').force_encoding("ISO-8859-1").unicode_normalize(:nfd)
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError)
end
it "raises an ArgumentError if the specified form is invalid" do
-> {
@angstrom.unicode_normalize(:invalid_form)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
end
@@ -103,13 +104,13 @@ describe "String#unicode_normalize!" do
it "raises an Encoding::CompatibilityError if the string is not in an unicode encoding" do
-> {
[0xE0].pack('C').force_encoding("ISO-8859-1").unicode_normalize!
- }.should raise_error(Encoding::CompatibilityError)
+ }.should.raise(Encoding::CompatibilityError)
end
it "raises an ArgumentError if the specified form is invalid" do
ohm = "\u2126"
-> {
ohm.unicode_normalize!(:invalid_form)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/unicode_normalized_spec.rb b/spec/ruby/core/string/unicode_normalized_spec.rb
index 87f3740459..3ca27d35dd 100644
--- a/spec/ruby/core/string/unicode_normalized_spec.rb
+++ b/spec/ruby/core/string/unicode_normalized_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe "String#unicode_normalized?" do
@@ -37,38 +38,38 @@ describe "String#unicode_normalized?" do
end
it "raises an Encoding::CompatibilityError if the string is not in an unicode encoding" do
- -> { @nfc_normalized_str.force_encoding("ISO-8859-1").unicode_normalized? }.should raise_error(Encoding::CompatibilityError)
+ -> { @nfc_normalized_str.force_encoding("ISO-8859-1").unicode_normalized? }.should.raise(Encoding::CompatibilityError)
end
it "raises an ArgumentError if the specified form is invalid" do
- -> { @nfc_normalized_str.unicode_normalized?(:invalid_form) }.should raise_error(ArgumentError)
+ -> { @nfc_normalized_str.unicode_normalized?(:invalid_form) }.should.raise(ArgumentError)
end
it "returns true if str is in Unicode normalization form (nfc)" do
str = "a\u0300"
- str.unicode_normalized?(:nfc).should be_false
+ str.unicode_normalized?(:nfc).should == false
str.unicode_normalize!(:nfc)
- str.unicode_normalized?(:nfc).should be_true
+ str.unicode_normalized?(:nfc).should == true
end
it "returns true if str is in Unicode normalization form (nfd)" do
str = "a\u00E0"
- str.unicode_normalized?(:nfd).should be_false
+ str.unicode_normalized?(:nfd).should == false
str.unicode_normalize!(:nfd)
- str.unicode_normalized?(:nfd).should be_true
+ str.unicode_normalized?(:nfd).should == true
end
it "returns true if str is in Unicode normalization form (nfkc)" do
str = "a\u0300"
- str.unicode_normalized?(:nfkc).should be_false
+ str.unicode_normalized?(:nfkc).should == false
str.unicode_normalize!(:nfkc)
- str.unicode_normalized?(:nfkc).should be_true
+ str.unicode_normalized?(:nfkc).should == true
end
it "returns true if str is in Unicode normalization form (nfkd)" do
str = "a\u00E0"
- str.unicode_normalized?(:nfkd).should be_false
+ str.unicode_normalized?(:nfkd).should == false
str.unicode_normalize!(:nfkd)
- str.unicode_normalized?(:nfkd).should be_true
+ str.unicode_normalized?(:nfkd).should == true
end
end
diff --git a/spec/ruby/core/string/unpack/a_spec.rb b/spec/ruby/core/string/unpack/a_spec.rb
index 2d83b4c824..a68e842e15 100644
--- a/spec/ruby/core/string/unpack/a_spec.rb
+++ b/spec/ruby/core/string/unpack/a_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -31,7 +31,7 @@ describe "String#unpack with format 'A'" do
end
it "decodes into raw (ascii) string values" do
- str = "str".force_encoding('UTF-8').unpack("A*")[0]
+ str = "str".dup.force_encoding('UTF-8').unpack("A*")[0]
str.encoding.should == Encoding::BINARY
end
diff --git a/spec/ruby/core/string/unpack/at_spec.rb b/spec/ruby/core/string/unpack/at_spec.rb
index 70b2389d69..f4999f5922 100644
--- a/spec/ruby/core/string/unpack/at_spec.rb
+++ b/spec/ruby/core/string/unpack/at_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -24,6 +24,6 @@ describe "String#unpack with format '@'" do
end
it "raises an ArgumentError if the count exceeds the size of the String" do
- -> { "\x01\x02\x03\x04".unpack("C2@5C") }.should raise_error(ArgumentError)
+ -> { "\x01\x02\x03\x04".unpack("C2@5C") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/unpack/b_spec.rb b/spec/ruby/core/string/unpack/b_spec.rb
index 1a838d6c7c..fac6ef5151 100644
--- a/spec/ruby/core/string/unpack/b_spec.rb
+++ b/spec/ruby/core/string/unpack/b_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -86,13 +86,20 @@ describe "String#unpack with format 'B'" do
].should be_computed_by(:unpack, "BBB")
end
- it "ignores NULL bytes between directives" do
- "\x80\x00".unpack("B\x00B").should == ["1", "0"]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x80\x00".unpack("B\x00B")
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
"\x80\x00".unpack("B B").should == ["1", "0"]
end
+
+ it "decodes into US-ASCII string values" do
+ str = "s".dup.force_encoding('UTF-8').unpack("B*")[0]
+ str.encoding.name.should == 'US-ASCII'
+ end
end
describe "String#unpack with format 'b'" do
@@ -177,8 +184,10 @@ describe "String#unpack with format 'b'" do
].should be_computed_by(:unpack, "bbb")
end
- it "ignores NULL bytes between directives" do
- "\x01\x00".unpack("b\x00b").should == ["1", "0"]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x00".unpack("b\x00b")
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -186,8 +195,7 @@ describe "String#unpack with format 'b'" do
end
it "decodes into US-ASCII string values" do
- str = "s".force_encoding('UTF-8').unpack("b*")[0]
+ str = "s".dup.force_encoding('UTF-8').unpack("b*")[0]
str.encoding.name.should == 'US-ASCII'
end
-
end
diff --git a/spec/ruby/core/string/unpack/c_spec.rb b/spec/ruby/core/string/unpack/c_spec.rb
index ed8caa4895..d881015b5e 100644
--- a/spec/ruby/core/string/unpack/c_spec.rb
+++ b/spec/ruby/core/string/unpack/c_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -35,8 +35,10 @@ describe :string_unpack_8bit, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "abc".unpack(unpack_format("\000", 2)).should == [97, 98]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "abc".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/carret_spec.rb b/spec/ruby/core/string/unpack/carret_spec.rb
new file mode 100644
index 0000000000..815df0c718
--- /dev/null
+++ b/spec/ruby/core/string/unpack/carret_spec.rb
@@ -0,0 +1,43 @@
+# encoding: binary
+ruby_version_is "4.1" do
+ require_relative '../../../spec_helper'
+ require_relative '../fixtures/classes'
+ require_relative 'shared/basic'
+
+ describe "String#unpack with format '^'" do
+ it_behaves_like :string_unpack_basic, '^'
+ it_behaves_like :string_unpack_no_platform, '^'
+
+ it "returns the current offset that start from 0" do
+ "".unpack("^").should == [0]
+ end
+
+ it "returns the current offset after the last decode ended" do
+ "a".unpack("CC^").should == [97, nil, 1]
+ end
+
+ it "returns the current offset that start from the given offset" do
+ "abc".unpack("^", offset: 1).should == [1]
+ end
+
+ it "returns the offset moved by 'X'" do
+ "\x01\x02\x03\x04".unpack("C3X2^").should == [1, 2, 3, 1]
+ end
+
+ it "returns the offset moved by 'x'" do
+ "\x01\x02\x03\x04".unpack("Cx2^").should == [1, 3]
+ end
+
+ it "returns the offset to the position the previous decode ended" do
+ "foo".unpack("A4^").should == ["foo", 3]
+ "foo".unpack("a4^").should == ["foo", 3]
+ "foo".unpack("Z5^").should == ["foo", 3]
+ end
+
+ it "returns the offset including truncated part" do
+ "foo ".unpack("A*^").should == ["foo", 6]
+ "foo\0".unpack("Z*^").should == ["foo", 4]
+ "foo\0\0\0".unpack("Z5^").should == ["foo", 5]
+ end
+ end
+end
diff --git a/spec/ruby/core/string/unpack/comment_spec.rb b/spec/ruby/core/string/unpack/comment_spec.rb
index e18a53df3c..050d2b7fc0 100644
--- a/spec/ruby/core/string/unpack/comment_spec.rb
+++ b/spec/ruby/core/string/unpack/comment_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/string/unpack/h_spec.rb b/spec/ruby/core/string/unpack/h_spec.rb
index f2f5dcf396..0cf8d943a7 100644
--- a/spec/ruby/core/string/unpack/h_spec.rb
+++ b/spec/ruby/core/string/unpack/h_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -56,8 +56,10 @@ describe "String#unpack with format 'H'" do
].should be_computed_by(:unpack, "HHH")
end
- it "ignores NULL bytes between directives" do
- "\x01\x10".unpack("H\x00H").should == ["0", "1"]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x10".unpack("H\x00H")
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -121,8 +123,10 @@ describe "String#unpack with format 'h'" do
].should be_computed_by(:unpack, "hhh")
end
- it "ignores NULL bytes between directives" do
- "\x01\x10".unpack("h\x00h").should == ["1", "0"]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x10".unpack("h\x00h")
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/l_spec.rb b/spec/ruby/core/string/unpack/l_spec.rb
index 18bb68b8d0..0adb567eca 100644
--- a/spec/ruby/core/string/unpack/l_spec.rb
+++ b/spec/ruby/core/string/unpack/l_spec.rb
@@ -14,7 +14,7 @@ describe "String#unpack with format 'L'" do
it_behaves_like :string_unpack_32bit_be_unsigned, 'L>'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'L<_'
it_behaves_like :string_unpack_32bit_le, 'L_<'
@@ -44,7 +44,7 @@ describe "String#unpack with format 'L'" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'L<_'
it_behaves_like :string_unpack_64bit_le, 'L_<'
@@ -86,7 +86,7 @@ describe "String#unpack with format 'l'" do
it_behaves_like :string_unpack_32bit_be_signed, 'l>'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'l<_'
it_behaves_like :string_unpack_32bit_le, 'l_<'
@@ -116,7 +116,7 @@ describe "String#unpack with format 'l'" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'l<_'
it_behaves_like :string_unpack_64bit_le, 'l_<'
@@ -160,7 +160,7 @@ little_endian do
it_behaves_like :string_unpack_32bit_le_signed, 'l'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'L_'
it_behaves_like :string_unpack_32bit_le_unsigned, 'L_'
@@ -182,7 +182,7 @@ little_endian do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_64bit_le, 'L_'
it_behaves_like :string_unpack_64bit_le_unsigned, 'L_'
@@ -218,7 +218,7 @@ big_endian do
it_behaves_like :string_unpack_32bit_be_signed, 'l'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_32bit_be, 'L_'
it_behaves_like :string_unpack_32bit_be_unsigned, 'L_'
@@ -240,7 +240,7 @@ big_endian do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_64bit_be, 'L_'
it_behaves_like :string_unpack_64bit_be_unsigned, 'L_'
diff --git a/spec/ruby/core/string/unpack/m_spec.rb b/spec/ruby/core/string/unpack/m_spec.rb
index 21134514a1..c1c1eea629 100644
--- a/spec/ruby/core/string/unpack/m_spec.rb
+++ b/spec/ruby/core/string/unpack/m_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -97,6 +97,11 @@ describe "String#unpack with format 'M'" do
["=FF=\n", ["\xff"]]
].should be_computed_by(:unpack, "M")
end
+
+ it "unpacks incomplete escape sequences as literal characters" do
+ "foo=".unpack("M").should == ["foo="]
+ "foo=4".unpack("M").should == ["foo=4"]
+ end
end
describe "String#unpack with format 'm'" do
@@ -181,7 +186,7 @@ describe "String#unpack with format 'm'" do
end
it "raises an ArgumentError for an invalid base64 character" do
- -> { "dGV%zdA==".unpack("m0") }.should raise_error(ArgumentError)
+ -> { "dGV%zdA==".unpack("m0") }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/string/unpack/p_spec.rb b/spec/ruby/core/string/unpack/p_spec.rb
index cd48c0523d..4103730269 100644
--- a/spec/ruby/core/string/unpack/p_spec.rb
+++ b/spec/ruby/core/string/unpack/p_spec.rb
@@ -15,7 +15,7 @@ describe "String#unpack with format 'P'" do
packed = ["hello"].pack("P")
packed.unpack("P5").should == ["hello"]
packed.dup.unpack("P5").should == ["hello"]
- -> { packed.to_sym.to_s.unpack("P5") }.should raise_error(ArgumentError, /no associated pointer/)
+ -> { packed.to_sym.to_s.unpack("P5") }.should.raise(ArgumentError, /no associated pointer/)
end
it "reads as many characters as specified" do
@@ -39,6 +39,6 @@ describe "String#unpack with format 'p'" do
packed = ["hello"].pack("p")
packed.unpack("p").should == ["hello"]
packed.dup.unpack("p").should == ["hello"]
- -> { packed.to_sym.to_s.unpack("p") }.should raise_error(ArgumentError, /no associated pointer/)
+ -> { packed.to_sym.to_s.unpack("p") }.should.raise(ArgumentError, /no associated pointer/)
end
end
diff --git a/spec/ruby/core/string/unpack/percent_spec.rb b/spec/ruby/core/string/unpack/percent_spec.rb
index 0e27663195..7142bbf241 100644
--- a/spec/ruby/core/string/unpack/percent_spec.rb
+++ b/spec/ruby/core/string/unpack/percent_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../../spec_helper'
describe "String#unpack with format '%'" do
it "raises an Argument Error" do
- -> { "abc".unpack("%") }.should raise_error(ArgumentError)
+ -> { "abc".unpack("%") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/unpack/r_spec.rb b/spec/ruby/core/string/unpack/r_spec.rb
new file mode 100644
index 0000000000..a385951aa8
--- /dev/null
+++ b/spec/ruby/core/string/unpack/r_spec.rb
@@ -0,0 +1,85 @@
+# encoding: binary
+require_relative '../../../spec_helper'
+require_relative '../fixtures/classes'
+require_relative 'shared/basic'
+
+ruby_version_is "4.1" do
+ describe "String#unpack with format 'R'" do
+ it_behaves_like :string_unpack_basic, 'R'
+ it_behaves_like :string_unpack_no_platform, 'R'
+
+ it "decodes a ULEB128 integer" do
+ [ ["\x00", [0]],
+ ["\x01", [1]],
+ ["\x7f", [127]],
+ ["\x80\x01", [128]],
+ ["\xff\x7f", [0x3fff]],
+ ["\x80\x80\x01", [0x4000]],
+ ["\xff\xff\xff\xff\x0f", [0xffffffff]],
+ ["\x80\x80\x80\x80\x10", [0x100000000]],
+ ["\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01", [0xffff_ffff_ffff_ffff]],
+ ].should be_computed_by(:unpack, "R")
+ end
+
+ it "decodes multiple values with '*' modifier" do
+ "\x01\x02".unpack("R*").should == [1, 2]
+ "\x7f\x80\x01".unpack("R*").should == [127, 128]
+ end
+
+ it "returns nil for incomplete data" do
+ "\xFF".unpack("R").should == [nil]
+ "\xFF".unpack1("R").should == nil
+ end
+
+ it "returns nil for remaining incomplete values after a valid one" do
+ bytes = [256].pack("R")
+ (bytes + "\xFF").unpack("RRRR").should == [256, nil, nil, nil]
+ end
+
+ it "skips incomplete values with '*' modifier" do
+ "\xFF".unpack("R*").should == []
+ end
+ end
+
+ describe "String#unpack with format 'r'" do
+ it_behaves_like :string_unpack_basic, 'r'
+ it_behaves_like :string_unpack_no_platform, 'r'
+
+ it "decodes a SLEB128 integer" do
+ [ ["\x00", [0]],
+ ["\x01", [1]],
+ ["\x7f", [-1]],
+ ["\x7e", [-2]],
+ ["\xff\x00", [127]],
+ ["\x80\x01", [128]],
+ ["\x81\x7f", [-127]],
+ ["\x80\x7f", [-128]],
+ ].should be_computed_by(:unpack, "r")
+ end
+
+ it "decodes larger numbers" do
+ "\xff\xff\x00".unpack("r").should == [0x3fff]
+ "\x80\x80\x01".unpack("r").should == [0x4000]
+ "\x81\x80\x7f".unpack("r").should == [-0x3fff]
+ "\x80\x80\x7f".unpack("r").should == [-0x4000]
+ end
+
+ it "decodes multiple values with '*' modifier" do
+ "\x00\x01\x7f".unpack("r*").should == [0, 1, -1]
+ end
+
+ it "returns nil for incomplete data" do
+ "\xFF".unpack("r").should == [nil]
+ "\xFF".unpack1("r").should == nil
+ end
+
+ it "returns nil for remaining incomplete values after a valid one" do
+ bytes = [256].pack("r")
+ (bytes + "\xFF").unpack("rrrr").should == [256, nil, nil, nil]
+ end
+
+ it "skips incomplete values with '*' modifier" do
+ "\xFF".unpack("r*").should == []
+ end
+ end
+end
diff --git a/spec/ruby/core/string/unpack/shared/basic.rb b/spec/ruby/core/string/unpack/shared/basic.rb
index f636f4689f..2ee2d6899a 100644
--- a/spec/ruby/core/string/unpack/shared/basic.rb
+++ b/spec/ruby/core/string/unpack/shared/basic.rb
@@ -1,49 +1,27 @@
describe :string_unpack_basic, shared: true do
it "ignores whitespace in the format string" do
- "abc".unpack("a \t\n\v\f\r"+unpack_format).should be_an_instance_of(Array)
+ "abc".unpack("a \t\n\v\f\r"+unpack_format).should.instance_of?(Array)
end
it "calls #to_str to coerce the directives string" do
d = mock("unpack directive")
d.should_receive(:to_str).and_return("a"+unpack_format)
- "abc".unpack(d).should be_an_instance_of(Array)
+ "abc".unpack(d).should.instance_of?(Array)
end
- it "raises a TypeError when passed nil" do
- -> { "abc".unpack(nil) }.should raise_error(TypeError)
- end
-
- it "raises a TypeError when passed an Integer" do
- -> { "abc".unpack(1) }.should raise_error(TypeError)
- end
-
- ruby_version_is "3.1" do
- it "starts unpacking from the given offset" do
- "abc".unpack("CC", offset: 1).should == [98, 99]
- end
+ it "raises ArgumentError when a directive is unknown" do
+ -> { "abcdefgh".unpack("a K" + unpack_format) }.should.raise(ArgumentError, "unknown unpack directive 'K' in 'a K#{unpack_format}'")
+ -> { "abcdefgh".unpack("a 0" + unpack_format) }.should.raise(ArgumentError, "unknown unpack directive '0' in 'a 0#{unpack_format}'")
+ -> { "abcdefgh".unpack("a :" + unpack_format) }.should.raise(ArgumentError, "unknown unpack directive ':' in 'a :#{unpack_format}'")
end
end
describe :string_unpack_no_platform, shared: true do
it "raises an ArgumentError when the format modifier is '_'" do
- -> { "abcdefgh".unpack(unpack_format("_")) }.should raise_error(ArgumentError)
+ -> { "abcdefgh".unpack(unpack_format("_")) }.should.raise(ArgumentError)
end
it "raises an ArgumentError when the format modifier is '!'" do
- -> { "abcdefgh".unpack(unpack_format("!")) }.should raise_error(ArgumentError)
- end
-
- ruby_version_is "3.1" do
- it "raises an ArgumentError when the offset is negative" do
- -> { "a".unpack("C", offset: -1) }.should raise_error(ArgumentError)
- end
-
- it "returns nil if the offset is at the end of the string" do
- "a".unpack("C", offset: 1).should == [nil]
- end
-
- it "raises an ArgumentError when the offset is larget than the string" do
- -> { "a".unpack("C", offset: 2) }.should raise_error(ArgumentError)
- end
+ -> { "abcdefgh".unpack(unpack_format("!")) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/unpack/shared/float.rb b/spec/ruby/core/string/unpack/shared/float.rb
index 99bd8a3401..5525c3fe73 100644
--- a/spec/ruby/core/string/unpack/shared/float.rb
+++ b/spec/ruby/core/string/unpack/shared/float.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_unpack_float_le, shared: true do
it "decodes one float for a single format character" do
@@ -53,12 +53,13 @@ describe :string_unpack_float_le, shared: true do
it "decodes NaN" do
# mumble mumble NaN mumble https://bugs.ruby-lang.org/issues/5884
- [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
+ [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should == true
end
- it "ignores NULL bytes between directives" do
- array = "\x9a\x999@33\xb3?".unpack(unpack_format("\000", 2))
- array.should == [2.9000000953674316, 1.399999976158142]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x9a\x999@33\xb3?".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -120,12 +121,13 @@ describe :string_unpack_float_be, shared: true do
it "decodes NaN" do
# mumble mumble NaN mumble https://bugs.ruby-lang.org/issues/5884
- [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
+ [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should == true
end
- it "ignores NULL bytes between directives" do
- array = "@9\x99\x9a?\xb333".unpack(unpack_format("\000", 2))
- array.should == [2.9000000953674316, 1.399999976158142]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "@9\x99\x9a?\xb333".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -190,11 +192,13 @@ describe :string_unpack_double_le, shared: true do
it "decodes NaN" do
# mumble mumble NaN mumble https://bugs.ruby-lang.org/issues/5884
- [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
+ [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should == true
end
- it "ignores NULL bytes between directives" do
- "333333\x07@ffffff\xf6?".unpack(unpack_format("\000", 2)).should == [2.9, 1.4]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "333333\x07@ffffff\xf6?".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -258,11 +262,13 @@ describe :string_unpack_double_be, shared: true do
it "decodes NaN" do
# mumble mumble NaN mumble https://bugs.ruby-lang.org/issues/5884
- [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
+ [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should == true
end
- it "ignores NULL bytes between directives" do
- "@\x07333333?\xf6ffffff".unpack(unpack_format("\000", 2)).should == [2.9, 1.4]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "@\x07333333?\xf6ffffff".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/shared/integer.rb b/spec/ruby/core/string/unpack/shared/integer.rb
index cbaa743683..c66156536b 100644
--- a/spec/ruby/core/string/unpack/shared/integer.rb
+++ b/spec/ruby/core/string/unpack/shared/integer.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_unpack_16bit_le, shared: true do
it "decodes one short for a single format character" do
@@ -32,8 +32,10 @@ describe :string_unpack_16bit_le, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "abcd".unpack(unpack_format("\000", 2)).should == [25185, 25699]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "abcd".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -85,8 +87,10 @@ describe :string_unpack_16bit_be, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "badc".unpack(unpack_format("\000", 2)).should == [25185, 25699]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "badc".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -139,8 +143,10 @@ describe :string_unpack_32bit_le, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "abcdefgh".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "abcdefgh".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -193,8 +199,10 @@ describe :string_unpack_32bit_be, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "dcbahgfe".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "dcbahgfe".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -243,9 +251,10 @@ describe :string_unpack_64bit_le, shared: true do
"abc".unpack(unpack_format('*')).should == []
end
- it "ignores NULL bytes between directives" do
- array = "abcdefghabghefcd".unpack(unpack_format("\000", 2))
- array.should == [7523094288207667809, 7233738012216484449]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "badc".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
@@ -305,9 +314,10 @@ describe :string_unpack_64bit_be, shared: true do
"abc".unpack(unpack_format('*')).should == []
end
- it "ignores NULL bytes between directives" do
- array = "hgfedcbadcfehgba".unpack(unpack_format("\000", 2))
- array.should == [7523094288207667809, 7233738012216484449]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "hgfedcbadcfehgba".unpack(unpack_format("\000", 2))
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/shared/unicode.rb b/spec/ruby/core/string/unpack/shared/unicode.rb
index a2b4e142b2..9b4e0c09de 100644
--- a/spec/ruby/core/string/unpack/shared/unicode.rb
+++ b/spec/ruby/core/string/unpack/shared/unicode.rb
@@ -50,8 +50,10 @@ describe :string_unpack_unicode, shared: true do
"\xc2\x80".unpack("UUUU").should == [0x80]
end
- it "ignores NULL bytes between directives" do
- "\x01\x02".unpack("U\x00U").should == [1, 2]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x02".unpack("U\x00U")
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/u_spec.rb b/spec/ruby/core/string/unpack/u_spec.rb
index 7845e6d5f2..720c1b8583 100644
--- a/spec/ruby/core/string/unpack/u_spec.rb
+++ b/spec/ruby/core/string/unpack/u_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -12,11 +12,11 @@ describe "String#unpack with format 'U'" do
it_behaves_like :string_unpack_taint, 'U'
it "raises ArgumentError on a malformed byte sequence" do
- -> { "\xE3".unpack('U') }.should raise_error(ArgumentError)
+ -> { "\xE3".unpack('U') }.should.raise(ArgumentError)
end
it "raises ArgumentError on a malformed byte sequence and doesn't continue when used with the * modifier" do
- -> { "\xE3".unpack('U*') }.should raise_error(ArgumentError)
+ -> { "\xE3".unpack('U*') }.should.raise(ArgumentError)
end
end
@@ -33,7 +33,7 @@ describe "String#unpack with format 'u'" do
str = "".unpack("u")[0]
str.encoding.should == Encoding::BINARY
- str = "1".force_encoding('UTF-8').unpack("u")[0]
+ str = "1".dup.force_encoding('UTF-8').unpack("u")[0]
str.encoding.should == Encoding::BINARY
end
diff --git a/spec/ruby/core/string/unpack/w_spec.rb b/spec/ruby/core/string/unpack/w_spec.rb
index 011c75f5c4..cc9aecac9c 100644
--- a/spec/ruby/core/string/unpack/w_spec.rb
+++ b/spec/ruby/core/string/unpack/w_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -15,8 +15,10 @@ describe "String#unpack with directive 'w'" do
].should be_computed_by(:unpack, "w")
end
- it "ignores NULL bytes between directives" do
- "\x01\x02\x03".unpack("w\x00w").should == [1, 2]
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x02\x03".unpack("w\x00w")
+ }.should.raise(ArgumentError, /unknown unpack directive/)
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/x_spec.rb b/spec/ruby/core/string/unpack/x_spec.rb
index 5e248de77e..fb2e79fc1f 100644
--- a/spec/ruby/core/string/unpack/x_spec.rb
+++ b/spec/ruby/core/string/unpack/x_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -24,11 +24,11 @@ describe "String#unpack with format 'X'" do
end
it "raises an ArgumentError when passed the '*' modifier if the remaining bytes exceed the bytes from the index to the start of the String" do
- -> { "abcd".unpack("CX*C") }.should raise_error(ArgumentError)
+ -> { "abcd".unpack("CX*C") }.should.raise(ArgumentError)
end
it "raises an ArgumentError if the count exceeds the bytes from current index to the start of the String" do
- -> { "\x01\x02\x03\x04".unpack("C3X4C") }.should raise_error(ArgumentError)
+ -> { "\x01\x02\x03\x04".unpack("C3X4C") }.should.raise(ArgumentError)
end
end
@@ -57,6 +57,6 @@ describe "String#unpack with format 'x'" do
end
it "raises an ArgumentError if the count exceeds the size of the String" do
- -> { "\x01\x02\x03\x04".unpack("C2x3C") }.should raise_error(ArgumentError)
+ -> { "\x01\x02\x03\x04".unpack("C2x3C") }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/string/unpack/z_spec.rb b/spec/ruby/core/string/unpack/z_spec.rb
index ce8da4b29e..1030390550 100644
--- a/spec/ruby/core/string/unpack/z_spec.rb
+++ b/spec/ruby/core/string/unpack/z_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack1_spec.rb b/spec/ruby/core/string/unpack1_spec.rb
index f59bd92d6a..ee10042eb8 100644
--- a/spec/ruby/core/string/unpack1_spec.rb
+++ b/spec/ruby/core/string/unpack1_spec.rb
@@ -8,23 +8,54 @@ describe "String#unpack1" do
"A".unpack1("B*").should == "01000001"
end
- ruby_version_is "3.1" do
- it "starts unpacking from the given offset" do
- "ZZABCD".unpack1('x3C', offset: 2).should == "ABCD".unpack('x3C')[0]
- "ZZZZaG9nZWZ1Z2E=".unpack1("m", offset: 4).should == "hogefuga"
- "ZA".unpack1("B*", offset: 1).should == "01000001"
+ it "starts unpacking from the given offset" do
+ "ZZABCD".unpack1('x3C', offset: 2).should == "ABCD".unpack('x3C')[0]
+ "ZZZZaG9nZWZ1Z2E=".unpack1("m", offset: 4).should == "hogefuga"
+ "ZA".unpack1("B*", offset: 1).should == "01000001"
+ end
+
+ it "traits offset as a bytes offset" do
+ "؈".unpack("CC").should == [216, 136]
+ "؈".unpack1("C").should == 216
+ "؈".unpack1("C", offset: 1).should == 136
+ end
+
+ describe "when the offset is negative" do
+ ruby_version_is "4.1" do
+ it "starts unpacking from the end" do
+ "abc".unpack1("C", offset: -2).should == 98
+ end
+
+ it "raises an ArgumentError if it is less than -length" do
+ -> { "a".unpack1("C", offset: -2) }.should.raise(ArgumentError, "offset outside of string")
+ end
end
- it "raises an ArgumentError when the offset is negative" do
- -> { "a".unpack1("C", offset: -1) }.should raise_error(ArgumentError)
+ ruby_version_is ""..."4.1" do
+ it "raises an ArgumentError" do
+ -> { "a".unpack1("C", offset: -1) }.should.raise(ArgumentError, "offset can't be negative")
+ end
end
+ end
+
+ it "returns nil if the offset is at the end of the string" do
+ "a".unpack1("C", offset: 1).should == nil
+ end
+
+ it "raises an ArgumentError when the offset is larger than the string bytesize" do
+ -> { "a".unpack1("C", offset: 2) }.should.raise(ArgumentError, "offset outside of string")
+ end
+
+ context "with format 'm0'" do
+ # unpack1("m0") takes a special code path that calls Pack.unpackBase46Strict instead of Pack.unpack_m,
+ # which is why we repeat the tests for unpack("m0") here.
- it "returns nil if the offset is at the end of the string" do
- "a".unpack1("C", offset: 1).should == nil
+ it "decodes base64" do
+ "dGVzdA==".unpack1("m0").should == "test"
end
- it "raises an ArgumentError when the offset is larget than the string" do
- -> { "a".unpack1("C", offset: 2) }.should raise_error(ArgumentError)
+ it "raises an ArgumentError for an invalid base64 character" do
+ -> { "dGV%zdA==".unpack1("m0") }.should.raise(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/string/unpack_spec.rb b/spec/ruby/core/string/unpack_spec.rb
new file mode 100644
index 0000000000..eb4710ce14
--- /dev/null
+++ b/spec/ruby/core/string/unpack_spec.rb
@@ -0,0 +1,46 @@
+require_relative '../../spec_helper'
+
+describe "String#unpack" do
+ it "raises a TypeError when passed nil" do
+ -> { "abc".unpack(nil) }.should.raise(TypeError)
+ end
+
+ it "raises a TypeError when passed an Integer" do
+ -> { "abc".unpack(1) }.should.raise(TypeError)
+ end
+
+ it "starts unpacking from the given offset" do
+ "abc".unpack("CC", offset: 1).should == [98, 99]
+ end
+
+ it "traits offset as a bytes offset" do
+ "؈".unpack("CC").should == [216, 136]
+ "؈".unpack("CC", offset: 1).should == [136, nil]
+ end
+
+ describe "when the offset is negative" do
+ ruby_version_is "4.1" do
+ it "starts unpacking from the end" do
+ "abc".unpack("CC", offset: -2).should == [98, 99]
+ end
+
+ it "raises an ArgumentError if it is less than -length" do
+ -> { "a".unpack("C", offset: -2) }.should.raise(ArgumentError, "offset outside of string")
+ end
+ end
+
+ ruby_version_is ""..."4.1" do
+ it "raises an ArgumentError" do
+ -> { "a".unpack("C", offset: -1) }.should.raise(ArgumentError, "offset can't be negative")
+ end
+ end
+ end
+
+ it "returns nil if the offset is at the end of the string" do
+ "a".unpack("C", offset: 1).should == [nil]
+ end
+
+ it "raises an ArgumentError when the offset is larger than the string" do
+ -> { "a".unpack("C", offset: 2) }.should.raise(ArgumentError, "offset outside of string")
+ end
+end
diff --git a/spec/ruby/core/string/upcase_spec.rb b/spec/ruby/core/string/upcase_spec.rb
index 209fe73b6e..a6e1869267 100644
--- a/spec/ruby/core/string/upcase_spec.rb
+++ b/spec/ruby/core/string/upcase_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -8,6 +9,10 @@ describe "String#upcase" do
"hello".upcase.should == "HELLO"
end
+ it "returns a String in the same encoding as self" do
+ "hello".encode("US-ASCII").upcase.encoding.should == Encoding::US_ASCII
+ end
+
describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do
"äöü".upcase.should == "ÄÖÜ"
@@ -19,7 +24,7 @@ describe "String#upcase" do
upcased.should == "ASSET"
upcased.size.should == 5
upcased.bytesize.should == 5
- upcased.ascii_only?.should be_true
+ upcased.ascii_only?.should == true
end
end
@@ -43,7 +48,7 @@ describe "String#upcase" do
end
it "does not allow any other additional option" do
- -> { "i".upcase(:turkic, :ascii) }.should raise_error(ArgumentError)
+ -> { "i".upcase(:turkic, :ascii) }.should.raise(ArgumentError)
end
end
@@ -57,35 +62,27 @@ describe "String#upcase" do
end
it "does not allow any other additional option" do
- -> { "iß".upcase(:lithuanian, :ascii) }.should raise_error(ArgumentError)
+ -> { "iß".upcase(:lithuanian, :ascii) }.should.raise(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
- -> { "abc".upcase(:fold) }.should raise_error(ArgumentError)
+ -> { "abc".upcase(:fold) }.should.raise(ArgumentError)
end
it "does not allow invalid options" do
- -> { "abc".upcase(:invalid_option) }.should raise_error(ArgumentError)
- end
-
- ruby_version_is ''...'3.0' do
- it "returns a subclass instance for subclasses" do
- StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(StringSpecs::MyString)
- end
+ -> { "abc".upcase(:invalid_option) }.should.raise(ArgumentError)
end
- ruby_version_is '3.0' do
- it "returns a String instance for subclasses" do
- StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(String)
- end
+ it "returns a String instance for subclasses" do
+ StringSpecs::MyString.new("fooBAR").upcase.should.instance_of?(String)
end
end
describe "String#upcase!" do
it "modifies self in place" do
a = "HeLlO"
- a.upcase!.should equal(a)
+ a.upcase!.should.equal?(a)
a.should == "HELLO"
end
@@ -115,7 +112,7 @@ describe "String#upcase!" do
upcased.should == "ASSET"
upcased.size.should == 5
upcased.bytesize.should == 5
- upcased.ascii_only?.should be_true
+ upcased.ascii_only?.should == true
end
end
@@ -147,7 +144,7 @@ describe "String#upcase!" do
end
it "does not allow any other additional option" do
- -> { a = "i"; a.upcase!(:turkic, :ascii) }.should raise_error(ArgumentError)
+ -> { a = "i"; a.upcase!(:turkic, :ascii) }.should.raise(ArgumentError)
end
end
@@ -165,16 +162,16 @@ describe "String#upcase!" do
end
it "does not allow any other additional option" do
- -> { a = "iß"; a.upcase!(:lithuanian, :ascii) }.should raise_error(ArgumentError)
+ -> { a = "iß"; a.upcase!(:lithuanian, :ascii) }.should.raise(ArgumentError)
end
end
it "does not allow the :fold option for upcasing" do
- -> { a = "abc"; a.upcase!(:fold) }.should raise_error(ArgumentError)
+ -> { a = "abc"; a.upcase!(:fold) }.should.raise(ArgumentError)
end
it "does not allow invalid options" do
- -> { a = "abc"; a.upcase!(:invalid_option) }.should raise_error(ArgumentError)
+ -> { a = "abc"; a.upcase!(:invalid_option) }.should.raise(ArgumentError)
end
it "returns nil if no modifications were made" do
@@ -184,7 +181,7 @@ describe "String#upcase!" do
end
it "raises a FrozenError when self is frozen" do
- -> { "HeLlo".freeze.upcase! }.should raise_error(FrozenError)
- -> { "HELLO".freeze.upcase! }.should raise_error(FrozenError)
+ -> { "HeLlo".freeze.upcase! }.should.raise(FrozenError)
+ -> { "HELLO".freeze.upcase! }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/string/uplus_spec.rb b/spec/ruby/core/string/uplus_spec.rb
index 038b283c90..20767bcc01 100644
--- a/spec/ruby/core/string/uplus_spec.rb
+++ b/spec/ruby/core/string/uplus_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe 'String#+@' do
@@ -7,16 +8,53 @@ describe 'String#+@' do
output.should_not.frozen?
output.should == 'foo'
+
+ output << 'bar'
+ output.should == 'foobar'
end
- it 'returns self if the String is not frozen' do
- input = 'foo'
+ it 'returns a mutable String itself' do
+ input = String.new("foo")
output = +input
- output.equal?(input).should == true
+ output.should.equal?(input)
+
+ input << "bar"
+ output.should == "foobar"
+ end
+
+ context 'if file has "frozen_string_literal: true" magic comment' do
+ it 'returns mutable copy of a literal' do
+ ruby_exe(fixture(__FILE__, "freeze_magic_comment.rb")).should == 'mutable'
+ end
end
- it 'returns mutable copy despite freeze-magic-comment in file' do
- ruby_exe(fixture(__FILE__, "freeze_magic_comment.rb")).should == 'mutable'
+ context 'if file has "frozen_string_literal: false" magic comment' do
+ it 'returns literal string itself' do
+ input = 'foo'
+ output = +input
+
+ output.equal?(input).should == true
+ end
+ end
+
+ context 'if file has no frozen_string_literal magic comment' do
+ ruby_version_is ''...'3.4' do
+ it 'returns literal string itself' do
+ eval(<<~RUBY).should == true
+ s = "foo"
+ s.equal?(+s)
+ RUBY
+ end
+ end
+
+ ruby_version_is '3.4' do
+ it 'returns mutable copy of a literal' do
+ eval(<<~RUBY).should == false
+ s = "foo"
+ s.equal?(+s)
+ RUBY
+ end
+ end
end
end
diff --git a/spec/ruby/core/string/upto_spec.rb b/spec/ruby/core/string/upto_spec.rb
index f8529b1d2b..2eea06fd01 100644
--- a/spec/ruby/core/string/upto_spec.rb
+++ b/spec/ruby/core/string/upto_spec.rb
@@ -53,13 +53,13 @@ describe "String#upto" do
end
it "raises a TypeError if other can't be converted to a string" do
- -> { "abc".upto(123) { } }.should raise_error(TypeError)
- -> { "abc".upto(mock('x')){ } }.should raise_error(TypeError)
+ -> { "abc".upto(123) { } }.should.raise(TypeError)
+ -> { "abc".upto(mock('x')){ } }.should.raise(TypeError)
end
it "does not work with symbols" do
- -> { "a".upto(:c).to_a }.should raise_error(TypeError)
+ -> { "a".upto(:c).to_a }.should.raise(TypeError)
end
it "returns non-alphabetic characters in the ASCII range for single letters" do
@@ -80,6 +80,12 @@ describe "String#upto" do
a.should == ["Σ", "Τ", "Υ", "Φ", "Χ", "Ψ", "Ω"]
end
+ it "raises Encoding::CompatibilityError when incompatible characters are given" do
+ char1 = 'a'.dup.force_encoding("EUC-JP")
+ char2 = 'b'.dup.force_encoding("ISO-2022-JP")
+ -> { char1.upto(char2) {} }.should.raise(Encoding::CompatibilityError, "incompatible character encodings: EUC-JP and ISO-2022-JP")
+ end
+
describe "on sequence of numbers" do
it "calls the block as Integer#upto" do
"8".upto("11").to_a.should == 8.upto(11).map(&:to_s)
@@ -89,7 +95,7 @@ describe "String#upto" do
describe "when no block is given" do
it "returns an enumerator" do
enum = "aaa".upto("baa", true)
- enum.should be_an_instance_of(Enumerator)
+ enum.should.instance_of?(Enumerator)
enum.count.should == 26**2
end
diff --git a/spec/ruby/core/string/valid_encoding/utf_8_spec.rb b/spec/ruby/core/string/valid_encoding/utf_8_spec.rb
new file mode 100644
index 0000000000..a14c3af830
--- /dev/null
+++ b/spec/ruby/core/string/valid_encoding/utf_8_spec.rb
@@ -0,0 +1,214 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../../spec_helper'
+
+describe "String#valid_encoding? and UTF-8" do
+ def utf8(bytes)
+ bytes.pack("C*").force_encoding("UTF-8")
+ end
+
+ describe "1-byte character" do
+ it "is valid if is in format 0xxxxxxx" do
+ utf8([0b00000000]).valid_encoding?.should == true
+ utf8([0b01111111]).valid_encoding?.should == true
+ end
+
+ it "is not valid if is not in format 0xxxxxxx" do
+ utf8([0b10000000]).valid_encoding?.should == false
+ utf8([0b11111111]).valid_encoding?.should == false
+ end
+ end
+
+ describe "2-bytes character" do
+ it "is valid if in format [110xxxxx 10xxxxx]" do
+ utf8([0b11000010, 0b10000000]).valid_encoding?.should == true
+ utf8([0b11000010, 0b10111111]).valid_encoding?.should == true
+
+ utf8([0b11011111, 0b10000000]).valid_encoding?.should == true
+ utf8([0b11011111, 0b10111111]).valid_encoding?.should == true
+ end
+
+ it "is not valid if the first byte is not in format 110xxxxx" do
+ utf8([0b00000010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b00100010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01000010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01100010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10000010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10100010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11000010, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11100010, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is not in format 10xxxxxx" do
+ utf8([0b11000010, 0b00000000]).valid_encoding?.should == false
+ utf8([0b11000010, 0b01000000]).valid_encoding?.should == false
+ utf8([0b11000010, 0b11000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if is smaller than [xxxxxx10 xx000000] (codepoints < U+007F, that are encoded with the 1-byte format)" do
+ utf8([0b11000000, 0b10111111]).valid_encoding?.should == false
+ utf8([0b11000001, 0b10111111]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the first byte is missing" do
+ bytes = [0b11000010, 0b10000000]
+ utf8(bytes[1..1]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is missing" do
+ bytes = [0b11000010, 0b10000000]
+ utf8(bytes[0..0]).valid_encoding?.should == false
+ end
+ end
+
+ describe "3-bytes character" do
+ it "is valid if in format [1110xxxx 10xxxxxx 10xxxxxx]" do
+ utf8([0b11100000, 0b10100000, 0b10000000]).valid_encoding?.should == true
+ utf8([0b11100000, 0b10100000, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11100000, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11101111, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ end
+
+ it "is not valid if the first byte is not in format 1110xxxx" do
+ utf8([0b00000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b00010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b00100000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b00110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01100000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10100000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10100000, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is not in format 10xxxxxx" do
+ utf8([0b11100000, 0b00100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b01100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b11100000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the third byte is not in format 10xxxxxx" do
+ utf8([0b11100000, 0b10100000, 0b00000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10100000, 0b01000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10100000, 0b01000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if is smaller than [xxxx0000 xx100000 xx000000] (codepoints < U+07FF that are encoded with the 2-byte format)" do
+ utf8([0b11100000, 0b10010000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10001000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10000100, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10000010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10000001, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if in range [xxxx1101 xx100000 xx000000] - [xxxx1101 xx111111 xx111111] (codepoints U+D800 - U+DFFF)" do
+ utf8([0b11101101, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11101101, 0b10100000, 0b10000001]).valid_encoding?.should == false
+ utf8([0b11101101, 0b10111111, 0b10111111]).valid_encoding?.should == false
+
+ utf8([0b11101101, 0b10011111, 0b10111111]).valid_encoding?.should == true # lower boundary - 1
+ utf8([0b11101110, 0b10000000, 0b10000000]).valid_encoding?.should == true # upper boundary + 1
+ end
+
+ it "is not valid if the first byte is missing" do
+ bytes = [0b11100000, 0b10100000, 0b10000000]
+ utf8(bytes[2..3]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is missing" do
+ bytes = [0b11100000, 0b10100000, 0b10000000]
+ utf8([bytes[0], bytes[2]]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second and the third bytes are missing" do
+ bytes = [0b11100000, 0b10100000, 0b10000000]
+ utf8(bytes[0..0]).valid_encoding?.should == false
+ end
+ end
+
+ describe "4-bytes character" do
+ it "is valid if in format [11110xxx 10xxxxxx 10xxxxxx 10xxxxxx]" do
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11110000, 0b10010000, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11110000, 0b10111111, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11110100, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ end
+
+ it "is not valid if the first byte is not in format 11110xxx" do
+ utf8([0b11100000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11010000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is not in format 10xxxxxx" do
+ utf8([0b11110000, 0b00010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b01010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11110000, 0b11010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the third byte is not in format 10xxxxxx" do
+ utf8([0b11110000, 0b10010000, 0b00000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b01000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11110000, 0b10010000, 0b11000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the forth byte is not in format 10xxxxxx" do
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b00000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b01000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b11000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if is smaller than [xxxxx000 xx001000 xx000000 xx000000] (codepoint < U+10000)" do
+ utf8([0b11110000, 0b10000111, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000110, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000101, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000100, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000011, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000010, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000001, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if is greater than [xxxxx100 xx001111 xx111111 xx111111] (codepoint > U+10FFFF)" do
+ utf8([0b11110100, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110100, 0b10100000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110100, 0b10110000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+
+ utf8([0b11110101, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == false
+ utf8([0b11110110, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == false
+ utf8([0b11110111, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the first byte is missing" do
+ bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
+ utf8(bytes[1..3]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is missing" do
+ bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
+ utf8([bytes[0], bytes[2], bytes[3]]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second and the third bytes are missing" do
+ bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
+ utf8([bytes[0], bytes[3]]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second, the third and the fourth bytes are missing" do
+ bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
+ utf8(bytes[0..0]).valid_encoding?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/string/valid_encoding_spec.rb b/spec/ruby/core/string/valid_encoding_spec.rb
index be7cef7a8e..f29220fc99 100644
--- a/spec/ruby/core/string/valid_encoding_spec.rb
+++ b/spec/ruby/core/string/valid_encoding_spec.rb
@@ -2,134 +2,132 @@ require_relative '../../spec_helper'
describe "String#valid_encoding?" do
it "returns true if the String's encoding is valid" do
- "a".valid_encoding?.should be_true
- "\u{8365}\u{221}".valid_encoding?.should be_true
+ "a".valid_encoding?.should == true
+ "\u{8365}\u{221}".valid_encoding?.should == true
end
it "returns true if self is valid in the current encoding and other encodings" do
- str = "\x77"
- str.force_encoding('utf-8').valid_encoding?.should be_true
- str.force_encoding('binary').valid_encoding?.should be_true
+ str = +"\x77"
+ str.force_encoding('utf-8').valid_encoding?.should == true
+ str.force_encoding('binary').valid_encoding?.should == true
end
it "returns true for all encodings self is valid in" do
- str = "\xE6\x9D\x94"
- str.force_encoding('BINARY').valid_encoding?.should be_true
- str.force_encoding('UTF-8').valid_encoding?.should be_true
- str.force_encoding('US-ASCII').valid_encoding?.should be_false
- str.force_encoding('Big5').valid_encoding?.should be_false
- str.force_encoding('CP949').valid_encoding?.should be_false
- str.force_encoding('Emacs-Mule').valid_encoding?.should be_false
- str.force_encoding('EUC-JP').valid_encoding?.should be_false
- str.force_encoding('EUC-KR').valid_encoding?.should be_false
- str.force_encoding('EUC-TW').valid_encoding?.should be_false
- str.force_encoding('GB18030').valid_encoding?.should be_false
- str.force_encoding('GBK').valid_encoding?.should be_false
- str.force_encoding('ISO-8859-1').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-2').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-3').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-4').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-5').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-6').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-7').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-8').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-9').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-10').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-11').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-13').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-14').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-15').valid_encoding?.should be_true
- str.force_encoding('ISO-8859-16').valid_encoding?.should be_true
- str.force_encoding('KOI8-R').valid_encoding?.should be_true
- str.force_encoding('KOI8-U').valid_encoding?.should be_true
- str.force_encoding('Shift_JIS').valid_encoding?.should be_false
- "\xD8\x00".force_encoding('UTF-16BE').valid_encoding?.should be_false
- "\x00\xD8".force_encoding('UTF-16LE').valid_encoding?.should be_false
- "\x04\x03\x02\x01".force_encoding('UTF-32BE').valid_encoding?.should be_false
- "\x01\x02\x03\x04".force_encoding('UTF-32LE').valid_encoding?.should be_false
- str.force_encoding('Windows-1251').valid_encoding?.should be_true
- str.force_encoding('IBM437').valid_encoding?.should be_true
- str.force_encoding('IBM737').valid_encoding?.should be_true
- str.force_encoding('IBM775').valid_encoding?.should be_true
- str.force_encoding('CP850').valid_encoding?.should be_true
- str.force_encoding('IBM852').valid_encoding?.should be_true
- str.force_encoding('CP852').valid_encoding?.should be_true
- str.force_encoding('IBM855').valid_encoding?.should be_true
- str.force_encoding('CP855').valid_encoding?.should be_true
- str.force_encoding('IBM857').valid_encoding?.should be_true
- str.force_encoding('IBM860').valid_encoding?.should be_true
- str.force_encoding('IBM861').valid_encoding?.should be_true
- str.force_encoding('IBM862').valid_encoding?.should be_true
- str.force_encoding('IBM863').valid_encoding?.should be_true
- str.force_encoding('IBM864').valid_encoding?.should be_true
- str.force_encoding('IBM865').valid_encoding?.should be_true
- str.force_encoding('IBM866').valid_encoding?.should be_true
- str.force_encoding('IBM869').valid_encoding?.should be_true
- str.force_encoding('Windows-1258').valid_encoding?.should be_true
- str.force_encoding('GB1988').valid_encoding?.should be_true
- str.force_encoding('macCentEuro').valid_encoding?.should be_true
- str.force_encoding('macCroatian').valid_encoding?.should be_true
- str.force_encoding('macCyrillic').valid_encoding?.should be_true
- str.force_encoding('macGreek').valid_encoding?.should be_true
- str.force_encoding('macIceland').valid_encoding?.should be_true
- str.force_encoding('macRoman').valid_encoding?.should be_true
- str.force_encoding('macRomania').valid_encoding?.should be_true
- str.force_encoding('macThai').valid_encoding?.should be_true
- str.force_encoding('macTurkish').valid_encoding?.should be_true
- str.force_encoding('macUkraine').valid_encoding?.should be_true
- str.force_encoding('stateless-ISO-2022-JP').valid_encoding?.should be_false
- str.force_encoding('eucJP-ms').valid_encoding?.should be_false
- str.force_encoding('CP51932').valid_encoding?.should be_false
- str.force_encoding('GB2312').valid_encoding?.should be_false
- str.force_encoding('GB12345').valid_encoding?.should be_false
- str.force_encoding('ISO-2022-JP').valid_encoding?.should be_true
- str.force_encoding('ISO-2022-JP-2').valid_encoding?.should be_true
- str.force_encoding('CP50221').valid_encoding?.should be_true
- str.force_encoding('Windows-1252').valid_encoding?.should be_true
- str.force_encoding('Windows-1250').valid_encoding?.should be_true
- str.force_encoding('Windows-1256').valid_encoding?.should be_true
- str.force_encoding('Windows-1253').valid_encoding?.should be_true
- str.force_encoding('Windows-1255').valid_encoding?.should be_true
- str.force_encoding('Windows-1254').valid_encoding?.should be_true
- str.force_encoding('TIS-620').valid_encoding?.should be_true
- str.force_encoding('Windows-874').valid_encoding?.should be_true
- str.force_encoding('Windows-1257').valid_encoding?.should be_true
- str.force_encoding('Windows-31J').valid_encoding?.should be_false
- str.force_encoding('MacJapanese').valid_encoding?.should be_false
- str.force_encoding('UTF-7').valid_encoding?.should be_true
- str.force_encoding('UTF8-MAC').valid_encoding?.should be_true
+ str = +"\xE6\x9D\x94"
+ str.force_encoding('BINARY').valid_encoding?.should == true
+ str.force_encoding('UTF-8').valid_encoding?.should == true
+ str.force_encoding('US-ASCII').valid_encoding?.should == false
+ str.force_encoding('Big5').valid_encoding?.should == false
+ str.force_encoding('CP949').valid_encoding?.should == false
+ str.force_encoding('Emacs-Mule').valid_encoding?.should == false
+ str.force_encoding('EUC-JP').valid_encoding?.should == false
+ str.force_encoding('EUC-KR').valid_encoding?.should == false
+ str.force_encoding('EUC-TW').valid_encoding?.should == false
+ str.force_encoding('GB18030').valid_encoding?.should == false
+ str.force_encoding('GBK').valid_encoding?.should == false
+ str.force_encoding('ISO-8859-1').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-2').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-3').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-4').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-5').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-6').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-7').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-8').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-9').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-10').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-11').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-13').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-14').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-15').valid_encoding?.should == true
+ str.force_encoding('ISO-8859-16').valid_encoding?.should == true
+ str.force_encoding('KOI8-R').valid_encoding?.should == true
+ str.force_encoding('KOI8-U').valid_encoding?.should == true
+ str.force_encoding('Shift_JIS').valid_encoding?.should == false
+ "\xD8\x00".dup.force_encoding('UTF-16BE').valid_encoding?.should == false
+ "\x00\xD8".dup.force_encoding('UTF-16LE').valid_encoding?.should == false
+ "\x04\x03\x02\x01".dup.force_encoding('UTF-32BE').valid_encoding?.should == false
+ "\x01\x02\x03\x04".dup.force_encoding('UTF-32LE').valid_encoding?.should == false
+ str.force_encoding('Windows-1251').valid_encoding?.should == true
+ str.force_encoding('IBM437').valid_encoding?.should == true
+ str.force_encoding('IBM737').valid_encoding?.should == true
+ str.force_encoding('IBM775').valid_encoding?.should == true
+ str.force_encoding('CP850').valid_encoding?.should == true
+ str.force_encoding('IBM852').valid_encoding?.should == true
+ str.force_encoding('CP852').valid_encoding?.should == true
+ str.force_encoding('IBM855').valid_encoding?.should == true
+ str.force_encoding('CP855').valid_encoding?.should == true
+ str.force_encoding('IBM857').valid_encoding?.should == true
+ str.force_encoding('IBM860').valid_encoding?.should == true
+ str.force_encoding('IBM861').valid_encoding?.should == true
+ str.force_encoding('IBM862').valid_encoding?.should == true
+ str.force_encoding('IBM863').valid_encoding?.should == true
+ str.force_encoding('IBM864').valid_encoding?.should == true
+ str.force_encoding('IBM865').valid_encoding?.should == true
+ str.force_encoding('IBM866').valid_encoding?.should == true
+ str.force_encoding('IBM869').valid_encoding?.should == true
+ str.force_encoding('Windows-1258').valid_encoding?.should == true
+ str.force_encoding('GB1988').valid_encoding?.should == true
+ str.force_encoding('macCentEuro').valid_encoding?.should == true
+ str.force_encoding('macCroatian').valid_encoding?.should == true
+ str.force_encoding('macCyrillic').valid_encoding?.should == true
+ str.force_encoding('macGreek').valid_encoding?.should == true
+ str.force_encoding('macIceland').valid_encoding?.should == true
+ str.force_encoding('macRoman').valid_encoding?.should == true
+ str.force_encoding('macRomania').valid_encoding?.should == true
+ str.force_encoding('macThai').valid_encoding?.should == true
+ str.force_encoding('macTurkish').valid_encoding?.should == true
+ str.force_encoding('macUkraine').valid_encoding?.should == true
+ str.force_encoding('stateless-ISO-2022-JP').valid_encoding?.should == false
+ str.force_encoding('eucJP-ms').valid_encoding?.should == false
+ str.force_encoding('CP51932').valid_encoding?.should == false
+ str.force_encoding('GB2312').valid_encoding?.should == false
+ str.force_encoding('GB12345').valid_encoding?.should == false
+ str.force_encoding('ISO-2022-JP').valid_encoding?.should == true
+ str.force_encoding('ISO-2022-JP-2').valid_encoding?.should == true
+ str.force_encoding('CP50221').valid_encoding?.should == true
+ str.force_encoding('Windows-1252').valid_encoding?.should == true
+ str.force_encoding('Windows-1250').valid_encoding?.should == true
+ str.force_encoding('Windows-1256').valid_encoding?.should == true
+ str.force_encoding('Windows-1253').valid_encoding?.should == true
+ str.force_encoding('Windows-1255').valid_encoding?.should == true
+ str.force_encoding('Windows-1254').valid_encoding?.should == true
+ str.force_encoding('TIS-620').valid_encoding?.should == true
+ str.force_encoding('Windows-874').valid_encoding?.should == true
+ str.force_encoding('Windows-1257').valid_encoding?.should == true
+ str.force_encoding('Windows-31J').valid_encoding?.should == false
+ str.force_encoding('MacJapanese').valid_encoding?.should == false
+ str.force_encoding('UTF-7').valid_encoding?.should == true
+ str.force_encoding('UTF8-MAC').valid_encoding?.should == true
end
- ruby_version_is '3.0' do
- it "returns true for IBM720 encoding self is valid in" do
- str = "\xE6\x9D\x94"
- str.force_encoding('IBM720').valid_encoding?.should be_true
- str.force_encoding('CP720').valid_encoding?.should be_true
- end
+ it "returns true for IBM720 encoding self is valid in" do
+ str = +"\xE6\x9D\x94"
+ str.force_encoding('IBM720').valid_encoding?.should == true
+ str.force_encoding('CP720').valid_encoding?.should == true
end
it "returns false if self is valid in one encoding, but invalid in the one it's tagged with" do
- str = "\u{8765}"
- str.valid_encoding?.should be_true
- str = str.force_encoding('ascii')
- str.valid_encoding?.should be_false
+ str = +"\u{8765}"
+ str.valid_encoding?.should == true
+ str.force_encoding('ascii')
+ str.valid_encoding?.should == false
end
it "returns false if self contains a character invalid in the associated encoding" do
- "abc#{[0x80].pack('C')}".force_encoding('ascii').valid_encoding?.should be_false
+ "abc#{[0x80].pack('C')}".dup.force_encoding('ascii').valid_encoding?.should == false
end
it "returns false if a valid String had an invalid character appended to it" do
- str = "a"
- str.valid_encoding?.should be_true
+ str = +"a"
+ str.valid_encoding?.should == true
str << [0xDD].pack('C').force_encoding('utf-8')
- str.valid_encoding?.should be_false
+ str.valid_encoding?.should == false
end
it "returns true if an invalid string is appended another invalid one but both make a valid string" do
str = [0xD0].pack('C').force_encoding('utf-8')
- str.valid_encoding?.should be_false
+ str.valid_encoding?.should == false
str << [0xBF].pack('C').force_encoding('utf-8')
- str.valid_encoding?.should be_true
+ str.valid_encoding?.should == true
end
end
diff --git a/spec/ruby/core/struct/constants_spec.rb b/spec/ruby/core/struct/constants_spec.rb
new file mode 100644
index 0000000000..7e8af1a211
--- /dev/null
+++ b/spec/ruby/core/struct/constants_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+
+describe "Struct::Group" do
+ it "is no longer defined" do
+ Struct.should_not.const_defined?(:Group)
+ end
+end
+
+describe "Struct::Passwd" do
+ it "is no longer defined" do
+ Struct.should_not.const_defined?(:Passwd)
+ end
+end
diff --git a/spec/ruby/core/struct/deconstruct_keys_spec.rb b/spec/ruby/core/struct/deconstruct_keys_spec.rb
index 088803d028..590e1ab40b 100644
--- a/spec/ruby/core/struct/deconstruct_keys_spec.rb
+++ b/spec/ruby/core/struct/deconstruct_keys_spec.rb
@@ -14,7 +14,7 @@ describe "Struct#deconstruct_keys" do
-> {
obj.deconstruct_keys
- }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
+ }.should.raise(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
end
it "returns only specified keys" do
@@ -40,6 +40,21 @@ describe "Struct#deconstruct_keys" do
s.deconstruct_keys([0, 1, 2]).should == {0 => 10, 1 => 20, 2 => 30}
s.deconstruct_keys([0, 1] ).should == {0 => 10, 1 => 20}
s.deconstruct_keys([0] ).should == {0 => 10}
+ s.deconstruct_keys([-1] ).should == {-1 => 30}
+ end
+
+ it "ignores incorrect position numbers" do
+ struct = Struct.new(:x, :y, :z)
+ s = struct.new(10, 20, 30)
+
+ s.deconstruct_keys([0, 3]).should == {0 => 10}
+ end
+
+ it "support mixing attribute names and argument position numbers" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys([0, :x]).should == {0 => 1, :x => 1}
end
it "returns an empty hash when there are more keys than attributes" do
@@ -57,6 +72,14 @@ describe "Struct#deconstruct_keys" do
s.deconstruct_keys([:x, :a]).should == {x: 1}
end
+ it "returns at first not existing argument position number" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys([3, 0]).should == {}
+ s.deconstruct_keys([0, 3]).should == {0 => 1}
+ end
+
it "accepts nil argument and return all the attributes" do
struct = Struct.new(:x, :y)
obj = struct.new(1, 2)
@@ -64,13 +87,44 @@ describe "Struct#deconstruct_keys" do
obj.deconstruct_keys(nil).should == {x: 1, y: 2}
end
- it "raise TypeError if passed anything accept nil or array" do
+ it "tries to convert a key with #to_int if index is not a String nor a Symbol, but responds to #to_int" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ key = mock("to_int")
+ key.should_receive(:to_int).and_return(1)
+
+ s.deconstruct_keys([key]).should == { key => 2 }
+ end
+
+ it "raises a TypeError if the conversion with #to_int does not return an Integer" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ key = mock("to_int")
+ key.should_receive(:to_int).and_return("not an Integer")
+
+ -> {
+ s.deconstruct_keys([key])
+ }.should raise_consistent_error(TypeError, /can't convert MockObject into Integer/)
+ end
+
+ it "raises TypeError if index is not a String, a Symbol and not convertible to Integer" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ -> {
+ s.deconstruct_keys([0, []])
+ }.should.raise(TypeError, "no implicit conversion of Array into Integer")
+ end
+
+ it "raise TypeError if passed anything except nil or array" do
struct = Struct.new(:x, :y)
s = struct.new(1, 2)
- -> { s.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/)
- -> { s.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/)
- -> { s.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/)
- -> { s.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys('x') }.should.raise(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys(1) }.should.raise(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys(:x) }.should.raise(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys({}) }.should.raise(TypeError, /expected Array or nil/)
end
end
diff --git a/spec/ruby/core/struct/dig_spec.rb b/spec/ruby/core/struct/dig_spec.rb
index 93a52dbbe1..52e4d1dd9a 100644
--- a/spec/ruby/core/struct/dig_spec.rb
+++ b/spec/ruby/core/struct/dig_spec.rb
@@ -32,11 +32,11 @@ describe "Struct#dig" do
instance = @klass.new(1)
-> {
instance.dig(:a, 3)
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises an ArgumentError if no arguments provided" do
- -> { @instance.dig }.should raise_error(ArgumentError)
+ -> { @instance.dig }.should.raise(ArgumentError)
end
it "calls #dig on any intermediate step with the rest of the sequence as arguments" do
diff --git a/spec/ruby/core/struct/each_pair_spec.rb b/spec/ruby/core/struct/each_pair_spec.rb
index 1230ca9026..db146c81e9 100644
--- a/spec/ruby/core/struct/each_pair_spec.rb
+++ b/spec/ruby/core/struct/each_pair_spec.rb
@@ -21,11 +21,11 @@ describe "Struct#each_pair" do
end
it "returns self if passed a block" do
- @car.each_pair {}.should equal(@car)
+ @car.each_pair {}.should.equal?(@car)
end
it "returns an Enumerator if not passed a block" do
- @car.each_pair.should be_an_instance_of(Enumerator)
+ @car.each_pair.should.instance_of?(Enumerator)
end
it_behaves_like :struct_accessor, :each_pair
diff --git a/spec/ruby/core/struct/each_spec.rb b/spec/ruby/core/struct/each_spec.rb
index 41c0fbd4d0..4fbdfee02a 100644
--- a/spec/ruby/core/struct/each_spec.rb
+++ b/spec/ruby/core/struct/each_spec.rb
@@ -19,7 +19,7 @@ describe "Struct#each" do
it "returns an Enumerator if not passed a block" do
car = StructClasses::Car.new('Ford', 'Ranger')
- car.each.should be_an_instance_of(Enumerator)
+ car.each.should.instance_of?(Enumerator)
end
it_behaves_like :struct_accessor, :each
diff --git a/spec/ruby/core/struct/element_reference_spec.rb b/spec/ruby/core/struct/element_reference_spec.rb
index 0f6d547f66..b94f3aae8c 100644
--- a/spec/ruby/core/struct/element_reference_spec.rb
+++ b/spec/ruby/core/struct/element_reference_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Struct[]" do
it "is a synonym for new" do
- StructClasses::Ruby['2.0', 'i686'].should be_kind_of(StructClasses::Ruby)
+ StructClasses::Ruby['2.0', 'i686'].should.is_a?(StructClasses::Ruby)
end
end
@@ -26,20 +26,20 @@ describe "Struct#[]" do
it "fails when it does not know about the requested attribute" do
car = StructClasses::Car.new('Ford', 'Ranger')
- -> { car[3] }.should raise_error(IndexError)
- -> { car[-4] }.should raise_error(IndexError)
- -> { car[:body] }.should raise_error(NameError)
- -> { car['wheels'] }.should raise_error(NameError)
+ -> { car[3] }.should.raise(IndexError)
+ -> { car[-4] }.should.raise(IndexError)
+ -> { car[:body] }.should.raise(NameError)
+ -> { car['wheels'] }.should.raise(NameError)
end
it "fails if passed too many arguments" do
car = StructClasses::Car.new('Ford', 'Ranger')
- -> { car[:make, :model] }.should raise_error(ArgumentError)
+ -> { car[:make, :model] }.should.raise(ArgumentError)
end
it "fails if not passed a string, symbol, or integer" do
car = StructClasses::Car.new('Ford', 'Ranger')
- -> { car[Object.new] }.should raise_error(TypeError)
+ -> { car[Object.new] }.should.raise(TypeError)
end
it "returns attribute names that contain hyphens" do
diff --git a/spec/ruby/core/struct/element_set_spec.rb b/spec/ruby/core/struct/element_set_spec.rb
index 6ba7b081a9..e5438ca09a 100644
--- a/spec/ruby/core/struct/element_set_spec.rb
+++ b/spec/ruby/core/struct/element_set_spec.rb
@@ -21,9 +21,16 @@ describe "Struct#[]=" do
it "fails when trying to assign attributes which don't exist" do
car = StructClasses::Car.new('Ford', 'Ranger')
- -> { car[:something] = true }.should raise_error(NameError)
- -> { car[3] = true }.should raise_error(IndexError)
- -> { car[-4] = true }.should raise_error(IndexError)
- -> { car[Object.new] = true }.should raise_error(TypeError)
+ -> { car[:something] = true }.should.raise(NameError)
+ -> { car[3] = true }.should.raise(IndexError)
+ -> { car[-4] = true }.should.raise(IndexError)
+ -> { car[Object.new] = true }.should.raise(TypeError)
+ end
+
+ it "raises a FrozenError on a frozen struct" do
+ car = StructClasses::Car.new('Ford', 'Ranger')
+ car.freeze
+
+ -> { car[:model] = 'Escape' }.should.raise(FrozenError)
end
end
diff --git a/spec/ruby/core/struct/eql_spec.rb b/spec/ruby/core/struct/eql_spec.rb
index c864b2b943..327c927278 100644
--- a/spec/ruby/core/struct/eql_spec.rb
+++ b/spec/ruby/core/struct/eql_spec.rb
@@ -8,6 +8,6 @@ describe "Struct#eql?" do
it "returns false if any corresponding elements are not #eql?" do
car = StructClasses::Car.new("Honda", "Accord", 1998)
similar_car = StructClasses::Car.new("Honda", "Accord", 1998.0)
- car.should_not eql(similar_car)
+ car.should_not.eql?(similar_car)
end
end
diff --git a/spec/ruby/core/struct/fixtures/classes.rb b/spec/ruby/core/struct/fixtures/classes.rb
index 6d620f9060..675d403abd 100644
--- a/spec/ruby/core/struct/fixtures/classes.rb
+++ b/spec/ruby/core/struct/fixtures/classes.rb
@@ -3,6 +3,7 @@ module StructClasses
class Apple < Struct; end
Ruby = Struct.new(:version, :platform)
+ Single = Struct.new(:value)
Car = Struct.new(:make, :model, :year)
@@ -13,6 +14,12 @@ module StructClasses
end
end
+ class StructWithOverriddenName < Struct.new(:a)
+ def self.name
+ "A"
+ end
+ end
+
class SubclassX < Struct
end
@@ -23,4 +30,6 @@ module StructClasses
super
end
end
+
+ class StructSubclass < Struct; end
end
diff --git a/spec/ruby/core/struct/hash_spec.rb b/spec/ruby/core/struct/hash_spec.rb
index 53361eb7a9..750387b326 100644
--- a/spec/ruby/core/struct/hash_spec.rb
+++ b/spec/ruby/core/struct/hash_spec.rb
@@ -8,14 +8,14 @@ describe "Struct#hash" do
[StructClasses::Ruby.new("1.8.6", "PPC"),
StructClasses::Car.new("Hugo", "Foo", "1972")].each do |stc|
stc.hash.should == stc.dup.hash
- stc.hash.should be_kind_of(Integer)
+ stc.hash.should.is_a?(Integer)
end
end
it "returns the same value if structs are #eql?" do
car = StructClasses::Car.new("Honda", "Accord", "1998")
similar_car = StructClasses::Car.new("Honda", "Accord", "1998")
- car.should eql(similar_car)
+ car.should.eql?(similar_car)
car.hash.should == similar_car.hash
end
diff --git a/spec/ruby/core/struct/initialize_spec.rb b/spec/ruby/core/struct/initialize_spec.rb
index e82289071a..c824f52e13 100644
--- a/spec/ruby/core/struct/initialize_spec.rb
+++ b/spec/ruby/core/struct/initialize_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
describe "Struct#initialize" do
it "is private" do
- StructClasses::Car.should have_private_instance_method(:initialize)
+ StructClasses::Car.private_instance_methods(true).should.include?(:initialize)
end
it 'allows valid Ruby method names for members' do
@@ -40,4 +40,35 @@ describe "Struct#initialize" do
it "can be overridden" do
StructClasses::SubclassX.new(:y).new.key.should == :value
end
+
+ it "can be initialized with keyword arguments" do
+ positional_args = StructClasses::Ruby.new("3.2", "OS")
+ keyword_args = StructClasses::Ruby.new(version: "3.2", platform: "OS")
+
+ positional_args.version.should == keyword_args.version
+ positional_args.platform.should == keyword_args.platform
+ end
+
+ it "accepts positional arguments with empty keyword arguments" do
+ data = StructClasses::Single.new(42, **{})
+
+ data.value.should == 42
+
+ data = StructClasses::Ruby.new("3.2", "OS", **{})
+
+ data.version.should == "3.2"
+ data.platform.should == "OS"
+ end
+
+ it "can be called via delegated ... from a prepended module" do
+ wrapper = Module.new do
+ def initialize(...)
+ super(...)
+ end
+ end
+
+ klass = Class.new(Struct.new(:a)) { prepend wrapper }
+ s = klass.new("x")
+ s.a.should == "x"
+ end
end
diff --git a/spec/ruby/core/struct/inspect_spec.rb b/spec/ruby/core/struct/inspect_spec.rb
index 83e13597ba..657b06abc1 100644
--- a/spec/ruby/core/struct/inspect_spec.rb
+++ b/spec/ruby/core/struct/inspect_spec.rb
@@ -3,10 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/inspect'
describe "Struct#inspect" do
- it "returns a string representation showing members and values" do
- car = StructClasses::Car.new('Ford', 'Ranger')
- car.inspect.should == '#<struct StructClasses::Car make="Ford", model="Ranger", year=nil>'
- end
-
it_behaves_like :struct_inspect, :inspect
end
diff --git a/spec/ruby/core/struct/instance_variable_get_spec.rb b/spec/ruby/core/struct/instance_variable_get_spec.rb
index e4a3ea87dc..e3555cd246 100644
--- a/spec/ruby/core/struct/instance_variable_get_spec.rb
+++ b/spec/ruby/core/struct/instance_variable_get_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
describe "Struct#instance_variable_get" do
it "returns nil for attributes" do
car = StructClasses::Car.new("Hugo", "Foo", "1972")
- car.instance_variable_get(:@make).should be_nil
+ car.instance_variable_get(:@make).should == nil
end
it "returns a user value for variables with the same name as attributes" do
diff --git a/spec/ruby/core/struct/keyword_init_spec.rb b/spec/ruby/core/struct/keyword_init_spec.rb
new file mode 100644
index 0000000000..42fcd3cc29
--- /dev/null
+++ b/spec/ruby/core/struct/keyword_init_spec.rb
@@ -0,0 +1,45 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+# See https://bugs.ruby-lang.org/issues/18008
+describe "StructClass#keyword_init?" do
+ it "returns true for a struct that accepts keyword arguments to initialize" do
+ struct = Struct.new(:arg, keyword_init: true)
+ struct.keyword_init?.should == true
+ end
+
+ it "returns false for a struct that does not accept keyword arguments to initialize" do
+ struct = Struct.new(:arg, keyword_init: false)
+ struct.keyword_init?.should == false
+ end
+
+ it "returns nil for a struct that did not explicitly specify keyword_init" do
+ struct = Struct.new(:arg)
+ struct.keyword_init?.should == nil
+ end
+
+ it "returns nil for a struct that does specify keyword_init to be nil" do
+ struct = Struct.new(:arg, keyword_init: nil)
+ struct.keyword_init?.should == nil
+ end
+
+ it "returns true for any truthy value, not just for true" do
+ struct = Struct.new(:arg, keyword_init: 1)
+ struct.keyword_init?.should == true
+
+ struct = Struct.new(:arg, keyword_init: "")
+ struct.keyword_init?.should == true
+
+ struct = Struct.new(:arg, keyword_init: [])
+ struct.keyword_init?.should == true
+
+ struct = Struct.new(:arg, keyword_init: {})
+ struct.keyword_init?.should == true
+ end
+
+ context "class inheriting Struct" do
+ it "isn't available in a subclass" do
+ StructClasses::StructSubclass.should_not.respond_to?(:keyword_init?)
+ end
+ end
+end
diff --git a/spec/ruby/core/struct/members_spec.rb b/spec/ruby/core/struct/members_spec.rb
index 1f2ff950d9..1ff7b9387a 100644
--- a/spec/ruby/core/struct/members_spec.rb
+++ b/spec/ruby/core/struct/members_spec.rb
@@ -11,3 +11,15 @@ describe "Struct#members" do
it_behaves_like :struct_accessor, :members
end
+
+describe "StructClass#members" do
+ it "returns an array of attribute names" do
+ StructClasses::Car.members.should == [:make, :model, :year]
+ end
+
+ context "class inheriting Struct" do
+ it "isn't available in a subclass" do
+ StructClasses::StructSubclass.should_not.respond_to?(:members)
+ end
+ end
+end
diff --git a/spec/ruby/core/struct/new_spec.rb b/spec/ruby/core/struct/new_spec.rb
index 7b4a4f7980..b3ece2efed 100644
--- a/spec/ruby/core/struct/new_spec.rb
+++ b/spec/ruby/core/struct/new_spec.rb
@@ -6,6 +6,8 @@ describe "Struct.new" do
struct = Struct.new('Animal', :name, :legs, :eyeballs)
struct.should == Struct::Animal
struct.name.should == "Struct::Animal"
+ ensure
+ Struct.send(:remove_const, :Animal)
end
it "overwrites previously defined constants with string as first argument" do
@@ -19,6 +21,8 @@ describe "Struct.new" do
second.should == Struct::Person
first.members.should_not == second.members
+ ensure
+ Struct.send(:remove_const, :Person)
end
it "calls to_str on its first argument (constant name)" do
@@ -27,70 +31,71 @@ describe "Struct.new" do
struct = Struct.new(obj)
struct.should == Struct::Foo
struct.name.should == "Struct::Foo"
+ ensure
+ Struct.send(:remove_const, :Foo)
end
it "creates a new anonymous class with nil first argument" do
struct = Struct.new(nil, :foo)
struct.new("bar").foo.should == "bar"
- struct.should be_kind_of(Class)
- struct.name.should be_nil
+ struct.should.is_a?(Class)
+ struct.name.should == nil
end
it "creates a new anonymous class with symbol arguments" do
struct = Struct.new(:make, :model)
- struct.should be_kind_of(Class)
+ struct.should.is_a?(Class)
struct.name.should == nil
end
it "does not create a constant with symbol as first argument" do
Struct.new(:Animal2, :name, :legs, :eyeballs)
- Struct.const_defined?("Animal2").should be_false
+ Struct.const_defined?("Animal2").should == false
end
+ it "allows non-ASCII member name" do
+ name = "r\xe9sum\xe9".dup.force_encoding(Encoding::ISO_8859_1).to_sym
+ struct = Struct.new(name)
+ struct.new("foo").send(name).should == "foo"
+ end
it "fails with invalid constant name as first argument" do
- -> { Struct.new('animal', :name, :legs, :eyeballs) }.should raise_error(NameError)
+ -> { Struct.new('animal', :name, :legs, :eyeballs) }.should.raise(NameError)
end
it "raises a TypeError if object doesn't respond to to_sym" do
- -> { Struct.new(:animal, mock('giraffe')) }.should raise_error(TypeError)
- -> { Struct.new(:animal, 1.0) }.should raise_error(TypeError)
- -> { Struct.new(:animal, Time.now) }.should raise_error(TypeError)
- -> { Struct.new(:animal, Class) }.should raise_error(TypeError)
- -> { Struct.new(:animal, nil) }.should raise_error(TypeError)
- -> { Struct.new(:animal, true) }.should raise_error(TypeError)
- -> { Struct.new(:animal, ['chris', 'evan']) }.should raise_error(TypeError)
- end
-
- ruby_version_is ""..."3.2" do
- it "raises a TypeError or ArgumentError if passed a Hash with an unknown key" do
- # CRuby < 3.2 raises ArgumentError: unknown keyword: :name, but that seems a bug:
- # https://bugs.ruby-lang.org/issues/18632
- -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(StandardError) { |e|
- [ArgumentError, TypeError].should.include?(e.class)
- }
- end
+ -> { Struct.new(:animal, mock('giraffe')) }.should.raise(TypeError)
+ -> { Struct.new(:animal, 1.0) }.should.raise(TypeError)
+ -> { Struct.new(:animal, Time.now) }.should.raise(TypeError)
+ -> { Struct.new(:animal, Class) }.should.raise(TypeError)
+ -> { Struct.new(:animal, nil) }.should.raise(TypeError)
+ -> { Struct.new(:animal, true) }.should.raise(TypeError)
+ -> { Struct.new(:animal, ['chris', 'evan']) }.should.raise(TypeError)
end
- ruby_version_is "3.2" do
- it "raises a TypeError if passed a Hash with an unknown key" do
- -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError)
- end
+ it "raises a TypeError if passed a Hash with an unknown key" do
+ -> { Struct.new(:animal, { name: 'chris' }) }.should.raise(TypeError)
+ end
+
+ it "works when not provided any arguments" do
+ c = Struct.new
+ c.should.is_a?(Class)
+ c.superclass.should == Struct
end
it "raises ArgumentError when there is a duplicate member" do
- -> { Struct.new(:foo, :foo) }.should raise_error(ArgumentError, "duplicate member: foo")
+ -> { Struct.new(:foo, :foo) }.should.raise(ArgumentError, "duplicate member: foo")
end
it "raises a TypeError if object is not a Symbol" do
obj = mock(':ruby')
def obj.to_sym() :ruby end
- -> { Struct.new(:animal, obj) }.should raise_error(TypeError)
+ -> { Struct.new(:animal, obj) }.should.raise(TypeError)
end
it "processes passed block with instance_eval" do
klass = Struct.new(:something) { @something_else = 'something else entirely!' }
- klass.instance_variables.should include(:@something_else)
+ klass.instance_variables.should.include?(:@something_else)
end
context "with a block" do
@@ -111,7 +116,7 @@ describe "Struct.new" do
klass = Struct.new(:attr) do |block_parameter|
given = block_parameter
end
- klass.should equal(given)
+ klass.should.equal?(given)
end
end
@@ -119,6 +124,8 @@ describe "Struct.new" do
it "creates a constant in subclass' namespace" do
struct = StructClasses::Apple.new('Computer', :size)
struct.should == StructClasses::Apple::Computer
+ ensure
+ StructClasses::Apple.send(:remove_const, :Computer)
end
it "creates an instance" do
@@ -126,42 +133,56 @@ describe "Struct.new" do
end
it "creates reader methods" do
- StructClasses::Ruby.new.should have_method(:version)
- StructClasses::Ruby.new.should have_method(:platform)
+ StructClasses::Ruby.new.should.respond_to?(:version)
+ StructClasses::Ruby.new.should.respond_to?(:platform)
end
it "creates writer methods" do
- StructClasses::Ruby.new.should have_method(:version=)
- StructClasses::Ruby.new.should have_method(:platform=)
+ StructClasses::Ruby.new.should.respond_to?(:version=)
+ StructClasses::Ruby.new.should.respond_to?(:platform=)
end
it "fails with too many arguments" do
- -> { StructClasses::Ruby.new('2.0', 'i686', true) }.should raise_error(ArgumentError)
+ -> { StructClasses::Ruby.new('2.0', 'i686', true) }.should.raise(ArgumentError)
end
- ruby_version_is ''...'3.1' do
- it "passes a hash as a normal argument" do
- type = Struct.new(:args)
+ it "accepts keyword arguments to initialize" do
+ type = Struct.new(:args)
- obj = suppress_warning {type.new(keyword: :arg)}
- obj2 = type.new(*[{keyword: :arg}])
+ obj = type.new(args: 42)
+ obj2 = type.new(42)
- obj.should == obj2
- obj.args.should == {keyword: :arg}
- obj2.args.should == {keyword: :arg}
- end
+ obj.should == obj2
+ obj.args.should == 42
+ obj2.args.should == 42
end
- ruby_version_is '3.2' do
- it "accepts keyword arguments to initialize" do
- type = Struct.new(:args)
+ context "given positional and keyword arguments" do
+ it "treats keyword arguments as a positional parameter" do
+ type = Struct.new(:a, :b)
+ s = type.new("a", b: "b")
+ s.a.should == "a"
+ s.b.should == {b: "b"}
+
+ type = Struct.new(:a, :b, :c)
+ s = type.new("a", b: "b", c: "c")
+ s.a.should == "a"
+ s.b.should == {b: "b", c: "c"}
+ s.c.should == nil
+ end
- obj = type.new(args: 42)
- obj2 = type.new(42)
+ it "ignores empty keyword arguments" do
+ type = Struct.new(:a, :b)
+ h = {}
+ s = type.new("a", **h)
+
+ s.a.should == "a"
+ s.b.should == nil
+ end
- obj.should == obj2
- obj.args.should == 42
- obj2.args.should == 42
+ it "raises ArgumentError when all struct attribute values are specified" do
+ type = Struct.new(:a, :b)
+ -> { type.new("a", "b", c: "c") }.should.raise(ArgumentError, "struct size differs")
end
end
end
@@ -178,7 +199,7 @@ describe "Struct.new" do
end
it "raises when there is a duplicate member" do
- -> { Struct.new(:foo, :foo, keyword_init: true) }.should raise_error(ArgumentError, "duplicate member: foo")
+ -> { Struct.new(:foo, :foo, keyword_init: true) }.should.raise(ArgumentError, "duplicate member: foo")
end
describe "new class instantiation" do
@@ -191,31 +212,31 @@ describe "Struct.new" do
it "allows missing arguments" do
obj = @struct_with_kwa.new(name: "elefant")
obj.name.should == "elefant"
- obj.legs.should be_nil
+ obj.legs.should == nil
end
it "allows no arguments" do
obj = @struct_with_kwa.new
- obj.name.should be_nil
- obj.legs.should be_nil
+ obj.name.should == nil
+ obj.legs.should == nil
end
it "raises ArgumentError when passed not declared keyword argument" do
-> {
@struct_with_kwa.new(name: "elefant", legs: 4, foo: "bar")
- }.should raise_error(ArgumentError, /unknown keywords: foo/)
+ }.should.raise(ArgumentError, /unknown keywords: foo/)
end
it "raises ArgumentError when passed a list of arguments" do
-> {
@struct_with_kwa.new("elefant", 4)
- }.should raise_error(ArgumentError, /wrong number of arguments/)
+ }.should.raise(ArgumentError, /wrong number of arguments/)
end
it "raises ArgumentError when passed a single non-hash argument" do
-> {
@struct_with_kwa.new("elefant")
- }.should raise_error(ArgumentError, /wrong number of arguments/)
+ }.should.raise(ArgumentError, /wrong number of arguments/)
end
end
end
diff --git a/spec/ruby/core/struct/shared/inspect.rb b/spec/ruby/core/struct/shared/inspect.rb
index 90594a5452..1a0fb6a6b2 100644
--- a/spec/ruby/core/struct/shared/inspect.rb
+++ b/spec/ruby/core/struct/shared/inspect.rb
@@ -1,5 +1,40 @@
describe :struct_inspect, shared: true do
+ it "returns a string representation showing members and values" do
+ car = StructClasses::Car.new('Ford', 'Ranger')
+ car.send(@method).should == '#<struct StructClasses::Car make="Ford", model="Ranger", year=nil>'
+ end
+
it "returns a string representation without the class name for anonymous structs" do
Struct.new(:a).new("").send(@method).should == '#<struct a="">'
end
+
+ it "returns a string representation without the class name for structs nested in anonymous classes" do
+ c = Class.new
+ c.class_eval <<~DOC
+ class Foo < Struct.new(:a); end
+ DOC
+
+ c::Foo.new("").send(@method).should == '#<struct a="">'
+ end
+
+ it "returns a string representation without the class name for structs nested in anonymous modules" do
+ m = Module.new
+ m.module_eval <<~DOC
+ class Foo < Struct.new(:a); end
+ DOC
+
+ m::Foo.new("").send(@method).should == '#<struct a="">'
+ end
+
+ it "does not call #name method" do
+ struct = StructClasses::StructWithOverriddenName.new("")
+ struct.send(@method).should == '#<struct StructClasses::StructWithOverriddenName a="">'
+ end
+
+ it "does not call #name method when struct is anonymous" do
+ struct = Struct.new(:a)
+ def struct.name; "A"; end
+
+ struct.new("").send(@method).should == '#<struct a="">'
+ end
end
diff --git a/spec/ruby/core/struct/shared/select.rb b/spec/ruby/core/struct/shared/select.rb
index 35abee461b..dfa1a809fe 100644
--- a/spec/ruby/core/struct/shared/select.rb
+++ b/spec/ruby/core/struct/shared/select.rb
@@ -4,7 +4,7 @@ require_relative '../fixtures/classes'
describe :struct_select, shared: true do
it "raises an ArgumentError if given any non-block arguments" do
struct = StructClasses::Car.new
- -> { struct.send(@method, 1) { } }.should raise_error(ArgumentError)
+ -> { struct.send(@method, 1) { } }.should.raise(ArgumentError)
end
it "returns a new array of elements for which block is true" do
@@ -14,13 +14,13 @@ describe :struct_select, shared: true do
it "returns an instance of Array" do
struct = StructClasses::Car.new("Ford", "Escort", "1995")
- struct.send(@method) { true }.should be_an_instance_of(Array)
+ struct.send(@method) { true }.should.instance_of?(Array)
end
describe "without block" do
it "returns an instance of Enumerator" do
struct = Struct.new(:foo).new
- struct.send(@method).should be_an_instance_of(Enumerator)
+ struct.send(@method).should.instance_of?(Enumerator)
end
end
end
diff --git a/spec/ruby/core/struct/struct_spec.rb b/spec/ruby/core/struct/struct_spec.rb
index 8817dc1a58..9fab9c0629 100644
--- a/spec/ruby/core/struct/struct_spec.rb
+++ b/spec/ruby/core/struct/struct_spec.rb
@@ -21,7 +21,7 @@ describe "Struct anonymous class instance methods" do
it "reader method should not interfere with undefined methods" do
car = StructClasses::Car.new('Ford', 'Ranger')
- -> { car.something_weird }.should raise_error(NoMethodError)
+ -> { car.something_weird }.should.raise(NoMethodError)
end
it "writer method be a synonym for []=" do
@@ -33,6 +33,13 @@ describe "Struct anonymous class instance methods" do
car['model'].should == 'F150'
car[1].should == 'F150'
end
+
+ it "writer methods raise a FrozenError on a frozen struct" do
+ car = StructClasses::Car.new('Ford', 'Ranger')
+ car.freeze
+
+ -> { car.model = 'Escape' }.should.raise(FrozenError)
+ end
end
describe "Struct subclasses" do
diff --git a/spec/ruby/core/struct/to_h_spec.rb b/spec/ruby/core/struct/to_h_spec.rb
index bfb0af07ba..e0846ef268 100644
--- a/spec/ruby/core/struct/to_h_spec.rb
+++ b/spec/ruby/core/struct/to_h_spec.rb
@@ -21,20 +21,32 @@ describe "Struct#to_h" do
h.should == { "make" => "ford", "model" => "ranger", "year" => "" }
end
+ it "passes to a block each pair's key and value as separate arguments" do
+ s = StructClasses::Ruby.new('3.2.4', 'macos')
+
+ ScratchPad.record []
+ s.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
+ ScratchPad.recorded.sort.should == [[:platform, 'macos'], [:version, '3.2.4']]
+
+ ScratchPad.record []
+ s.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[:platform, 'macos'], [:version, '3.2.4']]
+ end
+
it "raises ArgumentError if block returns longer or shorter array" do
-> do
StructClasses::Car.new.to_h { |k, v| [k.to_s, "#{v}".downcase, 1] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
+ end.should.raise(ArgumentError, /element has wrong array length/)
-> do
StructClasses::Car.new.to_h { |k, v| [k] }
- end.should raise_error(ArgumentError, /element has wrong array length/)
+ end.should.raise(ArgumentError, /element has wrong array length/)
end
it "raises TypeError if block returns something other than Array" do
-> do
StructClasses::Car.new.to_h { |k, v| "not-array" }
- end.should raise_error(TypeError, /wrong element type String/)
+ end.should.raise(TypeError, /wrong element type String/)
end
it "coerces returned pair to Array with #to_ary" do
@@ -50,7 +62,7 @@ describe "Struct#to_h" do
-> do
StructClasses::Car.new.to_h { |k| x }
- end.should raise_error(TypeError, /wrong element type MockObject/)
+ end.should.raise(TypeError, /wrong element type MockObject/)
end
end
end
diff --git a/spec/ruby/core/struct/values_at_spec.rb b/spec/ruby/core/struct/values_at_spec.rb
index e7d287cba2..6aac5d96b3 100644
--- a/spec/ruby/core/struct/values_at_spec.rb
+++ b/spec/ruby/core/struct/values_at_spec.rb
@@ -1,16 +1,59 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+# Should be synchronized with core/array/values_at_spec.rb
describe "Struct#values_at" do
- it "returns an array of values" do
+ before do
clazz = Struct.new(:name, :director, :year)
- movie = clazz.new('Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002)
- movie.values_at(0, 1).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park']
- movie.values_at(0..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002]
+ @movie = clazz.new('Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002)
+ end
+
+ context "when passed a list of Integers" do
+ it "returns an array containing each value given by one of integers" do
+ @movie.values_at(0, 1).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park']
+ end
+
+ it "raises IndexError if any of integers is out of range" do
+ -> { @movie.values_at(3) }.should.raise(IndexError, "offset 3 too large for struct(size:3)")
+ -> { @movie.values_at(-4) }.should.raise(IndexError, "offset -4 too small for struct(size:3)")
+ end
+ end
+
+ context "when passed an integer Range" do
+ it "returns an array containing each value given by the elements of the range" do
+ @movie.values_at(0..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002]
+ end
+
+ it "fills with nil values for range elements larger than the structure" do
+ @movie.values_at(0..3).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, nil]
+ end
+
+ it "raises RangeError if any element of the range is negative and out of range" do
+ -> { @movie.values_at(-4..3) }.should.raise(RangeError, "-4..3 out of range")
+ end
+
+ it "supports endless Range" do
+ @movie.values_at(0..).should == ["Sympathy for Mr. Vengeance", "Chan-wook Park", 2002]
+ end
+
+ it "supports beginningless Range" do
+ @movie.values_at(..2).should == ["Sympathy for Mr. Vengeance", "Chan-wook Park", 2002]
+ end
+ end
+
+ it "supports multiple integer Ranges" do
+ @movie.values_at(0..2, 1..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, 'Chan-wook Park', 2002]
+ end
+
+ it "supports mixing integer Ranges and Integers" do
+ @movie.values_at(0..2, 2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, 2002]
+ end
+
+ it "returns a new empty Array if no arguments given" do
+ @movie.values_at().should == []
end
it "fails when passed unsupported types" do
- car = StructClasses::Car.new('Ford', 'Ranger')
- -> { car.values_at('make') }.should raise_error(TypeError)
+ -> { @movie.values_at('make') }.should.raise(TypeError, "no implicit conversion of String into Integer")
end
end
diff --git a/spec/ruby/core/symbol/all_symbols_spec.rb b/spec/ruby/core/symbol/all_symbols_spec.rb
index 1e21809093..689f6211de 100644
--- a/spec/ruby/core/symbol/all_symbols_spec.rb
+++ b/spec/ruby/core/symbol/all_symbols_spec.rb
@@ -3,17 +3,17 @@ require_relative '../../spec_helper'
describe "Symbol.all_symbols" do
it "returns an array of Symbols" do
all_symbols = Symbol.all_symbols
- all_symbols.should be_an_instance_of(Array)
- all_symbols.each { |s| s.should be_an_instance_of(Symbol) }
+ all_symbols.should.instance_of?(Array)
+ all_symbols.each { |s| s.should.instance_of?(Symbol) }
end
it "includes symbols that are strongly referenced" do
symbol = "symbol_specs_#{rand(5_000_000)}".to_sym
- Symbol.all_symbols.should include(symbol)
+ Symbol.all_symbols.should.include?(symbol)
end
it "includes symbols that are referenced in source code but not yet executed" do
- Symbol.all_symbols.any? { |s| s.to_s == 'symbol_specs_referenced_in_source_code' }.should be_true
+ Symbol.all_symbols.any? { |s| s.to_s == 'symbol_specs_referenced_in_source_code' }.should == true
:symbol_specs_referenced_in_source_code
end
end
diff --git a/spec/ruby/core/symbol/capitalize_spec.rb b/spec/ruby/core/symbol/capitalize_spec.rb
index a84bcf280a..a93d951e6a 100644
--- a/spec/ruby/core/symbol/capitalize_spec.rb
+++ b/spec/ruby/core/symbol/capitalize_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Symbol#capitalize" do
it "returns a Symbol" do
- :glark.capitalize.should be_an_instance_of(Symbol)
+ :glark.capitalize.should.instance_of?(Symbol)
end
it "converts the first character to uppercase if it is ASCII" do
diff --git a/spec/ruby/core/symbol/casecmp_spec.rb b/spec/ruby/core/symbol/casecmp_spec.rb
index 80ea51e910..dcb77a8350 100644
--- a/spec/ruby/core/symbol/casecmp_spec.rb
+++ b/spec/ruby/core/symbol/casecmp_spec.rb
@@ -56,20 +56,24 @@ describe "Symbol#casecmp with Symbol" do
lower_a_tilde.casecmp(upper_a_tilde).should == 1
lower_a_umlaut.casecmp(upper_a_umlaut).should == 1
end
+
+ it "returns 0 for empty strings in different encodings" do
+ ''.to_sym.casecmp(''.encode("UTF-32LE").to_sym).should == 0
+ end
end
describe "Symbol#casecmp" do
it "returns nil if other is a String" do
- :abc.casecmp("abc").should be_nil
+ :abc.casecmp("abc").should == nil
end
it "returns nil if other is an Integer" do
- :abc.casecmp(1).should be_nil
+ :abc.casecmp(1).should == nil
end
it "returns nil if other is an object" do
obj = mock("string <=>")
- :abc.casecmp(obj).should be_nil
+ :abc.casecmp(obj).should == nil
end
end
@@ -141,4 +145,8 @@ describe 'Symbol#casecmp?' do
upper_a_tilde.casecmp?(lower_a_tilde).should == nil
lower_a_tilde.casecmp?(upper_a_tilde).should == nil
end
+
+ it "returns true for empty symbols in different encodings" do
+ ''.to_sym.should.casecmp?(''.encode("UTF-32LE").to_sym)
+ end
end
diff --git a/spec/ruby/core/symbol/comparison_spec.rb b/spec/ruby/core/symbol/comparison_spec.rb
index 613177be05..6d56176e97 100644
--- a/spec/ruby/core/symbol/comparison_spec.rb
+++ b/spec/ruby/core/symbol/comparison_spec.rb
@@ -37,15 +37,15 @@ end
describe "Symbol#<=>" do
it "returns nil if other is a String" do
- (:abc <=> "abc").should be_nil
+ (:abc <=> "abc").should == nil
end
it "returns nil if other is an Integer" do
- (:abc <=> 1).should be_nil
+ (:abc <=> 1).should == nil
end
it "returns nil if other is an object" do
obj = mock("string <=>")
- (:abc <=> obj).should be_nil
+ (:abc <=> obj).should == nil
end
end
diff --git a/spec/ruby/core/symbol/downcase_spec.rb b/spec/ruby/core/symbol/downcase_spec.rb
index 7e94c669cc..76418aa9da 100644
--- a/spec/ruby/core/symbol/downcase_spec.rb
+++ b/spec/ruby/core/symbol/downcase_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Symbol#downcase" do
it "returns a Symbol" do
- :glark.downcase.should be_an_instance_of(Symbol)
+ :glark.downcase.should.instance_of?(Symbol)
end
it "converts uppercase ASCII characters to their lowercase equivalents" do
diff --git a/spec/ruby/core/symbol/dup_spec.rb b/spec/ruby/core/symbol/dup_spec.rb
index 8b35917c27..eef3078030 100644
--- a/spec/ruby/core/symbol/dup_spec.rb
+++ b/spec/ruby/core/symbol/dup_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../spec_helper'
describe "Symbol#dup" do
it "returns self" do
- :a_symbol.dup.should equal(:a_symbol)
+ :a_symbol.dup.should.equal?(:a_symbol)
end
end
diff --git a/spec/ruby/core/symbol/empty_spec.rb b/spec/ruby/core/symbol/empty_spec.rb
index 19c23cfe5f..1d90a59a5b 100644
--- a/spec/ruby/core/symbol/empty_spec.rb
+++ b/spec/ruby/core/symbol/empty_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Symbol#empty?" do
it "returns true if self is empty" do
- :"".empty?.should be_true
+ :"".empty?.should == true
end
it "returns false if self is non-empty" do
- :"a".empty?.should be_false
+ :"a".empty?.should == false
end
end
diff --git a/spec/ruby/core/symbol/inspect_spec.rb b/spec/ruby/core/symbol/inspect_spec.rb
index 58402ab261..f2269996af 100644
--- a/spec/ruby/core/symbol/inspect_spec.rb
+++ b/spec/ruby/core/symbol/inspect_spec.rb
@@ -5,6 +5,8 @@ describe "Symbol#inspect" do
fred: ":fred",
:fred? => ":fred?",
:fred! => ":fred!",
+ :BAD! => ":BAD!",
+ :_BAD! => ":_BAD!",
:$ruby => ":$ruby",
:@ruby => ":@ruby",
:@@ruby => ":@@ruby",
@@ -64,9 +66,9 @@ describe "Symbol#inspect" do
:~ => ":~",
:| => ":|",
- :"!" => [":\"!\"", ":!" ],
- :"!=" => [":\"!=\"", ":!="],
- :"!~" => [":\"!~\"", ":!~"],
+ :"!" => ":!",
+ :"!=" => ":!=",
+ :"!~" => ":!~",
:"\$" => ":\"$\"", # for justice!
:"&&" => ":\"&&\"",
:"'" => ":\"\'\"",
@@ -94,12 +96,36 @@ describe "Symbol#inspect" do
:"foo " => ":\"foo \"",
:" foo" => ":\" foo\"",
:" " => ":\" \"",
+
+ :"ê" => [":ê", ":\"\\u00EA\""],
+ :"测" => [":测", ":\"\\u6D4B\""],
+ :"🦊" => [":🦊", ":\"\\u{1F98A}\""],
}
+ expected_by_encoding = Encoding::default_external == Encoding::UTF_8 ? 0 : 1
symbols.each do |input, expected|
- expected = expected[1] if expected.is_a?(Array)
+ expected = expected[expected_by_encoding] if expected.is_a?(Array)
it "returns self as a symbol literal for #{expected}" do
input.inspect.should == expected
end
end
+
+ it "quotes BINARY symbols" do
+ sym = "foo\xA4".b.to_sym
+ sym.inspect.should == ':"foo\xA4"'
+ end
+
+ it "quotes symbols in non-ASCII-compatible encodings" do
+ Encoding.list.reject(&:ascii_compatible?).reject(&:dummy?).each do |encoding|
+ sym = "foo".encode(encoding).to_sym
+ sym.inspect.should == ':"foo"'
+ end
+ end
+
+ it "quotes and escapes symbols in dummy encodings" do
+ Encoding.list.select(&:dummy?).each do |encoding|
+ sym = "abcd".dup.force_encoding(encoding).to_sym
+ sym.inspect.should == ':"\x61\x62\x63\x64"'
+ end
+ end
end
diff --git a/spec/ruby/core/symbol/intern_spec.rb b/spec/ruby/core/symbol/intern_spec.rb
index ea04b87e8a..9d0914c7fb 100644
--- a/spec/ruby/core/symbol/intern_spec.rb
+++ b/spec/ruby/core/symbol/intern_spec.rb
@@ -6,6 +6,6 @@ describe "Symbol#intern" do
end
it "returns a Symbol" do
- :foo.intern.should be_kind_of(Symbol)
+ :foo.intern.should.is_a?(Symbol)
end
end
diff --git a/spec/ruby/core/symbol/match_spec.rb b/spec/ruby/core/symbol/match_spec.rb
index 41e058f977..7b165218c6 100644
--- a/spec/ruby/core/symbol/match_spec.rb
+++ b/spec/ruby/core/symbol/match_spec.rb
@@ -6,7 +6,7 @@ describe :symbol_match, shared: true do
end
it "returns nil if there is no match" do
- :a.send(@method, /b/).should be_nil
+ :a.send(@method, /b/).should == nil
end
it "sets the last match pseudo-variables" do
@@ -22,12 +22,12 @@ end
describe "Symbol#match" do
it "returns the MatchData" do
result = :abc.match(/b/)
- result.should be_kind_of(MatchData)
+ result.should.is_a?(MatchData)
result[0].should == 'b'
end
it "returns nil if there is no match" do
- :a.match(/b/).should be_nil
+ :a.match(/b/).should == nil
end
it "sets the last match pseudo-variables" do
@@ -38,7 +38,7 @@ describe "Symbol#match" do
describe "when passed a block" do
it "yields the MatchData" do
:abc.match(/./) {|m| ScratchPad.record m }
- ScratchPad.recorded.should be_kind_of(MatchData)
+ ScratchPad.recorded.should.is_a?(MatchData)
end
it "returns the block result" do
@@ -61,17 +61,17 @@ describe "Symbol#match?" do
context "when matches the given regex" do
it "returns true but does not set Regexp.last_match" do
- :string.match?(/string/i).should be_true
- Regexp.last_match.should be_nil
+ :string.match?(/string/i).should == true
+ Regexp.last_match.should == nil
end
end
it "returns false when does not match the given regex" do
- :string.match?(/STRING/).should be_false
+ :string.match?(/STRING/).should == false
end
it "takes matching position as the 2nd argument" do
- :string.match?(/str/i, 0).should be_true
- :string.match?(/str/i, 1).should be_false
+ :string.match?(/str/i, 0).should == true
+ :string.match?(/str/i, 1).should == false
end
end
diff --git a/spec/ruby/core/symbol/name_spec.rb b/spec/ruby/core/symbol/name_spec.rb
index 15b9aa75e9..f9b631266c 100644
--- a/spec/ruby/core/symbol/name_spec.rb
+++ b/spec/ruby/core/symbol/name_spec.rb
@@ -1,19 +1,17 @@
require_relative '../../spec_helper'
-ruby_version_is "3.0" do
- describe "Symbol#name" do
- it "returns string" do
- :ruby.name.should == "ruby"
- :ルビー.name.should == "ルビー"
- end
+describe "Symbol#name" do
+ it "returns string" do
+ :ruby.name.should == "ruby"
+ :ルビー.name.should == "ルビー"
+ end
- it "returns same string instance" do
- :"ruby_3".name.should.equal?(:ruby_3.name)
- :"ruby_#{1+2}".name.should.equal?(:ruby_3.name)
- end
+ it "returns same string instance" do
+ :"ruby_3".name.should.equal?(:ruby_3.name)
+ :"ruby_#{1+2}".name.should.equal?(:ruby_3.name)
+ end
- it "returns frozen string" do
- :symbol.name.should.frozen?
- end
+ it "returns frozen string" do
+ :symbol.name.should.frozen?
end
end
diff --git a/spec/ruby/core/symbol/shared/id2name.rb b/spec/ruby/core/symbol/shared/id2name.rb
index 47f97bd332..00a9c7d7dc 100644
--- a/spec/ruby/core/symbol/shared/id2name.rb
+++ b/spec/ruby/core/symbol/shared/id2name.rb
@@ -6,4 +6,25 @@ describe :symbol_id2name, shared: true do
:@ruby.send(@method).should == "@ruby"
:@@ruby.send(@method).should == "@@ruby"
end
+
+ it "returns a String in the same encoding as self" do
+ string = "ruby".encode("US-ASCII")
+ symbol = string.to_sym
+
+ symbol.send(@method).encoding.should == Encoding::US_ASCII
+ end
+
+ ruby_version_is "3.4" do
+ it "warns about mutating returned string" do
+ -> { :bad!.send(@method).upcase! }.should complain(/warning: string returned by :bad!.to_s will be frozen in the future/)
+ end
+
+ it "does not warn about mutation when Warning[:deprecated] is false" do
+ deprecated = Warning[:deprecated]
+ Warning[:deprecated] = false
+ -> { :bad!.send(@method).upcase! }.should_not complain
+ ensure
+ Warning[:deprecated] = deprecated
+ end
+ end
end
diff --git a/spec/ruby/core/symbol/shared/slice.rb b/spec/ruby/core/symbol/shared/slice.rb
index 0df87e183d..4e3a35240c 100644
--- a/spec/ruby/core/symbol/shared/slice.rb
+++ b/spec/ruby/core/symbol/shared/slice.rb
@@ -7,11 +7,11 @@ describe :symbol_slice, shared: true do
end
it "returns nil if the index starts from the end and is greater than the length" do
- :symbol.send(@method, -10).should be_nil
+ :symbol.send(@method, -10).should == nil
end
it "returns nil if the index is greater than the length" do
- :symbol.send(@method, 42).should be_nil
+ :symbol.send(@method, 42).should == nil
end
end
@@ -31,14 +31,14 @@ describe :symbol_slice, shared: true do
end
it "returns nil if the index is greater than the length" do
- :symbol.send(@method, 10,1).should be_nil
+ :symbol.send(@method, 10,1).should == nil
end
end
describe "and a positive index and negative length" do
it "returns nil" do
- :symbol.send(@method, 0,-1).should be_nil
- :symbol.send(@method, 1,-1).should be_nil
+ :symbol.send(@method, 0,-1).should == nil
+ :symbol.send(@method, 1,-1).should == nil
end
end
@@ -56,13 +56,13 @@ describe :symbol_slice, shared: true do
end
it "returns nil if the index is past the start" do
- :symbol.send(@method, -10,1).should be_nil
+ :symbol.send(@method, -10,1).should == nil
end
end
describe "and a negative index and negative length" do
it "returns nil" do
- :symbol.send(@method, -1,-1).should be_nil
+ :symbol.send(@method, -1,-1).should == nil
end
end
@@ -74,21 +74,21 @@ describe :symbol_slice, shared: true do
describe "and a nil length" do
it "raises a TypeError" do
- -> { :symbol.send(@method, 1,nil) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, 1,nil) }.should.raise(TypeError)
end
end
describe "and a length that cannot be converted into an Integer" do
it "raises a TypeError when given an Array" do
- -> { :symbol.send(@method, 1,Array.new) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, 1,Array.new) }.should.raise(TypeError)
end
it "raises a TypeError when given an Hash" do
- -> { :symbol.send(@method, 1,Hash.new) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, 1,Hash.new) }.should.raise(TypeError)
end
it "raises a TypeError when given an Object" do
- -> { :symbol.send(@method, 1,Object.new) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, 1,Object.new) }.should.raise(TypeError)
end
end
end
@@ -101,21 +101,21 @@ describe :symbol_slice, shared: true do
describe "with a nil index" do
it "raises a TypeError" do
- -> { :symbol.send(@method, nil) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, nil) }.should.raise(TypeError)
end
end
describe "with an index that cannot be converted into an Integer" do
it "raises a TypeError when given an Array" do
- -> { :symbol.send(@method, Array.new) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, Array.new) }.should.raise(TypeError)
end
it "raises a TypeError when given an Hash" do
- -> { :symbol.send(@method, Hash.new) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, Hash.new) }.should.raise(TypeError)
end
it "raises a TypeError when given an Object" do
- -> { :symbol.send(@method, Object.new) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, Object.new) }.should.raise(TypeError)
end
end
@@ -136,7 +136,7 @@ describe :symbol_slice, shared: true do
describe "that is out of bounds" do
it "returns nil if the first range value begins past the end" do
- :symbol.send(@method, 10..12).should be_nil
+ :symbol.send(@method, 10..12).should == nil
end
it "returns a blank string if the first range value is within bounds and the last range value is not" do
@@ -145,11 +145,11 @@ describe :symbol_slice, shared: true do
end
it "returns nil if the first range value starts from the end and is within bounds and the last value starts from the end and is greater than the length" do
- :symbol.send(@method, -10..-12).should be_nil
+ :symbol.send(@method, -10..-12).should == nil
end
it "returns nil if the first range value starts from the end and is out of bounds and the last value starts from the end and is less than the length" do
- :symbol.send(@method, -10..-2).should be_nil
+ :symbol.send(@method, -10..-2).should == nil
end
end
@@ -178,7 +178,7 @@ describe :symbol_slice, shared: true do
end
it "returns nil if the expression does not match" do
- :symbol.send(@method, /0-9/).should be_nil
+ :symbol.send(@method, /0-9/).should == nil
end
it "sets $~ to the MatchData if there is a match" do
@@ -188,7 +188,7 @@ describe :symbol_slice, shared: true do
it "does not set $~ if there if there is not a match" do
:symbol.send(@method, /[0-9]+/)
- $~.should be_nil
+ $~.should == nil
end
end
@@ -203,8 +203,8 @@ describe :symbol_slice, shared: true do
end
it "returns nil if there is no capture for the index" do
- :symbol.send(@method, /(sy)(mb)(ol)/, 4).should be_nil
- :symbol.send(@method, /(sy)(mb)(ol)/, -4).should be_nil
+ :symbol.send(@method, /(sy)(mb)(ol)/, 4).should == nil
+ :symbol.send(@method, /(sy)(mb)(ol)/, -4).should == nil
end
it "converts the index to an Integer" do
@@ -213,20 +213,20 @@ describe :symbol_slice, shared: true do
describe "and an index that cannot be converted to an Integer" do
it "raises a TypeError when given an Hash" do
- -> { :symbol.send(@method, /(sy)(mb)(ol)/, Hash.new) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, /(sy)(mb)(ol)/, Hash.new) }.should.raise(TypeError)
end
it "raises a TypeError when given an Array" do
- -> { :symbol.send(@method, /(sy)(mb)(ol)/, Array.new) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, /(sy)(mb)(ol)/, Array.new) }.should.raise(TypeError)
end
it "raises a TypeError when given an Object" do
- -> { :symbol.send(@method, /(sy)(mb)(ol)/, Object.new) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, /(sy)(mb)(ol)/, Object.new) }.should.raise(TypeError)
end
end
it "raises a TypeError if the index is nil" do
- -> { :symbol.send(@method, /(sy)(mb)(ol)/, nil) }.should raise_error(TypeError)
+ -> { :symbol.send(@method, /(sy)(mb)(ol)/, nil) }.should.raise(TypeError)
end
it "sets $~ to the MatchData if there is a match" do
@@ -239,7 +239,7 @@ describe :symbol_slice, shared: true do
it "does not set $~ to the MatchData if there is not a match" do
:symbol.send(@method, /0-9/, 0)
- $~.should be_nil
+ $~.should == nil
end
end
end
@@ -248,7 +248,7 @@ describe :symbol_slice, shared: true do
it "does not set $~" do
$~ = nil
:symbol.send(@method, "sym")
- $~.should be_nil
+ $~.should == nil
end
it "returns a string if there is match" do
@@ -256,7 +256,7 @@ describe :symbol_slice, shared: true do
end
it "returns nil if there is not a match" do
- :symbol.send(@method, "foo").should be_nil
+ :symbol.send(@method, "foo").should == nil
end
end
end
diff --git a/spec/ruby/core/symbol/swapcase_spec.rb b/spec/ruby/core/symbol/swapcase_spec.rb
index 24709cac30..95fc29e32b 100644
--- a/spec/ruby/core/symbol/swapcase_spec.rb
+++ b/spec/ruby/core/symbol/swapcase_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Symbol#swapcase" do
it "returns a Symbol" do
- :glark.swapcase.should be_an_instance_of(Symbol)
+ :glark.swapcase.should.instance_of?(Symbol)
end
it "converts lowercase ASCII characters to their uppercase equivalents" do
diff --git a/spec/ruby/core/symbol/symbol_spec.rb b/spec/ruby/core/symbol/symbol_spec.rb
index cefe70bc99..3534686a08 100644
--- a/spec/ruby/core/symbol/symbol_spec.rb
+++ b/spec/ruby/core/symbol/symbol_spec.rb
@@ -8,12 +8,12 @@ describe "Symbol" do
it ".allocate raises a TypeError" do
-> do
Symbol.allocate
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it ".new is undefined" do
-> do
Symbol.new
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
end
diff --git a/spec/ruby/core/symbol/to_proc_spec.rb b/spec/ruby/core/symbol/to_proc_spec.rb
index 47f2a939ab..93ed1e9e9b 100644
--- a/spec/ruby/core/symbol/to_proc_spec.rb
+++ b/spec/ruby/core/symbol/to_proc_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Symbol#to_proc" do
it "returns a new Proc" do
proc = :to_s.to_proc
- proc.should be_kind_of(Proc)
+ proc.should.is_a?(Proc)
end
it "sends self to arguments passed when calling #call on the Proc" do
@@ -12,44 +12,50 @@ describe "Symbol#to_proc" do
:to_s.to_proc.call(obj).should == "Received #to_s"
end
- ruby_version_is ""..."3.0" do
- it "returns a Proc with #lambda? false" do
- pr = :to_s.to_proc
- pr.should_not.lambda?
- end
+ it "returns a Proc with #lambda? true" do
+ pr = :to_s.to_proc
+ pr.should.lambda?
+ end
- it "produces a Proc with arity -1" do
- pr = :to_s.to_proc
- pr.arity.should == -1
- end
+ it "produces a Proc with arity -2" do
+ pr = :to_s.to_proc
+ pr.arity.should == -2
+ end
- it "produces a Proc that always returns [[:rest]] for #parameters" do
- pr = :to_s.to_proc
- pr.parameters.should == [[:rest]]
- end
+ it "produces a Proc that always returns [[:req], [:rest]] for #parameters" do
+ pr = :to_s.to_proc
+ pr.parameters.should == [[:req], [:rest]]
end
- ruby_version_is "3.0" do
- it "returns a Proc with #lambda? true" do
- pr = :to_s.to_proc
- pr.should.lambda?
+ it "only calls public methods" do
+ body = proc do
+ public def pub; @a << :pub end
+ protected def pro; @a << :pro end
+ private def pri; @a << :pri end
+ attr_reader :a
end
- it "produces a Proc with arity -2" do
- pr = :to_s.to_proc
- pr.arity.should == -2
- end
+ @a = []
+ singleton_class.class_eval(&body)
+ tap(&:pub)
+ proc{tap(&:pro)}.should.raise(NoMethodError, /protected method [`']pro' called/)
+ proc{tap(&:pri)}.should.raise(NoMethodError, /private method [`']pri' called/)
+ @a.should == [:pub]
- it "produces a Proc that always returns [[:req], [:rest]] for #parameters" do
- pr = :to_s.to_proc
- pr.parameters.should == [[:req], [:rest]]
- end
+ @a = []
+ c = Class.new(&body)
+ o = c.new
+ o.instance_variable_set(:@a, [])
+ o.tap(&:pub)
+ proc{tap(&:pro)}.should.raise(NoMethodError, /protected method [`']pro' called/)
+ proc{o.tap(&:pri)}.should.raise(NoMethodError, /private method [`']pri' called/)
+ o.a.should == [:pub]
end
it "raises an ArgumentError when calling #call on the Proc without receiver" do
-> {
:object_id.to_proc.call
- }.should raise_error(ArgumentError, /no receiver given|wrong number of arguments \(given 0, expected 1\+\)/)
+ }.should.raise(ArgumentError, /no receiver given|wrong number of arguments \(given 0, expected 1\+\)/)
end
it "passes along the block passed to Proc#call" do
diff --git a/spec/ruby/core/symbol/upcase_spec.rb b/spec/ruby/core/symbol/upcase_spec.rb
index f704bdcbf3..3895d95efb 100644
--- a/spec/ruby/core/symbol/upcase_spec.rb
+++ b/spec/ruby/core/symbol/upcase_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Symbol#upcase" do
it "returns a Symbol" do
- :glark.upcase.should be_an_instance_of(Symbol)
+ :glark.upcase.should.instance_of?(Symbol)
end
it "converts lowercase ASCII characters to their uppercase equivalents" do
diff --git a/spec/ruby/core/thread/abort_on_exception_spec.rb b/spec/ruby/core/thread/abort_on_exception_spec.rb
index 34b648ca0f..aeca50e5c1 100644
--- a/spec/ruby/core/thread/abort_on_exception_spec.rb
+++ b/spec/ruby/core/thread/abort_on_exception_spec.rb
@@ -13,12 +13,12 @@ describe "Thread#abort_on_exception" do
end
it "is false by default" do
- @thread.abort_on_exception.should be_false
+ @thread.abort_on_exception.should == false
end
it "returns true when #abort_on_exception= is passed true" do
@thread.abort_on_exception = true
- @thread.abort_on_exception.should be_true
+ @thread.abort_on_exception.should == true
end
end
@@ -39,7 +39,7 @@ describe :thread_abort_on_exception, shared: true do
ThreadSpecs.state = :run
# Wait for the main thread to be interrupted
sleep
- end.should raise_error(RuntimeError, "Thread#abort_on_exception= specs")
+ end.should.raise(RuntimeError, "Thread#abort_on_exception= specs")
ScratchPad << :after
rescue Exception => e
@@ -72,7 +72,7 @@ describe "Thread.abort_on_exception" do
end
after do
- Thread.abort_on_exception = @abort_on_exception
+ Thread.abort_on_exception = @abort_on_exception
end
it "is false by default" do
@@ -81,7 +81,7 @@ describe "Thread.abort_on_exception" do
it "returns true when .abort_on_exception= is passed true" do
Thread.abort_on_exception = true
- Thread.abort_on_exception.should be_true
+ Thread.abort_on_exception.should == true
end
end
diff --git a/spec/ruby/core/thread/allocate_spec.rb b/spec/ruby/core/thread/allocate_spec.rb
index cfd556812f..0b4e4f1b1f 100644
--- a/spec/ruby/core/thread/allocate_spec.rb
+++ b/spec/ruby/core/thread/allocate_spec.rb
@@ -4,6 +4,6 @@ describe "Thread.allocate" do
it "raises a TypeError" do
-> {
Thread.allocate
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/thread/backtrace/limit_spec.rb b/spec/ruby/core/thread/backtrace/limit_spec.rb
new file mode 100644
index 0000000000..b55ca67ea0
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/limit_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../../spec_helper'
+
+describe "Thread::Backtrace.limit" do
+ it "returns maximum backtrace length set by --backtrace-limit command-line option" do
+ out = ruby_exe("print Thread::Backtrace.limit", options: "--backtrace-limit=2")
+ out.should == "2"
+ end
+
+ it "returns -1 when --backtrace-limit command-line option is not set" do
+ out = ruby_exe("print Thread::Backtrace.limit")
+ out.should == "-1"
+ end
+end
diff --git a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
index 4136f09348..6d9482f2ae 100644
--- a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
@@ -17,21 +17,21 @@ describe 'Thread::Backtrace::Location#absolute_path' do
end
end
- context "when used in eval with a given filename" do
- code = "caller_locations(0)[0].absolute_path"
-
- ruby_version_is ""..."3.1" do
- it "returns filename with absolute_path" do
- eval(code, nil, "foo.rb").should == "foo.rb"
- eval(code, nil, "foo/bar.rb").should == "foo/bar.rb"
- end
+ it 'returns the correct absolute path when using a relative main script path and changing CWD' do
+ script = fixture(__FILE__, 'subdir/absolute_path_main_chdir.rb')
+ sibling = fixture(__FILE__, 'subdir/sibling.rb')
+ subdir = File.dirname script
+ Dir.chdir(fixture(__FILE__)) do
+ ruby_exe('subdir/absolute_path_main_chdir.rb').should == "subdir/absolute_path_main_chdir.rb\n#{subdir}\n#{subdir}\n#{script}\n#{sibling}\n"
end
+ end
- ruby_version_is "3.1" do
- it "returns nil with absolute_path" do
- eval(code, nil, "foo.rb").should == nil
- eval(code, nil, "foo/bar.rb").should == nil
- end
+ context "when used in eval with a given filename" do
+ it "returns nil with absolute_path" do
+ code = "caller_locations(0)[0].absolute_path"
+
+ eval(code, nil, "foo.rb").should == nil
+ eval(code, nil, "foo/bar.rb").should == nil
end
end
@@ -42,7 +42,7 @@ describe 'Thread::Backtrace::Location#absolute_path' do
locations = ScratchPad.recorded
locations[0].absolute_path.should == path
# Make sure it's from the class body, not from the file top-level
- locations[0].label.should include 'MethodAddedAbsolutePath'
+ locations[0].label.should.include? 'MethodAddedAbsolutePath'
end
end
@@ -50,7 +50,7 @@ describe 'Thread::Backtrace::Location#absolute_path' do
it "returns nil" do
location = nil
tap { location = caller_locations(1, 1)[0] }
- location.label.should == "tap"
+ location.label.should =~ /\A(?:Kernel#)?tap\z/
if location.path.start_with?("<internal:")
location.absolute_path.should == nil
else
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/classes.rb b/spec/ruby/core/thread/backtrace/location/fixtures/classes.rb
index e903c3e450..103c36b3a0 100644
--- a/spec/ruby/core/thread/backtrace/location/fixtures/classes.rb
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/classes.rb
@@ -1,10 +1,26 @@
+# These are top-level def on purpose to test those cases
+
+def label_top_method = ThreadBacktraceLocationSpecs::LABEL.call
+
+def self.label_sdef_method_of_main = ThreadBacktraceLocationSpecs::LABEL.call
+
+class << self
+ def label_sclass_method_of_main = ThreadBacktraceLocationSpecs::LABEL.call
+end
+
module ThreadBacktraceLocationSpecs
MODULE_LOCATION = caller_locations(0) rescue nil
+ INSTANCE = Object.new.extend(self)
+ LABEL = -> { caller_locations(1, 1)[0].label }
def self.locations
caller_locations
end
+ def instance_method_location
+ caller_locations(0)
+ end
+
def self.method_location
caller_locations(0)
end
@@ -15,6 +31,12 @@ module ThreadBacktraceLocationSpecs
end
end
+ def instance_block_location
+ 1.times do
+ return caller_locations(0)
+ end
+ end
+
def self.locations_inside_nested_blocks
first_level_location = nil
second_level_location = nil
@@ -32,4 +54,86 @@ module ThreadBacktraceLocationSpecs
[first_level_location, second_level_location, third_level_location]
end
+
+ def instance_locations_inside_nested_block
+ loc = nil
+ 1.times do
+ 1.times do
+ loc = caller_locations(0)
+ end
+ end
+ loc
+ end
+
+ def original_method = LABEL.call
+ alias_method :aliased_method, :original_method
+
+ module M
+ class C
+ def regular_instance_method = LABEL.call
+
+ def self.sdef_class_method = LABEL.call
+
+ class << self
+ def sclass_method = LABEL.call
+
+ def block_in_sclass_method
+ -> {
+ -> { LABEL.call }.call
+ }.call
+ end
+ end
+ block_in_sclass_method
+ end
+ end
+
+ class M::D
+ def scoped_method = LABEL.call
+
+ def self.sdef_scoped_method = LABEL.call
+
+ class << self
+ def sclass_scoped_method = LABEL.call
+ end
+
+ module ::ThreadBacktraceLocationSpecs
+ def top = LABEL.call
+ end
+
+ class ::ThreadBacktraceLocationSpecs::Nested
+ def top_nested = LABEL.call
+
+ class C
+ def top_nested_c = LABEL.call
+ end
+ end
+ end
+
+ SOME_OBJECT = Object.new
+ SOME_OBJECT.instance_exec do
+ def unknown_def_singleton_method = LABEL.call
+
+ def self.unknown_sdef_singleton_method = LABEL.call
+ end
+
+ M.module_eval do
+ def module_eval_method = LABEL.call
+
+ def self.sdef_module_eval_method = LABEL.call
+ end
+
+ def ThreadBacktraceLocationSpecs.string_class_method = LABEL.call
+
+ module M
+ def ThreadBacktraceLocationSpecs.nested_class_method = LABEL.call
+ end
+
+ module M
+ module_function def mod_function = LABEL.call
+ end
+
+ expr = self
+ def expr.sdef_expression = LABEL.call
+
+ def expr.block_in_sdef_expression = -> { LABEL.call }.call
end
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb
new file mode 100644
index 0000000000..33c8fb36ef
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb
@@ -0,0 +1,11 @@
+puts __FILE__
+puts __dir__
+Dir.chdir __dir__
+
+# Check __dir__ is still correct after chdir
+puts __dir__
+
+puts caller_locations(0)[0].absolute_path
+
+# require_relative also needs to know the absolute path of the current file so we test it here too
+require_relative 'sibling'
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb
new file mode 100644
index 0000000000..2a854ddccd
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb
@@ -0,0 +1 @@
+puts __FILE__
diff --git a/spec/ruby/core/thread/backtrace/location/inspect_spec.rb b/spec/ruby/core/thread/backtrace/location/inspect_spec.rb
index 20e477a5a6..4df88a2f33 100644
--- a/spec/ruby/core/thread/backtrace/location/inspect_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/inspect_spec.rb
@@ -8,6 +8,6 @@ describe 'Thread::Backtrace::Location#inspect' do
end
it 'converts the call frame to a String' do
- @frame.inspect.should include("#{__FILE__}:#{@line}:in ")
+ @frame.inspect.should.include?("#{__FILE__}:#{@line}:in ")
end
end
diff --git a/spec/ruby/core/thread/backtrace/location/label_spec.rb b/spec/ruby/core/thread/backtrace/location/label_spec.rb
index 7312d017e5..5f6a7b73df 100644
--- a/spec/ruby/core/thread/backtrace/location/label_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/label_spec.rb
@@ -3,28 +3,28 @@ require_relative 'fixtures/classes'
describe 'Thread::Backtrace::Location#label' do
it 'returns the base label of the call frame' do
- ThreadBacktraceLocationSpecs.locations[0].label.should include('<top (required)>')
+ ThreadBacktraceLocationSpecs.locations[0].label.should.include?('<top (required)>')
end
it 'returns the method name for a method location' do
- ThreadBacktraceLocationSpecs.method_location[0].label.should == "method_location"
+ ThreadBacktraceLocationSpecs.method_location[0].label.should =~ /\A(?:ThreadBacktraceLocationSpecs\.)?method_location\z/
end
it 'returns the block name for a block location' do
- ThreadBacktraceLocationSpecs.block_location[0].label.should == "block in block_location"
+ ThreadBacktraceLocationSpecs.block_location[0].label.should =~ /\Ablock in (?:ThreadBacktraceLocationSpecs\.)?block_location\z/
end
it 'returns the module name for a module location' do
- ThreadBacktraceLocationSpecs::MODULE_LOCATION[0].label.should include "ThreadBacktraceLocationSpecs"
+ ThreadBacktraceLocationSpecs::MODULE_LOCATION[0].label.should == "<module:ThreadBacktraceLocationSpecs>"
end
it 'includes the nesting level of a block as part of the location label' do
first_level_location, second_level_location, third_level_location =
ThreadBacktraceLocationSpecs.locations_inside_nested_blocks
- first_level_location.label.should == 'block in locations_inside_nested_blocks'
- second_level_location.label.should == 'block (2 levels) in locations_inside_nested_blocks'
- third_level_location.label.should == 'block (3 levels) in locations_inside_nested_blocks'
+ first_level_location.label.should =~ /\Ablock in (?:ThreadBacktraceLocationSpecs\.)?locations_inside_nested_blocks\z/
+ second_level_location.label.should =~ /\Ablock \(2 levels\) in (?:ThreadBacktraceLocationSpecs\.)?locations_inside_nested_blocks\z/
+ third_level_location.label.should =~ /\Ablock \(3 levels\) in (?:ThreadBacktraceLocationSpecs\.)?locations_inside_nested_blocks\z/
end
it 'sets the location label for a top-level block differently depending on it being in the main file or a required file' do
@@ -34,4 +34,194 @@ describe 'Thread::Backtrace::Location#label' do
main_label.should == "block in <main>\n"
required_label.should == "block in <top (required)>\n"
end
+
+ it "return the same name as the caller for eval" do
+ this = caller_locations(0)[0].label
+ eval("caller_locations(0)[0]").label.should == this
+
+ b = binding
+ b.eval("caller_locations(0)[0]").label.should == this
+
+ b.local_variable_set(:binding_var1, 1)
+ b.eval("caller_locations(0)[0]").label.should == this
+
+ b.local_variable_set(:binding_var2, 2)
+ b.eval("caller_locations(0)[0]").label.should == this
+
+ b.local_variable_set(:binding_var2, 2)
+ eval("caller_locations(0)[0]", b).label.should == this
+ end
+
+ ruby_version_is "3.4" do
+ describe "is Module#method for" do
+ it "a core method defined natively" do
+ BasicObject.instance_method(:instance_exec).should_not.source_location
+ loc = nil
+ loc = instance_exec { caller_locations(1, 1)[0] }
+ loc.label.should == "BasicObject#instance_exec"
+ end
+
+ it "a core method defined in Ruby" do
+ Kernel.instance_method(:tap).should.source_location
+ loc = nil
+ tap { loc = caller_locations(1, 1)[0] }
+ loc.label.should == "Kernel#tap"
+ end
+
+ it "an instance method defined in Ruby" do
+ ThreadBacktraceLocationSpecs::INSTANCE.instance_method_location[0].label.should == "ThreadBacktraceLocationSpecs#instance_method_location"
+ end
+
+ it "a block in an instance method defined in Ruby" do
+ ThreadBacktraceLocationSpecs::INSTANCE.instance_block_location[0].label.should == "block in ThreadBacktraceLocationSpecs#instance_block_location"
+ end
+
+ it "a nested block in an instance method defined in Ruby" do
+ ThreadBacktraceLocationSpecs::INSTANCE.instance_locations_inside_nested_block[0].label.should == "block (2 levels) in ThreadBacktraceLocationSpecs#instance_locations_inside_nested_block"
+ end
+
+ it "a method defined via module_exec" do
+ ThreadBacktraceLocationSpecs.module_exec do
+ def in_module_exec
+ caller_locations(0)
+ end
+ end
+ ThreadBacktraceLocationSpecs::INSTANCE.in_module_exec[0].label.should == "ThreadBacktraceLocationSpecs#in_module_exec"
+ end
+
+ it "a method defined via module_eval" do
+ ThreadBacktraceLocationSpecs.module_eval <<~RUBY
+ def in_module_eval
+ caller_locations(0)
+ end
+ RUBY
+ ThreadBacktraceLocationSpecs::INSTANCE.in_module_eval[0].label.should == "ThreadBacktraceLocationSpecs#in_module_eval"
+ end
+ end
+
+ describe "is Module.method for" do
+ it "a singleton method defined in Ruby" do
+ ThreadBacktraceLocationSpecs.method_location[0].label.should == "ThreadBacktraceLocationSpecs.method_location"
+ end
+
+ it "a block in a singleton method defined in Ruby" do
+ ThreadBacktraceLocationSpecs.block_location[0].label.should == "block in ThreadBacktraceLocationSpecs.block_location"
+ end
+
+ it "a nested block in a singleton method defined in Ruby" do
+ ThreadBacktraceLocationSpecs.locations_inside_nested_blocks[2].label.should == "block (3 levels) in ThreadBacktraceLocationSpecs.locations_inside_nested_blocks"
+ end
+
+ it "a singleton method defined via def Const.method" do
+ def ThreadBacktraceLocationSpecs.def_singleton
+ caller_locations(0)
+ end
+ ThreadBacktraceLocationSpecs.def_singleton[0].label.should == "ThreadBacktraceLocationSpecs.def_singleton"
+ end
+ end
+
+ it "shows the original method name for an aliased method" do
+ ThreadBacktraceLocationSpecs::INSTANCE.aliased_method.should == "ThreadBacktraceLocationSpecs#original_method"
+ end
+
+ # A wide variety of cases.
+ # These show interesting cases when trying to determine the name statically/at parse time
+ describe "is correct for" do
+ base = ThreadBacktraceLocationSpecs
+
+ it "M::C#regular_instance_method" do
+ base::M::C.new.regular_instance_method.should == "#{base}::M::C#regular_instance_method"
+ end
+
+ it "M::C.sdef_class_method" do
+ base::M::C.sdef_class_method.should == "#{base}::M::C.sdef_class_method"
+ end
+
+ it "M::C.sclass_method" do
+ base::M::C.sclass_method.should == "#{base}::M::C.sclass_method"
+ end
+
+ it "M::C.block_in_sclass_method" do
+ base::M::C.block_in_sclass_method.should == "block (2 levels) in #{base}::M::C.block_in_sclass_method"
+ end
+
+ it "M::D#scoped_method" do
+ base::M::D.new.scoped_method.should == "#{base}::M::D#scoped_method"
+ end
+
+ it "M::D.sdef_scoped_method" do
+ base::M::D.sdef_scoped_method.should == "#{base}::M::D.sdef_scoped_method"
+ end
+
+ it "M::D.sclass_scoped_method" do
+ base::M::D.sclass_scoped_method.should == "#{base}::M::D.sclass_scoped_method"
+ end
+
+ it "ThreadBacktraceLocationSpecs#top" do
+ ThreadBacktraceLocationSpecs::INSTANCE.top.should == "ThreadBacktraceLocationSpecs#top"
+ end
+
+ it "ThreadBacktraceLocationSpecs::Nested#top_nested" do
+ ThreadBacktraceLocationSpecs::Nested.new.top_nested.should == "ThreadBacktraceLocationSpecs::Nested#top_nested"
+ end
+
+ it "ThreadBacktraceLocationSpecs::Nested::C#top_nested_c" do
+ ThreadBacktraceLocationSpecs::Nested::C.new.top_nested_c.should == "ThreadBacktraceLocationSpecs::Nested::C#top_nested_c"
+ end
+
+ it "Object#label_top_method" do
+ label_top_method.should == "Object#label_top_method"
+ end
+
+ it "main.label_sdef_method_of_main" do
+ main = TOPLEVEL_BINDING.receiver
+ main.label_sdef_method_of_main.should == "label_sdef_method_of_main"
+ end
+
+ it "main.label_sclass_method_of_main" do
+ main = TOPLEVEL_BINDING.receiver
+ main.label_sclass_method_of_main.should == "label_sclass_method_of_main"
+ end
+
+ it "unknown_def_singleton_method" do
+ base::SOME_OBJECT.unknown_def_singleton_method.should == "unknown_def_singleton_method"
+ end
+
+ it "unknown_sdef_singleton_method" do
+ base::SOME_OBJECT.unknown_sdef_singleton_method.should == "unknown_sdef_singleton_method"
+ end
+
+ it "M#module_eval_method" do
+ Object.new.extend(base::M).module_eval_method.should == "#{base}::M#module_eval_method"
+ end
+
+ it "M.sdef_module_eval_method" do
+ base::M.sdef_module_eval_method.should == "#{base}::M.sdef_module_eval_method"
+ end
+
+ it "ThreadBacktraceLocationSpecs.string_class_method" do
+ ThreadBacktraceLocationSpecs.string_class_method.should == "ThreadBacktraceLocationSpecs.string_class_method"
+ end
+
+ it "ThreadBacktraceLocationSpecs.nested_class_method" do
+ ThreadBacktraceLocationSpecs.nested_class_method.should == "ThreadBacktraceLocationSpecs.nested_class_method"
+ end
+
+ it "M#mod_function" do
+ Object.new.extend(base::M).send(:mod_function).should == "#{base}::M#mod_function"
+ end
+
+ it "M.mod_function" do
+ base::M.mod_function.should == "#{base}::M.mod_function"
+ end
+
+ it "sdef_expression" do
+ base.sdef_expression.should == "#{base}.sdef_expression"
+ end
+
+ it "block_in_sdef_expression" do
+ base.block_in_sdef_expression.should == "block in #{base}.block_in_sdef_expression"
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/thread/backtrace/location/lineno_spec.rb b/spec/ruby/core/thread/backtrace/location/lineno_spec.rb
index d14cf17514..10457f80f0 100644
--- a/spec/ruby/core/thread/backtrace/location/lineno_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/lineno_spec.rb
@@ -7,7 +7,7 @@ describe 'Thread::Backtrace::Location#lineno' do
@line = __LINE__ - 1
end
- it 'returns the absolute path of the call frame' do
+ it 'returns the line number of the call frame' do
@frame.lineno.should == @line
end
diff --git a/spec/ruby/core/thread/backtrace/location/path_spec.rb b/spec/ruby/core/thread/backtrace/location/path_spec.rb
index 7863c055d3..75f76833a9 100644
--- a/spec/ruby/core/thread/backtrace/location/path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/path_spec.rb
@@ -41,7 +41,7 @@ describe 'Thread::Backtrace::Location#path' do
context 'when using a relative script path' do
it 'returns a path relative to the working directory' do
path = 'fixtures/main.rb'
- directory = File.dirname(__FILE__)
+ directory = __dir__
Dir.chdir(directory) {
ruby_exe(path)
}.should == path
diff --git a/spec/ruby/core/thread/backtrace/location/to_s_spec.rb b/spec/ruby/core/thread/backtrace/location/to_s_spec.rb
index 5911cdced0..983ce4c3f8 100644
--- a/spec/ruby/core/thread/backtrace/location/to_s_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/to_s_spec.rb
@@ -8,6 +8,6 @@ describe 'Thread::Backtrace::Location#to_s' do
end
it 'converts the call frame to a String' do
- @frame.to_s.should include("#{__FILE__}:#{@line}:in ")
+ @frame.to_s.should.include?("#{__FILE__}:#{@line}:in ")
end
end
diff --git a/spec/ruby/core/thread/backtrace_locations_spec.rb b/spec/ruby/core/thread/backtrace_locations_spec.rb
index c970ae023b..28a488f311 100644
--- a/spec/ruby/core/thread/backtrace_locations_spec.rb
+++ b/spec/ruby/core/thread/backtrace_locations_spec.rb
@@ -3,20 +3,20 @@ require_relative '../../spec_helper'
describe "Thread#backtrace_locations" do
it "returns an Array" do
locations = Thread.current.backtrace_locations
- locations.should be_an_instance_of(Array)
- locations.should_not be_empty
+ locations.should.instance_of?(Array)
+ locations.should_not.empty?
end
it "sets each element to a Thread::Backtrace::Location" do
locations = Thread.current.backtrace_locations
- locations.each { |loc| loc.should be_an_instance_of(Thread::Backtrace::Location) }
+ locations.each { |loc| loc.should.instance_of?(Thread::Backtrace::Location) }
end
it "can be called on any Thread" do
locations = Thread.new { Thread.current.backtrace_locations }.value
- locations.should be_an_instance_of(Array)
- locations.should_not be_empty
- locations.each { |loc| loc.should be_an_instance_of(Thread::Backtrace::Location) }
+ locations.should.instance_of?(Array)
+ locations.should_not.empty?
+ locations.each { |loc| loc.should.instance_of?(Thread::Backtrace::Location) }
end
it "can be called with a number of locations to omit" do
@@ -70,7 +70,7 @@ describe "Thread#backtrace_locations" do
end
it "the first location reports the call to #backtrace_locations" do
- Thread.current.backtrace_locations(0..0)[0].to_s.should == "#{__FILE__ }:#{__LINE__ }:in `backtrace_locations'"
+ Thread.current.backtrace_locations(0..0)[0].to_s.should =~ /\A#{__FILE__ }:#{__LINE__ }:in [`'](?:Thread#)?backtrace_locations'\z/
end
it "[1..-1] is the same as #caller_locations(0..-1) for Thread.current" do
diff --git a/spec/ruby/core/thread/backtrace_spec.rb b/spec/ruby/core/thread/backtrace_spec.rb
index 9001b1b7eb..770c300f06 100644
--- a/spec/ruby/core/thread/backtrace_spec.rb
+++ b/spec/ruby/core/thread/backtrace_spec.rb
@@ -12,8 +12,8 @@ describe "Thread#backtrace" do
Thread.pass while t.status && t.status != 'sleep'
backtrace = t.backtrace
- backtrace.should be_kind_of(Array)
- backtrace.first.should =~ /`sleep'/
+ backtrace.should.is_a?(Array)
+ backtrace.first.should =~ /[`'](?:Kernel#)?sleep'/
t.raise 'finish the thread'
t.join
@@ -30,7 +30,7 @@ describe "Thread#backtrace" do
backtrace = t.backtrace
t.kill
t.join
- backtrace.should be_kind_of(Array)
+ backtrace.should.is_a?(Array)
end
it "can be called with a number of locations to omit" do
diff --git a/spec/ruby/core/thread/current_spec.rb b/spec/ruby/core/thread/current_spec.rb
index f5ed1d95cd..f893f078ba 100644
--- a/spec/ruby/core/thread/current_spec.rb
+++ b/spec/ruby/core/thread/current_spec.rb
@@ -4,13 +4,13 @@ require_relative 'fixtures/classes'
describe "Thread.current" do
it "returns a thread" do
current = Thread.current
- current.should be_kind_of(Thread)
+ current.should.is_a?(Thread)
end
it "returns the current thread" do
t = Thread.new { Thread.current }
- t.value.should equal(t)
- Thread.current.should_not equal(t.value)
+ t.value.should.equal?(t)
+ Thread.current.should_not.equal?(t.value)
end
it "returns the correct thread in a Fiber" do
@@ -22,10 +22,10 @@ describe "Thread.current" do
cur = Thread.current
Fiber.new {
Thread.current
- }.resume.should equal cur
+ }.resume.should.equal? cur
cur
}
- t.value.should equal t
+ t.value.should.equal? t
end
end
end
diff --git a/spec/ruby/core/thread/each_caller_location_spec.rb b/spec/ruby/core/thread/each_caller_location_spec.rb
new file mode 100644
index 0000000000..15fda1a37b
--- /dev/null
+++ b/spec/ruby/core/thread/each_caller_location_spec.rb
@@ -0,0 +1,47 @@
+require_relative '../../spec_helper'
+
+describe "Thread.each_caller_location" do
+ it "iterates through the current execution stack and matches caller_locations content and type" do
+ ScratchPad.record []
+ Thread.each_caller_location { |l| ScratchPad << l; }
+
+ ScratchPad.recorded.map(&:to_s).should == caller_locations.map(&:to_s)
+ ScratchPad.recorded[0].should.is_a?(Thread::Backtrace::Location)
+ end
+
+ it "returns subset of 'Thread.to_enum(:each_caller_location)' locations" do
+ ar = []
+ ecl = Thread.each_caller_location { |x| ar << x }
+
+ (ar.map(&:to_s) - Thread.to_enum(:each_caller_location).to_a.map(&:to_s)).should.empty?
+ end
+
+ it "stops the backtrace iteration if 'break' occurs" do
+ i = 0
+ ar = []
+ ecl = Thread.each_caller_location do |x|
+ ar << x
+ i += 1
+ break x if i == 2
+ end
+
+ ar.map(&:to_s).should == caller_locations(1, 2).map(&:to_s)
+ ecl.should.is_a?(Thread::Backtrace::Location)
+ end
+
+ it "returns nil" do
+ Thread.each_caller_location {}.should == nil
+ end
+
+ it "raises LocalJumpError when called without a block" do
+ -> {
+ Thread.each_caller_location
+ }.should.raise(LocalJumpError, "no block given")
+ end
+
+ it "doesn't accept keyword arguments" do
+ -> {
+ Thread.each_caller_location(12, foo: 10) {}
+ }.should.raise(ArgumentError);
+ end
+end
diff --git a/spec/ruby/core/thread/element_reference_spec.rb b/spec/ruby/core/thread/element_reference_spec.rb
index 85280cb287..72892f6c50 100644
--- a/spec/ruby/core/thread/element_reference_spec.rb
+++ b/spec/ruby/core/thread/element_reference_spec.rb
@@ -37,8 +37,19 @@ describe "Thread#[]" do
t2["value"].should == 2
end
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('value')
+ key.should_receive(:to_str).and_return('value')
+
+ th = Thread.new do
+ Thread.current[:value] = 1
+ end.join
+
+ th[key].should == 1
+ end
+
it "raises exceptions on the wrong type of keys" do
- -> { Thread.current[nil] }.should raise_error(TypeError)
- -> { Thread.current[5] }.should raise_error(TypeError)
+ -> { Thread.current[nil] }.should.raise(TypeError)
+ -> { Thread.current[5] }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/thread/element_set_spec.rb b/spec/ruby/core/thread/element_set_spec.rb
index c7498f7ac9..97d6c23980 100644
--- a/spec/ruby/core/thread/element_set_spec.rb
+++ b/spec/ruby/core/thread/element_set_spec.rb
@@ -12,13 +12,36 @@ describe "Thread#[]=" do
th.freeze
-> {
th[:foo] = "bar"
- }.should raise_error(FrozenError, /frozen/)
+ }.should.raise(FrozenError, "can't modify frozen thread locals")
end.join
end
+ it "accepts Strings and Symbols" do
+ t1 = Thread.new do
+ Thread.current[:value] = 1
+ end.join
+ t2 = Thread.new do
+ Thread.current["value"] = 2
+ end.join
+
+ t1[:value].should == 1
+ t2[:value].should == 2
+ end
+
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('value')
+ key.should_receive(:to_str).and_return('value')
+
+ th = Thread.new do
+ Thread.current[key] = 1
+ end.join
+
+ th[:value].should == 1
+ end
+
it "raises exceptions on the wrong type of keys" do
- -> { Thread.current[nil] = true }.should raise_error(TypeError)
- -> { Thread.current[5] = true }.should raise_error(TypeError)
+ -> { Thread.current[nil] = true }.should.raise(TypeError)
+ -> { Thread.current[5] = true }.should.raise(TypeError)
end
it "is not shared across fibers" do
@@ -28,7 +51,7 @@ describe "Thread#[]=" do
Thread.current[:value].should == 1
end
fib.resume
- Thread.current[:value].should be_nil
+ Thread.current[:value].should == nil
Thread.current[:value] = 2
fib.resume
Thread.current[:value] = 2
diff --git a/spec/ruby/core/thread/exclusive_spec.rb b/spec/ruby/core/thread/exclusive_spec.rb
deleted file mode 100644
index 37c4b19d1a..0000000000
--- a/spec/ruby/core/thread/exclusive_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-require_relative '../../spec_helper'
-
-ruby_version_is ''...'3.0' do
- describe "Thread.exclusive" do
- before :each do
- ScratchPad.clear
- $VERBOSE, @verbose = nil, $VERBOSE
- end
-
- after :each do
- $VERBOSE = @verbose
- end
-
- it "yields to the block" do
- Thread.exclusive { ScratchPad.record true }
- ScratchPad.recorded.should == true
- end
-
- it "returns the result of yielding" do
- Thread.exclusive { :result }.should == :result
- end
-
- it "blocks the caller if another thread is also in an exclusive block" do
- m = Mutex.new
- q1 = Queue.new
- q2 = Queue.new
-
- t = Thread.new {
- Thread.exclusive {
- q1.push :ready
- q2.pop
- }
- }
-
- q1.pop.should == :ready
-
- -> { Thread.exclusive { } }.should block_caller
-
- q2.push :done
- t.join
- end
-
- it "is not recursive" do
- Thread.exclusive do
- -> { Thread.exclusive { } }.should raise_error(ThreadError)
- end
- end
- end
-end
diff --git a/spec/ruby/core/thread/exit_spec.rb b/spec/ruby/core/thread/exit_spec.rb
index c3f710920e..b2e923c680 100644
--- a/spec/ruby/core/thread/exit_spec.rb
+++ b/spec/ruby/core/thread/exit_spec.rb
@@ -10,6 +10,6 @@ describe "Thread.exit" do
it "causes the current thread to exit" do
thread = Thread.new { Thread.exit; sleep }
thread.join
- thread.status.should be_false
+ thread.status.should == false
end
end
diff --git a/spec/ruby/core/thread/fetch_spec.rb b/spec/ruby/core/thread/fetch_spec.rb
index 6b37d4cfc5..fe27dec4a2 100644
--- a/spec/ruby/core/thread/fetch_spec.rb
+++ b/spec/ruby/core/thread/fetch_spec.rb
@@ -19,7 +19,7 @@ describe 'Thread#fetch' do
it 'raises a KeyError when the Thread does not have a fiber-local variable of the same name' do
th = Thread.new {}
th.join
- -> { th.fetch(:cat) }.should raise_error(KeyError)
+ -> { th.fetch(:cat) }.should.raise(KeyError)
end
it 'returns the value of the fiber-local variable if value has been assigned' do
@@ -29,8 +29,38 @@ describe 'Thread#fetch' do
end
end
+ describe 'with a block' do
+ it 'returns the value of the fiber-local variable if value has been assigned' do
+ th = Thread.new { Thread.current[:cat] = 'meow' }
+ th.join
+ th.fetch(:cat) { true }.should == 'meow'
+ end
+
+ it "returns the block value if fiber-local variable hasn't been assigned" do
+ th = Thread.new {}
+ th.join
+ th.fetch(:cat) { true }.should == true
+ end
+
+ it "does not call the block if value has been assigned" do
+ th = Thread.new { Thread.current[:cat] = 'meow' }
+ th.join
+ var = :not_updated
+ th.fetch(:cat) { var = :updated }.should == 'meow'
+ var.should == :not_updated
+ end
+
+ it "uses the block if a default is given and warns about it" do
+ th = Thread.new {}
+ th.join
+ -> {
+ th.fetch(:cat, false) { true }.should == true
+ }.should complain(/warning: block supersedes default value argument/)
+ end
+ end
+
it 'raises an ArgumentError when not passed one or two arguments' do
- -> { Thread.current.fetch() }.should raise_error(ArgumentError)
- -> { Thread.current.fetch(1, 2, 3) }.should raise_error(ArgumentError)
+ -> { Thread.current.fetch() }.should.raise(ArgumentError)
+ -> { Thread.current.fetch(1, 2, 3) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/thread/fixtures/classes.rb b/spec/ruby/core/thread/fixtures/classes.rb
index 23a090feb0..14d5d2f7bf 100644
--- a/spec/ruby/core/thread/fixtures/classes.rb
+++ b/spec/ruby/core/thread/fixtures/classes.rb
@@ -6,6 +6,31 @@ module ThreadSpecs
end
end
+ class NewThreadToRaise
+ def self.raise(*args, **kwargs, &block)
+ thread = Thread.new do
+ Thread.current.report_on_exception = false
+
+ if block_given?
+ block.call do
+ sleep
+ end
+ else
+ sleep
+ end
+ end
+
+ Thread.pass until thread.stop?
+
+ thread.raise(*args, **kwargs)
+
+ thread.join
+ ensure
+ thread.kill if thread.alive?
+ Thread.pass while thread.alive? # Thread#kill may not terminate a thread immediately so it may be detected as a leaked one
+ end
+ end
+
class Status
attr_reader :thread, :inspect, :status, :to_s
def initialize(thread)
@@ -182,7 +207,7 @@ module ThreadSpecs
def self.join_dying_thread_with_outer_ensure(kill_method_name=:kill)
t = dying_thread_with_outer_ensure(kill_method_name) { yield }
- -> { t.join }.should raise_error(RuntimeError, "In dying thread")
+ -> { t.join }.should.raise(RuntimeError, "In dying thread")
return t
end
diff --git a/spec/ruby/core/thread/group_spec.rb b/spec/ruby/core/thread/group_spec.rb
index 59f5ac37c8..d0d4704b66 100644
--- a/spec/ruby/core/thread/group_spec.rb
+++ b/spec/ruby/core/thread/group_spec.rb
@@ -1,5 +1,16 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+
describe "Thread#group" do
- it "needs to be reviewed for spec completeness"
+ it "returns the default thread group for the main thread" do
+ Thread.main.group.should == ThreadGroup::Default
+ end
+
+ it "returns the thread group explicitly set for this thread" do
+ thread = Thread.new { nil }
+ thread_group = ThreadGroup.new
+ thread_group.add(thread)
+ thread.group.should == thread_group
+ ensure
+ thread.join if thread
+ end
end
diff --git a/spec/ruby/core/thread/handle_interrupt_spec.rb b/spec/ruby/core/thread/handle_interrupt_spec.rb
index ea7e81cb98..aa03d4c66d 100644
--- a/spec/ruby/core/thread/handle_interrupt_spec.rb
+++ b/spec/ruby/core/thread/handle_interrupt_spec.rb
@@ -75,7 +75,7 @@ describe "Thread.handle_interrupt" do
Thread.handle_interrupt(RuntimeError => :immediate) {
flunk "not reached"
}
- }.should raise_error(RuntimeError, "interrupt immediate")
+ }.should.raise(RuntimeError, "interrupt immediate")
Thread.pending_interrupt?.should == false
end
end
@@ -95,7 +95,7 @@ describe "Thread.handle_interrupt" do
Thread.handle_interrupt(RuntimeError => :immediate) {
flunk "not reached"
}
- }.should raise_error(RuntimeError, "interrupt with fibers")
+ }.should.raise(RuntimeError, "interrupt with fibers")
Thread.pending_interrupt?.should == false
end
@@ -115,7 +115,7 @@ describe "Thread.handle_interrupt" do
executed = true
raise "regular exception"
end
- }.should raise_error(RuntimeError, "interrupt exception")
+ }.should.raise(RuntimeError, "interrupt exception")
executed.should == true
end
diff --git a/spec/ruby/core/thread/ignore_deadlock_spec.rb b/spec/ruby/core/thread/ignore_deadlock_spec.rb
index 53cc2a7f5b..b48bc9f9b0 100644
--- a/spec/ruby/core/thread/ignore_deadlock_spec.rb
+++ b/spec/ruby/core/thread/ignore_deadlock_spec.rb
@@ -1,21 +1,19 @@
require_relative '../../spec_helper'
-ruby_version_is "3.0" do
- describe "Thread.ignore_deadlock" do
- it "returns false by default" do
- Thread.ignore_deadlock.should == false
- end
+describe "Thread.ignore_deadlock" do
+ it "returns false by default" do
+ Thread.ignore_deadlock.should == false
end
+end
- describe "Thread.ignore_deadlock=" do
- it "changes the value of Thread.ignore_deadlock" do
- ignore_deadlock = Thread.ignore_deadlock
- Thread.ignore_deadlock = true
- begin
- Thread.ignore_deadlock.should == true
- ensure
- Thread.ignore_deadlock = ignore_deadlock
- end
+describe "Thread.ignore_deadlock=" do
+ it "changes the value of Thread.ignore_deadlock" do
+ ignore_deadlock = Thread.ignore_deadlock
+ Thread.ignore_deadlock = true
+ begin
+ Thread.ignore_deadlock.should == true
+ ensure
+ Thread.ignore_deadlock = ignore_deadlock
end
end
end
diff --git a/spec/ruby/core/thread/initialize_spec.rb b/spec/ruby/core/thread/initialize_spec.rb
index 4fca900cd8..b9a94560ee 100644
--- a/spec/ruby/core/thread/initialize_spec.rb
+++ b/spec/ruby/core/thread/initialize_spec.rb
@@ -19,7 +19,7 @@ describe "Thread#initialize" do
@t.instance_eval do
initialize {}
end
- }.should raise_error(ThreadError)
+ }.should.raise(ThreadError)
end
end
diff --git a/spec/ruby/core/thread/join_spec.rb b/spec/ruby/core/thread/join_spec.rb
index 213fe2e505..f4332167f1 100644
--- a/spec/ruby/core/thread/join_spec.rb
+++ b/spec/ruby/core/thread/join_spec.rb
@@ -4,28 +4,28 @@ require_relative 'fixtures/classes'
describe "Thread#join" do
it "returns the thread when it is finished" do
t = Thread.new {}
- t.join.should equal(t)
+ t.join.should.equal?(t)
end
it "returns the thread when it is finished when given a timeout" do
t = Thread.new {}
t.join
- t.join(0).should equal(t)
+ t.join(0).should.equal?(t)
end
it "coerces timeout to a Float if it is not nil" do
t = Thread.new {}
t.join
- t.join(0).should equal(t)
- t.join(0.0).should equal(t)
- t.join(nil).should equal(t)
+ t.join(0).should.equal?(t)
+ t.join(0.0).should.equal?(t)
+ t.join(nil).should.equal?(t)
end
it "raises TypeError if the argument is not a valid timeout" do
t = Thread.new { }
t.join
- -> { t.join(:foo) }.should raise_error TypeError
- -> { t.join("bar") }.should raise_error TypeError
+ -> { t.join(:foo) }.should.raise TypeError
+ -> { t.join("bar") }.should.raise TypeError
end
it "returns nil if it is not finished when given a timeout" do
@@ -55,16 +55,16 @@ describe "Thread#join" do
Thread.current.report_on_exception = false
raise NotImplementedError.new("Just kidding")
}
- -> { t.join }.should raise_error(NotImplementedError)
+ -> { t.join }.should.raise(NotImplementedError)
end
it "returns the dead thread" do
t = Thread.new { Thread.current.kill }
- t.join.should equal(t)
+ t.join.should.equal?(t)
end
it "raises any uncaught exception encountered in ensure block" do
t = ThreadSpecs.dying_thread_ensures { raise NotImplementedError.new("Just kidding") }
- -> { t.join }.should raise_error(NotImplementedError)
+ -> { t.join }.should.raise(NotImplementedError)
end
end
diff --git a/spec/ruby/core/thread/key_spec.rb b/spec/ruby/core/thread/key_spec.rb
index 6940cf5f28..a14aeb8d31 100644
--- a/spec/ruby/core/thread/key_spec.rb
+++ b/spec/ruby/core/thread/key_spec.rb
@@ -16,31 +16,38 @@ describe "Thread#key?" do
@th.key?(:stanley.to_s).should == false
end
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('oliver')
+
+ @th.key?(key).should == true
+ end
+
it "raises exceptions on the wrong type of keys" do
- -> { Thread.current.key? nil }.should raise_error(TypeError)
- -> { Thread.current.key? 5 }.should raise_error(TypeError)
+ -> { Thread.current.key? nil }.should.raise(TypeError)
+ -> { Thread.current.key? 5 }.should.raise(TypeError)
end
it "is not shared across fibers" do
fib = Fiber.new do
Thread.current[:val1] = 1
Fiber.yield
- Thread.current.key?(:val1).should be_true
- Thread.current.key?(:val2).should be_false
+ Thread.current.key?(:val1).should == true
+ Thread.current.key?(:val2).should == false
end
- Thread.current.key?(:val1).should_not be_true
+ Thread.current.key?(:val1).should_not == true
fib.resume
Thread.current[:val2] = 2
fib.resume
- Thread.current.key?(:val1).should be_false
- Thread.current.key?(:val2).should be_true
+ Thread.current.key?(:val1).should == false
+ Thread.current.key?(:val2).should == true
end
it "stores a local in another thread when in a fiber" do
fib = Fiber.new do
t = Thread.new do
sleep
- Thread.current.key?(:value).should be_true
+ Thread.current.key?(:value).should == true
end
Thread.pass while t.status and t.status != "sleep"
diff --git a/spec/ruby/core/thread/keys_spec.rb b/spec/ruby/core/thread/keys_spec.rb
index 15efda51d6..3a2edd2456 100644
--- a/spec/ruby/core/thread/keys_spec.rb
+++ b/spec/ruby/core/thread/keys_spec.rb
@@ -16,22 +16,22 @@ describe "Thread#keys" do
fib = Fiber.new do
Thread.current[:val1] = 1
Fiber.yield
- Thread.current.keys.should include(:val1)
- Thread.current.keys.should_not include(:val2)
+ Thread.current.keys.should.include?(:val1)
+ Thread.current.keys.should_not.include?(:val2)
end
- Thread.current.keys.should_not include(:val1)
+ Thread.current.keys.should_not.include?(:val1)
fib.resume
Thread.current[:val2] = 2
fib.resume
- Thread.current.keys.should include(:val2)
- Thread.current.keys.should_not include(:val1)
+ Thread.current.keys.should.include?(:val2)
+ Thread.current.keys.should_not.include?(:val1)
end
it "stores a local in another thread when in a fiber" do
fib = Fiber.new do
t = Thread.new do
sleep
- Thread.current.keys.should include(:value)
+ Thread.current.keys.should.include?(:value)
end
Thread.pass while t.status and t.status != "sleep"
diff --git a/spec/ruby/core/thread/kill_spec.rb b/spec/ruby/core/thread/kill_spec.rb
index f932bf5232..f9f1f46744 100644
--- a/spec/ruby/core/thread/kill_spec.rb
+++ b/spec/ruby/core/thread/kill_spec.rb
@@ -9,17 +9,13 @@ platform_is_not :mingw do
it_behaves_like :thread_exit, :kill
end
- describe "Thread#kill!" do
- it "needs to be reviewed for spec completeness"
- end
-
describe "Thread.kill" do
it "causes the given thread to exit" do
thread = Thread.new { sleep }
Thread.pass while thread.status and thread.status != "sleep"
Thread.kill(thread).should == thread
thread.join
- thread.status.should be_false
+ thread.status.should == false
end
end
end
diff --git a/spec/ruby/core/thread/list_spec.rb b/spec/ruby/core/thread/list_spec.rb
index 3c6f70c13e..5036841d58 100644
--- a/spec/ruby/core/thread/list_spec.rb
+++ b/spec/ruby/core/thread/list_spec.rb
@@ -3,15 +3,15 @@ require_relative 'fixtures/classes'
describe "Thread.list" do
it "includes the current and main thread" do
- Thread.list.should include(Thread.current)
- Thread.list.should include(Thread.main)
+ Thread.list.should.include?(Thread.current)
+ Thread.list.should.include?(Thread.main)
end
it "includes threads of non-default thread groups" do
t = Thread.new { sleep }
begin
ThreadGroup.new.add(t)
- Thread.list.should include(t)
+ Thread.list.should.include?(t)
ensure
t.kill
t.join
@@ -21,7 +21,7 @@ describe "Thread.list" do
it "does not include deceased threads" do
t = Thread.new { 1; }
t.join
- Thread.list.should_not include(t)
+ Thread.list.should_not.include?(t)
end
it "includes waiting threads" do
@@ -29,7 +29,7 @@ describe "Thread.list" do
t = Thread.new { q.pop }
begin
Thread.pass while t.status and t.status != 'sleep'
- Thread.list.should include(t)
+ Thread.list.should.include?(t)
ensure
q << nil
t.join
@@ -45,7 +45,7 @@ describe "Thread.list" do
begin
Thread.list.each { |th|
- th.should be_kind_of(Thread)
+ th.should.is_a?(Thread)
}
end while spawner.alive?
diff --git a/spec/ruby/core/thread/name_spec.rb b/spec/ruby/core/thread/name_spec.rb
index 9b3d2f4b09..47d807be4d 100644
--- a/spec/ruby/core/thread/name_spec.rb
+++ b/spec/ruby/core/thread/name_spec.rb
@@ -36,7 +36,7 @@ describe "Thread#name=" do
it "raises an ArgumentError if the name includes a null byte" do
-> {
@thread.name = "new thread\0name"
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "can be reset to nil" do
diff --git a/spec/ruby/core/thread/native_thread_id_spec.rb b/spec/ruby/core/thread/native_thread_id_spec.rb
new file mode 100644
index 0000000000..cc72e0b853
--- /dev/null
+++ b/spec/ruby/core/thread/native_thread_id_spec.rb
@@ -0,0 +1,31 @@
+require_relative '../../spec_helper'
+
+platform_is :linux, :darwin, :windows, :freebsd do
+ describe "Thread#native_thread_id" do
+ it "returns an integer when the thread is alive" do
+ Thread.current.native_thread_id.should.is_a?(Integer)
+ end
+
+ it "returns nil when the thread is not running" do
+ t = Thread.new {}
+ t.join
+ t.native_thread_id.should == nil
+ end
+
+ it "each thread has different native thread id" do
+ t = Thread.new { sleep }
+ Thread.pass until t.stop?
+ main_thread_id = Thread.current.native_thread_id
+ t_thread_id = t.native_thread_id
+
+ # native_thread_id can be nil on a M:N scheduler
+ t_thread_id.should.is_a?(Integer) if t_thread_id != nil
+
+ main_thread_id.should_not == t_thread_id
+
+ t.run
+ t.join
+ t.native_thread_id.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/thread/new_spec.rb b/spec/ruby/core/thread/new_spec.rb
index 47a836201c..acb6cd4e30 100644
--- a/spec/ruby/core/thread/new_spec.rb
+++ b/spec/ruby/core/thread/new_spec.rb
@@ -18,7 +18,7 @@ describe "Thread.new" do
end
it "raises an exception when not given a block" do
- -> { Thread.new }.should raise_error(ThreadError)
+ -> { Thread.new }.should.raise(ThreadError)
end
it "creates a subclass of thread calls super with a block in initialize" do
@@ -36,7 +36,7 @@ describe "Thread.new" do
-> {
c.new
- }.should raise_error(ThreadError)
+ }.should.raise(ThreadError)
end
it "calls and respects #initialize for the block to use" do
diff --git a/spec/ruby/core/thread/pending_interrupt_spec.rb b/spec/ruby/core/thread/pending_interrupt_spec.rb
index cd565d92a4..5fbe7422a9 100644
--- a/spec/ruby/core/thread/pending_interrupt_spec.rb
+++ b/spec/ruby/core/thread/pending_interrupt_spec.rb
@@ -19,7 +19,7 @@ describe "Thread.pending_interrupt?" do
Thread.pending_interrupt?.should == true
executed = true
end
- }.should raise_error(RuntimeError, "interrupt")
+ }.should.raise(RuntimeError, "interrupt")
executed.should == true
Thread.pending_interrupt?.should == false
end
diff --git a/spec/ruby/core/thread/priority_spec.rb b/spec/ruby/core/thread/priority_spec.rb
index e13ad478b5..970f7f9971 100644
--- a/spec/ruby/core/thread/priority_spec.rb
+++ b/spec/ruby/core/thread/priority_spec.rb
@@ -15,19 +15,19 @@ describe "Thread#priority" do
end
it "inherits the priority of the current thread while running" do
- @thread.alive?.should be_true
+ @thread.alive?.should == true
@thread.priority.should == @current_priority
end
it "maintain the priority of the current thread after death" do
ThreadSpecs.state = :exit
@thread.join
- @thread.alive?.should be_false
+ @thread.alive?.should == false
@thread.priority.should == @current_priority
end
it "returns an integer" do
- @thread.priority.should be_kind_of(Integer)
+ @thread.priority.should.is_a?(Integer)
end
end
@@ -59,7 +59,7 @@ describe "Thread#priority=" do
describe "when set with a non-integer" do
it "raises a type error" do
- ->{ @thread.priority = Object.new }.should raise_error(TypeError)
+ ->{ @thread.priority = Object.new }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/thread/raise_spec.rb b/spec/ruby/core/thread/raise_spec.rb
index 49323cf270..efc09d4a35 100644
--- a/spec/ruby/core/thread/raise_spec.rb
+++ b/spec/ruby/core/thread/raise_spec.rb
@@ -3,6 +3,16 @@ require_relative 'fixtures/classes'
require_relative '../../shared/kernel/raise'
describe "Thread#raise" do
+ it "is a public method" do
+ Thread.public_instance_methods.should.include?(:raise)
+ end
+
+ it_behaves_like :kernel_raise, :raise, ThreadSpecs::NewThreadToRaise
+ it_behaves_like :kernel_raise_across_contexts, :raise, ThreadSpecs::NewThreadToRaise
+ ruby_version_is "4.0" do
+ it_behaves_like :kernel_raise_with_cause, :raise, ThreadSpecs::NewThreadToRaise
+ end
+
it "ignores dead threads and returns nil" do
t = Thread.new { :dead }
Thread.pass while t.alive?
@@ -26,27 +36,27 @@ describe "Thread#raise on a sleeping thread" do
it "raises a RuntimeError if no exception class is given" do
@thr.raise
Thread.pass while @thr.status
- ScratchPad.recorded.should be_kind_of(RuntimeError)
+ ScratchPad.recorded.should.is_a?(RuntimeError)
end
it "raises the given exception" do
@thr.raise Exception
Thread.pass while @thr.status
- ScratchPad.recorded.should be_kind_of(Exception)
+ ScratchPad.recorded.should.is_a?(Exception)
end
it "raises the given exception with the given message" do
@thr.raise Exception, "get to work"
Thread.pass while @thr.status
- ScratchPad.recorded.should be_kind_of(Exception)
+ ScratchPad.recorded.should.is_a?(Exception)
ScratchPad.recorded.message.should == "get to work"
end
it "raises the given exception and the backtrace is the one of the interrupted thread" do
@thr.raise Exception
Thread.pass while @thr.status
- ScratchPad.recorded.should be_kind_of(Exception)
- ScratchPad.recorded.backtrace[0].should include("sleep")
+ ScratchPad.recorded.should.is_a?(Exception)
+ ScratchPad.recorded.backtrace[0].should.include?("sleep")
end
it "is captured and raised by Thread#value" do
@@ -58,7 +68,7 @@ describe "Thread#raise on a sleeping thread" do
ThreadSpecs.spin_until_sleeping(t)
t.raise
- -> { t.value }.should raise_error(RuntimeError)
+ -> { t.value }.should.raise(RuntimeError)
end
it "raises a RuntimeError when called with no arguments inside rescue" do
@@ -76,7 +86,7 @@ describe "Thread#raise on a sleeping thread" do
ThreadSpecs.spin_until_sleeping(t)
t.raise
end
- -> { t.value }.should raise_error(RuntimeError)
+ -> { t.value }.should.raise(RuntimeError)
end
it "re-raises a previously rescued exception without overwriting the backtrace" do
@@ -98,8 +108,8 @@ describe "Thread#raise on a sleeping thread" do
raise_again_line = __LINE__; t.raise raised
raised_again = t.value
- raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:")
- raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
+ raised_again.backtrace.first.should.include?("#{__FILE__}:#{initial_raise_line}:")
+ raised_again.backtrace.first.should_not.include?("#{__FILE__}:#{raise_again_line}:")
end
end
@@ -126,6 +136,31 @@ describe "Thread#raise on a sleeping thread" do
[ScratchPad.recorded, @thr, []]
]
end
+
+ it "calls #set_backtrace only in the caller thread" do
+ cls = Class.new(Exception) do
+ attr_accessor :log
+ def initialize(*args)
+ @log = [] # This is shared because the super #exception uses a shallow clone
+ super
+ end
+
+ def set_backtrace(backtrace)
+ @log << [Thread.current, backtrace]
+ super
+ end
+ end
+ exc = cls.new
+
+ backtrace = ["a.rb:1"]
+
+ @thr.raise exc, "Thread#raise #set_backtrace spec", backtrace
+ @thr.join
+ ScratchPad.recorded.should.is_a?(cls)
+ exc.log.should == [
+ [Thread.current, backtrace]
+ ]
+ end
end
describe "Thread#raise on a running thread" do
@@ -145,19 +180,19 @@ describe "Thread#raise on a running thread" do
it "raises a RuntimeError if no exception class is given" do
@thr.raise
Thread.pass while @thr.status
- ScratchPad.recorded.should be_kind_of(RuntimeError)
+ ScratchPad.recorded.should.is_a?(RuntimeError)
end
it "raises the given exception" do
@thr.raise Exception
Thread.pass while @thr.status
- ScratchPad.recorded.should be_kind_of(Exception)
+ ScratchPad.recorded.should.is_a?(Exception)
end
it "raises the given exception with the given message" do
@thr.raise Exception, "get to work"
Thread.pass while @thr.status
- ScratchPad.recorded.should be_kind_of(Exception)
+ ScratchPad.recorded.should.is_a?(Exception)
ScratchPad.recorded.message.should == "get to work"
end
@@ -171,7 +206,7 @@ describe "Thread#raise on a running thread" do
q.pop # wait for `report_on_exception = false`.
t.raise
- -> { t.value }.should raise_error(RuntimeError)
+ -> { t.value }.should.raise(RuntimeError)
end
it "raises the given argument even when there is an active exception" do
@@ -190,7 +225,7 @@ describe "Thread#raise on a running thread" do
rescue
Thread.pass until raised
t.raise RangeError
- -> { t.value }.should raise_error(RangeError)
+ -> { t.value }.should.raise(RangeError)
end
end
@@ -211,7 +246,7 @@ describe "Thread#raise on a running thread" do
Thread.pass until raised
t.raise
end
- -> { t.value }.should raise_error(RuntimeError)
+ -> { t.value }.should.raise(RuntimeError)
end
end
@@ -227,6 +262,6 @@ describe "Thread#raise on same thread" do
Thread.current.raise
end
end
- -> { t.value }.should raise_error(RuntimeError, '')
+ -> { t.value }.should.raise(RuntimeError, '')
end
end
diff --git a/spec/ruby/core/thread/report_on_exception_spec.rb b/spec/ruby/core/thread/report_on_exception_spec.rb
index 9279fa1da5..9cf5260808 100644
--- a/spec/ruby/core/thread/report_on_exception_spec.rb
+++ b/spec/ruby/core/thread/report_on_exception_spec.rb
@@ -58,37 +58,35 @@ describe "Thread#report_on_exception=" do
-> {
t.join
- }.should raise_error(RuntimeError, "Thread#report_on_exception specs")
+ }.should.raise(RuntimeError, "Thread#report_on_exception specs")
end
- ruby_version_is "3.0" do
- it "prints a backtrace on $stderr in the regular backtrace order" do
- line_raise = __LINE__ + 2
- def foo
- raise RuntimeError, "Thread#report_on_exception specs backtrace order"
- end
+ it "prints a backtrace on $stderr in the regular backtrace order" do
+ line_raise = __LINE__ + 2
+ def foo
+ raise RuntimeError, "Thread#report_on_exception specs backtrace order"
+ end
- line_call_foo = __LINE__ + 5
- go = false
- t = Thread.new {
- Thread.current.report_on_exception = true
- Thread.pass until go
- foo
- }
+ line_call_foo = __LINE__ + 5
+ go = false
+ t = Thread.new {
+ Thread.current.report_on_exception = true
+ Thread.pass until go
+ foo
+ }
- -> {
- go = true
- Thread.pass while t.alive?
- }.should output("", <<ERR)
-#{t.inspect} terminated with exception (report_on_exception is true):
-#{__FILE__}:#{line_raise}:in `foo': Thread#report_on_exception specs backtrace order (RuntimeError)
-\tfrom #{__FILE__}:#{line_call_foo}:in `block (5 levels) in <top (required)>'
-ERR
+ -> {
+ go = true
+ Thread.pass while t.alive?
+ }.should output("", /\A
+#{Regexp.quote(t.inspect)}\sterminated\swith\sexception\s\(report_on_exception\sis\strue\):\n
+#{Regexp.quote(__FILE__)}:#{line_raise}:in\s[`']foo':\sThread\#report_on_exception\sspecs\sbacktrace\sorder\s\(RuntimeError\)\n
+\tfrom\s#{Regexp.quote(__FILE__)}:#{line_call_foo}:in\s[`']block\s\(4\slevels\)\sin\s<top\s\(required\)>'\n
+\z/x)
- -> {
- t.join
- }.should raise_error(RuntimeError, "Thread#report_on_exception specs backtrace order")
- end
+ -> {
+ t.join
+ }.should.raise(RuntimeError, "Thread#report_on_exception specs backtrace order")
end
it "prints the backtrace even if the thread was killed just after Thread#raise" do
@@ -109,7 +107,7 @@ ERR
-> {
t.join
- }.should raise_error(RuntimeError, "Thread#report_on_exception before kill spec")
+ }.should.raise(RuntimeError, "Thread#report_on_exception before kill spec")
end
end
@@ -126,7 +124,7 @@ ERR
-> {
t.join
- }.should raise_error(RuntimeError, "Thread#report_on_exception specs")
+ }.should.raise(RuntimeError, "Thread#report_on_exception specs")
end
end
@@ -146,12 +144,12 @@ ERR
-> {
mutex.sleep(5)
- }.should raise_error(RuntimeError, "Thread#report_on_exception specs")
+ }.should.raise(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")
+ }.should.raise(RuntimeError, "Thread#report_on_exception specs")
end
end
end
diff --git a/spec/ruby/core/thread/shared/exit.rb b/spec/ruby/core/thread/shared/exit.rb
index 3663827579..a294c3a4d6 100644
--- a/spec/ruby/core/thread/shared/exit.rb
+++ b/spec/ruby/core/thread/shared/exit.rb
@@ -56,8 +56,8 @@ describe :thread_exit, shared: true do
Thread.pass while @inner.status and @inner.status != "sleep"
@outer.send(@method)
@outer.join
- ScratchPad.recorded.should include(:inner_ensure_clause)
- ScratchPad.recorded.should include(:outer_ensure_clause)
+ ScratchPad.recorded.should.include?(:inner_ensure_clause)
+ ScratchPad.recorded.should.include?(:outer_ensure_clause)
end
it "does not set $!" do
@@ -113,6 +113,25 @@ describe :thread_exit, shared: true do
ScratchPad.recorded.should == nil
end
+ it "kills other fibers of that thread without running their ensure clauses" do
+ t = Thread.new do
+ f = Fiber.new do
+ ScratchPad.record :fiber_resumed
+ begin
+ Fiber.yield
+ ensure
+ ScratchPad.record :fiber_ensure
+ end
+ end
+ f.resume
+ sleep
+ end
+ Thread.pass until t.stop?
+ t.send(@method)
+ t.join
+ ScratchPad.recorded.should == :fiber_resumed
+ end
+
# This spec is a mess. It fails randomly, it hangs on MRI, it needs to be removed
quarantine! do
it "killing dying running does nothing" do
@@ -136,7 +155,7 @@ describe :thread_exit, shared: true do
it "propagates inner exception to Thread.join if there is an outer ensure clause" do
thread = ThreadSpecs.dying_thread_with_outer_ensure(@method) { }
- -> { thread.join }.should raise_error(RuntimeError, "In dying thread")
+ -> { thread.join }.should.raise(RuntimeError, "In dying thread")
end
it "runs all outer ensure clauses even if inner ensure clause raises exception" do
diff --git a/spec/ruby/core/thread/shared/start.rb b/spec/ruby/core/thread/shared/start.rb
index 2ba926bf00..c5d62ab098 100644
--- a/spec/ruby/core/thread/shared/start.rb
+++ b/spec/ruby/core/thread/shared/start.rb
@@ -6,22 +6,22 @@ describe :thread_start, shared: true do
it "raises an ArgumentError if not passed a block" do
-> {
Thread.send(@method)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "spawns a new Thread running the block" do
run = false
t = Thread.send(@method) { run = true }
- t.should be_kind_of(Thread)
+ t.should.is_a?(Thread)
t.join
- run.should be_true
+ run.should == true
end
it "respects Thread subclasses" do
c = Class.new(Thread)
t = c.send(@method) { }
- t.should be_kind_of(c)
+ t.should.is_a?(c)
t.join
end
diff --git a/spec/ruby/core/thread/shared/to_s.rb b/spec/ruby/core/thread/shared/to_s.rb
index 43640deb33..27e53ba4b8 100644
--- a/spec/ruby/core/thread/shared/to_s.rb
+++ b/spec/ruby/core/thread/shared/to_s.rb
@@ -12,42 +12,42 @@ describe :thread_to_s, shared: true do
end
it "can check it's own status" do
- ThreadSpecs.status_of_current_thread.send(@method).should include('run')
+ ThreadSpecs.status_of_current_thread.send(@method).should.include?('run')
end
it "describes a running thread" do
- ThreadSpecs.status_of_running_thread.send(@method).should include('run')
+ ThreadSpecs.status_of_running_thread.send(@method).should.include?('run')
end
it "describes a sleeping thread" do
- ThreadSpecs.status_of_sleeping_thread.send(@method).should include('sleep')
+ ThreadSpecs.status_of_sleeping_thread.send(@method).should.include?('sleep')
end
it "describes a blocked thread" do
- ThreadSpecs.status_of_blocked_thread.send(@method).should include('sleep')
+ ThreadSpecs.status_of_blocked_thread.send(@method).should.include?('sleep')
end
it "describes a completed thread" do
- ThreadSpecs.status_of_completed_thread.send(@method).should include('dead')
+ ThreadSpecs.status_of_completed_thread.send(@method).should.include?('dead')
end
it "describes a killed thread" do
- ThreadSpecs.status_of_killed_thread.send(@method).should include('dead')
+ ThreadSpecs.status_of_killed_thread.send(@method).should.include?('dead')
end
it "describes a thread with an uncaught exception" do
- ThreadSpecs.status_of_thread_with_uncaught_exception.send(@method).should include('dead')
+ ThreadSpecs.status_of_thread_with_uncaught_exception.send(@method).should.include?('dead')
end
it "describes a dying sleeping thread" do
- ThreadSpecs.status_of_dying_sleeping_thread.send(@method).should include('sleep')
+ ThreadSpecs.status_of_dying_sleeping_thread.send(@method).should.include?('sleep')
end
it "reports aborting on a killed thread" do
- ThreadSpecs.status_of_dying_running_thread.send(@method).should include('aborting')
+ ThreadSpecs.status_of_dying_running_thread.send(@method).should.include?('aborting')
end
it "reports aborting on a killed thread after sleep" do
- ThreadSpecs.status_of_dying_thread_after_sleep.send(@method).should include('aborting')
+ ThreadSpecs.status_of_dying_thread_after_sleep.send(@method).should.include?('aborting')
end
end
diff --git a/spec/ruby/core/thread/shared/wakeup.rb b/spec/ruby/core/thread/shared/wakeup.rb
index 6f010fea25..c89235ba60 100644
--- a/spec/ruby/core/thread/shared/wakeup.rb
+++ b/spec/ruby/core/thread/shared/wakeup.rb
@@ -57,6 +57,6 @@ describe :thread_wakeup, shared: true do
it "raises a ThreadError when trying to wake up a dead thread" do
t = Thread.new { 1 }
t.join
- -> { t.send @method }.should raise_error(ThreadError)
+ -> { t.send @method }.should.raise(ThreadError)
end
end
diff --git a/spec/ruby/core/thread/thread_variable_get_spec.rb b/spec/ruby/core/thread/thread_variable_get_spec.rb
index 38f90d5830..3d92cd5479 100644
--- a/spec/ruby/core/thread/thread_variable_get_spec.rb
+++ b/spec/ruby/core/thread/thread_variable_get_spec.rb
@@ -10,16 +10,51 @@ describe "Thread#thread_variable_get" do
end
it "returns nil if the variable is not set" do
- @t.thread_variable_get(:a).should be_nil
+ @t.thread_variable_get(:a).should == nil
end
- it "returns the value previously set by #[]=" do
- @t.thread_variable_set :a, 49
+ it "returns the value previously set by #thread_variable_set" do
+ @t.thread_variable_set(:a, 49)
@t.thread_variable_get(:a).should == 49
end
it "returns a value private to self" do
- @t.thread_variable_set :thread_variable_get_spec, 82
- Thread.current.thread_variable_get(:thread_variable_get_spec).should be_nil
+ @t.thread_variable_set(:thread_variable_get_spec, 82)
+ Thread.current.thread_variable_get(:thread_variable_get_spec).should == nil
+ end
+
+ it "accepts String and Symbol keys interchangeably" do
+ @t.thread_variable_set("a", 49)
+ @t.thread_variable_get("a").should == 49
+ @t.thread_variable_get(:a).should == 49
+ end
+
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('a')
+ @t.thread_variable_set(:a, 49)
+ @t.thread_variable_get(key).should == 49
+ end
+
+ it "does not raise FrozenError if the thread is frozen" do
+ @t.freeze
+ @t.thread_variable_get(:a).should == nil
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String when thread variables are already set" do
+ @t.thread_variable_set(:a, 49)
+ -> { @t.thread_variable_get(123) }.should.raise(TypeError, /123 is not a symbol/)
+ end
+
+ ruby_version_is '3.4' do
+ it "raises a TypeError if the key is neither Symbol nor String when no thread variables are set" do
+ -> { @t.thread_variable_get(123) }.should.raise(TypeError, /123 is not a symbol/)
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String without calling #to_sym" do
+ key = mock('key')
+ key.should_not_receive(:to_sym)
+ -> { @t.thread_variable_get(key) }.should.raise(TypeError, /#{Regexp.escape(key.inspect)} is not a symbol/)
+ end
end
end
diff --git a/spec/ruby/core/thread/thread_variable_set_spec.rb b/spec/ruby/core/thread/thread_variable_set_spec.rb
index 1338c306c7..f8d25364ae 100644
--- a/spec/ruby/core/thread/thread_variable_set_spec.rb
+++ b/spec/ruby/core/thread/thread_variable_set_spec.rb
@@ -10,17 +10,53 @@ describe "Thread#thread_variable_set" do
end
it "returns the value set" do
- (@t.thread_variable_set :a, 2).should == 2
+ @t.thread_variable_set(:a, 2).should == 2
end
it "sets a value that will be returned by #thread_variable_get" do
- @t.thread_variable_set :a, 49
+ @t.thread_variable_set(:a, 49)
@t.thread_variable_get(:a).should == 49
end
it "sets a value private to self" do
- @t.thread_variable_set :thread_variable_get_spec, 82
+ @t.thread_variable_set(:thread_variable_get_spec, 82)
@t.thread_variable_get(:thread_variable_get_spec).should == 82
- Thread.current.thread_variable_get(:thread_variable_get_spec).should be_nil
+ Thread.current.thread_variable_get(:thread_variable_get_spec).should == nil
+ end
+
+ it "accepts String and Symbol keys interchangeably" do
+ @t.thread_variable_set('a', 49)
+ @t.thread_variable_get('a').should == 49
+
+ @t.thread_variable_set(:a, 50)
+ @t.thread_variable_get('a').should == 50
+ end
+
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('a')
+ @t.thread_variable_set(key, 49)
+ @t.thread_variable_get(:a).should == 49
+ end
+
+ it "removes a key if the value is nil" do
+ @t.thread_variable_set(:a, 52)
+ @t.thread_variable_set(:a, nil)
+ @t.thread_variable?(:a).should == false
+ end
+
+ it "raises a FrozenError if the thread is frozen" do
+ @t.freeze
+ -> { @t.thread_variable_set(:a, 1) }.should.raise(FrozenError, "can't modify frozen thread locals")
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String, nor responds to #to_str" do
+ -> { @t.thread_variable_set(123, 1) }.should.raise(TypeError, /123 is not a symbol/)
+ end
+
+ it "does not try to convert the key with #to_sym" do
+ key = mock('key')
+ key.should_not_receive(:to_sym)
+ -> { @t.thread_variable_set(key, 42) }.should.raise(TypeError, /#{Regexp.quote(key.inspect)} is not a symbol/)
end
end
diff --git a/spec/ruby/core/thread/thread_variable_spec.rb b/spec/ruby/core/thread/thread_variable_spec.rb
index 6bd1950c04..ebafd4f3eb 100644
--- a/spec/ruby/core/thread/thread_variable_spec.rb
+++ b/spec/ruby/core/thread/thread_variable_spec.rb
@@ -10,12 +10,51 @@ describe "Thread#thread_variable?" do
end
it "returns false if the thread variables do not contain 'key'" do
- @t.thread_variable_set :a, 2
- @t.thread_variable?(:b).should be_false
+ @t.thread_variable_set(:a, 2)
+ @t.thread_variable?(:b).should == false
end
it "returns true if the thread variables contain 'key'" do
- @t.thread_variable_set :a, 2
- @t.thread_variable?(:a).should be_true
+ @t.thread_variable_set(:a, 2)
+ @t.thread_variable?(:a).should == true
+ end
+
+ it "accepts String and Symbol keys interchangeably" do
+ @t.thread_variable?('a').should == false
+ @t.thread_variable?(:a).should == false
+
+ @t.thread_variable_set(:a, 49)
+
+ @t.thread_variable?('a').should == true
+ @t.thread_variable?(:a).should == true
+ end
+
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('a')
+ @t.thread_variable_set(:a, 49)
+ @t.thread_variable?(key).should == true
+ end
+
+ it "does not raise FrozenError if the thread is frozen" do
+ @t.freeze
+ @t.thread_variable?(:a).should == false
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String when thread variables are already set" do
+ @t.thread_variable_set(:a, 49)
+ -> { @t.thread_variable?(123) }.should.raise(TypeError, /123 is not a symbol/)
+ end
+
+ ruby_version_is '3.4' do
+ it "raises a TypeError if the key is neither Symbol nor String when no thread variables are set" do
+ -> { @t.thread_variable?(123) }.should.raise(TypeError, /123 is not a symbol/)
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String without calling #to_sym" do
+ key = mock('key')
+ key.should_not_receive(:to_sym)
+ -> { @t.thread_variable?(key) }.should.raise(TypeError, /#{Regexp.escape(key.inspect)} is not a symbol/)
+ end
end
end
diff --git a/spec/ruby/core/thread/thread_variables_spec.rb b/spec/ruby/core/thread/thread_variables_spec.rb
index 1bd68b17f1..f15c681a8f 100644
--- a/spec/ruby/core/thread/thread_variables_spec.rb
+++ b/spec/ruby/core/thread/thread_variables_spec.rb
@@ -10,20 +10,31 @@ describe "Thread#thread_variables" do
end
it "returns the keys of all the values set" do
- @t.thread_variable_set :a, 2
- @t.thread_variable_set :b, 4
- @t.thread_variable_set :c, 6
+ @t.thread_variable_set(:a, 2)
+ @t.thread_variable_set(:b, 4)
+ @t.thread_variable_set(:c, 6)
@t.thread_variables.sort.should == [:a, :b, :c]
end
- it "sets a value private to self" do
- @t.thread_variable_set :a, 82
- @t.thread_variable_set :b, 82
- Thread.current.thread_variables.should_not include(:a, :b)
+ it "returns the keys private to self" do
+ @t.thread_variable_set(:a, 82)
+ @t.thread_variable_set(:b, 82)
+ Thread.current.thread_variables.should_not.include?(:a)
+ Thread.current.thread_variables.should_not.include?(:b)
end
it "only contains user thread variables and is empty initially" do
Thread.current.thread_variables.should == []
@t.thread_variables.should == []
end
+
+ it "returns keys as Symbols" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('a')
+
+ @t.thread_variable_set(key, 49)
+ @t.thread_variable_set('b', 50)
+ @t.thread_variable_set(:c, 51)
+ @t.thread_variables.sort.should == [:a, :b, :c]
+ end
end
diff --git a/spec/ruby/core/thread/value_spec.rb b/spec/ruby/core/thread/value_spec.rb
index 30e43abd1a..50c823171d 100644
--- a/spec/ruby/core/thread/value_spec.rb
+++ b/spec/ruby/core/thread/value_spec.rb
@@ -11,7 +11,7 @@ describe "Thread#value" do
Thread.current.report_on_exception = false
raise "Hello"
}
- -> { t.value }.should raise_error(RuntimeError, "Hello")
+ -> { t.value }.should.raise(RuntimeError, "Hello")
end
it "is nil for a killed thread" do
diff --git a/spec/ruby/core/threadgroup/default_spec.rb b/spec/ruby/core/threadgroup/default_spec.rb
index d7d4726cc2..4f57508abf 100644
--- a/spec/ruby/core/threadgroup/default_spec.rb
+++ b/spec/ruby/core/threadgroup/default_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "ThreadGroup::Default" do
it "is a ThreadGroup instance" do
- ThreadGroup::Default.should be_kind_of(ThreadGroup)
+ ThreadGroup::Default.should.is_a?(ThreadGroup)
end
it "is the ThreadGroup of the main thread" do
diff --git a/spec/ruby/core/threadgroup/enclose_spec.rb b/spec/ruby/core/threadgroup/enclose_spec.rb
index dd9a7a362d..6f703d4ce2 100644
--- a/spec/ruby/core/threadgroup/enclose_spec.rb
+++ b/spec/ruby/core/threadgroup/enclose_spec.rb
@@ -19,6 +19,6 @@ describe "ThreadGroup#enclose" do
thread_group.enclose
-> do
default_group.add(@thread)
- end.should raise_error(ThreadError)
+ end.should.raise(ThreadError)
end
end
diff --git a/spec/ruby/core/threadgroup/enclosed_spec.rb b/spec/ruby/core/threadgroup/enclosed_spec.rb
index a734256a64..cf8a5bb4c6 100644
--- a/spec/ruby/core/threadgroup/enclosed_spec.rb
+++ b/spec/ruby/core/threadgroup/enclosed_spec.rb
@@ -3,12 +3,12 @@ require_relative '../../spec_helper'
describe "ThreadGroup#enclosed?" do
it "returns false when a ThreadGroup has not been enclosed (default state)" do
thread_group = ThreadGroup.new
- thread_group.enclosed?.should be_false
+ thread_group.enclosed?.should == false
end
it "returns true when a ThreadGroup is enclosed" do
thread_group = ThreadGroup.new
thread_group.enclose
- thread_group.enclosed?.should be_true
+ thread_group.enclosed?.should == true
end
end
diff --git a/spec/ruby/core/threadgroup/list_spec.rb b/spec/ruby/core/threadgroup/list_spec.rb
index b2ac64324a..ef601d75ea 100644
--- a/spec/ruby/core/threadgroup/list_spec.rb
+++ b/spec/ruby/core/threadgroup/list_spec.rb
@@ -7,13 +7,13 @@ describe "ThreadGroup#list" do
q.pop.should == :go
tg = ThreadGroup.new
tg.add(th1)
- tg.list.should include(th1)
+ tg.list.should.include?(th1)
th2 = Thread.new { q << :go; sleep }
q.pop.should == :go
tg.add(th2)
- (tg.list & [th1, th2]).should include(th1, th2)
+ (tg.list & [th1, th2]).to_set.should == Set[th1, th2]
Thread.pass while th1.status and th1.status != 'sleep'
Thread.pass while th2.status and th2.status != 'sleep'
diff --git a/spec/ruby/core/time/_dump_spec.rb b/spec/ruby/core/time/_dump_spec.rb
index 4dc1c43cd2..21f0806327 100644
--- a/spec/ruby/core/time/_dump_spec.rb
+++ b/spec/ruby/core/time/_dump_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
describe "Time#_dump" do
@@ -10,7 +10,7 @@ describe "Time#_dump" do
end
it "is a private method" do
- Time.should have_private_instance_method(:_dump, false)
+ Time.private_instance_methods(false).should.include?(:_dump)
end
# http://redmine.ruby-lang.org/issues/show/627
@@ -25,7 +25,7 @@ describe "Time#_dump" do
end
it "dumps a Time object to a bytestring" do
- @s.should be_an_instance_of(String)
+ @s.should.instance_of?(String)
@s.should == [3222863947, 2235564032].pack("VV")
end
diff --git a/spec/ruby/core/time/_load_spec.rb b/spec/ruby/core/time/_load_spec.rb
index 152934370f..a74e3dc129 100644
--- a/spec/ruby/core/time/_load_spec.rb
+++ b/spec/ruby/core/time/_load_spec.rb
@@ -1,9 +1,9 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
describe "Time._load" do
it "is a private method" do
- Time.should have_private_method(:_load, false)
+ Time.private_methods(false).should.include?(:_load)
end
# http://redmine.ruby-lang.org/issues/show/627
@@ -44,8 +44,7 @@ describe "Time._load" do
end
it "treats the data as binary data" do
- data = "\x04\bu:\tTime\r\fM\x1C\xC0\x00\x00\xD0\xBE"
- data.force_encoding Encoding::UTF_8
+ data = "\x04\bu:\tTime\r\fM\x1C\xC0\x00\x00\xD0\xBE".dup.force_encoding Encoding::UTF_8
t = Marshal.load(data)
t.to_s.should == "2013-04-08 12:47:45 UTC"
end
diff --git a/spec/ruby/core/time/at_spec.rb b/spec/ruby/core/time/at_spec.rb
index 2cc46ab8c9..10d4d36a68 100644
--- a/spec/ruby/core/time/at_spec.rb
+++ b/spec/ruby/core/time/at_spec.rb
@@ -20,7 +20,7 @@ describe "Time.at" do
it "returns a subclass instance on a Time subclass" do
c = Class.new(Time)
t = c.at(0)
- t.should be_an_instance_of(c)
+ t.should.instance_of?(c)
end
it "roundtrips a Rational produced by #to_r" do
@@ -32,13 +32,6 @@ describe "Time.at" do
t2.nsec.should == t.nsec
end
- describe "passed BigDecimal" do
- it "doesn't round input value" do
- require 'bigdecimal'
- Time.at(BigDecimal('1.1')).to_f.should == 1.1
- end
- end
-
describe "passed Rational" do
it "returns Time with correct microseconds" do
t = Time.at(Rational(1_486_570_508_539_759, 1_000_000))
@@ -63,7 +56,7 @@ describe "Time.at" do
it "creates a dup time object with the value given by time" do
t1 = Time.new
t2 = Time.at(t1)
- t1.should_not equal t2
+ t1.should_not.equal? t2
end
it "returns a UTC time if the argument is UTC" do
@@ -79,17 +72,17 @@ describe "Time.at" do
it "returns a subclass instance" do
c = Class.new(Time)
t = c.at(Time.now)
- t.should be_an_instance_of(c)
+ t.should.instance_of?(c)
end
end
describe "passed non-Time, non-Numeric" do
it "raises a TypeError with a String argument" do
- -> { Time.at("0") }.should raise_error(TypeError)
+ -> { Time.at("0") }.should.raise(TypeError)
end
it "raises a TypeError with a nil argument" do
- -> { Time.at(nil) }.should raise_error(TypeError)
+ -> { Time.at(nil) }.should.raise(TypeError)
end
describe "with an argument that responds to #to_int" do
@@ -109,8 +102,8 @@ describe "Time.at" do
it "needs for the argument to respond to #to_int too" do
o = mock('rational-but-no-to_int')
- o.should_receive(:to_r).and_return(Rational(5, 2))
- -> { Time.at(o) }.should raise_error(TypeError)
+ def o.to_r; Rational(5, 2) end
+ -> { Time.at(o) }.should.raise(TypeError, "can't convert MockObject into an exact number")
end
end
end
@@ -147,20 +140,20 @@ describe "Time.at" do
describe "passed [Integer, nil]" do
it "raises a TypeError" do
- -> { Time.at(0, nil) }.should raise_error(TypeError)
+ -> { Time.at(0, nil) }.should.raise(TypeError)
end
end
describe "passed [Integer, String]" do
it "raises a TypeError" do
- -> { Time.at(0, "0") }.should raise_error(TypeError)
+ -> { Time.at(0, "0") }.should.raise(TypeError)
end
end
describe "passed [Time, Integer]" do
# #8173
it "raises a TypeError" do
- -> { Time.at(Time.now, 500000) }.should raise_error(TypeError)
+ -> { Time.at(Time.now, 500000) }.should.raise(TypeError)
end
end
@@ -197,15 +190,15 @@ describe "Time.at" do
context "not supported format" do
it "raises ArgumentError" do
- -> { Time.at(0, 123456, 2) }.should raise_error(ArgumentError)
- -> { Time.at(0, 123456, nil) }.should raise_error(ArgumentError)
- -> { Time.at(0, 123456, :invalid) }.should raise_error(ArgumentError)
+ -> { Time.at(0, 123456, 2) }.should.raise(ArgumentError)
+ -> { Time.at(0, 123456, nil) }.should.raise(ArgumentError)
+ -> { Time.at(0, 123456, :invalid) }.should.raise(ArgumentError)
end
it "does not try to convert format to Symbol with #to_sym" do
- format = "usec"
+ format = +"usec"
format.should_not_receive(:to_sym)
- -> { Time.at(0, 123456, format) }.should raise_error(ArgumentError)
+ -> { Time.at(0, 123456, format) }.should.raise(ArgumentError)
end
end
@@ -235,6 +228,12 @@ describe "Time.at" do
time.utc_offset.should == -9*60*60
time.zone.should == nil
time.to_i.should == @epoch_time
+
+ time = Time.at(@epoch_time, in: "-09:00:01")
+
+ time.utc_offset.should == -(9*60*60 + 1)
+ time.zone.should == nil
+ time.to_i.should == @epoch_time
end
it "could be UTC offset as a number of seconds" do
@@ -251,6 +250,22 @@ describe "Time.at" do
time.to_i.should == @epoch_time
end
+ it "could be UTC offset as a 'UTC' String" do
+ time = Time.at(@epoch_time, in: "UTC")
+
+ time.utc_offset.should == 0
+ time.zone.should == "UTC"
+ time.to_i.should == @epoch_time
+ end
+
+ it "could be UTC offset as a military zone A-Z" do
+ time = Time.at(@epoch_time, in: "B")
+
+ time.utc_offset.should == 3600 * 2
+ time.zone.should == nil
+ time.to_i.should == @epoch_time
+ end
+
it "could be a timezone object" do
zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
time = Time.at(@epoch_time, in: zone)
@@ -266,5 +281,36 @@ describe "Time.at" do
time.zone.should == zone
time.to_i.should == @epoch_time
end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.at(@epoch_time, in: "+09:99") }.should.raise(ArgumentError)
+ -> { Time.at(@epoch_time, in: "ABC") }.should.raise(ArgumentError)
+ end
+
+ it "raises ArgumentError if hours greater than 23" do # TODO
+ -> { Time.at(@epoch_time, in: "+24:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.at(@epoch_time, in: "+2400") }.should.raise(ArgumentError, "utc_offset out of range")
+
+ -> { Time.at(@epoch_time, in: "+99:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.at(@epoch_time, in: "+9900") }.should.raise(ArgumentError, "utc_offset out of range")
+ end
+
+ it "raises ArgumentError if minutes greater than 59" do # TODO
+ -> { Time.at(@epoch_time, in: "+00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.at(@epoch_time, in: "+0060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
+
+ -> { Time.at(@epoch_time, in: "+00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.at(@epoch_time, in: "+0099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
+ end
+
+ ruby_bug '#20797', ''...'3.4' do
+ it "raises ArgumentError if seconds greater than 59" do
+ -> { Time.at(@epoch_time, in: "+00:00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.at(@epoch_time, in: "+000060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
+
+ -> { Time.at(@epoch_time, in: "+00:00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.at(@epoch_time, in: "+000099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
+ end
+ end
end
end
diff --git a/spec/ruby/core/time/ceil_spec.rb b/spec/ruby/core/time/ceil_spec.rb
index 9d624a1ed0..18e26f9994 100644
--- a/spec/ruby/core/time/ceil_spec.rb
+++ b/spec/ruby/core/time/ceil_spec.rb
@@ -28,8 +28,8 @@ describe "Time#ceil" do
it "returns an instance of Time, even if #ceil is called on a subclass" do
subclass = Class.new(Time)
instance = subclass.at(0)
- instance.class.should equal subclass
- instance.ceil.should be_an_instance_of(Time)
+ instance.class.should.equal? subclass
+ instance.ceil.should.instance_of?(Time)
end
it "copies own timezone to the returning value" do
diff --git a/spec/ruby/core/time/comparison_spec.rb b/spec/ruby/core/time/comparison_spec.rb
index 5b53c9fb50..0790088f9e 100644
--- a/spec/ruby/core/time/comparison_spec.rb
+++ b/spec/ruby/core/time/comparison_spec.rb
@@ -55,6 +55,32 @@ describe "Time#<=>" do
}.should_not complain
end
+ context "given different timezones" do
+ it "returns 0 if time is the same as other" do
+ # three timezones, all at the same timestamp
+ time_utc = Time.new(2000, 1, 1, 0, 0, 0, 0)
+ time_cet = Time.new(2000, 1, 1, 1, 0, 0, '+01:00')
+ time_brt = Time.new(1999, 12, 31, 21, 0, 0, '-03:00')
+ (time_utc <=> time_cet).should == 0
+ (time_utc <=> time_brt).should == 0
+ (time_cet <=> time_brt).should == 0
+ end
+
+ it "returns -1 if the first argument is before the second argument" do
+ # time_brt is later, even though the date is earlier
+ time_utc = Time.new(2000, 1, 1, 0, 0, 0, 0)
+ time_brt = Time.new(1999, 12, 31, 23, 0, 0, '-03:00')
+ (time_utc <=> time_brt).should == -1
+ end
+
+ it "returns 1 if the first argument is before the second argument" do
+ # time_brt is later, even though the date is earlier
+ time_utc = Time.new(2000, 1, 1, 0, 0, 0, 0)
+ time_brt = Time.new(1999, 12, 31, 23, 0, 0, '-03:00')
+ (time_brt <=> time_utc).should == 1
+ end
+ end
+
describe "given a non-Time argument" do
it "returns nil if argument <=> self returns nil" do
t = Time.now
@@ -98,7 +124,7 @@ describe "Time#<=>" do
def r.<=>(other); other <=> self; end
r.should_receive(:<=>).once
- (t <=> r).should be_nil
+ (t <=> r).should == nil
end
end
end
diff --git a/spec/ruby/core/time/deconstruct_keys_spec.rb b/spec/ruby/core/time/deconstruct_keys_spec.rb
new file mode 100644
index 0000000000..9918728c1d
--- /dev/null
+++ b/spec/ruby/core/time/deconstruct_keys_spec.rb
@@ -0,0 +1,43 @@
+require_relative '../../spec_helper'
+
+describe "Time#deconstruct_keys" do
+ it "returns whole hash for nil as an argument" do
+ d = Time.utc(2022, 10, 5, 13, 30)
+ res = { year: 2022, month: 10, day: 5, yday: 278, wday: 3, hour: 13,
+ min: 30, sec: 0, subsec: 0, dst: false, zone: "UTC" }
+ d.deconstruct_keys(nil).should == res
+ end
+
+ it "returns only specified keys" do
+ d = Time.utc(2022, 10, 5, 13, 39)
+ d.deconstruct_keys([:zone, :subsec]).should == { zone: "UTC", subsec: 0 }
+ end
+
+ it "requires one argument" do
+ -> {
+ Time.new(2022, 10, 5, 13, 30).deconstruct_keys
+ }.should.raise(ArgumentError)
+ end
+
+ it "it raises error when argument is neither nil nor array" do
+ d = Time.new(2022, 10, 5, 13, 30)
+
+ -> { d.deconstruct_keys(1) }.should.raise(TypeError, "wrong argument type Integer (expected Array or nil)")
+ -> { d.deconstruct_keys("asd") }.should.raise(TypeError, "wrong argument type String (expected Array or nil)")
+ -> { d.deconstruct_keys(:x) }.should.raise(TypeError, "wrong argument type Symbol (expected Array or nil)")
+ -> { d.deconstruct_keys({}) }.should.raise(TypeError, "wrong argument type Hash (expected Array or nil)")
+ end
+
+ it "returns {} when passed []" do
+ Time.new(2022, 10, 5, 13, 30).deconstruct_keys([]).should == {}
+ end
+
+ it "ignores non-Symbol keys" do
+ Time.new(2022, 10, 5, 13, 30).deconstruct_keys(['year', []]).should == {}
+ end
+
+ it "ignores not existing Symbol keys and processes keys after the first non-existing one" do
+ d = Time.utc(2022, 10, 5, 13, 30)
+ d.deconstruct_keys([:year, :a, :month, :b, :day]).should == { year: 2022, month: 10, day: 5 }
+ end
+end
diff --git a/spec/ruby/core/time/dup_spec.rb b/spec/ruby/core/time/dup_spec.rb
index 5d6621beaa..33aa1304ef 100644
--- a/spec/ruby/core/time/dup_spec.rb
+++ b/spec/ruby/core/time/dup_spec.rb
@@ -22,25 +22,25 @@ describe "Time#dup" do
c = Class.new(Time)
t = c.now
- t.should be_an_instance_of(c)
- t.dup.should be_an_instance_of(c)
+ t.should.instance_of?(c)
+ t.dup.should.instance_of?(c)
end
it "returns a clone of Time instance" do
c = Time.dup
t = c.now
- t.should be_an_instance_of(c)
- t.should_not be_an_instance_of(Time)
+ t.should.instance_of?(c)
+ t.should_not.instance_of?(Time)
- t.dup.should be_an_instance_of(c)
- t.dup.should_not be_an_instance_of(Time)
+ t.dup.should.instance_of?(c)
+ t.dup.should_not.instance_of?(Time)
end
it "does not copy frozen status from the original" do
t = Time.now
t.freeze
t2 = t.dup
- t2.frozen?.should be_false
+ t2.frozen?.should == false
end
end
diff --git a/spec/ruby/core/time/eql_spec.rb b/spec/ruby/core/time/eql_spec.rb
index 2ffb4eec96..b7505969dd 100644
--- a/spec/ruby/core/time/eql_spec.rb
+++ b/spec/ruby/core/time/eql_spec.rb
@@ -2,28 +2,28 @@ require_relative '../../spec_helper'
describe "Time#eql?" do
it "returns true if self and other have the same whole number of seconds" do
- Time.at(100).should eql(Time.at(100))
+ Time.at(100).should.eql?(Time.at(100))
end
it "returns false if self and other have differing whole numbers of seconds" do
- Time.at(100).should_not eql(Time.at(99))
+ Time.at(100).should_not.eql?(Time.at(99))
end
it "returns true if self and other have the same number of microseconds" do
- Time.at(100, 100).should eql(Time.at(100, 100))
+ Time.at(100, 100).should.eql?(Time.at(100, 100))
end
it "returns false if self and other have differing numbers of microseconds" do
- Time.at(100, 100).should_not eql(Time.at(100, 99))
+ Time.at(100, 100).should_not.eql?(Time.at(100, 99))
end
it "returns false if self and other have differing fractional microseconds" do
- Time.at(100, Rational(100,1000)).should_not eql(Time.at(100, Rational(99,1000)))
+ Time.at(100, Rational(100,1000)).should_not.eql?(Time.at(100, Rational(99,1000)))
end
it "returns false when given a non-time value" do
- Time.at(100, 100).should_not eql("100")
- Time.at(100, 100).should_not eql(100)
- Time.at(100, 100).should_not eql(100.1)
+ Time.at(100, 100).should_not.eql?("100")
+ Time.at(100, 100).should_not.eql?(100)
+ Time.at(100, 100).should_not.eql?(100.1)
end
end
diff --git a/spec/ruby/core/time/fixtures/classes.rb b/spec/ruby/core/time/fixtures/classes.rb
index 1a9511b261..21c4e1effb 100644
--- a/spec/ruby/core/time/fixtures/classes.rb
+++ b/spec/ruby/core/time/fixtures/classes.rb
@@ -59,7 +59,6 @@ module TimeSpecs
Zone = Struct.new(:std, :dst, :dst_range)
Zones = {
"Asia/Colombo" => Zone[Z[5*3600+30*60, "MMT"], nil, nil],
- "Europe/Kiev" => Zone[Z[2*3600, "EET"], Z[3*3600, "EEST"], 4..10],
"PST" => Zone[Z[(-9*60*60), "PST"], nil, nil],
}
diff --git a/spec/ruby/core/time/floor_spec.rb b/spec/ruby/core/time/floor_spec.rb
index b0003469c9..41e5142b19 100644
--- a/spec/ruby/core/time/floor_spec.rb
+++ b/spec/ruby/core/time/floor_spec.rb
@@ -20,8 +20,8 @@ describe "Time#floor" do
it "returns an instance of Time, even if #floor is called on a subclass" do
subclass = Class.new(Time)
instance = subclass.at(0)
- instance.class.should equal subclass
- instance.floor.should be_an_instance_of(Time)
+ instance.class.should.equal? subclass
+ instance.floor.should.instance_of?(Time)
end
it "copies own timezone to the returning value" do
diff --git a/spec/ruby/core/time/getlocal_spec.rb b/spec/ruby/core/time/getlocal_spec.rb
index 926a6dbf45..7e5334c303 100644
--- a/spec/ruby/core/time/getlocal_spec.rb
+++ b/spec/ruby/core/time/getlocal_spec.rb
@@ -14,6 +14,7 @@ describe "Time#getlocal" do
t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal(3630)
t.should == Time.new(2007, 1, 9, 13, 0, 30, 3630)
t.utc_offset.should == 3630
+ t.zone.should == nil
end
platform_is_not :windows do
@@ -40,7 +41,7 @@ describe "Time#getlocal" do
it "returns a Time with a UTC offset of the specified number of Rational seconds" do
t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal(Rational(7201, 2))
t.should == Time.new(2007, 1, 9, 13, 0, Rational(1, 2), Rational(7201, 2))
- t.utc_offset.should eql(Rational(7201, 2))
+ t.utc_offset.should.eql?(Rational(7201, 2))
end
describe "with an argument that responds to #to_r" do
@@ -49,7 +50,7 @@ describe "Time#getlocal" do
o.should_receive(:to_r).and_return(Rational(7201, 2))
t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal(o)
t.should == Time.new(2007, 1, 9, 13, 0, Rational(1, 2), Rational(7201, 2))
- t.utc_offset.should eql(Rational(7201, 2))
+ t.utc_offset.should.eql?(Rational(7201, 2))
end
end
@@ -59,12 +60,24 @@ describe "Time#getlocal" do
t.utc_offset.should == 3600
end
+ it "returns a Time with a UTC offset specified as +HH:MM:SS" do
+ t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal("+01:00:01")
+ t.should == Time.new(2007, 1, 9, 13, 0, 1, 3601)
+ t.utc_offset.should == 3601
+ end
+
it "returns a Time with a UTC offset specified as -HH:MM" do
t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal("-01:00")
t.should == Time.new(2007, 1, 9, 11, 0, 0, -3600)
t.utc_offset.should == -3600
end
+ it "returns a Time with a UTC offset specified as -HH:MM:SS" do
+ t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal("-01:00:01")
+ t.should == Time.new(2007, 1, 9, 10, 59, 59, -3601)
+ t.utc_offset.should == -3601
+ end
+
describe "with an argument that responds to #to_str" do
it "coerces using #to_str" do
o = mock('string')
@@ -77,24 +90,50 @@ describe "Time#getlocal" do
it "raises ArgumentError if the String argument is not of the form (+|-)HH:MM" do
t = Time.now
- -> { t.getlocal("3600") }.should raise_error(ArgumentError)
+ -> { t.getlocal("3600") }.should.raise(ArgumentError)
end
it "raises ArgumentError if the String argument is not in an ASCII-compatible encoding" do
t = Time.now
- -> { t.getlocal("-01:00".encode("UTF-16LE")) }.should raise_error(ArgumentError)
+ -> { t.getlocal("-01:00".encode("UTF-16LE")) }.should.raise(ArgumentError)
end
it "raises ArgumentError if the argument represents a value less than or equal to -86400 seconds" do
t = Time.new
t.getlocal(-86400 + 1).utc_offset.should == (-86400 + 1)
- -> { t.getlocal(-86400) }.should raise_error(ArgumentError)
+ -> { t.getlocal(-86400) }.should.raise(ArgumentError)
end
it "raises ArgumentError if the argument represents a value greater than or equal to 86400 seconds" do
t = Time.new
t.getlocal(86400 - 1).utc_offset.should == (86400 - 1)
- -> { t.getlocal(86400) }.should raise_error(ArgumentError)
+ -> { t.getlocal(86400) }.should.raise(ArgumentError)
+ end
+
+ it "raises ArgumentError if String argument and hours greater than 23" do
+ -> { Time.now.getlocal("+24:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.now.getlocal("+2400") }.should.raise(ArgumentError, "utc_offset out of range")
+
+ -> { Time.now.getlocal("+99:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.now.getlocal("+9900") }.should.raise(ArgumentError, "utc_offset out of range")
+ end
+
+ it "raises ArgumentError if String argument and minutes greater than 59" do
+ -> { Time.now.getlocal("+00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.now.getlocal("+0060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
+
+ -> { Time.now.getlocal("+00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.now.getlocal("+0099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
+ end
+
+ ruby_bug '#20797', ''...'3.4' do
+ it "raises ArgumentError if String argument and seconds greater than 59" do
+ -> { Time.now.getlocal("+00:00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.now.getlocal("+000060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
+
+ -> { Time.now.getlocal("+00:00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.now.getlocal("+000099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
+ end
end
describe "with a timezone argument" do
@@ -116,8 +155,8 @@ describe "Time#getlocal" do
end
-> {
- Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone).should be_kind_of(Time)
- }.should_not raise_error
+ Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone).should.is_a?(Time)
+ }.should_not.raise
end
it "raises TypeError if timezone does not implement #utc_to_local method" do
@@ -128,7 +167,7 @@ describe "Time#getlocal" do
-> {
Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone)
- }.should raise_error(TypeError, /can't convert \w+ into an exact number/)
+ }.should.raise(TypeError, /can't convert \w+ into an exact number/)
end
it "does not raise exception if timezone does not implement #local_to_utc method" do
@@ -138,18 +177,18 @@ describe "Time#getlocal" do
end
-> {
- Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone).should be_kind_of(Time)
- }.should_not raise_error
+ Time.utc(2000, 1, 1, 12, 0, 0).getlocal(zone).should.is_a?(Time)
+ }.should_not.raise
end
context "subject's class implements .find_timezone method" do
it "calls .find_timezone to build a time object if passed zone name as a timezone argument" do
time = TimeSpecs::TimeWithFindTimezone.utc(2000, 1, 1, 12, 0, 0).getlocal("Asia/Colombo")
- time.zone.should be_kind_of TimeSpecs::TimezoneWithName
+ time.zone.should.is_a? TimeSpecs::TimezoneWithName
time.zone.name.should == "Asia/Colombo"
time = TimeSpecs::TimeWithFindTimezone.utc(2000, 1, 1, 12, 0, 0).getlocal("some invalid zone name")
- time.zone.should be_kind_of TimeSpecs::TimezoneWithName
+ time.zone.should.is_a? TimeSpecs::TimezoneWithName
time.zone.name.should == "some invalid zone name"
end
@@ -159,7 +198,7 @@ describe "Time#getlocal" do
-> {
time.getlocal(zone)
- }.should raise_error(TypeError, /can't convert \w+ into an exact number/)
+ }.should.raise(TypeError, /can't convert \w+ into an exact number/)
end
end
end
diff --git a/spec/ruby/core/time/hash_spec.rb b/spec/ruby/core/time/hash_spec.rb
index 4f4d11a2cd..1cfc56eab0 100644
--- a/spec/ruby/core/time/hash_spec.rb
+++ b/spec/ruby/core/time/hash_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Time#hash" do
it "returns an Integer" do
- Time.at(100).hash.should be_an_instance_of(Integer)
+ Time.at(100).hash.should.instance_of?(Integer)
end
it "is stable" do
diff --git a/spec/ruby/core/time/iso8601_spec.rb b/spec/ruby/core/time/iso8601_spec.rb
new file mode 100644
index 0000000000..ad60c3bb32
--- /dev/null
+++ b/spec/ruby/core/time/iso8601_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/xmlschema'
+
+describe "Time#iso8601" do
+ it_behaves_like :time_xmlschema, :iso8601
+end
diff --git a/spec/ruby/core/time/localtime_spec.rb b/spec/ruby/core/time/localtime_spec.rb
index 2975e112d0..1c0b11b7a6 100644
--- a/spec/ruby/core/time/localtime_spec.rb
+++ b/spec/ruby/core/time/localtime_spec.rb
@@ -12,7 +12,7 @@ describe "Time#localtime" do
it "returns self" do
t = Time.gm(2007, 1, 9, 12, 0, 0)
- t.localtime.should equal(t)
+ t.localtime.should.equal?(t)
end
it "converts time to the UTC offset specified as an Integer number of seconds" do
@@ -26,13 +26,13 @@ describe "Time#localtime" do
it "does not raise an error if already in the right time zone" do
time = Time.now
time.freeze
- time.localtime.should equal(time)
+ time.localtime.should.equal?(time)
end
- it "raises a RuntimeError if the time has a different time zone" do
+ it "raises a FrozenError if the time has a different time zone" do
time = Time.gm(2007, 1, 9, 12, 0, 0)
time.freeze
- -> { time.localtime }.should raise_error(RuntimeError)
+ -> { time.localtime }.should.raise(FrozenError)
end
end
@@ -51,7 +51,7 @@ describe "Time#localtime" do
t = Time.gm(2007, 1, 9, 12, 0, 0)
t.localtime(Rational(7201, 2))
t.should == Time.new(2007, 1, 9, 13, 0, Rational(1, 2), Rational(7201, 2))
- t.utc_offset.should eql(Rational(7201, 2))
+ t.utc_offset.should.eql?(Rational(7201, 2))
end
describe "with an argument that responds to #to_r" do
@@ -61,7 +61,7 @@ describe "Time#localtime" do
t = Time.gm(2007, 1, 9, 12, 0, 0)
t.localtime(o)
t.should == Time.new(2007, 1, 9, 13, 0, Rational(1, 2), Rational(7201, 2))
- t.utc_offset.should eql(Rational(7201, 2))
+ t.utc_offset.should.eql?(Rational(7201, 2))
end
end
@@ -72,6 +72,13 @@ describe "Time#localtime" do
t.utc_offset.should == 3600
end
+ it "returns a Time with a UTC offset specified as +HH:MM:SS" do
+ t = Time.gm(2007, 1, 9, 12, 0, 0)
+ t.localtime("+01:00:01")
+ t.should == Time.new(2007, 1, 9, 13, 0, 1, 3601)
+ t.utc_offset.should == 3601
+ end
+
it "returns a Time with a UTC offset specified as -HH:MM" do
t = Time.gm(2007, 1, 9, 12, 0, 0)
t.localtime("-01:00")
@@ -79,6 +86,51 @@ describe "Time#localtime" do
t.utc_offset.should == -3600
end
+ it "returns a Time with a UTC offset specified as -HH:MM:SS" do
+ t = Time.gm(2007, 1, 9, 12, 0, 0)
+ t.localtime("-01:00:01")
+ t.should == Time.new(2007, 1, 9, 10, 59, 59, -3601)
+ t.utc_offset.should == -3601
+ end
+
+ it "returns a Time with a UTC offset specified as UTC" do
+ t = Time.new(2007, 1, 9, 12, 0, 0, 3600)
+ t.localtime("UTC")
+ t.utc_offset.should == 0
+ end
+
+ it "returns a Time with a UTC offset specified as A-Z military zone" do
+ t = Time.new(2007, 1, 9, 12, 0, 0, 3600)
+ t.localtime("B")
+ t.utc_offset.should == 3600 * 2
+ end
+
+ it "raises ArgumentError if String argument and hours greater than 23" do
+ -> { Time.now.localtime("+24:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.now.localtime("+2400") }.should.raise(ArgumentError, "utc_offset out of range")
+
+ -> { Time.now.localtime("+99:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.now.localtime("+9900") }.should.raise(ArgumentError, "utc_offset out of range")
+ end
+
+ it "raises ArgumentError if String argument and minutes greater than 59" do
+ -> { Time.now.localtime("+00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.now.localtime("+0060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
+
+ -> { Time.now.localtime("+00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.now.localtime("+0099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
+ end
+
+ ruby_bug '#20797', ''...'3.4' do
+ it "raises ArgumentError if String argument and seconds greater than 59" do
+ -> { Time.now.localtime("+00:00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.now.localtime("+000060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
+
+ -> { Time.now.localtime("+00:00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.now.localtime("+000099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
+ end
+ end
+
platform_is_not :windows do
it "changes the timezone according to the set one" do
t = Time.new(2005, 2, 27, 22, 50, 0, -3600)
@@ -116,25 +168,36 @@ describe "Time#localtime" do
end
end
+ describe "with an argument that responds to #utc_to_local" do
+ it "coerces using #utc_to_local" do
+ o = mock('string')
+ o.should_receive(:utc_to_local).and_return(Time.new(2007, 1, 9, 13, 0, 0, 3600))
+ t = Time.gm(2007, 1, 9, 12, 0, 0)
+ t.localtime(o)
+ t.should == Time.new(2007, 1, 9, 13, 0, 0, 3600)
+ t.utc_offset.should == 3600
+ end
+ end
+
it "raises ArgumentError if the String argument is not of the form (+|-)HH:MM" do
t = Time.now
- -> { t.localtime("3600") }.should raise_error(ArgumentError)
+ -> { t.localtime("3600") }.should.raise(ArgumentError)
end
it "raises ArgumentError if the String argument is not in an ASCII-compatible encoding" do
t = Time.now
- -> { t.localtime("-01:00".encode("UTF-16LE")) }.should raise_error(ArgumentError)
+ -> { t.localtime("-01:00".encode("UTF-16LE")) }.should.raise(ArgumentError)
end
it "raises ArgumentError if the argument represents a value less than or equal to -86400 seconds" do
t = Time.new
t.localtime(-86400 + 1).utc_offset.should == (-86400 + 1)
- -> { t.localtime(-86400) }.should raise_error(ArgumentError)
+ -> { t.localtime(-86400) }.should.raise(ArgumentError)
end
it "raises ArgumentError if the argument represents a value greater than or equal to 86400 seconds" do
t = Time.new
t.localtime(86400 - 1).utc_offset.should == (86400 - 1)
- -> { t.localtime(86400) }.should raise_error(ArgumentError)
+ -> { t.localtime(86400) }.should.raise(ArgumentError)
end
end
diff --git a/spec/ruby/core/time/minus_spec.rb b/spec/ruby/core/time/minus_spec.rb
index 8449778465..ee3d8acda8 100644
--- a/spec/ruby/core/time/minus_spec.rb
+++ b/spec/ruby/core/time/minus_spec.rb
@@ -20,18 +20,18 @@ describe "Time#-" do
end
it "raises a TypeError if given argument is a coercible String" do
- -> { Time.now - "1" }.should raise_error(TypeError)
- -> { Time.now - "0.1" }.should raise_error(TypeError)
- -> { Time.now - "1/3" }.should raise_error(TypeError)
+ -> { Time.now - "1" }.should.raise(TypeError)
+ -> { Time.now - "0.1" }.should.raise(TypeError)
+ -> { Time.now - "1/3" }.should.raise(TypeError)
end
it "raises TypeError on argument that can't be coerced" do
- -> { Time.now - Object.new }.should raise_error(TypeError)
- -> { Time.now - "stuff" }.should raise_error(TypeError)
+ -> { Time.now - Object.new }.should.raise(TypeError)
+ -> { Time.now - "stuff" }.should.raise(TypeError)
end
it "raises TypeError on nil argument" do
- -> { Time.now - nil }.should raise_error(TypeError)
+ -> { Time.now - nil }.should.raise(TypeError)
end
it "tracks microseconds" do
@@ -109,8 +109,8 @@ describe "Time#-" do
it "does not return a subclass instance" do
c = Class.new(Time)
- x = c.now + 1
- x.should be_an_instance_of(Time)
+ x = c.now - 1
+ x.should.instance_of?(Time)
end
it "returns a time with nanoseconds precision between two time objects" do
diff --git a/spec/ruby/core/time/new_spec.rb b/spec/ruby/core/time/new_spec.rb
index 09b4d03a44..91ce4b2e3a 100644
--- a/spec/ruby/core/time/new_spec.rb
+++ b/spec/ruby/core/time/new_spec.rb
@@ -31,14 +31,14 @@ describe "Time.new with a utc_offset argument" do
end
it "returns a Time with a UTC offset of the specified number of Rational seconds" do
- Time.new(2000, 1, 1, 0, 0, 0, Rational(5, 2)).utc_offset.should eql(Rational(5, 2))
+ Time.new(2000, 1, 1, 0, 0, 0, Rational(5, 2)).utc_offset.should.eql?(Rational(5, 2))
end
describe "with an argument that responds to #to_r" do
it "coerces using #to_r" do
o = mock_numeric('rational')
o.should_receive(:to_r).and_return(Rational(5, 2))
- Time.new(2000, 1, 1, 0, 0, 0, o).utc_offset.should eql(Rational(5, 2))
+ Time.new(2000, 1, 1, 0, 0, 0, o).utc_offset.should.eql?(Rational(5, 2))
end
end
@@ -58,6 +58,30 @@ describe "Time.new with a utc_offset argument" do
Time.new(2000, 1, 1, 0, 0, 0, "-04:10:43").utc_offset.should == -15043
end
+ it "returns a Time with a UTC offset specified as +HH" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+05").utc_offset.should == 3600 * 5
+ end
+
+ it "returns a Time with a UTC offset specified as -HH" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-05").utc_offset.should == -3600 * 5
+ end
+
+ it "returns a Time with a UTC offset specified as +HHMM" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+0530").utc_offset.should == 19800
+ end
+
+ it "returns a Time with a UTC offset specified as -HHMM" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-0530").utc_offset.should == -19800
+ end
+
+ it "returns a Time with a UTC offset specified as +HHMMSS" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+053037").utc_offset.should == 19837
+ end
+
+ it "returns a Time with a UTC offset specified as -HHMMSS" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-053037").utc_offset.should == -19837
+ end
+
describe "with an argument that responds to #to_str" do
it "coerces using #to_str" do
o = mock('string')
@@ -66,6 +90,48 @@ describe "Time.new with a utc_offset argument" do
end
end
+ it "returns a Time with UTC offset specified as UTC" do
+ Time.new(2000, 1, 1, 0, 0, 0, "UTC").utc_offset.should == 0
+ end
+
+ it "returns a Time with UTC offset specified as a single letter military timezone" do
+ [
+ ["A", 3600],
+ ["B", 3600 * 2],
+ ["C", 3600 * 3],
+ ["D", 3600 * 4],
+ ["E", 3600 * 5],
+ ["F", 3600 * 6],
+ ["G", 3600 * 7],
+ ["H", 3600 * 8],
+ ["I", 3600 * 9],
+ # J is not supported
+ ["K", 3600 * 10],
+ ["L", 3600 * 11],
+ ["M", 3600 * 12],
+ ["N", 3600 * -1],
+ ["O", 3600 * -2],
+ ["P", 3600 * -3],
+ ["Q", 3600 * -4],
+ ["R", 3600 * -5],
+ ["S", 3600 * -6],
+ ["T", 3600 * -7],
+ ["U", 3600 * -8],
+ ["V", 3600 * -9],
+ ["W", 3600 * -10],
+ ["X", 3600 * -11],
+ ["Y", 3600 * -12],
+ ["Z", 0]
+ ].each do |letter, offset|
+ Time.new(2000, 1, 1, 0, 0, 0, letter).utc_offset.should == offset
+ end
+ end
+
+ it "raises ArgumentError if the string argument is J" do
+ message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: J'
+ -> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should.raise(ArgumentError, message)
+ end
+
it "returns a local Time if the argument is nil" do
with_timezone("PST", -8) do
t = Time.new(2000, 1, 1, 0, 0, 0, nil)
@@ -78,49 +144,45 @@ describe "Time.new with a utc_offset argument" do
it "disallows a value for minutes greater than 59" do
-> {
Time.new(2000, 1, 1, 0, 0, 0, "+01:60")
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
-> {
Time.new(2000, 1, 1, 0, 0, 0, "+01:99")
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises ArgumentError if the String argument is not of the form (+|-)HH:MM" do
- -> { Time.new(2000, 1, 1, 0, 0, 0, "3600") }.should raise_error(ArgumentError)
+ -> { Time.new(2000, 1, 1, 0, 0, 0, "3600") }.should.raise(ArgumentError)
end
it "raises ArgumentError if the hour value is greater than 23" do
- -> { Time.new(2000, 1, 1, 0, 0, 0, "+24:00") }.should raise_error(ArgumentError)
+ -> { Time.new(2000, 1, 1, 0, 0, 0, "+24:00") }.should.raise(ArgumentError)
end
it "raises ArgumentError if the String argument is not in an ASCII-compatible encoding" do
- -> { Time.new(2000, 1, 1, 0, 0, 0, "-04:10".encode("UTF-16LE")) }.should raise_error(ArgumentError)
+ # Don't check exception message - it was changed in previous CRuby versions:
+ # - "string contains null byte"
+ # - '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset'
+ -> {
+ Time.new(2000, 1, 1, 0, 0, 0, "-04:10".encode("UTF-16LE"))
+ }.should.raise(ArgumentError)
end
it "raises ArgumentError if the argument represents a value less than or equal to -86400 seconds" do
Time.new(2000, 1, 1, 0, 0, 0, -86400 + 1).utc_offset.should == (-86400 + 1)
- -> { Time.new(2000, 1, 1, 0, 0, 0, -86400) }.should raise_error(ArgumentError)
+ -> { Time.new(2000, 1, 1, 0, 0, 0, -86400) }.should.raise(ArgumentError)
end
it "raises ArgumentError if the argument represents a value greater than or equal to 86400 seconds" do
Time.new(2000, 1, 1, 0, 0, 0, 86400 - 1).utc_offset.should == (86400 - 1)
- -> { Time.new(2000, 1, 1, 0, 0, 0, 86400) }.should raise_error(ArgumentError)
- end
-
- it "raises ArgumentError if the seconds argument is negative" do
- -> { Time.new(2000, 1, 1, 0, 0, -1) }.should raise_error(ArgumentError)
+ -> { Time.new(2000, 1, 1, 0, 0, 0, 86400) }.should.raise(ArgumentError)
end
it "raises ArgumentError if the utc_offset argument is greater than or equal to 10e9" do
- -> { Time.new(2000, 1, 1, 0, 0, 0, 1000000000) }.should raise_error(ArgumentError)
- end
-
- it "raises ArgumentError if the month is greater than 12" do
- # For some reason MRI uses a different message for month in 13-15 and month>=16
- -> { Time.new(2000, 13, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, /(mon|argument) out of range/)
- -> { Time.new(2000, 16, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, "argument out of range")
+ -> { Time.new(2000, 1, 1, 0, 0, 0, 1000000000) }.should.raise(ArgumentError)
end
end
+# The method #local_to_utc is tested only here because Time.new is the only method that calls #local_to_utc.
describe "Time.new with a timezone argument" do
it "returns a Time in the timezone" do
zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60))
@@ -128,10 +190,8 @@ describe "Time.new with a timezone argument" do
time.zone.should == zone
time.utc_offset.should == 5*3600+30*60
- ruby_version_is "3.0" do
- time.wday.should == 6
- time.yday.should == 1
- end
+ time.wday.should == 6
+ time.yday.should == 1
end
it "accepts timezone argument that must have #local_to_utc and #utc_to_local methods" do
@@ -143,9 +203,7 @@ describe "Time.new with a timezone argument" do
time
end
- -> {
- Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time)
- }.should_not raise_error
+ Time.new(2000, 1, 1, 12, 0, 0, zone).should.is_a?(Time)
end
it "raises TypeError if timezone does not implement #local_to_utc method" do
@@ -156,7 +214,7 @@ describe "Time.new with a timezone argument" do
-> {
Time.new(2000, 1, 1, 12, 0, 0, zone)
- }.should raise_error(TypeError, /can't convert \w+ into an exact number/)
+ }.should.raise(TypeError, /can't convert Object into an exact number/)
end
it "does not raise exception if timezone does not implement #utc_to_local method" do
@@ -165,51 +223,48 @@ describe "Time.new with a timezone argument" do
time
end
- -> {
- Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time)
- }.should_not raise_error
+ Time.new(2000, 1, 1, 12, 0, 0, zone).should.is_a?(Time)
end
# The result also should be a Time or Time-like object (not necessary to be the same class)
- # The zone of the result is just ignored
+ # or respond to #to_int method. The zone of the result is just ignored.
describe "returned value by #utc_to_local and #local_to_utc methods" do
it "could be Time instance" do
zone = Object.new
def zone.local_to_utc(t)
- Time.utc(t.year, t.mon, t.day, t.hour - 1, t.min, t.sec)
+ time = Time.utc(t.year, t.mon, t.day, t.hour, t.min, t.sec)
+ time - 60 * 60 # - 1 hour
end
- -> {
- Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time)
- Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60
- }.should_not raise_error
+ Time.new(2000, 1, 1, 12, 0, 0, zone).should.is_a?(Time)
+ Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60
end
it "could be Time subclass instance" do
zone = Object.new
def zone.local_to_utc(t)
- Class.new(Time).utc(t.year, t.mon, t.day, t.hour - 1, t.min, t.sec)
+ time = Time.utc(t.year, t.mon, t.day, t.hour, t.min, t.sec)
+ time -= 60 * 60 # - 1 hour
+ Class.new(Time).utc(time.year, time.mon, time.day, time.hour, t.min, t.sec)
end
- -> {
- Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time)
- Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60
- }.should_not raise_error
+ Time.new(2000, 1, 1, 12, 0, 0, zone).should.is_a?(Time)
+ Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60
end
it "could be any object with #to_i method" do
zone = Object.new
def zone.local_to_utc(time)
- Struct.new(:to_i).new(time.to_i - 60*60)
+ obj = Object.new
+ obj.singleton_class.define_method(:to_i) { time.to_i - 60*60 }
+ obj
end
- -> {
- Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time)
- Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60
- }.should_not raise_error
+ Time.new(2000, 1, 1, 12, 0, 0, zone).should.is_a?(Time)
+ Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 60*60
end
- it "could have any #zone and #utc_offset because they are ignored" do
+ it "could have any #zone and #utc_offset because they are ignored if it isn't an instance of Time" do
zone = Object.new
def zone.local_to_utc(time)
Struct.new(:to_i, :zone, :utc_offset).new(time.to_i, 'America/New_York', -5*60*60)
@@ -223,7 +278,15 @@ describe "Time.new with a timezone argument" do
Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 0
end
- it "leads to raising Argument error if difference between argument and result is too large" do
+ it "cannot have arbitrary #utc_offset if it is an instance of Time" do
+ zone = Object.new
+ def zone.local_to_utc(t)
+ Time.new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, 9*60*60)
+ end
+ Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 9*60*60
+ end
+
+ it "raises ArgumentError if difference between argument and result is too large" do
zone = Object.new
def zone.local_to_utc(t)
Time.utc(t.year, t.mon, t.day + 1, t.hour, t.min, t.sec)
@@ -231,7 +294,7 @@ describe "Time.new with a timezone argument" do
-> {
Time.new(2000, 1, 1, 12, 0, 0, zone)
- }.should raise_error(ArgumentError, "utc_offset out of range")
+ }.should.raise(ArgumentError, "utc_offset out of range")
end
end
@@ -248,12 +311,9 @@ describe "Time.new with a timezone argument" do
end
it "implements subset of Time methods" do
+ # List only methods that are explicitly documented.
[
- :year, :mon, :month, :mday, :hour, :min, :sec,
- :tv_sec, :tv_usec, :usec, :tv_nsec, :nsec, :subsec,
- :to_i, :to_f, :to_r, :+, :-,
- :isdst, :dst?, :zone, :gmtoff, :gmt_offset, :utc_offset, :utc?, :gmt?,
- :to_s, :inspect, :to_a, :to_time,
+ :year, :mon, :mday, :hour, :min, :sec, :to_i, :isdst
].each do |name|
@obj.respond_to?(name).should == true
end
@@ -288,7 +348,7 @@ describe "Time.new with a timezone argument" do
-> {
Marshal.dump(time)
- }.should raise_error(NoMethodError, /undefined method `name' for/)
+ }.should.raise(NoMethodError, /undefined method [`']name' for/)
end
end
@@ -309,18 +369,18 @@ describe "Time.new with a timezone argument" do
time = TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, zone)
time_loaded = Marshal.load(Marshal.dump(time))
- time_loaded.zone.should be_kind_of TimeSpecs::TimezoneWithName
+ time_loaded.zone.should.is_a? TimeSpecs::TimezoneWithName
time_loaded.zone.name.should == "Asia/Colombo"
time_loaded.utc_offset.should == 5*3600+30*60
end
it "calls .find_timezone to build a time object if passed zone name as a timezone argument" do
time = TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, "Asia/Colombo")
- time.zone.should be_kind_of TimeSpecs::TimezoneWithName
+ time.zone.should.is_a? TimeSpecs::TimezoneWithName
time.zone.name.should == "Asia/Colombo"
time = TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, "some invalid zone name")
- time.zone.should be_kind_of TimeSpecs::TimezoneWithName
+ time.zone.should.is_a? TimeSpecs::TimezoneWithName
time.zone.name.should == "some invalid zone name"
end
@@ -328,8 +388,352 @@ describe "Time.new with a timezone argument" do
[Object.new, [], {}, :"some zone"].each do |zone|
-> {
TimeSpecs::TimeWithFindTimezone.new(2000, 1, 1, 12, 0, 0, zone)
- }.should raise_error(TypeError, /can't convert \w+ into an exact number/)
+ }.should.raise(TypeError, /can't convert \w+ into an exact number/)
+ end
+ end
+ end
+
+ describe ":in keyword argument" do
+ it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "+05:00")
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "-09:00")
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "-09:00:01")
+
+ time.utc_offset.should == -(9*60*60 + 1)
+ time.zone.should == nil
+ end
+
+ it "could be UTC offset as a number of seconds" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: 5*60*60)
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: -9*60*60)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "returns a Time with UTC offset specified as a single letter military timezone" do
+ Time.new(2000, 1, 1, 0, 0, 0, in: "W").utc_offset.should == 3600 * -10
+ end
+
+ it "could be a timezone object" do
+ zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+
+ time.utc_offset.should == 5*3600+30*60
+ time.zone.should == zone
+
+ zone = TimeSpecs::TimezoneWithName.new(name: "PST")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == zone
+ end
+
+ it "allows omitting minor arguments" do
+ Time.new(2000, 1, 1, 12, 1, 1, in: "+05:00").should == Time.new(2000, 1, 1, 12, 1, 1, "+05:00")
+ Time.new(2000, 1, 1, 12, 1, in: "+05:00").should == Time.new(2000, 1, 1, 12, 1, 0, "+05:00")
+ Time.new(2000, 1, 1, 12, in: "+05:00").should == Time.new(2000, 1, 1, 12, 0, 0, "+05:00")
+ Time.new(2000, 1, 1, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
+ Time.new(2000, 1, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
+ Time.new(2000, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
+ Time.new(in: "+05:00").should be_close(Time.now.getlocal("+05:00"), TIME_TOLERANCE)
+ end
+
+ it "converts to a provided timezone if all the positional arguments are omitted" do
+ Time.new(in: "+05:00").utc_offset.should == 5*3600
+ end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "+09:99") }.should.raise(ArgumentError)
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "ABC") }.should.raise(ArgumentError)
+ end
+
+ it "raises ArgumentError if two offset arguments are given" do
+ -> {
+ Time.new(2000, 1, 1, 12, 0, 0, "+05:00", in: "+05:00")
+ }.should.raise(ArgumentError, "timezone argument given as positional and keyword arguments")
+ end
+ end
+
+ describe "Time.new with a String argument" do
+ it "parses an ISO-8601 like format" do
+ t = Time.utc(2020, 12, 24, 15, 56, 17)
+
+ Time.new("2020-12-24T15:56:17Z").should == t
+ Time.new("2020-12-25 00:56:17 +09:00").should == t
+ Time.new("2020-12-25 00:57:47 +09:01:30").should == t
+ Time.new("2020-12-25 00:56:17 +0900").should == t
+ Time.new("2020-12-25 00:57:47 +090130").should == t
+ Time.new("2020-12-25T00:56:17+09:00").should == t
+
+ Time.new("2020-12-25T00:56:17.123456+09:00").should == Time.utc(2020, 12, 24, 15, 56, 17, 123456)
+ end
+
+ it "accepts precision keyword argument and truncates specified digits of sub-second part" do
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00").subsec.should == 0.123456789r
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: nil).subsec.should == 0.123456789876r
+ Time.new("2021-12-25 00:00:00 +09:00", precision: 0).subsec.should == 0
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: -1).subsec.should == 0.123456789876r
+ end
+
+ it "returns Time in local timezone if not provided in the String argument" do
+ Time.new("2021-12-25 00:00:00").zone.should == Time.new(2021, 12, 25).zone
+ Time.new("2021-12-25 00:00:00").utc_offset.should == Time.new(2021, 12, 25).utc_offset
+ end
+
+ it "returns Time in timezone specified in the String argument" do
+ Time.new("2021-12-25 00:00:00 +05:00").to_s.should == "2021-12-25 00:00:00 +0500"
+ end
+
+ it "returns Time in timezone specified in the String argument even if the in keyword argument provided" do
+ Time.new("2021-12-25 00:00:00 +09:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 +0900"
+ end
+
+ it "returns Time in timezone specified with in keyword argument if timezone isn't provided in the String argument" do
+ Time.new("2021-12-25 00:00:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 -0100"
+ end
+
+ it "returns Time of Jan 1 for string with just year" do
+ Time.new("2021").should == Time.new(2021, 1, 1)
+ Time.new("2021").zone.should == Time.new(2021, 1, 1).zone
+ Time.new("2021").utc_offset.should == Time.new(2021, 1, 1).utc_offset
+ end
+
+ it "returns Time of Jan 1 for string with just year in timezone specified with in keyword argument" do
+ Time.new("2021", in: "+17:00").to_s.should == "2021-01-01 00:00:00 +1700"
+ end
+
+ it "converts precision keyword argument into Integer if is not nil" do
+ obj = Object.new
+ def obj.to_int; 3; end
+
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 1.2).subsec.should == 0.1r
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: obj).subsec.should == 0.123r
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 3r).subsec.should == 0.123r
+ end
+
+ it "returns Time with correct subseconds when given seconds fraction is shorted than 6 digits" do
+ Time.new("2020-12-25T00:56:17.123 +09:00").nsec.should == 123000000
+ Time.new("2020-12-25T00:56:17.123 +09:00").usec.should == 123000
+ Time.new("2020-12-25T00:56:17.123 +09:00").subsec.should == 0.123
+ end
+
+ it "returns Time with correct subseconds when given seconds fraction is milliseconds" do
+ Time.new("2020-12-25T00:56:17.123456 +09:00").nsec.should == 123456000
+ Time.new("2020-12-25T00:56:17.123456 +09:00").usec.should == 123456
+ Time.new("2020-12-25T00:56:17.123456 +09:00").subsec.should == 0.123456
+ end
+
+ it "returns Time with correct subseconds when given seconds fraction is longer that 6 digits but shorted than 9 digits" do
+ Time.new("2020-12-25T00:56:17.12345678 +09:00").nsec.should == 123456780
+ Time.new("2020-12-25T00:56:17.12345678 +09:00").usec.should == 123456
+ Time.new("2020-12-25T00:56:17.12345678 +09:00").subsec.should == 0.12345678
+ end
+
+ it "returns Time with correct subseconds when given seconds fraction is nanoseconds" do
+ Time.new("2020-12-25T00:56:17.123456789 +09:00").nsec.should == 123456789
+ Time.new("2020-12-25T00:56:17.123456789 +09:00").usec.should == 123456
+ Time.new("2020-12-25T00:56:17.123456789 +09:00").subsec.should == 0.123456789
+ end
+
+ it "returns Time with correct subseconds when given seconds fraction is longer than 9 digits" do
+ Time.new("2020-12-25T00:56:17.123456789876 +09:00").nsec.should == 123456789
+ Time.new("2020-12-25T00:56:17.123456789876 +09:00").usec.should == 123456
+ Time.new("2020-12-25T00:56:17.123456789876 +09:00").subsec.should == 0.123456789
+ end
+
+ it "raise TypeError is can't convert precision keyword argument into Integer" do
+ -> {
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: "")
+ }.should.raise(TypeError, "no implicit conversion of String into Integer")
+ end
+
+ it "raises ArgumentError if part of time string is missing" do
+ -> {
+ Time.new("2020-12-25 00:56 +09:00")
+ }.should.raise(ArgumentError, /missing sec part: 00:56 |can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00 +09:00")
+ }.should.raise(ArgumentError, /missing min part: 00 |can't parse:/)
+ end
+
+ it "raises ArgumentError if the time part is missing" do
+ -> {
+ Time.new("2020-12-25")
+ }.should.raise(ArgumentError, /no time information|can't parse:/)
+ end
+
+ it "raises ArgumentError if day is missing" do
+ -> {
+ Time.new("2020-12")
+ }.should.raise(ArgumentError, /no time information|can't parse:/)
+ end
+
+ it "raises ArgumentError if subsecond is missing after dot" do
+ -> {
+ Time.new("2020-12-25 00:56:17. +0900")
+ }.should.raise(ArgumentError, /subsecond expected after dot: 00:56:17. |can't parse:/)
+ end
+
+ it "raises ArgumentError if String argument is not in the supported format" do
+ -> {
+ Time.new("021-12-25 00:00:00.123456 +09:00")
+ }.should.raise(ArgumentError, /year must be 4 or more digits: 021|can't parse:/)
+
+ -> {
+ Time.new("2020-012-25 00:56:17 +0900")
+ }.should.raise(ArgumentError, /\Atwo digits mon is expected after [`']-': -012-25 00:\z|can't parse:/)
+
+ -> {
+ Time.new("2020-2-25 00:56:17 +0900")
+ }.should.raise(ArgumentError, /\Atwo digits mon is expected after [`']-': -2-25 00:56\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-215 00:56:17 +0900")
+ }.should.raise(ArgumentError, /\Atwo digits mday is expected after [`']-': -215 00:56:\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 000:56:17 +0900")
+ }.should.raise(ArgumentError, /two digits hour is expected: 000:56:17 |can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 0:56:17 +0900")
+ }.should.raise(ArgumentError, /two digits hour is expected: 0:56:17 \+0|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:516:17 +0900")
+ }.should.raise(ArgumentError, /\Atwo digits min is expected after [`']:': :516:17 \+09\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:6:17 +0900")
+ }.should.raise(ArgumentError, /\Atwo digits min is expected after [`']:': :6:17 \+0900\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:56:137 +0900")
+ }.should.raise(ArgumentError, /\Atwo digits sec is expected after [`']:': :137 \+0900\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:56:7 +0900")
+ }.should.raise(ArgumentError, /\Atwo digits sec is expected after [`']:': :7 \+0900\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:56. +0900")
+ }.should.raise(ArgumentError, /fraction min is not supported: 00:56\.|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00. +0900")
+ }.should.raise(ArgumentError, /fraction hour is not supported: 00\.|can't parse:/)
+ end
+
+ it "raises ArgumentError if date/time parts values are not valid" do
+ -> {
+ Time.new("2020-13-25 00:56:17 +09:00")
+ }.should.raise(ArgumentError, /(mon|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-32 00:56:17 +09:00")
+ }.should.raise(ArgumentError, /(mday|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 25:56:17 +09:00")
+ }.should.raise(ArgumentError, /(hour|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:61:17 +09:00")
+ }.should.raise(ArgumentError, /(min|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:56:61 +09:00")
+ }.should.raise(ArgumentError, /(sec|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:56:17 +23:59:60")
+ }.should.raise(ArgumentError, /utc_offset|argument out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:56:17 +24:00")
+ }.should.raise(ArgumentError, /(utc_offset|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:56:17 +23:61")
+ }.should.raise(ArgumentError, /utc_offset/)
+
+ ruby_bug '#20797', ''...'3.4' do
+ -> {
+ Time.new("2020-12-25 00:56:17 +00:23:61")
+ }.should.raise(ArgumentError, /utc_offset/)
end
end
+
+ it "raises ArgumentError if utc offset parts are not valid" do
+ -> { Time.new("2020-12-25 00:56:17 +24:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.new("2020-12-25 00:56:17 +2400") }.should.raise(ArgumentError, "utc_offset out of range")
+
+ -> { Time.new("2020-12-25 00:56:17 +99:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.new("2020-12-25 00:56:17 +9900") }.should.raise(ArgumentError, "utc_offset out of range")
+
+ -> { Time.new("2020-12-25 00:56:17 +00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.new("2020-12-25 00:56:17 +0060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
+
+ -> { Time.new("2020-12-25 00:56:17 +00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.new("2020-12-25 00:56:17 +0099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
+
+ ruby_bug '#20797', ''...'3.4' do
+ -> { Time.new("2020-12-25 00:56:17 +00:00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.new("2020-12-25 00:56:17 +000060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
+
+ -> { Time.new("2020-12-25 00:56:17 +00:00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.new("2020-12-25 00:56:17 +000099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
+ end
+ end
+
+ it "raises ArgumentError if string has not ascii-compatible encoding" do
+ -> {
+ Time.new("2021-11-31 00:00:60 +09:00".encode("utf-32le"))
+ }.should.raise(ArgumentError, "time string should have ASCII compatible encoding")
+ end
+
+ it "raises ArgumentError if string doesn't start with year" do
+ -> {
+ Time.new("a\nb")
+ }.should.raise(ArgumentError, "can't parse: \"a\\nb\"")
+ end
+
+ it "raises ArgumentError if string has extra characters after offset" do
+ -> {
+ Time.new("2021-11-31 00:00:59 +09:00 abc")
+ }.should.raise(ArgumentError, /can't parse.+ abc/)
+ end
+
+ it "raises ArgumentError when there are leading space characters" do
+ -> { Time.new(" 2020-12-02 00:00:00") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("\t2020-12-02 00:00:00") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("\n2020-12-02 00:00:00") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("\v2020-12-02 00:00:00") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("\f2020-12-02 00:00:00") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("\r2020-12-02 00:00:00") }.should.raise(ArgumentError, /can't parse/)
+ end
+
+ it "raises ArgumentError when there are trailing whitespaces" do
+ -> { Time.new("2020-12-02 00:00:00 ") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\t") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\n") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\v") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\f") }.should.raise(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\r") }.should.raise(ArgumentError, /can't parse/)
+ end
end
end
diff --git a/spec/ruby/core/time/now_spec.rb b/spec/ruby/core/time/now_spec.rb
index 7dc7951996..533cf68380 100644
--- a/spec/ruby/core/time/now_spec.rb
+++ b/spec/ruby/core/time/now_spec.rb
@@ -3,4 +3,179 @@ require_relative 'shared/now'
describe "Time.now" do
it_behaves_like :time_now, :now
+
+ describe ":in keyword argument" do
+ it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
+ time = Time.now(in: "+05:00")
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.now(in: "-09:00")
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+
+ time = Time.now(in: "-09:00:01")
+
+ time.utc_offset.should == -(9*60*60 + 1)
+ time.zone.should == nil
+ end
+
+ it "could be UTC offset as a number of seconds" do
+ time = Time.now(in: 5*60*60)
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.now(in: -9*60*60)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "returns a Time with UTC offset specified as a single letter military timezone" do
+ Time.now(in: "W").utc_offset.should == 3600 * -10
+ end
+
+ it "could be a timezone object" do
+ zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
+ time = Time.now(in: zone)
+
+ time.utc_offset.should == 5*3600+30*60
+ time.zone.should == zone
+
+ zone = TimeSpecs::TimezoneWithName.new(name: "PST")
+ time = Time.now(in: zone)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == zone
+ end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.now(in: "+09:99") }.should.raise(ArgumentError)
+ -> { Time.now(in: "ABC") }.should.raise(ArgumentError)
+ end
+
+ it "raises ArgumentError if String argument and hours greater than 23" do
+ -> { Time.now(in: "+24:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.now(in: "+2400") }.should.raise(ArgumentError, "utc_offset out of range")
+
+ -> { Time.now(in: "+99:00") }.should.raise(ArgumentError, "utc_offset out of range")
+ -> { Time.now(in: "+9900") }.should.raise(ArgumentError, "utc_offset out of range")
+ end
+
+ it "raises ArgumentError if String argument and minutes greater than 59" do
+ -> { Time.now(in: "+00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.now(in: "+0060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
+
+ -> { Time.now(in: "+00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.now(in: "+0099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
+ end
+
+ ruby_bug '#20797', ''...'3.4' do
+ it "raises ArgumentError if String argument and seconds greater than 59" do
+ -> { Time.now(in: "+00:00:60") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.now(in: "+000060") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
+
+ -> { Time.now(in: "+00:00:99") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.now(in: "+000099") }.should.raise(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
+ end
+ end
+ end
+
+ describe "Timezone object" do # https://bugs.ruby-lang.org/issues/17485
+ it "raises TypeError if timezone does not implement #utc_to_local method" do
+ zone = Object.new
+ def zone.local_to_utc(time)
+ time
+ end
+
+ -> {
+ Time.now(in: zone)
+ }.should.raise(TypeError, /can't convert Object into an exact number/)
+ end
+
+ it "does not raise exception if timezone does not implement #local_to_utc method" do
+ zone = Object.new
+ def zone.utc_to_local(time)
+ time
+ end
+
+ Time.now(in: zone).should.is_a?(Time)
+ end
+
+ # The result also should be a Time or Time-like object (not necessary to be the same class)
+ # or Integer. The zone of the result is just ignored.
+ describe "returned value by #utc_to_local and #local_to_utc methods" do
+ it "could be Time instance" do
+ zone = Object.new
+ def zone.utc_to_local(t)
+ time = Time.new(t.year, t.mon, t.day, t.hour, t.min, t.sec, t.utc_offset)
+ time + 60 * 60 # + 1 hour
+ end
+
+ Time.now(in: zone).should.is_a?(Time)
+ Time.now(in: zone).utc_offset.should == 3600
+ end
+
+ it "could be Time subclass instance" do
+ zone = Object.new
+ def zone.utc_to_local(t)
+ time = Time.new(t.year, t.mon, t.day, t.hour, t.min, t.sec, t.utc_offset)
+ time += 60 * 60 # + 1 hour
+
+ Class.new(Time).new(time.year, time.mon, time.day, time.hour, time.min, time.sec, time.utc_offset)
+ end
+
+ Time.now(in: zone).should.is_a?(Time)
+ Time.now(in: zone).utc_offset.should == 3600
+ end
+
+ it "could be Integer" do
+ zone = Object.new
+ def zone.utc_to_local(time)
+ time.to_i + 60*60
+ end
+
+ Time.now(in: zone).should.is_a?(Time)
+ Time.now(in: zone).utc_offset.should == 60*60
+ end
+
+ it "could have any #zone and #utc_offset because they are ignored" do
+ zone = Object.new
+ def zone.utc_to_local(t)
+ Struct.new(:year, :mon, :mday, :hour, :min, :sec, :isdst, :to_i, :zone, :utc_offset) # rubocop:disable Lint/StructNewOverride
+ .new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.isdst, t.to_i, 'America/New_York', -5*60*60)
+ end
+ Time.now(in: zone).utc_offset.should == 0
+
+ zone = Object.new
+ def zone.utc_to_local(t)
+ Struct.new(:year, :mon, :mday, :hour, :min, :sec, :isdst, :to_i, :zone, :utc_offset) # rubocop:disable Lint/StructNewOverride
+ .new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.isdst, t.to_i, 'Asia/Tokyo', 9*60*60)
+ end
+ Time.now(in: zone).utc_offset.should == 0
+
+ zone = Object.new
+ def zone.utc_to_local(t)
+ Time.new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, 9*60*60)
+ end
+ Time.now(in: zone).utc_offset.should == 0
+ end
+
+ it "raises ArgumentError if difference between argument and result is too large" do
+ zone = Object.new
+ def zone.utc_to_local(t)
+ time = Time.utc(t.year, t.mon, t.day, t.hour, t.min, t.sec, t.utc_offset)
+ time -= 24 * 60 * 60 # - 1 day
+ Time.utc(time.year, time.mon, time.day, time.hour, time.min, time.sec, time.utc_offset)
+ end
+
+ -> {
+ Time.now(in: zone)
+ }.should.raise(ArgumentError, "utc_offset out of range")
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/time/plus_spec.rb b/spec/ruby/core/time/plus_spec.rb
index 642393b615..6bd01bcdf3 100644
--- a/spec/ruby/core/time/plus_spec.rb
+++ b/spec/ruby/core/time/plus_spec.rb
@@ -17,9 +17,9 @@ describe "Time#+" do
end
it "raises a TypeError if given argument is a coercible String" do
- -> { Time.now + "1" }.should raise_error(TypeError)
- -> { Time.now + "0.1" }.should raise_error(TypeError)
- -> { Time.now + "1/3" }.should raise_error(TypeError)
+ -> { Time.now + "1" }.should.raise(TypeError)
+ -> { Time.now + "0.1" }.should.raise(TypeError)
+ -> { Time.now + "1/3" }.should.raise(TypeError)
end
it "increments the time by the specified amount as rational numbers" do
@@ -32,8 +32,8 @@ describe "Time#+" do
end
it "raises TypeError on argument that can't be coerced into Rational" do
- -> { Time.now + Object.new }.should raise_error(TypeError)
- -> { Time.now + "stuff" }.should raise_error(TypeError)
+ -> { Time.now + Object.new }.should.raise(TypeError)
+ -> { Time.now + "stuff" }.should.raise(TypeError)
end
it "returns a UTC time if self is UTC" do
@@ -68,15 +68,15 @@ describe "Time#+" do
it "does not return a subclass instance" do
c = Class.new(Time)
x = c.now + 1
- x.should be_an_instance_of(Time)
+ x.should.instance_of?(Time)
end
it "raises TypeError on Time argument" do
- -> { Time.now + Time.now }.should raise_error(TypeError)
+ -> { Time.now + Time.now }.should.raise(TypeError)
end
it "raises TypeError on nil argument" do
- -> { Time.now + nil }.should raise_error(TypeError)
+ -> { Time.now + nil }.should.raise(TypeError)
end
#see [ruby-dev:38446]
diff --git a/spec/ruby/core/time/round_spec.rb b/spec/ruby/core/time/round_spec.rb
index 0cbed04ade..a739cabfdf 100644
--- a/spec/ruby/core/time/round_spec.rb
+++ b/spec/ruby/core/time/round_spec.rb
@@ -20,8 +20,8 @@ describe "Time#round" do
it "returns an instance of Time, even if #round is called on a subclass" do
subclass = Class.new(Time)
instance = subclass.at(0)
- instance.class.should equal subclass
- instance.round.should be_an_instance_of(Time)
+ instance.class.should.equal? subclass
+ instance.round.should.instance_of?(Time)
end
it "copies own timezone to the returning value" do
diff --git a/spec/ruby/core/time/shared/gmtime.rb b/spec/ruby/core/time/shared/gmtime.rb
index 5ed64c2ab6..aa76b436cc 100644
--- a/spec/ruby/core/time/shared/gmtime.rb
+++ b/spec/ruby/core/time/shared/gmtime.rb
@@ -4,14 +4,21 @@ describe :time_gmtime, shared: true do
with_timezone("CST", -6) do
t = Time.local(2007, 1, 9, 6, 0, 0)
t.send(@method)
- t.should == Time.gm(2007, 1, 9, 12, 0, 0)
+ # Time#== compensates for time zones, so check all parts separately
+ t.year.should == 2007
+ t.month.should == 1
+ t.mday.should == 9
+ t.hour.should == 12
+ t.min.should == 0
+ t.sec.should == 0
+ t.zone.should == "UTC"
end
end
it "returns self" do
with_timezone("CST", -6) do
t = Time.local(2007, 1, 9, 12, 0, 0)
- t.send(@method).should equal(t)
+ t.send(@method).should.equal?(t)
end
end
@@ -19,14 +26,14 @@ describe :time_gmtime, shared: true do
it "does not raise an error if already in UTC" do
time = Time.gm(2007, 1, 9, 12, 0, 0)
time.freeze
- time.send(@method).should equal(time)
+ time.send(@method).should.equal?(time)
end
- it "raises a RuntimeError if the time is not UTC" do
+ it "raises a FrozenError if the time is not UTC" do
with_timezone("CST", -6) do
time = Time.now
time.freeze
- -> { time.send(@method) }.should raise_error(RuntimeError)
+ -> { time.send(@method) }.should.raise(FrozenError)
end
end
end
diff --git a/spec/ruby/core/time/shared/inspect.rb b/spec/ruby/core/time/shared/inspect.rb
index 4133671924..82f7f3c686 100644
--- a/spec/ruby/core/time/shared/inspect.rb
+++ b/spec/ruby/core/time/shared/inspect.rb
@@ -16,6 +16,6 @@ describe :inspect, shared: true do
end
it "returns a US-ASCII encoded string" do
- Time.now.send(@method).encoding.should equal(Encoding::US_ASCII)
+ Time.now.send(@method).encoding.should.equal?(Encoding::US_ASCII)
end
end
diff --git a/spec/ruby/core/time/shared/local.rb b/spec/ruby/core/time/shared/local.rb
index 43f331c4c1..068e314999 100644
--- a/spec/ruby/core/time/shared/local.rb
+++ b/spec/ruby/core/time/shared/local.rb
@@ -7,12 +7,10 @@ describe :time_local, shared: true do
end
platform_is_not :windows do
- describe "timezone changes" do
- it "correctly adjusts the timezone change to 'CEST' on 'Europe/Amsterdam'" do
- with_timezone("Europe/Amsterdam") do
- Time.send(@method, 1940, 5, 16).to_a.should ==
- [0, 40, 1, 16, 5, 1940, 4, 137, true, "CEST"]
- end
+ it "uses the 'CET' timezone with TZ=Europe/Amsterdam in 1970" do
+ with_timezone("Europe/Amsterdam") do
+ Time.send(@method, 1970, 5, 16).to_a.should ==
+ [0, 0, 0, 16, 5, 1970, 6, 136, false, "CET"]
end
end
end
@@ -41,5 +39,4 @@ describe :time_local_10_arg, shared: true do
end
end
end
-
end
diff --git a/spec/ruby/core/time/shared/now.rb b/spec/ruby/core/time/shared/now.rb
index f4018d72f4..839cfdcd2a 100644
--- a/spec/ruby/core/time/shared/now.rb
+++ b/spec/ruby/core/time/shared/now.rb
@@ -2,8 +2,8 @@ require_relative '../fixtures/classes'
describe :time_now, shared: true do
it "creates a subclass instance if called on a subclass" do
- TimeSpecs::SubTime.send(@method).should be_an_instance_of(TimeSpecs::SubTime)
- TimeSpecs::MethodHolder.send(@method).should be_an_instance_of(Time)
+ TimeSpecs::SubTime.send(@method).should.instance_of?(TimeSpecs::SubTime)
+ TimeSpecs::MethodHolder.send(@method).should.instance_of?(Time)
end
it "sets the current time" do
diff --git a/spec/ruby/core/time/shared/time_params.rb b/spec/ruby/core/time/shared/time_params.rb
index 63d0dbc120..f0de986b8e 100644
--- a/spec/ruby/core/time/shared/time_params.rb
+++ b/spec/ruby/core/time/shared/time_params.rb
@@ -30,7 +30,7 @@ describe :time_params, shared: true do
end
it "raises a TypeError if the year is nil" do
- -> { Time.send(@method, nil) }.should raise_error(TypeError)
+ -> { Time.send(@method, nil) }.should.raise(TypeError)
end
it "accepts nil month, day, hour, minute, and second" do
@@ -145,46 +145,55 @@ describe :time_params, shared: true do
end
it "raises an ArgumentError for out of range month" do
+ # For some reason MRI uses a different message for month in 13-15 and month>=16
-> {
- Time.send(@method, 2008, 13, 31, 23, 59, 59)
- }.should raise_error(ArgumentError)
+ Time.send(@method, 2008, 16, 31, 23, 59, 59)
+ }.should.raise(ArgumentError, /(mon|argument) out of range/)
end
it "raises an ArgumentError for out of range day" do
-> {
Time.send(@method, 2008, 12, 32, 23, 59, 59)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises an ArgumentError for out of range hour" do
-> {
Time.send(@method, 2008, 12, 31, 25, 59, 59)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises an ArgumentError for out of range minute" do
-> {
Time.send(@method, 2008, 12, 31, 23, 61, 59)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "raises an ArgumentError for out of range second" do
+ # For some reason MRI uses different messages for seconds 61-63 and seconds >= 64
-> {
Time.send(@method, 2008, 12, 31, 23, 59, 61)
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError, /(sec|argument) out of range/)
+ -> {
+ Time.send(@method, 2008, 12, 31, 23, 59, -1)
+ }.should.raise(ArgumentError, "argument out of range")
+ end
+
+ it "raises ArgumentError when given 8 arguments" do
+ -> { Time.send(@method, *[0]*8) }.should.raise(ArgumentError)
end
it "raises ArgumentError when given 9 arguments" do
- -> { Time.send(@method, *[0]*9) }.should raise_error(ArgumentError)
+ -> { Time.send(@method, *[0]*9) }.should.raise(ArgumentError)
end
it "raises ArgumentError when given 11 arguments" do
- -> { Time.send(@method, *[0]*11) }.should raise_error(ArgumentError)
+ -> { Time.send(@method, *[0]*11) }.should.raise(ArgumentError)
end
it "returns subclass instances" do
c = Class.new(Time)
- c.send(@method, 2008, "12").should be_an_instance_of(c)
+ c.send(@method, 2008, "12").should.instance_of?(c)
end
end
@@ -204,23 +213,23 @@ describe :time_params_10_arg, shared: true do
it "raises an ArgumentError for out of range values" do
-> {
Time.send(@method, 61, 59, 23, 31, 12, 2008, :ignored, :ignored, :ignored, :ignored)
- }.should raise_error(ArgumentError) # sec
+ }.should.raise(ArgumentError) # sec
-> {
Time.send(@method, 59, 61, 23, 31, 12, 2008, :ignored, :ignored, :ignored, :ignored)
- }.should raise_error(ArgumentError) # min
+ }.should.raise(ArgumentError) # min
-> {
Time.send(@method, 59, 59, 25, 31, 12, 2008, :ignored, :ignored, :ignored, :ignored)
- }.should raise_error(ArgumentError) # hour
+ }.should.raise(ArgumentError) # hour
-> {
Time.send(@method, 59, 59, 23, 32, 12, 2008, :ignored, :ignored, :ignored, :ignored)
- }.should raise_error(ArgumentError) # day
+ }.should.raise(ArgumentError) # day
-> {
Time.send(@method, 59, 59, 23, 31, 13, 2008, :ignored, :ignored, :ignored, :ignored)
- }.should raise_error(ArgumentError) # month
+ }.should.raise(ArgumentError) # month
end
end
@@ -231,7 +240,7 @@ describe :time_params_microseconds, shared: true do
end
it "raises an ArgumentError for out of range microsecond" do
- -> { Time.send(@method, 2000, 1, 1, 20, 15, 1, 1000000) }.should raise_error(ArgumentError)
+ -> { Time.send(@method, 2000, 1, 1, 20, 15, 1, 1000000) }.should.raise(ArgumentError)
end
it "handles fractional microseconds as a Float" do
diff --git a/spec/ruby/core/time/shared/xmlschema.rb b/spec/ruby/core/time/shared/xmlschema.rb
new file mode 100644
index 0000000000..d68c18df36
--- /dev/null
+++ b/spec/ruby/core/time/shared/xmlschema.rb
@@ -0,0 +1,31 @@
+describe :time_xmlschema, shared: true do
+ ruby_version_is "3.4" do
+ it "generates ISO-8601 strings in Z for UTC times" do
+ t = Time.utc(1985, 4, 12, 23, 20, 50, 521245)
+ t.send(@method).should == "1985-04-12T23:20:50Z"
+ t.send(@method, 2).should == "1985-04-12T23:20:50.52Z"
+ t.send(@method, 9).should == "1985-04-12T23:20:50.521245000Z"
+ end
+
+ it "generates ISO-8601 string with timeone offset for non-UTC times" do
+ t = Time.new(1985, 4, 12, 23, 20, 50, "+02:00")
+ t.send(@method).should == "1985-04-12T23:20:50+02:00"
+ t.send(@method, 2).should == "1985-04-12T23:20:50.00+02:00"
+ end
+
+ it "year is always at least 4 digits" do
+ t = Time.utc(12, 4, 12)
+ t.send(@method).should == "0012-04-12T00:00:00Z"
+ end
+
+ it "year can be more than 4 digits" do
+ t = Time.utc(40_000, 4, 12)
+ t.send(@method).should == "40000-04-12T00:00:00Z"
+ end
+
+ it "year can be negative" do
+ t = Time.utc(-2000, 4, 12)
+ t.send(@method).should == "-2000-04-12T00:00:00Z"
+ end
+ end
+end
diff --git a/spec/ruby/core/time/strftime_spec.rb b/spec/ruby/core/time/strftime_spec.rb
index 1bd24b0538..1528a668a1 100644
--- a/spec/ruby/core/time/strftime_spec.rb
+++ b/spec/ruby/core/time/strftime_spec.rb
@@ -25,7 +25,7 @@ describe "Time#strftime" do
# Differences with date
it "requires an argument" do
- -> { @time.strftime }.should raise_error(ArgumentError)
+ -> { @time.strftime }.should.raise(ArgumentError)
end
# %Z is zone name or empty for Time
@@ -49,4 +49,43 @@ describe "Time#strftime" do
time = @new_time_with_offset[2012, 1, 1, 0, 0, 0, Rational(36645, 10)]
time.strftime("%::z").should == "+01:01:05"
end
+
+ it "supports RFC 3339 UTC for unknown offset local time, -0000, as %-z" do
+ time = Time.gm(2022)
+
+ time.strftime("%z").should == "+0000"
+ time.strftime("%-z").should == "-0000"
+ time.strftime("%-:z").should == "-00:00"
+ time.strftime("%-::z").should == "-00:00:00"
+ end
+
+ it "applies '-' flag to UTC time" do
+ time = Time.utc(2022)
+ time.strftime("%-z").should == "-0000"
+
+ time = Time.gm(2022)
+ time.strftime("%-z").should == "-0000"
+
+ time = Time.new(2022, 1, 1, 0, 0, 0, "Z")
+ time.strftime("%-z").should == "-0000"
+
+ time = Time.new(2022, 1, 1, 0, 0, 0, "-00:00")
+ time.strftime("%-z").should == "-0000"
+
+ time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00").utc
+ time.strftime("%-z").should == "-0000"
+ end
+
+ it "ignores '-' flag for non-UTC time" do
+ time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00")
+ time.strftime("%-z").should == "+0300"
+ end
+
+ it "works correctly with width, _ and 0 flags, and :" do
+ Time.now.utc.strftime("%-_10z").should == " -000"
+ Time.now.utc.strftime("%-10z").should == "-000000000"
+ Time.now.utc.strftime("%-010:z").should == "-000000:00"
+ Time.now.utc.strftime("%-_10:z").should == " -0:00"
+ Time.now.utc.strftime("%-_10::z").should == " -0:00:00"
+ end
end
diff --git a/spec/ruby/core/time/subsec_spec.rb b/spec/ruby/core/time/subsec_spec.rb
index 0f2c4eb856..3ed1bf5dd1 100644
--- a/spec/ruby/core/time/subsec_spec.rb
+++ b/spec/ruby/core/time/subsec_spec.rb
@@ -2,26 +2,26 @@ require_relative '../../spec_helper'
describe "Time#subsec" do
it "returns 0 as an Integer for a Time with a whole number of seconds" do
- Time.at(100).subsec.should eql(0)
+ Time.at(100).subsec.should.eql?(0)
end
it "returns the fractional seconds as a Rational for a Time constructed with a Rational number of seconds" do
- Time.at(Rational(3, 2)).subsec.should eql(Rational(1, 2))
+ Time.at(Rational(3, 2)).subsec.should.eql?(Rational(1, 2))
end
it "returns the fractional seconds as a Rational for a Time constructed with a Float number of seconds" do
- Time.at(10.75).subsec.should eql(Rational(3, 4))
+ Time.at(10.75).subsec.should.eql?(Rational(3, 4))
end
it "returns the fractional seconds as a Rational for a Time constructed with an Integer number of microseconds" do
- Time.at(0, 999999).subsec.should eql(Rational(999999, 1000000))
+ Time.at(0, 999999).subsec.should.eql?(Rational(999999, 1000000))
end
it "returns the fractional seconds as a Rational for a Time constructed with an Rational number of microseconds" do
- Time.at(0, Rational(9, 10)).subsec.should eql(Rational(9, 10000000))
+ Time.at(0, Rational(9, 10)).subsec.should.eql?(Rational(9, 10000000))
end
it "returns the fractional seconds as a Rational for a Time constructed with an Float number of microseconds" do
- Time.at(0, 0.75).subsec.should eql(Rational(3, 4000000))
+ Time.at(0, 0.75).subsec.should.eql?(Rational(3, 4000000))
end
end
diff --git a/spec/ruby/core/time/succ_spec.rb b/spec/ruby/core/time/succ_spec.rb
deleted file mode 100644
index e8249059d1..0000000000
--- a/spec/ruby/core/time/succ_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-ruby_version_is ""..."3.0" do
- require_relative '../../spec_helper'
- require_relative 'fixtures/classes'
-
- describe "Time#succ" do
- it "returns a new time one second later than time" do
- suppress_warning {
- @result = Time.at(100).succ
- }
-
- @result.should == Time.at(101)
- end
-
- it "returns a new instance" do
- time = Time.at(100)
-
- suppress_warning {
- @result = time.succ
- }
-
- @result.should_not equal time
- end
-
- it "is obsolete" do
- -> {
- Time.at(100).succ
- }.should complain(/Time#succ is obsolete/)
- end
-
- context "zone is a timezone object" do
- it "preserves time zone" do
- zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60))
- time = Time.new(2012, 1, 1, 12, 0, 0, zone) - 1
-
- time.zone.should == zone
- end
- end
- end
-end
diff --git a/spec/ruby/core/time/to_r_spec.rb b/spec/ruby/core/time/to_r_spec.rb
index 6af2d9b7ea..e30f5d8f94 100644
--- a/spec/ruby/core/time/to_r_spec.rb
+++ b/spec/ruby/core/time/to_r_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Time#to_r" do
it "returns the a Rational representing seconds and subseconds since the epoch" do
- Time.at(Rational(11, 10)).to_r.should eql(Rational(11, 10))
+ Time.at(Rational(11, 10)).to_r.should.eql?(Rational(11, 10))
end
it "returns a Rational even for a whole number of seconds" do
- Time.at(2).to_r.should eql(Rational(2))
+ Time.at(2).to_r.should.eql?(Rational(2))
end
end
diff --git a/spec/ruby/core/time/utc_spec.rb b/spec/ruby/core/time/utc_spec.rb
index 74c17a93d1..ab3c0df657 100644
--- a/spec/ruby/core/time/utc_spec.rb
+++ b/spec/ruby/core/time/utc_spec.rb
@@ -4,8 +4,53 @@ require_relative 'shared/gmtime'
require_relative 'shared/time_params'
describe "Time#utc?" do
- it "returns true if time represents a time in UTC (GMT)" do
- Time.now.should_not.utc?
+ it "returns true only if time represents a time in UTC (GMT)" do
+ Time.now.utc?.should == false
+ Time.now.utc.utc?.should == true
+ end
+
+ it "treats time as UTC what was created in different ways" do
+ Time.now.utc.utc?.should == true
+ Time.now.gmtime.utc?.should == true
+ Time.now.getgm.utc?.should == true
+ Time.now.getutc.utc?.should == true
+ Time.utc(2022).utc?.should == true
+ end
+
+ it "does treat time with 'UTC' offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, "UTC").utc?.should == true
+ Time.now.localtime("UTC").utc?.should == true
+ Time.at(Time.now, in: 'UTC').utc?.should == true
+
+ Time.new(2022, 1, 1, 0, 0, 0, in: "UTC").utc?.should == true
+ Time.now(in: "UTC").utc?.should == true
+ end
+
+ it "does treat time with Z offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, "Z").utc?.should == true
+ Time.now.localtime("Z").utc?.should == true
+ Time.at(Time.now, in: 'Z').utc?.should == true
+
+ Time.new(2022, 1, 1, 0, 0, 0, in: "Z").utc?.should == true
+ Time.now(in: "Z").utc?.should == true
+ end
+
+ it "does treat time with -00:00 offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, "-00:00").utc?.should == true
+ Time.now.localtime("-00:00").utc?.should == true
+ Time.at(Time.now, in: '-00:00').utc?.should == true
+ end
+
+ it "does not treat time with +00:00 offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, "+00:00").utc?.should == false
+ Time.now.localtime("+00:00").utc?.should == false
+ Time.at(Time.now, in: "+00:00").utc?.should == false
+ end
+
+ it "does not treat time with 0 offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, 0).utc?.should == false
+ Time.now.localtime(0).utc?.should == false
+ Time.at(Time.now, in: 0).utc?.should == false
end
end
diff --git a/spec/ruby/core/time/xmlschema_spec.rb b/spec/ruby/core/time/xmlschema_spec.rb
new file mode 100644
index 0000000000..bdf1dc7923
--- /dev/null
+++ b/spec/ruby/core/time/xmlschema_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/xmlschema'
+
+describe "Time#xmlschema" do
+ it_behaves_like :time_xmlschema, :xmlschema
+end
diff --git a/spec/ruby/core/time/yday_spec.rb b/spec/ruby/core/time/yday_spec.rb
index 6ea5ff8f1b..e920c2e28d 100644
--- a/spec/ruby/core/time/yday_spec.rb
+++ b/spec/ruby/core/time/yday_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative '../../shared/time/yday'
describe "Time#yday" do
it "returns an integer representing the day of the year, 1..366" do
@@ -7,15 +8,5 @@ describe "Time#yday" do
end
end
- it 'returns the correct value for each day of each month' do
- mdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
-
- yday = 1
- mdays.each_with_index do |days, month|
- days.times do |day|
- Time.new(2014, month+1, day+1).yday.should == yday
- yday += 1
- end
- end
- end
+ it_behaves_like :time_yday, -> year, month, day { Time.new(year, month, day).yday }
end
diff --git a/spec/ruby/core/time/zone_spec.rb b/spec/ruby/core/time/zone_spec.rb
index 907ccf9f4b..2cb3c5e7bb 100644
--- a/spec/ruby/core/time/zone_spec.rb
+++ b/spec/ruby/core/time/zone_spec.rb
@@ -6,7 +6,7 @@ describe "Time#zone" do
with_timezone("America/New_York") do
Time.new(2001, 1, 1, 0, 0, 0).zone.should == "EST"
Time.new(2001, 7, 1, 0, 0, 0).zone.should == "EDT"
- %w[EST EDT].should include Time.now.zone
+ %w[EST EDT].should.include? Time.now.zone
end
end
end
@@ -29,7 +29,7 @@ describe "Time#zone" do
t = Time.new(2005, 2, 27, 22, 50, 0, -3600)
with_timezone("America/New_York") do
- t.getlocal("+05:00").zone.should be_nil
+ t.getlocal("+05:00").zone.should == nil
end
end
@@ -52,14 +52,35 @@ describe "Time#zone" do
end
it "doesn't raise errors for a Time with a fixed offset" do
- -> {
- Time.new(2001, 1, 1, 0, 0, 0, "+05:00").zone
- }.should_not raise_error
+ Time.new(2001, 1, 1, 0, 0, 0, "+05:00").zone.should == nil
end
end
it "returns UTC when called on a UTC time" do
Time.now.utc.zone.should == "UTC"
+ Time.now.gmtime.zone.should == "UTC"
+ Time.now.getgm.zone.should == "UTC"
+ Time.now.getutc.zone.should == "UTC"
+ Time.utc(2022).zone.should == "UTC"
+ Time.new(2022, 1, 1, 0, 0, 0, "UTC").zone.should == "UTC"
+ Time.new(2022, 1, 1, 0, 0, 0, "Z").zone.should == "UTC"
+ Time.now.localtime("UTC").zone.should == "UTC"
+ Time.now.localtime("Z").zone.should == "UTC"
+ Time.at(Time.now, in: 'UTC').zone.should == "UTC"
+ Time.at(Time.now, in: 'Z').zone.should == "UTC"
+
+ Time.new(2022, 1, 1, 0, 0, 0, "-00:00").zone.should == "UTC"
+ Time.now.localtime("-00:00").zone.should == "UTC"
+ Time.at(Time.now, in: '-00:00').zone.should == "UTC"
+
+ Time.new(2022, 1, 1, 0, 0, 0, in: "UTC").zone.should == "UTC"
+ Time.new(2022, 1, 1, 0, 0, 0, in: "Z").zone.should == "UTC"
+
+ Time.now(in: 'UTC').zone.should == "UTC"
+ Time.now(in: 'Z').zone.should == "UTC"
+
+ Time.at(Time.now, in: 'UTC').zone.should == "UTC"
+ Time.at(Time.now, in: 'Z').zone.should == "UTC"
end
platform_is_not :aix, :windows do
diff --git a/spec/ruby/core/tracepoint/allow_reentry_spec.rb b/spec/ruby/core/tracepoint/allow_reentry_spec.rb
new file mode 100644
index 0000000000..475cca29a9
--- /dev/null
+++ b/spec/ruby/core/tracepoint/allow_reentry_spec.rb
@@ -0,0 +1,30 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe 'TracePoint.allow_reentry' do
+ it 'allows the reentrance in a given block' do
+ event_lines = []
+ l1 = l2 = l3 = l4 = nil
+ TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
+
+ event_lines << tp.lineno
+ next if (__LINE__ + 2 .. __LINE__ + 4).cover?(tp.lineno)
+ TracePoint.allow_reentry do
+ a = 1; l3 = __LINE__
+ b = 2; l4 = __LINE__
+ end
+ end.enable do
+ c = 3; l1 = __LINE__
+ d = 4; l2 = __LINE__
+ end
+
+ event_lines.should == [l1, l3, l4, l2, l3, l4]
+ end
+
+ it 'raises RuntimeError when not called inside a TracePoint' do
+ -> {
+ TracePoint.allow_reentry{}
+ }.should.raise(RuntimeError)
+ end
+end
diff --git a/spec/ruby/core/tracepoint/binding_spec.rb b/spec/ruby/core/tracepoint/binding_spec.rb
index 6a7ef5f85a..6de6e47d7d 100644
--- a/spec/ruby/core/tracepoint/binding_spec.rb
+++ b/spec/ruby/core/tracepoint/binding_spec.rb
@@ -15,7 +15,7 @@ describe 'TracePoint#binding' do
test
}
bindings.size.should == 1
- bindings[0].should be_kind_of(Binding)
+ bindings[0].should.is_a?(Binding)
bindings[0].local_variables.should == [:secret]
end
end
diff --git a/spec/ruby/core/tracepoint/defined_class_spec.rb b/spec/ruby/core/tracepoint/defined_class_spec.rb
index 4593db6d1f..53c86a8210 100644
--- a/spec/ruby/core/tracepoint/defined_class_spec.rb
+++ b/spec/ruby/core/tracepoint/defined_class_spec.rb
@@ -9,19 +9,19 @@ describe 'TracePoint#defined_class' do
last_class_name = tp.defined_class
end.enable do
TracePointSpec::B.new.foo
- last_class_name.should equal(TracePointSpec::B)
+ last_class_name.should.equal?(TracePointSpec::B)
TracePointSpec::B.new.bar
- last_class_name.should equal(TracePointSpec::A)
+ last_class_name.should.equal?(TracePointSpec::A)
c = TracePointSpec::C.new
- last_class_name.should equal(TracePointSpec::C)
+ last_class_name.should.equal?(TracePointSpec::C)
c.foo
- last_class_name.should equal(TracePointSpec::B)
+ last_class_name.should.equal?(TracePointSpec::B)
c.bar
- last_class_name.should equal(TracePointSpec::A)
+ last_class_name.should.equal?(TracePointSpec::A)
end
end
end
diff --git a/spec/ruby/core/tracepoint/enable_spec.rb b/spec/ruby/core/tracepoint/enable_spec.rb
index 24f6070b97..bf61c35154 100644
--- a/spec/ruby/core/tracepoint/enable_spec.rb
+++ b/spec/ruby/core/tracepoint/enable_spec.rb
@@ -54,53 +54,28 @@ describe 'TracePoint#enable' do
TracePoint.new(:line) do |tp|
next unless TracePointSpec.target_thread?
event_name = tp.event
- end.enable { event_name.should equal(:line) }
+ end.enable { event_name.should.equal?(:line) }
end
- ruby_version_is '3.2' do
- it 'enables the trace object only for the current thread' do
- threads = []
- trace = TracePoint.new(:line) do |tp|
- # Runs on purpose on any Thread
- threads << Thread.current
- end
-
- thread = nil
- trace.enable do
- line_event = true
- thread = Thread.new do
- event_in_other_thread = true
- end
- thread.join
- end
-
- threads = threads.uniq
- threads.should.include?(Thread.current)
- threads.should_not.include?(thread)
+ it 'enables the trace object only for the current thread' do
+ threads = []
+ trace = TracePoint.new(:line) do |tp|
+ # Runs on purpose on any Thread
+ threads << Thread.current
end
- end
-
- ruby_version_is ''...'3.2' do
- it 'enables the trace object for any thread' do
- threads = []
- trace = TracePoint.new(:line) do |tp|
- # Runs on purpose on any Thread
- threads << Thread.current
- end
- thread = nil
- trace.enable do
- line_event = true
- thread = Thread.new do
- event_in_other_thread = true
- end
- thread.join
+ thread = nil
+ trace.enable do
+ line_event = true
+ thread = Thread.new do
+ event_in_other_thread = true
end
-
- threads = threads.uniq
- threads.should.include?(Thread.current)
- threads.should.include?(thread)
+ thread.join
end
+
+ threads = threads.uniq
+ threads.should.include?(Thread.current)
+ threads.should_not.include?(thread)
end
it 'can accept arguments within a block but it should not yield arguments' do
@@ -110,7 +85,7 @@ describe 'TracePoint#enable' do
event_name = tp.event
end
trace.enable do |*args|
- event_name.should equal(:line)
+ event_name.should.equal?(:line)
args.should == []
end
trace.should_not.enabled?
@@ -149,13 +124,7 @@ describe 'TracePoint#enable' do
describe "when nested" do
before do
- ruby_version_is ""..."3.0" do
- @path_prefix = '@'
- end
-
- ruby_version_is "3.0" do
- @path_prefix = ' '
- end
+ @path_prefix = ' '
end
it "enables both TracePoints but only calls the respective callbacks" do
@@ -332,7 +301,7 @@ describe 'TracePoint#enable' do
end
ScratchPad.recorded.should == [lineno]
- lineno.should be_kind_of(Integer)
+ lineno.should.is_a?(Integer)
end
end
@@ -348,7 +317,7 @@ describe 'TracePoint#enable' do
trace.enable(target: block) do
block.call # triggers :b_call and :b_return events
end
- }.should raise_error(ArgumentError, /can not enable any hooks/)
+ }.should.raise(ArgumentError, /can not enable any hooks/)
end
it "raises ArgumentError if passed not Method/UnboundMethod/Proc" do
@@ -357,7 +326,7 @@ describe 'TracePoint#enable' do
-> {
trace.enable(target: Object.new) do
end
- }.should raise_error(ArgumentError, /specified target is not supported/)
+ }.should.raise(ArgumentError, /specified target is not supported/)
end
context "nested enabling and disabling" do
@@ -369,7 +338,7 @@ describe 'TracePoint#enable' do
trace.enable(target: -> {}) do
end
end
- }.should raise_error(ArgumentError, /can't nest-enable a targett?ing TracePoint/)
+ }.should.raise(ArgumentError, /can't nest-enable a targett?ing TracePoint/)
end
it "raises ArgumentError if trace point already enabled without target is re-enabled with target" do
@@ -380,7 +349,7 @@ describe 'TracePoint#enable' do
trace.enable(target: -> {}) do
end
end
- }.should raise_error(ArgumentError, /can't nest-enable a targett?ing TracePoint/)
+ }.should.raise(ArgumentError, /can't nest-enable a targett?ing TracePoint/)
end
it "raises ArgumentError if trace point already enabled with target is re-enabled without target" do
@@ -391,7 +360,7 @@ describe 'TracePoint#enable' do
trace.enable do
end
end
- }.should raise_error(ArgumentError, /can't nest-enable a targett?ing TracePoint/)
+ }.should.raise(ArgumentError, /can't nest-enable a targett?ing TracePoint/)
end
it "raises ArgumentError if trace point already enabled with target is disabled with block" do
@@ -402,7 +371,7 @@ describe 'TracePoint#enable' do
trace.disable do
end
end
- }.should raise_error(ArgumentError, /can't disable a targett?ing TracePoint in a block/)
+ }.should.raise(ArgumentError, /can't disable a targett?ing TracePoint in a block/)
end
it "traces events when trace point with target is enabled in another trace point enabled without target" do
@@ -505,7 +474,7 @@ describe 'TracePoint#enable' do
-> {
trace.enable(target_line: 67) do
end
- }.should raise_error(ArgumentError, /only target_line is specified/)
+ }.should.raise(ArgumentError, /only target_line is specified/)
end
it "raises ArgumentError if :line event isn't registered" do
@@ -522,7 +491,7 @@ describe 'TracePoint#enable' do
-> {
trace.enable(target_line: target_line, target: target) do
end
- }.should raise_error(ArgumentError, /target_line is specified, but line event is not specified/)
+ }.should.raise(ArgumentError, /target_line is specified, but line event is not specified/)
end
it "raises ArgumentError if :target_line value is out of target code lines range" do
@@ -531,7 +500,7 @@ describe 'TracePoint#enable' do
-> {
trace.enable(target_line: 1, target: -> { }) do
end
- }.should raise_error(ArgumentError, /can not enable any hooks/)
+ }.should.raise(ArgumentError, /can not enable any hooks/)
end
it "raises TypeError if :target_line value couldn't be coerced to Integer" do
@@ -540,7 +509,7 @@ describe 'TracePoint#enable' do
-> {
trace.enable(target_line: Object.new, target: -> { }) do
end
- }.should raise_error(TypeError, /no implicit conversion of \w+? into Integer/)
+ }.should.raise(TypeError, /no implicit conversion of \w+? into Integer/)
end
it "raises ArgumentError if :target_line value is negative" do
@@ -549,7 +518,7 @@ describe 'TracePoint#enable' do
-> {
trace.enable(target_line: -2, target: -> { }) do
end
- }.should raise_error(ArgumentError, /can not enable any hooks/)
+ }.should.raise(ArgumentError, /can not enable any hooks/)
end
it "accepts value that could be coerced to Integer" do
diff --git a/spec/ruby/core/tracepoint/event_spec.rb b/spec/ruby/core/tracepoint/event_spec.rb
index 9dea24d125..58017dc98d 100644
--- a/spec/ruby/core/tracepoint/event_spec.rb
+++ b/spec/ruby/core/tracepoint/event_spec.rb
@@ -9,13 +9,13 @@ describe 'TracePoint#event' do
event_name = tp.event
end.enable do
TracePointSpec.test
- event_name.should equal(:call)
+ event_name.should.equal?(:call)
TracePointSpec::B.new.foo
- event_name.should equal(:call)
+ event_name.should.equal?(:call)
class TracePointSpec::B; end
- event_name.should equal(:end)
+ event_name.should.equal?(:end)
end
end
diff --git a/spec/ruby/core/tracepoint/inspect_spec.rb b/spec/ruby/core/tracepoint/inspect_spec.rb
index a07b626212..6cc2ebe243 100644
--- a/spec/ruby/core/tracepoint/inspect_spec.rb
+++ b/spec/ruby/core/tracepoint/inspect_spec.rb
@@ -3,24 +3,29 @@ require_relative 'fixtures/classes'
describe 'TracePoint#inspect' do
before do
- ruby_version_is ""..."3.0" do
- @path_prefix = '@'
- end
-
- ruby_version_is "3.0" do
- @path_prefix = ' '
- end
+ @path_prefix = ' '
end
it 'returns a string containing a human-readable TracePoint status' do
TracePoint.new(:line) {}.inspect.should == '#<TracePoint:disabled>'
end
+ it "shows only whether it's enabled when outside the TracePoint handler" do
+ trace = TracePoint.new(:line) {}
+ trace.enable
+
+ trace.inspect.should == '#<TracePoint:enabled>'
+
+ trace.disable
+ end
+
it 'returns a String showing the event, path and line' do
inspect = nil
line = nil
TracePoint.new(:line) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}.enable do
line = __LINE__
@@ -34,6 +39,8 @@ describe 'TracePoint#inspect' do
line = nil
TracePoint.new(:call) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}.enable do
line = __LINE__ + 1
@@ -41,7 +48,7 @@ describe 'TracePoint#inspect' do
trace_point_spec_test_call
end
- inspect.should == "#<TracePoint:call `trace_point_spec_test_call'#{@path_prefix}#{__FILE__}:#{line}>"
+ inspect.should =~ /\A#<TracePoint:call [`']trace_point_spec_test_call'#{@path_prefix}#{__FILE__}:#{line}>\z/
end
it 'returns a String showing the event, method, path and line for a :return event' do
@@ -49,6 +56,8 @@ describe 'TracePoint#inspect' do
line = nil
TracePoint.new(:return) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}.enable do
line = __LINE__ + 4
@@ -58,14 +67,17 @@ describe 'TracePoint#inspect' do
end
trace_point_spec_test_return
end
+ ruby_version_is("3.4") { line -= 1 }
- inspect.should == "#<TracePoint:return `trace_point_spec_test_return'#{@path_prefix}#{__FILE__}:#{line}>"
+ inspect.should =~ /\A#<TracePoint:return [`']trace_point_spec_test_return'#{@path_prefix}#{__FILE__}:#{line}>\z/
end
it 'returns a String showing the event, method, path and line for a :c_call event' do
inspect = nil
tracepoint = TracePoint.new(:c_call) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}
line = __LINE__ + 2
@@ -73,7 +85,7 @@ describe 'TracePoint#inspect' do
[0, 1].max
end
- inspect.should == "#<TracePoint:c_call `max'#{@path_prefix}#{__FILE__}:#{line}>"
+ inspect.should =~ /\A#<TracePoint:c_call [`']max'#{@path_prefix}#{__FILE__}:#{line}>\z/
end
it 'returns a String showing the event, path and line for a :class event' do
@@ -81,6 +93,8 @@ describe 'TracePoint#inspect' do
line = nil
TracePoint.new(:class) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}.enable do
line = __LINE__ + 1
@@ -97,6 +111,7 @@ describe 'TracePoint#inspect' do
thread_inspection = nil
TracePoint.new(:thread_begin) { |tp|
next unless Thread.current == thread
+
inspect ||= tp.inspect
}.enable(target_thread: nil) do
thread = Thread.new {}
@@ -113,6 +128,7 @@ describe 'TracePoint#inspect' do
thread_inspection = nil
TracePoint.new(:thread_end) { |tp|
next unless Thread.current == thread
+
inspect ||= tp.inspect
}.enable(target_thread: nil) do
thread = Thread.new {}
diff --git a/spec/ruby/core/tracepoint/lineno_spec.rb b/spec/ruby/core/tracepoint/lineno_spec.rb
index 77b3ac8b54..7c46d5222b 100644
--- a/spec/ruby/core/tracepoint/lineno_spec.rb
+++ b/spec/ruby/core/tracepoint/lineno_spec.rb
@@ -15,6 +15,6 @@ describe 'TracePoint#lineno' do
it 'raises RuntimeError if accessed from outside' do
tp = TracePoint.new(:line) {}
- -> { tp.lineno }.should raise_error(RuntimeError, 'access from outside')
+ -> { tp.lineno }.should.raise(RuntimeError, 'access from outside')
end
end
diff --git a/spec/ruby/core/tracepoint/method_id_spec.rb b/spec/ruby/core/tracepoint/method_id_spec.rb
index 43e23248b7..67740f2d7d 100644
--- a/spec/ruby/core/tracepoint/method_id_spec.rb
+++ b/spec/ruby/core/tracepoint/method_id_spec.rb
@@ -9,7 +9,7 @@ describe 'TracePoint#method_id' do
method_name = tp.method_id
}.enable do
TracePointSpec.test
- method_name.should equal(:test)
+ method_name.should.equal?(:test)
end
end
end
diff --git a/spec/ruby/core/tracepoint/new_spec.rb b/spec/ruby/core/tracepoint/new_spec.rb
index e53c2b04a2..763b35292b 100644
--- a/spec/ruby/core/tracepoint/new_spec.rb
+++ b/spec/ruby/core/tracepoint/new_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe 'TracePoint.new' do
it 'returns a new TracePoint object, not enabled by default' do
- TracePoint.new(:line) {}.enabled?.should be_false
+ TracePoint.new(:line) {}.enabled?.should == false
end
it 'includes :line event when event is not specified' do
@@ -12,15 +12,15 @@ describe 'TracePoint.new' do
next unless TracePointSpec.target_thread?
event_name = tp.event
}.enable do
- event_name.should equal(:line)
+ event_name.should.equal?(:line)
event_name = nil
TracePointSpec.test
- event_name.should equal(:line)
+ event_name.should.equal?(:line)
event_name = nil
TracePointSpec::B.new.foo
- event_name.should equal(:line)
+ event_name.should.equal?(:line)
end
end
@@ -44,29 +44,29 @@ describe 'TracePoint.new' do
event_name = tp.event
end.enable do
TracePointSpec.test
- event_name.should equal(:call)
+ event_name.should.equal?(:call)
TracePointSpec::B.new.foo
- event_name.should equal(:call)
+ event_name.should.equal?(:call)
class TracePointSpec::B; end
- event_name.should equal(:end)
+ event_name.should.equal?(:end)
end
end
it 'raises a TypeError when the given object is not a string/symbol' do
o = mock('123')
- -> { TracePoint.new(o) {} }.should raise_error(TypeError)
+ -> { TracePoint.new(o) {} }.should.raise(TypeError)
o.should_receive(:to_sym).and_return(123)
- -> { TracePoint.new(o) {} }.should raise_error(TypeError)
+ -> { TracePoint.new(o) {} }.should.raise(TypeError)
end
it 'expects to be called with a block' do
- -> { TracePoint.new(:line) }.should raise_error(ArgumentError, "must be called with a block")
+ -> { TracePoint.new(:line) }.should.raise(ArgumentError, "must be called with a block")
end
it "raises a Argument error when the given argument doesn't match an event name" do
- -> { TracePoint.new(:test) }.should raise_error(ArgumentError, "unknown event: test")
+ -> { TracePoint.new(:test) }.should.raise(ArgumentError, "unknown event: test")
end
end
diff --git a/spec/ruby/core/tracepoint/path_spec.rb b/spec/ruby/core/tracepoint/path_spec.rb
index 5b6c6d4cfc..aa6868ead2 100644
--- a/spec/ruby/core/tracepoint/path_spec.rb
+++ b/spec/ruby/core/tracepoint/path_spec.rb
@@ -13,7 +13,7 @@ describe 'TracePoint#path' do
path.should == "#{__FILE__}"
end
- it 'equals (eval) inside an eval for :end event' do
+ it 'equals "(eval at __FILE__:__LINE__)" inside an eval for :end event' do
path = nil
TracePoint.new(:end) { |tp|
next unless TracePointSpec.target_thread?
@@ -21,6 +21,6 @@ describe 'TracePoint#path' do
}.enable do
eval("module TracePointSpec; end")
end
- path.should == '(eval)'
+ path.should == "(eval at #{__FILE__}:#{__LINE__ - 2})"
end
end
diff --git a/spec/ruby/core/tracepoint/raised_exception_spec.rb b/spec/ruby/core/tracepoint/raised_exception_spec.rb
index ca2f50abb3..b1199902f2 100644
--- a/spec/ruby/core/tracepoint/raised_exception_spec.rb
+++ b/spec/ruby/core/tracepoint/raised_exception_spec.rb
@@ -14,7 +14,23 @@ describe 'TracePoint#raised_exception' do
rescue => e
error_result = e
end
- raised_exception.should equal(error_result)
+ raised_exception.should.equal?(error_result)
+ end
+ end
+
+ it 'returns value from exception rescued on the :rescue event' do
+ raised_exception, error_result = nil
+ trace = TracePoint.new(:rescue) { |tp|
+ next unless TracePointSpec.target_thread?
+ raised_exception = tp.raised_exception
+ }
+ trace.enable do
+ begin
+ raise StandardError
+ rescue => e
+ error_result = e
+ end
+ raised_exception.should.equal?(error_result)
end
end
end
diff --git a/spec/ruby/core/tracepoint/self_spec.rb b/spec/ruby/core/tracepoint/self_spec.rb
index 2098860e59..bf9a2b6a45 100644
--- a/spec/ruby/core/tracepoint/self_spec.rb
+++ b/spec/ruby/core/tracepoint/self_spec.rb
@@ -8,7 +8,7 @@ describe 'TracePoint#self' do
next unless TracePointSpec.target_thread?
trace = tp.self
}.enable do
- trace.equal?(self).should be_true
+ trace.equal?(self).should == true
end
end
@@ -21,6 +21,6 @@ describe 'TracePoint#self' do
class TracePointSpec::C
end
end
- trace.should equal TracePointSpec::C
+ trace.should.equal? TracePointSpec::C
end
end
diff --git a/spec/ruby/core/true/dup_spec.rb b/spec/ruby/core/true/dup_spec.rb
index 351457ed22..2628f6d374 100644
--- a/spec/ruby/core/true/dup_spec.rb
+++ b/spec/ruby/core/true/dup_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../spec_helper'
describe "TrueClass#dup" do
it "returns self" do
- true.dup.should equal(true)
+ true.dup.should.equal?(true)
end
end
diff --git a/spec/ruby/core/true/singleton_method_spec.rb b/spec/ruby/core/true/singleton_method_spec.rb
new file mode 100644
index 0000000000..58689fb6e5
--- /dev/null
+++ b/spec/ruby/core/true/singleton_method_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+
+describe "TrueClass#singleton_method" do
+ it "raises regardless of whether TrueClass defines the method" do
+ -> { true.singleton_method(:foo) }.should.raise(NameError)
+ begin
+ def (true).foo; end
+ -> { true.singleton_method(:foo) }.should.raise(NameError)
+ ensure
+ TrueClass.send(:remove_method, :foo)
+ end
+ end
+end
diff --git a/spec/ruby/core/true/to_s_spec.rb b/spec/ruby/core/true/to_s_spec.rb
index fa1b53a580..2c6f3889e9 100644
--- a/spec/ruby/core/true/to_s_spec.rb
+++ b/spec/ruby/core/true/to_s_spec.rb
@@ -10,6 +10,6 @@ describe "TrueClass#to_s" do
end
it "always returns the same string" do
- true.to_s.should equal(true.to_s)
+ true.to_s.should.equal?(true.to_s)
end
end
diff --git a/spec/ruby/core/true/trueclass_spec.rb b/spec/ruby/core/true/trueclass_spec.rb
index 02af649d09..1c1a0ddbe2 100644
--- a/spec/ruby/core/true/trueclass_spec.rb
+++ b/spec/ruby/core/true/trueclass_spec.rb
@@ -4,12 +4,12 @@ describe "TrueClass" do
it ".allocate raises a TypeError" do
-> do
TrueClass.allocate
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it ".new is undefined" do
-> do
TrueClass.new
- end.should raise_error(NoMethodError)
+ end.should.raise(NoMethodError)
end
end
diff --git a/spec/ruby/core/unboundmethod/bind_call_spec.rb b/spec/ruby/core/unboundmethod/bind_call_spec.rb
index 8f25f8bd0d..ee1dad9c9e 100644
--- a/spec/ruby/core/unboundmethod/bind_call_spec.rb
+++ b/spec/ruby/core/unboundmethod/bind_call_spec.rb
@@ -7,10 +7,12 @@ describe "UnboundMethod#bind_call" do
@parent_um = UnboundMethodSpecs::Parent.new.method(:foo).unbind
@child1_um = UnboundMethodSpecs::Child1.new.method(:foo).unbind
@child2_um = UnboundMethodSpecs::Child2.new.method(:foo).unbind
+ @normal_um_super = UnboundMethodSpecs::Mod.instance_method(:foo_super)
+ @parent_um_super = UnboundMethodSpecs::Parent.new.method(:foo_super).unbind
end
it "raises TypeError if object is not kind_of? the Module the method defined in" do
- -> { @normal_um.bind_call(UnboundMethodSpecs::B.new) }.should raise_error(TypeError)
+ -> { @normal_um.bind_call(UnboundMethodSpecs::B.new) }.should.raise(TypeError)
end
it "binds and calls the method if object is kind_of the Module the method defined in" do
@@ -45,6 +47,12 @@ describe "UnboundMethod#bind_call" do
end
end
um = p.method(:singleton_method).unbind
- ->{ um.bind_call(other) }.should raise_error(TypeError)
+ ->{ um.bind_call(other) }.should.raise(TypeError)
+ end
+
+ it "allows calling super for module methods bound to hierarchies that do not already have that module" do
+ p = UnboundMethodSpecs::Parent.new
+
+ @normal_um_super.bind_call(p).should == true
end
end
diff --git a/spec/ruby/core/unboundmethod/bind_spec.rb b/spec/ruby/core/unboundmethod/bind_spec.rb
index 03aaa22e74..087994ff57 100644
--- a/spec/ruby/core/unboundmethod/bind_spec.rb
+++ b/spec/ruby/core/unboundmethod/bind_spec.rb
@@ -7,18 +7,20 @@ describe "UnboundMethod#bind" do
@parent_um = UnboundMethodSpecs::Parent.new.method(:foo).unbind
@child1_um = UnboundMethodSpecs::Child1.new.method(:foo).unbind
@child2_um = UnboundMethodSpecs::Child2.new.method(:foo).unbind
+ @normal_um_super = UnboundMethodSpecs::Mod.instance_method(:foo_super)
+ @parent_um_super = UnboundMethodSpecs::Parent.new.method(:foo_super).unbind
end
it "raises TypeError if object is not kind_of? the Module the method defined in" do
- -> { @normal_um.bind(UnboundMethodSpecs::B.new) }.should raise_error(TypeError)
+ -> { @normal_um.bind(UnboundMethodSpecs::B.new) }.should.raise(TypeError)
end
it "returns Method for any object that is kind_of? the Module method was extracted from" do
- @normal_um.bind(UnboundMethodSpecs::Methods.new).should be_kind_of(Method)
+ @normal_um.bind(UnboundMethodSpecs::Methods.new).should.is_a?(Method)
end
it "returns Method on any object when UnboundMethod is unbound from a module" do
- UnboundMethodSpecs::Mod.instance_method(:from_mod).bind(Object.new).should be_kind_of(Method)
+ UnboundMethodSpecs::Mod.instance_method(:from_mod).bind(Object.new).should.is_a?(Method)
end
it "the returned Method is equal to the one directly returned by obj.method" do
@@ -27,9 +29,9 @@ describe "UnboundMethod#bind" do
end
it "returns Method for any object kind_of? the Module the method is defined in" do
- @parent_um.bind(UnboundMethodSpecs::Child1.new).should be_kind_of(Method)
- @child1_um.bind(UnboundMethodSpecs::Parent.new).should be_kind_of(Method)
- @child2_um.bind(UnboundMethodSpecs::Child1.new).should be_kind_of(Method)
+ @parent_um.bind(UnboundMethodSpecs::Child1.new).should.is_a?(Method)
+ @child1_um.bind(UnboundMethodSpecs::Parent.new).should.is_a?(Method)
+ @child2_um.bind(UnboundMethodSpecs::Child1.new).should.is_a?(Method)
end
it "allows binding a Kernel method retrieved from Object on BasicObject" do
@@ -43,7 +45,7 @@ describe "UnboundMethod#bind" do
it "binds a Parent's class method to any Child's class methods" do
m = UnboundMethodSpecs::Parent.method(:class_method).unbind.bind(UnboundMethodSpecs::Child1)
- m.should be_an_instance_of(Method)
+ m.should.instance_of?(Method)
m.call.should == "I am UnboundMethodSpecs::Child1"
end
@@ -56,6 +58,12 @@ describe "UnboundMethod#bind" do
end
end
um = p.method(:singleton_method).unbind
- ->{ um.bind(other) }.should raise_error(TypeError)
+ ->{ um.bind(other) }.should.raise(TypeError)
+ end
+
+ it "allows calling super for module methods bound to hierarchies that do not already have that module" do
+ p = UnboundMethodSpecs::Parent.new
+
+ @normal_um_super.bind(p).call.should == true
end
end
diff --git a/spec/ruby/core/unboundmethod/clone_spec.rb b/spec/ruby/core/unboundmethod/clone_spec.rb
index 098ee61476..1e7fb18744 100644
--- a/spec/ruby/core/unboundmethod/clone_spec.rb
+++ b/spec/ruby/core/unboundmethod/clone_spec.rb
@@ -1,12 +1,13 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+require_relative 'shared/dup'
describe "UnboundMethod#clone" do
- it "returns a copy of the UnboundMethod" do
- um1 = UnboundMethodSpecs::Methods.instance_method(:foo)
- um2 = um1.clone
+ it_behaves_like :unboundmethod_dup, :clone
- (um1 == um2).should == true
- um1.bind(UnboundMethodSpecs::Methods.new).call.should == um2.bind(UnboundMethodSpecs::Methods.new).call
+ it "preserves frozen status" do
+ method = Class.instance_method(:instance_method)
+ method.freeze
+ method.frozen?.should == true
+ method.clone.frozen?.should == true
end
end
diff --git a/spec/ruby/core/unboundmethod/dup_spec.rb b/spec/ruby/core/unboundmethod/dup_spec.rb
new file mode 100644
index 0000000000..5a78dd8e36
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/dup_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+require_relative 'shared/dup'
+
+describe "UnboundMethod#dup" do
+ ruby_version_is "3.4" do
+ it_behaves_like :unboundmethod_dup, :dup
+
+ it "resets frozen status" do
+ method = Class.instance_method(:instance_method)
+ method.freeze
+ method.frozen?.should == true
+ method.dup.frozen?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/equal_value_spec.rb b/spec/ruby/core/unboundmethod/equal_value_spec.rb
index 6242b04884..24d5233299 100644
--- a/spec/ruby/core/unboundmethod/equal_value_spec.rb
+++ b/spec/ruby/core/unboundmethod/equal_value_spec.rb
@@ -3,8 +3,8 @@ require_relative 'fixtures/classes'
context "Creating UnboundMethods" do
specify "there is no difference between Method#unbind and Module#instance_method" do
- UnboundMethodSpecs::Methods.instance_method(:foo).should be_kind_of(UnboundMethod)
- UnboundMethodSpecs::Methods.new.method(:foo).unbind.should be_kind_of(UnboundMethod)
+ UnboundMethodSpecs::Methods.instance_method(:foo).should.is_a?(UnboundMethod)
+ UnboundMethodSpecs::Methods.new.method(:foo).unbind.should.is_a?(UnboundMethod)
end
end
@@ -35,6 +35,12 @@ describe "UnboundMethod#==" do
@method_one = UnboundMethodSpecs::Methods.instance_method(:one)
@method_two = UnboundMethodSpecs::Methods.instance_method(:two)
+
+ @mixin = UnboundMethodSpecs::Mixin.instance_method(:mixin_method)
+ @includer_base = UnboundMethodSpecs::IncluderBase.new.method(:mixin_method).unbind
+ @includer_child = UnboundMethodSpecs::IncluderChild.new.method(:mixin_method).unbind
+ @extender_base = UnboundMethodSpecs::ExtenderBase.method(:mixin_method).unbind
+ @extender_child = UnboundMethodSpecs::ExtenderChild.method(:mixin_method).unbind
end
it "returns true if objects refer to the same method" do
@@ -76,19 +82,43 @@ describe "UnboundMethod#==" do
(@identical_body == @original_body).should == false
end
- it "returns false if same method but one extracted from a subclass" do
- (@parent == @child1).should == false
- (@child1 == @parent).should == false
+ it "returns true if same method but one extracted from a subclass" do
+ (@parent == @child1).should == true
+ (@child1 == @parent).should == true
end
- it "returns false if same method but extracted from two different subclasses" do
- (@child2 == @child1).should == false
- (@child1 == @child2).should == false
+ it "returns true if same method but extracted from two different subclasses" do
+ (@child2 == @child1).should == true
+ (@child1 == @child2).should == true
end
- it "returns false if methods are the same but added from an included Module" do
- (@includee == @includer).should == false
- (@includer == @includee).should == false
+ it "returns true if methods are the same but added from an included Module" do
+ (@includee == @includer).should == true
+ (@includer == @includee).should == true
+ end
+
+ ruby_bug "#21873", ""..."4.1" do
+ it "returns true if same method is present in an object through module inclusion" do
+ (@mixin == @includer_base).should == true
+ (@includer_base == @mixin).should == true
+
+ (@mixin == @includer_child).should == true
+ (@includer_child == @mixin).should == true
+
+ (@includer_base == @includer_child).should == true
+ (@includer_child == @includer_base).should == true
+ end
+
+ it "returns true if same method is present in an object through module extension" do
+ (@mixin == @extender_base).should == true
+ (@extender_base == @mixin).should == true
+
+ (@mixin == @extender_child).should == true
+ (@extender_child == @mixin).should == true
+
+ (@extender_base == @extender_child).should == true
+ (@extender_child == @extender_base).should == true
+ end
end
it "returns false if both have same Module, same name, identical body but not the same" do
@@ -98,4 +128,38 @@ describe "UnboundMethod#==" do
(@discard_1 == UnboundMethodSpecs::Methods.instance_method(:discard_1)).should == false
end
+
+ it "considers methods through aliasing equal" do
+ c = Class.new do
+ class << self
+ alias_method :n, :new
+ end
+ end
+
+ c.method(:new).should == c.method(:n)
+ c.method(:n).should == Class.instance_method(:new).bind(c)
+ end
+
+ it "considers methods through visibility change equal" do
+ c = Class.new do
+ class << self
+ private :new
+ end
+ end
+
+ c.method(:new).should == Class.instance_method(:new).bind(c)
+ end
+
+ it "considers methods through aliasing and visibility change equal" do
+ c = Class.new do
+ class << self
+ alias_method :n, :new
+ private :new
+ end
+ end
+
+ c.method(:new).should == c.method(:n)
+ c.method(:n).should == Class.instance_method(:new).bind(c)
+ c.method(:new).should == Class.instance_method(:new).bind(c)
+ end
end
diff --git a/spec/ruby/core/unboundmethod/fixtures/classes.rb b/spec/ruby/core/unboundmethod/fixtures/classes.rb
index 46b1c51669..58120c2f88 100644
--- a/spec/ruby/core/unboundmethod/fixtures/classes.rb
+++ b/spec/ruby/core/unboundmethod/fixtures/classes.rb
@@ -22,6 +22,7 @@ module UnboundMethodSpecs
module Mod
def from_mod; end
+ def foo_super; super; end
end
class Methods
@@ -35,6 +36,7 @@ module UnboundMethodSpecs
alias bar foo
alias baz bar
+ alias qux baz
alias alias_1 foo
alias alias_2 foo
@@ -53,10 +55,19 @@ module UnboundMethodSpecs
def discard_1(); :discard; end
def discard_2(); :discard; end
+
+ def my_public_method; end
+ def my_protected_method; end
+ def my_private_method; end
+ protected :my_protected_method
+ private :my_private_method
end
class Parent
def foo; end
+ def foo_super
+ true
+ end
def self.class_method
"I am #{name}"
end
@@ -70,6 +81,22 @@ module UnboundMethodSpecs
end
end
+ module Mixin
+ def mixin_method; end
+ end
+
+ class IncluderBase
+ include Mixin
+ end
+
+ class IncluderChild < IncluderBase; end
+
+ class ExtenderBase
+ extend Mixin
+ end
+
+ class ExtenderChild < ExtenderBase; end
+
class A
def baz(a, b)
return [__FILE__, self.class]
@@ -84,4 +111,14 @@ module UnboundMethodSpecs
class C < B
def overridden; end
end
+
+ module HashSpecs
+ class SuperClass
+ def foo
+ end
+ end
+
+ class SubClass < SuperClass
+ end
+ end
end
diff --git a/spec/ruby/core/unboundmethod/hash_spec.rb b/spec/ruby/core/unboundmethod/hash_spec.rb
index 12dce0020f..6888675bc1 100644
--- a/spec/ruby/core/unboundmethod/hash_spec.rb
+++ b/spec/ruby/core/unboundmethod/hash_spec.rb
@@ -12,4 +12,11 @@ describe "UnboundMethod#hash" do
to_s, inspect = Array.instance_method(:to_s), Array.instance_method(:inspect)
to_s.hash.should == inspect.hash
end
+
+ it "equals a hash of the same method in the superclass" do
+ foo_in_superclass = UnboundMethodSpecs::HashSpecs::SuperClass.instance_method(:foo)
+ foo = UnboundMethodSpecs::HashSpecs::SubClass.instance_method(:foo)
+
+ foo.hash.should == foo_in_superclass.hash
+ end
end
diff --git a/spec/ruby/core/unboundmethod/inspect_spec.rb b/spec/ruby/core/unboundmethod/inspect_spec.rb
index cecf542fcd..3abed94f7f 100644
--- a/spec/ruby/core/unboundmethod/inspect_spec.rb
+++ b/spec/ruby/core/unboundmethod/inspect_spec.rb
@@ -1,7 +1,9 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/to_s'
+require_relative '../method/shared/aliased_inspect'
describe "UnboundMethod#inspect" do
it_behaves_like :unboundmethod_to_s, :inspect
+ it_behaves_like :method_to_s_aliased, :inspect, -> meth { meth.unbind }
end
diff --git a/spec/ruby/core/unboundmethod/original_name_spec.rb b/spec/ruby/core/unboundmethod/original_name_spec.rb
index 7280dcb2b4..cd5f55805d 100644
--- a/spec/ruby/core/unboundmethod/original_name_spec.rb
+++ b/spec/ruby/core/unboundmethod/original_name_spec.rb
@@ -19,4 +19,41 @@ describe "UnboundMethod#original_name" do
obj.method(:baz).unbind.original_name.should == :foo
UnboundMethodSpecs::Methods.instance_method(:baz).original_name.should == :foo
end
+
+ it "returns the original name even when aliased thrice" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:qux).unbind.original_name.should == :foo
+ UnboundMethodSpecs::Methods.instance_method(:qux).original_name.should == :foo
+ end
+
+ it "returns the source UnboundMethod's name (not the name given to define_method)" do
+ klass = Class.new { define_method(:my_inspect, ::Kernel.instance_method(:inspect)) }
+ klass.instance_method(:my_inspect).original_name.should == :inspect
+ end
+
+ it "preserves the source method's name through define_method and alias" do
+ source = Class.new { def my_method; end }
+ klass = Class.new(source) do
+ define_method(:renamed, source.instance_method(:my_method))
+ alias aliased renamed
+ end
+ klass.instance_method(:renamed).original_name.should == :my_method
+ klass.instance_method(:aliased).original_name.should == :my_method
+ end
+
+ it "returns the source UnboundMethod's name for Kernel#is_a? and Kernel#kind_of?" do
+ klass = Class.new { define_method(:my_is_a?, ::Kernel.instance_method(:is_a?)) }
+ klass.instance_method(:my_is_a?).original_name.should == :is_a?
+
+ klass = Class.new { define_method(:my_kind_of?, ::Kernel.instance_method(:kind_of?)) }
+ klass.instance_method(:my_kind_of?).original_name.should == :kind_of?
+ end
+
+ it "preserves the source name when aliasing a define_method'd Kernel method" do
+ klass = Class.new do
+ define_method(:my_is_a?, ::Kernel.instance_method(:is_a?))
+ alias_method :renamed_is_a?, :my_is_a?
+ end
+ klass.instance_method(:renamed_is_a?).original_name.should == :is_a?
+ end
end
diff --git a/spec/ruby/core/unboundmethod/owner_spec.rb b/spec/ruby/core/unboundmethod/owner_spec.rb
index 5f1f4646b3..b099c56de1 100644
--- a/spec/ruby/core/unboundmethod/owner_spec.rb
+++ b/spec/ruby/core/unboundmethod/owner_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../method/fixtures/classes'
describe "UnboundMethod#owner" do
it "returns the owner of the method" do
@@ -23,4 +24,8 @@ describe "UnboundMethod#owner" do
child_singleton_class.instance_method(:class_method).owner.should == parent_singleton_class
child_singleton_class.instance_method(:another_class_method).owner.should == child_singleton_class
end
+
+ it "returns the class on which public was called for a private method in ancestor" do
+ MethodSpecs::InheritedMethods::C.instance_method(:derp).owner.should == MethodSpecs::InheritedMethods::C
+ end
end
diff --git a/spec/ruby/core/unboundmethod/private_spec.rb b/spec/ruby/core/unboundmethod/private_spec.rb
new file mode 100644
index 0000000000..5a563939d1
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/private_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "UnboundMethod#private?" do
+ it "has been removed" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_private_method).unbind.should_not.respond_to?(:private?)
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/protected_spec.rb b/spec/ruby/core/unboundmethod/protected_spec.rb
new file mode 100644
index 0000000000..70622d658d
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/protected_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "UnboundMethod#protected?" do
+ it "has been removed" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_protected_method).unbind.should_not.respond_to?(:protected?)
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/public_spec.rb b/spec/ruby/core/unboundmethod/public_spec.rb
new file mode 100644
index 0000000000..ae75e2601c
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/public_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "UnboundMethod#public?" do
+ it "has been removed" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_public_method).unbind.should_not.respond_to?(:public?)
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/shared/dup.rb b/spec/ruby/core/unboundmethod/shared/dup.rb
new file mode 100644
index 0000000000..fd30f75c5b
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/shared/dup.rb
@@ -0,0 +1,32 @@
+describe :unboundmethod_dup, shared: true do
+ it "returns a copy of self" do
+ a = Class.instance_method(:instance_method)
+ b = a.send(@method)
+
+ a.should == b
+ a.should_not.equal?(b)
+ end
+
+ ruby_version_is "3.4" do
+ it "copies instance variables" do
+ method = Class.instance_method(:instance_method)
+ method.instance_variable_set(:@ivar, 1)
+ cl = method.send(@method)
+ cl.instance_variables.should == [:@ivar]
+ end
+
+ it "copies the finalizer" do
+ code = <<-'RUBY'
+ obj = Class.instance_method(:instance_method)
+
+ ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
+
+ obj.clone
+
+ exit 0
+ RUBY
+
+ ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"]
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/shared/to_s.rb b/spec/ruby/core/unboundmethod/shared/to_s.rb
index 38503c3c60..848c1eba2e 100644
--- a/spec/ruby/core/unboundmethod/shared/to_s.rb
+++ b/spec/ruby/core/unboundmethod/shared/to_s.rb
@@ -8,8 +8,8 @@ describe :unboundmethod_to_s, shared: true do
end
it "returns a String" do
- @from_module.send(@method).should be_kind_of(String)
- @from_method.send(@method).should be_kind_of(String)
+ @from_module.send(@method).should.is_a?(String)
+ @from_method.send(@method).should.is_a?(String)
end
it "the String reflects that this is an UnboundMethod object" do
@@ -20,12 +20,11 @@ describe :unboundmethod_to_s, shared: true do
it "the String shows the method name, Module defined in and Module extracted from" do
@from_module.send(@method).should =~ /\bfrom_mod\b/
@from_module.send(@method).should =~ /\bUnboundMethodSpecs::Mod\b/
- @from_method.send(@method).should =~ /\bUnboundMethodSpecs::Methods\b/
end
it "returns a String including all details" do
- @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
- @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
+ @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod"
+ @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod"
end
it "does not show the defining module if it is the same as the origin" do
diff --git a/spec/ruby/core/unboundmethod/source_location_spec.rb b/spec/ruby/core/unboundmethod/source_location_spec.rb
index 96933a5d40..927600bfcb 100644
--- a/spec/ruby/core/unboundmethod/source_location_spec.rb
+++ b/spec/ruby/core/unboundmethod/source_location_spec.rb
@@ -8,13 +8,13 @@ describe "UnboundMethod#source_location" do
it "sets the first value to the path of the file in which the method was defined" do
file = @method.source_location.first
- file.should be_an_instance_of(String)
- file.should == File.realpath('../fixtures/classes.rb', __FILE__)
+ file.should.instance_of?(String)
+ file.should == File.realpath('fixtures/classes.rb', __dir__)
end
it "sets the last value to an Integer representing the line on which the method was defined" do
line = @method.source_location.last
- line.should be_an_instance_of(Integer)
+ line.should.instance_of?(Integer)
line.should == 5
end
@@ -49,4 +49,11 @@ describe "UnboundMethod#source_location" do
method.source_location[0].should =~ /#{__FILE__}/
method.source_location[1].should == line
end
+
+ it "works for eval with a given line" do
+ c = Class.new do
+ eval('def m; end', nil, "foo", 100)
+ end
+ c.instance_method(:m).source_location.should == ["foo", 100]
+ end
end
diff --git a/spec/ruby/core/unboundmethod/super_method_spec.rb b/spec/ruby/core/unboundmethod/super_method_spec.rb
index c9fa1ec533..aa7c129377 100644
--- a/spec/ruby/core/unboundmethod/super_method_spec.rb
+++ b/spec/ruby/core/unboundmethod/super_method_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../method/fixtures/classes'
describe "UnboundMethod#super_method" do
it "returns the method that would be called by super in the method" do
@@ -25,4 +26,24 @@ describe "UnboundMethod#super_method" do
method.super_method.should == nil
end
+
+ # https://github.com/jruby/jruby/issues/7240
+ context "after changing an inherited methods visibility" do
+ it "calls the proper super method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
+ method.bind(MethodSpecs::InheritedMethods::C.new).call.should == 'BA'
+ end
+
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
+
+ context "after aliasing an inherited method" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:meow)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
end
diff --git a/spec/ruby/core/unboundmethod/to_s_spec.rb b/spec/ruby/core/unboundmethod/to_s_spec.rb
index a508229b49..615d88675b 100644
--- a/spec/ruby/core/unboundmethod/to_s_spec.rb
+++ b/spec/ruby/core/unboundmethod/to_s_spec.rb
@@ -1,7 +1,9 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/to_s'
+require_relative '../method/shared/aliased_inspect'
describe "UnboundMethod#to_s" do
it_behaves_like :unboundmethod_to_s, :to_s
+ it_behaves_like :method_to_s_aliased, :to_s, -> meth { meth.unbind }
end
diff --git a/spec/ruby/core/warning/categories_spec.rb b/spec/ruby/core/warning/categories_spec.rb
new file mode 100644
index 0000000000..1e310ef38b
--- /dev/null
+++ b/spec/ruby/core/warning/categories_spec.rb
@@ -0,0 +1,12 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.4" do
+ describe "Warning.categories" do
+ # There might be more, but these are standard across Ruby implementations
+ it "returns the list of possible warning categories" do
+ Warning.categories.should.include? :deprecated
+ Warning.categories.should.include? :experimental
+ Warning.categories.should.include? :performance
+ end
+ end
+end
diff --git a/spec/ruby/core/warning/element_reference_spec.rb b/spec/ruby/core/warning/element_reference_spec.rb
index 67728ca0f6..5f977759ec 100644
--- a/spec/ruby/core/warning/element_reference_spec.rb
+++ b/spec/ruby/core/warning/element_reference_spec.rb
@@ -1,20 +1,27 @@
require_relative '../../spec_helper'
describe "Warning.[]" do
- ruby_version_is '2.7.2' do
- it "returns default values for categories :deprecated and :experimental" do
- ruby_exe('p Warning[:deprecated]').chomp.should == "false"
- ruby_exe('p Warning[:experimental]').chomp.should == "true"
- end
+ it "returns default values for categories :deprecated and :experimental" do
+ # If any warning options were set on the Ruby that will be executed, then
+ # it's possible this test will fail. In this case we will skip this test.
+ skip if ruby_exe.any? { |opt| opt.start_with?("-W") }
+
+ ruby_exe('p [Warning[:deprecated], Warning[:experimental]]').chomp.should == "[false, true]"
+ ruby_exe('p [Warning[:deprecated], Warning[:experimental]]', options: "-w").chomp.should == "[true, true]"
+ end
+
+ it "returns default values for :performance category" do
+ ruby_exe('p Warning[:performance]').chomp.should == "false"
+ ruby_exe('p Warning[:performance]', options: "-w").chomp.should == "false"
end
it "raises for unknown category" do
- -> { Warning[:noop] }.should raise_error(ArgumentError, /unknown category: noop/)
+ -> { Warning[:noop] }.should.raise(ArgumentError, /unknown category: noop/)
end
it "raises for non-Symbol category" do
- -> { Warning[42] }.should raise_error(TypeError)
- -> { Warning[false] }.should raise_error(TypeError)
- -> { Warning["noop"] }.should raise_error(TypeError)
+ -> { Warning[42] }.should.raise(TypeError)
+ -> { Warning[false] }.should.raise(TypeError)
+ -> { Warning["noop"] }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/warning/element_set_spec.rb b/spec/ruby/core/warning/element_set_spec.rb
index d20ee215ad..3c8ceb721e 100644
--- a/spec/ruby/core/warning/element_set_spec.rb
+++ b/spec/ruby/core/warning/element_set_spec.rb
@@ -8,13 +8,7 @@ describe "Warning.[]=" do
describe ":experimental" do
before do
- ruby_version_is ""..."3.0" do
- @src = 'case [0, 1]; in [a, b]; end'
- end
-
- ruby_version_is "3.0" do
- @src = 'warn "This is experimental warning.", category: :experimental'
- end
+ @src = 'warn "This is experimental warning.", category: :experimental'
end
it "emits and suppresses warnings for :experimental" do
@@ -23,13 +17,23 @@ describe "Warning.[]=" do
end
end
+ it "enables or disables performance warnings" do
+ original = Warning[:performance]
+ begin
+ Warning[:performance] = !original
+ Warning[:performance].should == !original
+ ensure
+ Warning[:performance] = original
+ end
+ end
+
it "raises for unknown category" do
- -> { Warning[:noop] = false }.should raise_error(ArgumentError, /unknown category: noop/)
+ -> { Warning[:noop] = false }.should.raise(ArgumentError, /unknown category: noop/)
end
it "raises for non-Symbol category" do
- -> { Warning[42] = false }.should raise_error(TypeError)
- -> { Warning[false] = false }.should raise_error(TypeError)
- -> { Warning["noop"] = false }.should raise_error(TypeError)
+ -> { Warning[42] = false }.should.raise(TypeError)
+ -> { Warning[false] = false }.should.raise(TypeError)
+ -> { Warning["noop"] = false }.should.raise(TypeError)
end
end
diff --git a/spec/ruby/core/warning/performance_warning_spec.rb b/spec/ruby/core/warning/performance_warning_spec.rb
new file mode 100644
index 0000000000..ab0badcd3d
--- /dev/null
+++ b/spec/ruby/core/warning/performance_warning_spec.rb
@@ -0,0 +1,28 @@
+require_relative '../../spec_helper'
+
+
+describe "Performance warnings" do
+ guard -> { ruby_version_is("3.4") || RUBY_ENGINE == "truffleruby" } do
+ # Optimising Integer, Float or Symbol methods is kind of implementation detail
+ # but multiple implementations do so. So it seems reasonable to have a test case
+ # for at least one such common method.
+ # See https://bugs.ruby-lang.org/issues/20429
+ context "when redefined optimised methods" do
+ it "emits performance warning for redefining Integer#+" do
+ code = <<~CODE
+ Warning[:performance] = true
+
+ class Integer
+ ORIG_METHOD = instance_method(:+)
+
+ def +(...)
+ ORIG_METHOD.bind(self).call(...)
+ end
+ end
+ CODE
+
+ ruby_exe(code, args: "2>&1").should.include?("warning: Redefining 'Integer#+' disables interpreter and JIT optimizations")
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/warning/warn_spec.rb b/spec/ruby/core/warning/warn_spec.rb
index 5ccff3aa2b..62f36e3454 100644
--- a/spec/ruby/core/warning/warn_spec.rb
+++ b/spec/ruby/core/warning/warn_spec.rb
@@ -16,7 +16,7 @@ describe "Warning.warn" do
end
it "extends itself" do
- Warning.singleton_class.ancestors.should include(Warning)
+ Warning.singleton_class.ancestors.should.include?(Warning)
end
it "has Warning as the method owner" do
@@ -51,40 +51,137 @@ describe "Warning.warn" do
end
end
- ruby_version_is '3.0' do
- it "is called by Kernel.warn with nil category keyword" do
- Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil)
- verbose = $VERBOSE
- $VERBOSE = false
+ it "is called by Kernel.warn with nil category keyword" do
+ Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!")
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+
+ it "is called by Kernel.warn with given category keyword converted to a symbol" do
+ Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!", category: "deprecated")
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+
+ it "warns when category is :deprecated and Warning[:deprecated] is true" do
+ warn_deprecated = Warning[:deprecated]
+ Warning[:deprecated] = true
+ begin
+ -> {
+ Warning.warn("foo", category: :deprecated)
+ }.should complain("foo")
+ ensure
+ Warning[:deprecated] = warn_deprecated
+ end
+ end
+
+ it "warns when category is :experimental and Warning[:experimental] is true" do
+ warn_experimental = Warning[:experimental]
+ Warning[:experimental] = true
+ begin
+ -> {
+ Warning.warn("foo", category: :experimental)
+ }.should complain("foo")
+ ensure
+ Warning[:experimental] = warn_experimental
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "warns when category is :strict_unused_block but Warning[:strict_unused_block] is false" do
+ warn_strict_unused_block = Warning[:strict_unused_block]
+ Warning[:strict_unused_block] = true
begin
- Kernel.warn("Chunky bacon!")
+ -> {
+ Warning.warn("foo", category: :strict_unused_block)
+ }.should complain("foo")
ensure
- $VERBOSE = verbose
+ Warning[:strict_unused_block] = warn_strict_unused_block
end
end
+ end
+
+ it "doesn't print message when category is :deprecated but Warning[:deprecated] is false" do
+ warn_deprecated = Warning[:deprecated]
+ Warning[:deprecated] = false
+ begin
+ -> {
+ Warning.warn("foo", category: :deprecated)
+ }.should_not complain
+ ensure
+ Warning[:deprecated] = warn_deprecated
+ end
+ end
+
+ it "doesn't print message when category is :experimental but Warning[:experimental] is false" do
+ warn_experimental = Warning[:experimental]
+ Warning[:experimental] = false
+ begin
+ -> {
+ Warning.warn("foo", category: :experimental)
+ }.should_not complain
+ ensure
+ Warning[:experimental] = warn_experimental
+ end
+ end
- it "is called by Kernel.warn with given category keyword converted to a symbol" do
- Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated)
- verbose = $VERBOSE
- $VERBOSE = false
+ ruby_version_is "3.4" do
+ it "doesn't print message when category is :strict_unused_block but Warning[:strict_unused_block] is false" do
+ warn_strict_unused_block = Warning[:strict_unused_block]
+ Warning[:strict_unused_block] = false
begin
- Kernel.warn("Chunky bacon!", category: "deprecated")
+ -> {
+ Warning.warn("foo", category: :strict_unused_block)
+ }.should_not complain
ensure
- $VERBOSE = verbose
+ Warning[:strict_unused_block] = warn_strict_unused_block
end
end
end
- ruby_version_is ''...'3.0' do
- it "is called by Kernel.warn" do
- Warning.should_receive(:warn).with("Chunky bacon!\n")
- verbose = $VERBOSE
- $VERBOSE = false
+ ruby_bug '#20573', ''...'3.4' do
+ it "isn't called by Kernel.warn when category is :deprecated but Warning[:deprecated] is false" do
+ warn_deprecated = Warning[:deprecated]
+ begin
+ Warning[:deprecated] = false
+ Warning.should_not_receive(:warn)
+ Kernel.warn("foo", category: :deprecated)
+ ensure
+ Warning[:deprecated] = warn_deprecated
+ end
+ end
+
+ it "isn't called by Kernel.warn when category is :experimental but Warning[:experimental] is false" do
+ warn_experimental = Warning[:experimental]
begin
- Kernel.warn("Chunky bacon!")
+ Warning[:experimental] = false
+ Warning.should_not_receive(:warn)
+ Kernel.warn("foo", category: :experimental)
ensure
- $VERBOSE = verbose
+ Warning[:experimental] = warn_experimental
end
end
end
+
+ it "prints the message when VERBOSE is false" do
+ -> { Warning.warn("foo") }.should complain("foo")
+ end
+
+ it "prints the message when VERBOSE is nil" do
+ -> { Warning.warn("foo") }.should complain("foo", verbose: nil)
+ end
+
+ it "prints the message when VERBOSE is true" do
+ -> { Warning.warn("foo") }.should complain("foo", verbose: true)
+ end
end
diff --git a/spec/ruby/default.mspec b/spec/ruby/default.mspec
index a0dc69c03d..c8b1215f56 100644
--- a/spec/ruby/default.mspec
+++ b/spec/ruby/default.mspec
@@ -1,3 +1,4 @@
+# -*- ruby -*-
# Configuration file for Ruby >= 2.0 implementations.
class MSpecScript
@@ -19,8 +20,11 @@ class MSpecScript
# C extension API specs
set :capi, [ 'optional/capi' ]
+ # Thread safety specs
+ set :thread_safety, [ 'optional/thread_safety' ]
+
# A list of _all_ optional specs
- set :optional, get(:capi)
+ set :optional, get(:capi) + get(:thread_safety)
# An ordered list of the directories containing specs to run
set :files, get(:command_line) + get(:language) + get(:core) + get(:library) + get(:security) + get(:optional)
diff --git a/spec/ruby/fixtures/code/concurrent_require_fixture.rb b/spec/ruby/fixtures/code/concurrent_require_fixture.rb
new file mode 100644
index 0000000000..d4ce734183
--- /dev/null
+++ b/spec/ruby/fixtures/code/concurrent_require_fixture.rb
@@ -0,0 +1,4 @@
+object = ScratchPad.recorded
+thread = Thread.new { object.require(__FILE__) }
+Thread.pass until thread.stop?
+ScratchPad.record(thread)
diff --git a/spec/ruby/fixtures/code/d/load_fixture.rb.rb b/spec/ruby/fixtures/code/d/load_fixture.rb.rb
new file mode 100644
index 0000000000..7e9217729a
--- /dev/null
+++ b/spec/ruby/fixtures/code/d/load_fixture.rb.rb
@@ -0,0 +1 @@
+ScratchPad << :rbrb
diff --git a/spec/ruby/fixtures/code/load_wrap_fixture.rb b/spec/ruby/fixtures/code/load_wrap_fixture.rb
new file mode 100644
index 0000000000..526bbf8c82
--- /dev/null
+++ b/spec/ruby/fixtures/code/load_wrap_fixture.rb
@@ -0,0 +1,12 @@
+class LoadSpecWrap
+ ScratchPad << String
+end
+
+LOAD_WRAP_SPECS_TOP_LEVEL_CONSTANT = 1
+
+def load_wrap_specs_top_level_method
+ :load_wrap_specs_top_level_method
+end
+ScratchPad << method(:load_wrap_specs_top_level_method).owner
+
+ScratchPad << self
diff --git a/spec/ruby/fixtures/code/wrap_fixture.rb b/spec/ruby/fixtures/code/wrap_fixture.rb
deleted file mode 100644
index 7ddf5a62e0..0000000000
--- a/spec/ruby/fixtures/code/wrap_fixture.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class LoadSpecWrap
- ScratchPad << String
-end
-
-def load_wrap_specs_top_level_method
-end
-ScratchPad << method(:load_wrap_specs_top_level_method).owner
-
-ScratchPad << self
diff --git a/spec/ruby/fixtures/constants.rb b/spec/ruby/fixtures/constants.rb
index 4c456dae89..7f0b88daab 100644
--- a/spec/ruby/fixtures/constants.rb
+++ b/spec/ruby/fixtures/constants.rb
@@ -10,7 +10,7 @@
# variety in class and module configurations, including hierarchy,
# containment, inclusion, singletons and toplevel.
#
-# Constants are numbered for for uniqueness. The CS_ prefix is uniformly used
+# Constants are numbered for uniqueness. The CS_ prefix is uniformly used
# and is to minimize clashes with other toplevel constants (see e.g. ModuleA
# which is included in Object). Constant values are symbols. A numbered suffix
# is used to distinguish constants with the same name defined in different
@@ -44,6 +44,7 @@ module ConstantSpecs
# Included in ParentA
module ModuleB
+ LINE = __LINE__ - 1
CS_CONST10 = :const10_9
CS_CONST11 = :const11_2
CS_CONST12 = :const12_1
@@ -75,12 +76,19 @@ module ConstantSpecs
CS_CONST10 = :const10_8
end
+ # Included in ContainerA
+ module ModuleIncludePrepended
+ prepend ModuleD
+
+ CS_CONST11 = :const11_8
+ end
+
# The following classes/modules have all the constants set "statically".
# Contrast with the classes below where the constants are set as the specs
# are run.
class ClassA
- CS_CLASS_A_LINE = __LINE__ - 1
+ LINE = __LINE__ - 1
CS_CONST10 = :const10_10
CS_CONST10_LINE = __LINE__ - 1
CS_CONST16 = :const16
@@ -169,6 +177,10 @@ module ConstantSpecs
def const10; CS_CONST10; end
end
+ class ContainerPrepend
+ include ModuleIncludePrepended
+ end
+
class ContainerA::ChildA
def self.const23; CS_CONST23; end
end
diff --git a/spec/ruby/fixtures/io.rb b/spec/ruby/fixtures/io.rb
new file mode 100644
index 0000000000..87ebbbb2bd
--- /dev/null
+++ b/spec/ruby/fixtures/io.rb
@@ -0,0 +1,12 @@
+module IOSpec
+ def self.exhaust_write_buffer(io)
+ written = 0
+ buf = " " * 4096
+
+ while true
+ written += io.write_nonblock(buf)
+ end
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK
+ written
+ end
+end
diff --git a/spec/ruby/language/BEGIN_spec.rb b/spec/ruby/language/BEGIN_spec.rb
index 5aef5a1d7c..25db32b96a 100644
--- a/spec/ruby/language/BEGIN_spec.rb
+++ b/spec/ruby/language/BEGIN_spec.rb
@@ -15,7 +15,7 @@ describe "The BEGIN keyword" do
end
it "must appear in a top-level context" do
- -> { eval "1.times { BEGIN { 1 } }" }.should raise_error(SyntaxError)
+ -> { eval "1.times { BEGIN { 1 } }" }.should.raise(SyntaxError)
end
it "uses top-level for self" do
diff --git a/spec/ruby/language/END_spec.rb b/spec/ruby/language/END_spec.rb
index 762a8db0c0..c84f0cc9ac 100644
--- a/spec/ruby/language/END_spec.rb
+++ b/spec/ruby/language/END_spec.rb
@@ -1,15 +1,33 @@
require_relative '../spec_helper'
+require_relative '../shared/kernel/at_exit'
describe "The END keyword" do
+ it_behaves_like :kernel_at_exit, :END
+
it "runs only once for multiple calls" do
ruby_exe("10.times { END { puts 'foo' }; } ").should == "foo\n"
end
- it "runs last in a given code unit" do
- ruby_exe("END { puts 'bar' }; puts'foo'; ").should == "foo\nbar\n"
+ it "is affected by the toplevel assignment" do
+ ruby_exe("foo = 'foo'; END { puts foo }").should == "foo\n"
+ end
+
+ it "warns when END is used in a method" do
+ ruby_exe(<<~ruby, args: "2>&1").should =~ /warning: END in method; use at_exit/
+ def foo
+ END { }
+ end
+ ruby
end
- it "runs multiple ends in LIFO order" do
- ruby_exe("END { puts 'foo' }; END { puts 'bar' }").should == "bar\nfoo\n"
+ context "END blocks and at_exit callbacks are mixed" do
+ it "runs them all in reverse order of registration" do
+ ruby_exe(<<~ruby).should == "at_exit#2\nEND#2\nat_exit#1\nEND#1\n"
+ END { puts 'END#1' }
+ at_exit { puts 'at_exit#1' }
+ END { puts 'END#2' }
+ at_exit { puts 'at_exit#2' }
+ ruby
+ end
end
end
diff --git a/spec/ruby/language/alias_spec.rb b/spec/ruby/language/alias_spec.rb
index c353390679..4b3d36d308 100644
--- a/spec/ruby/language/alias_spec.rb
+++ b/spec/ruby/language/alias_spec.rb
@@ -52,6 +52,15 @@ describe "The alias keyword" do
@obj.a.should == 5
end
+ it "works with an interpolated symbol with non-literal embedded expression on the left-hand side" do
+ @meta.class_eval do
+ eval %Q{
+ alias :"#{'a' + ''.to_s}" value
+ }
+ end
+ @obj.a.should == 5
+ end
+
it "works with a simple symbol on the right-hand side" do
@meta.class_eval do
alias a :value
@@ -80,6 +89,15 @@ describe "The alias keyword" do
@obj.a.should == 5
end
+ it "works with an interpolated symbol with non-literal embedded expression on the right-hand side" do
+ @meta.class_eval do
+ eval %Q{
+ alias a :"#{'value' + ''.to_s}"
+ }
+ end
+ @obj.a.should == 5
+ end
+
it "adds the new method to the list of methods" do
original_methods = @obj.methods
@meta.class_eval do
@@ -122,7 +140,7 @@ describe "The alias keyword" do
end
@obj.__value.should == 5
- -> { AliasObject.new.__value }.should raise_error(NoMethodError)
+ -> { AliasObject.new.__value }.should.raise(NoMethodError)
end
it "operates on the class/module metaclass when used in instance_eval" do
@@ -131,7 +149,7 @@ describe "The alias keyword" do
end
AliasObject.__klass_method.should == 7
- -> { Object.__klass_method }.should raise_error(NoMethodError)
+ -> { Object.__klass_method }.should.raise(NoMethodError)
end
it "operates on the class/module metaclass when used in instance_exec" do
@@ -140,7 +158,7 @@ describe "The alias keyword" do
end
AliasObject.__klass_method2.should == 7
- -> { Object.__klass_method2 }.should raise_error(NoMethodError)
+ -> { Object.__klass_method2 }.should.raise(NoMethodError)
end
it "operates on methods defined via attr, attr_reader, and attr_accessor" do
@@ -223,22 +241,22 @@ describe "The alias keyword" do
1.instance_eval do
alias :foo :to_s
end
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
-> do
:blah.instance_eval do
alias :foo :to_s
end
- end.should raise_error(TypeError)
+ end.should.raise(TypeError)
end
it "on top level defines the alias on Object" do
# because it defines on the default definee / current module
- ruby_exe("def foo; end; alias bla foo; print method(:bla).owner", escape: true).should == "Object"
+ ruby_exe("def foo; end; alias bla foo; print method(:bla).owner").should == "Object"
end
it "raises a NameError when passed a missing name" do
- -> { @meta.class_eval { alias undef_method not_exist } }.should raise_error(NameError) { |e|
+ -> { @meta.class_eval { alias undef_method not_exist } }.should.raise(NameError) { |e|
# a NameError and not a NoMethodError
e.class.should == NameError
}
@@ -254,7 +272,7 @@ describe "The alias keyword" do
end
child.instance_method(:parent_method_alias).owner.should == child
- child.instance_methods(false).should include(:parent_method_alias)
+ child.instance_methods(false).should.include?(:parent_method_alias)
end
end
diff --git a/spec/ruby/language/and_spec.rb b/spec/ruby/language/and_spec.rb
index 55a2a3103a..c5c255989b 100644
--- a/spec/ruby/language/and_spec.rb
+++ b/spec/ruby/language/and_spec.rb
@@ -5,7 +5,7 @@ describe "The '&&' statement" do
it "short-circuits evaluation at the first condition to be false" do
x = nil
true && false && x = 1
- x.should be_nil
+ x.should == nil
end
it "evaluates to the first condition not to be true" do
@@ -33,9 +33,9 @@ describe "The '&&' statement" do
end
it "treats empty expressions as nil" do
- (() && true).should be_nil
- (true && ()).should be_nil
- (() && ()).should be_nil
+ (() && true).should == nil
+ (true && ()).should == nil
+ (() && ()).should == nil
end
end
@@ -44,7 +44,7 @@ describe "The 'and' statement" do
it "short-circuits evaluation at the first condition to be false" do
x = nil
true and false and x = 1
- x.should be_nil
+ x.should == nil
end
it "evaluates to the first condition not to be true" do
@@ -72,9 +72,9 @@ describe "The 'and' statement" do
end
it "treats empty expressions as nil" do
- (() and true).should be_nil
- (true and ()).should be_nil
- (() and ()).should be_nil
+ (() and true).should == nil
+ (true and ()).should == nil
+ (() and ()).should == nil
end
end
diff --git a/spec/ruby/language/array_spec.rb b/spec/ruby/language/array_spec.rb
index 2583cffbf7..78cf36c201 100644
--- a/spec/ruby/language/array_spec.rb
+++ b/spec/ruby/language/array_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/array'
describe "Array literals" do
it "[] should return a new array populated with the given elements" do
array = [1, 'a', nil]
- array.should be_kind_of(Array)
+ array.should.is_a?(Array)
array[0].should == 1
array[1].should == 'a'
array[2].should == nil
@@ -12,7 +12,7 @@ describe "Array literals" do
it "[] treats empty expressions as nil elements" do
array = [0, (), 2, (), 4]
- array.should be_kind_of(Array)
+ array.should.is_a?(Array)
array[0].should == 0
array[1].should == nil
array[2].should == 2
@@ -89,7 +89,7 @@ describe "The unpacking splat operator (*)" do
it "returns a new array containing the same values when applied to an array inside an empty array" do
splatted_array = [3, 4, 5]
[*splatted_array].should == splatted_array
- [*splatted_array].should_not equal(splatted_array)
+ [*splatted_array].should_not.equal?(splatted_array)
end
it "unpacks the start and count arguments in an array slice assignment" do
@@ -135,7 +135,7 @@ describe "The unpacking splat operator (*)" do
it "when applied to a non-Array value uses it unchanged if it does not respond_to?(:to_a)" do
obj = Object.new
- obj.should_not respond_to(:to_a)
+ obj.should_not.respond_to?(:to_a)
[1, *obj].should == [1, obj]
end
@@ -155,8 +155,12 @@ describe "The unpacking splat operator (*)" do
b = [1, 0]
[*a, 3, *a, *b].should == [1, 2, 3, 1, 2, 1, 0]
end
-end
-
-describe "The packing splat operator (*)" do
+ ruby_version_is "4.0" do
+ it "does not call #to_a on nil" do
+ e = nil
+ e.should_not_receive(:to_a)
+ [*e].should == []
+ end
+ end
end
diff --git a/spec/ruby/language/assignments_spec.rb b/spec/ruby/language/assignments_spec.rb
new file mode 100644
index 0000000000..d621c9f0c6
--- /dev/null
+++ b/spec/ruby/language/assignments_spec.rb
@@ -0,0 +1,582 @@
+require_relative '../spec_helper'
+
+# Should be synchronized with spec/ruby/language/optional_assignments_spec.rb
+# Some specs for assignments are located in language/variables_spec.rb
+describe 'Assignments' do
+ describe 'using =' do
+ describe 'evaluation order' do
+ it 'evaluates expressions left to right when assignment with an accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
+
+ (ScratchPad << :receiver; object).a = (ScratchPad << :rhs; :value)
+ ScratchPad.recorded.should == [:receiver, :rhs]
+ end
+
+ it 'evaluates expressions left to right when assignment with a #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
+
+ (ScratchPad << :receiver; object)[(ScratchPad << :argument; :a)] = (ScratchPad << :rhs; :value)
+ ScratchPad.recorded.should == [:receiver, :argument, :rhs]
+ end
+
+ it 'evaluates expressions left to right when assignment with compounded constant' do
+ m = Module.new
+ ScratchPad.record []
+
+ (ScratchPad << :module; m)::A = (ScratchPad << :rhs; :value)
+ ScratchPad.recorded.should == [:module, :rhs]
+ end
+
+ it 'raises TypeError after evaluation of right-hand-side when compounded constant module is not a module' do
+ ScratchPad.record []
+
+ -> {
+ (:not_a_module)::A = (ScratchPad << :rhs; :value)
+ }.should.raise(TypeError)
+
+ ScratchPad.recorded.should == [:rhs]
+ end
+ end
+
+ context "given block argument" do
+ before do
+ @klass = Class.new do
+ def initialize(h) @h = h end
+ def [](k, &block) @h[k]; end
+ def []=(k, v, &block) @h[k] = v; end
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "accepts block argument" do
+ obj = @klass.new(a: 1)
+ block = proc {}
+
+ eval "obj[:a, &block] = 2"
+ eval("obj[:a, &block]").should == 2
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises SyntaxError" do
+ obj = @klass.new(a: 1)
+ block = proc {}
+
+ -> {
+ eval "obj[:a, &block] = 2"
+ }.should.raise(SyntaxError, /unexpected block arg given in index assignment|block arg given in index assignment/)
+ end
+ end
+ end
+
+ context "given keyword arguments" do
+ before do
+ @klass = Class.new do
+ attr_reader :x
+
+ def []=(*args, **kw)
+ @x = [args, kw]
+ end
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "supports keyword arguments in index assignments" do
+ a = @klass.new
+ eval "a[1, 2, 3, b: 4] = 5"
+ a.x.should == [[1, 2, 3, {b: 4}, 5], {}]
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises SyntaxError when given keyword arguments in index assignments" do
+ a = @klass.new
+ -> { eval "a[1, 2, 3, b: 4] = 5" }.should.raise(SyntaxError,
+ /keywords are not allowed in index assignment expressions|keyword arg given in index assignment/) # prism|parse.y
+ end
+ end
+ end
+ end
+
+ describe 'using +=' do
+ describe 'using an accessor' do
+ before do
+ klass = Class.new { attr_accessor :b }
+ @a = klass.new
+ end
+
+ it 'does evaluate receiver only once when assigns' do
+ ScratchPad.record []
+ @a.b = 1
+
+ (ScratchPad << :evaluated; @a).b += 2
+
+ ScratchPad.recorded.should == [:evaluated]
+ @a.b.should == 3
+ end
+
+ it 'ignores method visibility when receiver is self' do
+ klass_with_private_methods = Class.new do
+ def initialize(n) @a = n end
+ def public_method(n); self.a += n end
+ private
+ def a; @a end
+ def a=(n) @a = n; 42 end
+ end
+
+ a = klass_with_private_methods.new(0)
+ a.public_method(2).should == 2
+ end
+ end
+
+ describe 'using a #[]' do
+ before do
+ klass = Class.new do
+ def [](k)
+ @hash ||= {}
+ @hash[k]
+ end
+
+ def []=(k, v)
+ @hash ||= {}
+ @hash[k] = v
+ 7
+ end
+ end
+ @b = klass.new
+ end
+
+ it 'evaluates receiver only once when assigns' do
+ ScratchPad.record []
+ a = {k: 1}
+
+ (ScratchPad << :evaluated; a)[:k] += 2
+
+ ScratchPad.recorded.should == [:evaluated]
+ a[:k].should == 3
+ end
+
+ it 'ignores method visibility when receiver is self' do
+ klass_with_private_methods = Class.new do
+ def initialize(h) @a = h end
+ def public_method(k, n); self[k] += n end
+ private
+ def [](k) @a[k] end
+ def []=(k, v) @a[k] = v; 42 end
+ end
+
+ a = klass_with_private_methods.new(k: 0)
+ a.public_method(:k, 2).should == 2
+ end
+
+ context "given block argument" do
+ before do
+ @klass = Class.new do
+ def initialize(h) @h = h end
+ def [](k, &block) @h[k]; end
+ def []=(k, v, &block) @h[k] = v; end
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "accepts block argument" do
+ obj = @klass.new(a: 1)
+ block = proc {}
+
+ eval "obj[:a, &block] += 2"
+ eval("obj[:a, &block]").should == 3
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises SyntaxError" do
+ obj = @klass.new(a: 1)
+ block = proc {}
+
+ -> {
+ eval "obj[:a, &block] += 2"
+ }.should.raise(SyntaxError, /unexpected block arg given in index assignment|block arg given in index assignment/)
+ end
+ end
+ end
+
+ context "given keyword arguments" do
+ before do
+ @klass = Class.new do
+ attr_reader :x
+
+ def [](*args)
+ 100
+ end
+
+ def []=(*args, **kw)
+ @x = [args, kw]
+ end
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "supports keyword arguments in index assignments" do
+ a = @klass.new
+ eval "a[1, 2, 3, b: 4] += 5"
+ a.x.should == [[1, 2, 3, 105], {b: 4}]
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises SyntaxError when given keyword arguments in index assignments" do
+ a = @klass.new
+ -> { eval "a[1, 2, 3, b: 4] += 5" }.should.raise(SyntaxError,
+ /keywords are not allowed in index assignment expressions|keyword arg given in index assignment/) # prism|parse.y
+ end
+ end
+ end
+
+ context 'splatted argument' do
+ it 'correctly handles it' do
+ @b[:m] = 10
+ (@b[*[:m]] += 10).should == 20
+ @b[:m].should == 20
+
+ @b[:n] = 10
+ (@b[*(1; [:n])] += 10).should == 20
+ @b[:n].should == 20
+
+ @b[:k] = 10
+ (@b[*begin 1; [:k] end] += 10).should == 20
+ @b[:k].should == 20
+ end
+
+ it 'calls #to_a only once' do
+ k = Object.new
+ def k.to_a
+ ScratchPad << :to_a
+ [:k]
+ end
+
+ ScratchPad.record []
+ @b[:k] = 10
+ (@b[*k] += 10).should == 20
+ @b[:k].should == 20
+ ScratchPad.recorded.should == [:to_a]
+ end
+
+ it 'correctly handles a nested splatted argument' do
+ @b[:k] = 10
+ (@b[*[*[:k]]] += 10).should == 20
+ @b[:k].should == 20
+ end
+
+ it 'correctly handles multiple nested splatted arguments' do
+ klass_with_multiple_parameters = Class.new do
+ def [](k1, k2, k3)
+ @hash ||= {}
+ @hash[:"#{k1}#{k2}#{k3}"]
+ end
+
+ def []=(k1, k2, k3, v)
+ @hash ||= {}
+ @hash[:"#{k1}#{k2}#{k3}"] = v
+ 7
+ end
+ end
+ a = klass_with_multiple_parameters.new
+
+ a[:a, :b, :c] = 10
+ (a[*[:a], *[:b], *[:c]] += 10).should == 20
+ a[:a, :b, :c].should == 20
+ end
+ end
+ end
+
+ describe 'using compounded constants' do
+ it 'causes side-effects of the module part to be applied only once (when assigns)' do
+ module ConstantSpecs
+ OpAssignTrue = 1
+ end
+
+ suppress_warning do # already initialized constant
+ x = 0
+ (x += 1; ConstantSpecs)::OpAssignTrue += 2
+ x.should == 1
+ ConstantSpecs::OpAssignTrue.should == 3
+ end
+
+ ConstantSpecs.send :remove_const, :OpAssignTrue
+ end
+ end
+ end
+end
+
+# generic cases
+describe 'Multiple assignments' do
+ it 'assigns multiple targets when assignment with an accessor' do
+ object = Object.new
+ class << object
+ attr_accessor :a, :b
+ end
+
+ object.a, object.b = :a, :b
+
+ object.a.should == :a
+ object.b.should == :b
+ end
+
+ it 'assigns multiple targets when assignment with a nested accessor' do
+ object = Object.new
+ class << object
+ attr_accessor :a, :b
+ end
+
+ (object.a, object.b), c = [:a, :b], nil
+
+ object.a.should == :a
+ object.b.should == :b
+ end
+
+ it 'assigns multiple targets when assignment with a #[]=' do
+ object = Object.new
+ class << object
+ def []=(k, v) (@h ||= {})[k] = v; end
+ def [](k) (@h ||= {})[k]; end
+ end
+
+ object[:a], object[:b] = :a, :b
+
+ object[:a].should == :a
+ object[:b].should == :b
+ end
+
+ it 'assigns multiple targets when assignment with a nested #[]=' do
+ object = Object.new
+ class << object
+ def []=(k, v) (@h ||= {})[k] = v; end
+ def [](k) (@h ||= {})[k]; end
+ end
+
+ (object[:a], object[:b]), c = [:v1, :v2], nil
+
+ object[:a].should == :v1
+ object[:b].should == :v2
+ end
+
+ it 'assigns multiple targets when assignment with compounded constant' do
+ m = Module.new
+
+ m::A, m::B = :a, :b
+
+ m::A.should == :a
+ m::B.should == :b
+ end
+
+ it 'assigns multiple targets when assignment with a nested compounded constant' do
+ m = Module.new
+
+ (m::A, m::B), c = [:a, :b], nil
+
+ m::A.should == :a
+ m::B.should == :b
+ end
+end
+
+describe 'Multiple assignments' do
+ describe 'evaluation order' do
+ it 'evaluates expressions left to right when assignment with an accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
+
+ (ScratchPad << :a; object).a, (ScratchPad << :b; object).a = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
+ ScratchPad.recorded.should == [:a, :b, :c, :d]
+ end
+
+ it 'evaluates expressions left to right when assignment with a nested accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
+
+ ((ScratchPad << :a; object).a, foo), bar = [(ScratchPad << :b; :b)]
+ ScratchPad.recorded.should == [:a, :b]
+ end
+
+ it 'evaluates expressions left to right when assignment with a deeply nested accessor' do
+ o = Object.new
+ def o.a=(value) end
+ def o.b=(value) end
+ def o.c=(value) end
+ def o.d=(value) end
+ def o.e=(value) end
+ def o.f=(value) end
+ ScratchPad.record []
+
+ (ScratchPad << :a; o).a,
+ ((ScratchPad << :b; o).b,
+ ((ScratchPad << :c; o).c, (ScratchPad << :d; o).d),
+ (ScratchPad << :e; o).e),
+ (ScratchPad << :f; o).f = (ScratchPad << :value; :value)
+
+ ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f, :value]
+ end
+
+ it 'evaluates expressions left to right when assignment with a #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
+
+ (ScratchPad << :a; object)[(ScratchPad << :b; :b)], (ScratchPad << :c; object)[(ScratchPad << :d; :d)] = (ScratchPad << :e; :e), (ScratchPad << :f; :f)
+ ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f]
+ end
+
+ it 'evaluates expressions left to right when assignment with a nested #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
+
+ ((ScratchPad << :a; object)[(ScratchPad << :b; :b)], foo), bar = [(ScratchPad << :c; :c)]
+ ScratchPad.recorded.should == [:a, :b, :c]
+ end
+
+ it 'evaluates expressions left to right when assignment with a deeply nested #[]=' do
+ o = Object.new
+ def o.[]=(_, _) end
+ ScratchPad.record []
+
+ (ScratchPad << :ra; o)[(ScratchPad << :aa; :aa)],
+ ((ScratchPad << :rb; o)[(ScratchPad << :ab; :ab)],
+ ((ScratchPad << :rc; o)[(ScratchPad << :ac; :ac)], (ScratchPad << :rd; o)[(ScratchPad << :ad; :ad)]),
+ (ScratchPad << :re; o)[(ScratchPad << :ae; :ae)]),
+ (ScratchPad << :rf; o)[(ScratchPad << :af; :af)] = (ScratchPad << :value; :value)
+
+ ScratchPad.recorded.should == [:ra, :aa, :rb, :ab, :rc, :ac, :rd, :ad, :re, :ae, :rf, :af, :value]
+ end
+
+ it 'evaluates expressions left to right when assignment with compounded constant' do
+ m = Module.new
+ ScratchPad.record []
+
+ (ScratchPad << :a; m)::A, (ScratchPad << :b; m)::B = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
+ ScratchPad.recorded.should == [:a, :b, :c, :d]
+ end
+
+ it 'evaluates expressions left to right when assignment with a nested compounded constant' do
+ m = Module.new
+ ScratchPad.record []
+
+ ((ScratchPad << :a; m)::A, foo), bar = [(ScratchPad << :b; :b)]
+ ScratchPad.recorded.should == [:a, :b]
+ end
+
+ it 'evaluates expressions left to right when assignment with deeply nested compounded constants' do
+ m = Module.new
+ ScratchPad.record []
+
+ (ScratchPad << :a; m)::A,
+ ((ScratchPad << :b; m)::B,
+ ((ScratchPad << :c; m)::C, (ScratchPad << :d; m)::D),
+ (ScratchPad << :e; m)::E),
+ (ScratchPad << :f; m)::F = (ScratchPad << :value; :value)
+
+ ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f, :value]
+ end
+ end
+
+ context 'when assignment with method call and receiver is self' do
+ it 'assigns values correctly when assignment with accessor' do
+ object = Object.new
+ class << object
+ attr_accessor :a, :b
+
+ def assign(v1, v2)
+ self.a, self.b = v1, v2
+ end
+ end
+
+ object.assign :v1, :v2
+ object.a.should == :v1
+ object.b.should == :v2
+ end
+
+ it 'evaluates expressions right to left when assignment with a nested accessor' do
+ object = Object.new
+ class << object
+ attr_accessor :a, :b
+
+ def assign(v1, v2)
+ (self.a, self.b), c = [v1, v2], nil
+ end
+ end
+
+ object.assign :v1, :v2
+ object.a.should == :v1
+ object.b.should == :v2
+ end
+
+ it 'assigns values correctly when assignment with a #[]=' do
+ object = Object.new
+ class << object
+ def []=(key, v)
+ @h ||= {}
+ @h[key] = v
+ end
+
+ def [](key)
+ (@h || {})[key]
+ end
+
+ def assign(k1, v1, k2, v2)
+ self[k1], self[k2] = v1, v2
+ end
+ end
+
+ object.assign :k1, :v1, :k2, :v2
+ object[:k1].should == :v1
+ object[:k2].should == :v2
+ end
+
+ it 'assigns values correctly when assignment with a nested #[]=' do
+ object = Object.new
+ class << object
+ def []=(key, v)
+ @h ||= {}
+ @h[key] = v
+ end
+
+ def [](key)
+ (@h || {})[key]
+ end
+
+ def assign(k1, v1, k2, v2)
+ (self[k1], self[k2]), c = [v1, v2], nil
+ end
+ end
+
+ object.assign :k1, :v1, :k2, :v2
+ object[:k1].should == :v1
+ object[:k2].should == :v2
+ end
+
+ it 'assigns values correctly when assignment with compounded constant' do
+ m = Module.new
+ m.module_exec do
+ self::A, self::B = :v1, :v2
+ end
+
+ m::A.should == :v1
+ m::B.should == :v2
+ end
+
+ it 'assigns values correctly when assignment with a nested compounded constant' do
+ m = Module.new
+ m.module_exec do
+ (self::A, self::B), c = [:v1, :v2], nil
+ end
+
+ m::A.should == :v1
+ m::B.should == :v2
+ end
+ end
+end
diff --git a/spec/ruby/language/block_spec.rb b/spec/ruby/language/block_spec.rb
index 42652152a1..5bdb993aea 100644
--- a/spec/ruby/language/block_spec.rb
+++ b/spec/ruby/language/block_spec.rb
@@ -13,7 +13,7 @@ describe "A block yielded a single" do
it "receives the identical Array object" do
ary = [1, 2]
- m(ary) { |a| a }.should equal(ary)
+ m(ary) { |a| a }.should.equal?(ary)
end
it "assigns the Array to a single rest argument" do
@@ -40,79 +40,54 @@ describe "A block yielded a single" do
m([1, 2]) { |a=5, b, c, d| [a, b, c, d] }.should == [5, 1, 2, nil]
end
- ruby_version_is "3.2" do
- it "does not autosplat single argument to required arguments when a keyword rest argument is present" do
- m([1, 2]) { |a, **k| [a, k] }.should == [[1, 2], {}]
- end
+ it "assigns elements to pre arguments" do
+ m([1, 2]) { |a, b, c, d=5| [a, b, c, d] }.should == [1, 2, nil, 5]
end
- ruby_version_is ''..."3.2" do
- # https://bugs.ruby-lang.org/issues/18633
- it "autosplats single argument to required arguments when a keyword rest argument is present" do
- m([1, 2]) { |a, **k| [a, k] }.should == [1, {}]
- end
+ it "assigns elements to pre and post arguments" do
+ m([1 ]) { |a, b=5, c=6, d, e| [a, b, c, d, e] }.should == [1, 5, 6, nil, nil]
+ m([1, 2 ]) { |a, b=5, c=6, d, e| [a, b, c, d, e] }.should == [1, 5, 6, 2, nil]
+ m([1, 2, 3 ]) { |a, b=5, c=6, d, e| [a, b, c, d, e] }.should == [1, 5, 6, 2, 3]
+ m([1, 2, 3, 4 ]) { |a, b=5, c=6, d, e| [a, b, c, d, e] }.should == [1, 2, 6, 3, 4]
+ m([1, 2, 3, 4, 5 ]) { |a, b=5, c=6, d, e| [a, b, c, d, e] }.should == [1, 2, 3, 4, 5]
+ m([1, 2, 3, 4, 5, 6]) { |a, b=5, c=6, d, e| [a, b, c, d, e] }.should == [1, 2, 3, 4, 5]
end
- ruby_version_is ''..."3.0" do
- it "assigns elements to mixed argument types" do
- suppress_keyword_warning do
- result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
- result.should == [1, 2, [], 3, 2, {x: 9}]
- end
- end
-
- it "assigns symbol keys from a Hash to keyword arguments" do
- suppress_keyword_warning do
- result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] }
- result.should == [{"a" => 1}, a: 10]
- end
- end
-
- it "assigns symbol keys from a Hash returned by #to_hash to keyword arguments" do
- suppress_keyword_warning do
- obj = mock("coerce block keyword arguments")
- obj.should_receive(:to_hash).and_return({"a" => 1, b: 2})
-
- result = m([obj]) { |a=nil, **b| [a, b] }
- result.should == [{"a" => 1}, b: 2]
- end
- end
+ it "assigns elements to pre and post arguments when *rest is present" do
+ m([1 ]) { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.should == [1, 5, 6, [], nil, nil]
+ m([1, 2 ]) { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.should == [1, 5, 6, [], 2, nil]
+ m([1, 2, 3 ]) { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.should == [1, 5, 6, [], 2, 3]
+ m([1, 2, 3, 4 ]) { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.should == [1, 2, 6, [], 3, 4]
+ m([1, 2, 3, 4, 5 ]) { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.should == [1, 2, 3, [], 4, 5]
+ m([1, 2, 3, 4, 5, 6]) { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.should == [1, 2, 3, [4], 5, 6]
end
- ruby_version_is "3.0" do
- it "assigns elements to mixed argument types" do
- result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
- result.should == [1, 2, [3], {x: 9}, 2, {}]
- end
-
- it "does not treat final Hash as keyword arguments and does not autosplat" do
- result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] }
- result.should == [[{"a" => 1, a: 10}], {}]
- end
+ it "does not autosplat single argument to required arguments when a keyword rest argument is present" do
+ m([1, 2]) { |a, **k| [a, k] }.should == [[1, 2], {}]
+ end
- it "does not call #to_hash on final argument to get keyword arguments and does not autosplat" do
- suppress_keyword_warning do
- obj = mock("coerce block keyword arguments")
- obj.should_not_receive(:to_hash)
+ it "does not autosplat single argument to required arguments when keyword arguments are present" do
+ m([1, 2]) { |a, b: :b, c: :c| [a, b, c] }.should == [[1, 2], :b, :c]
+ end
- result = m([obj]) { |a=nil, **b| [a, b] }
- result.should == [[obj], {}]
- end
- end
+ it "raises error when required keyword arguments are present" do
+ -> {
+ m([1, 2]) { |a, b:, c:| [a, b, c] }
+ }.should.raise(ArgumentError, "missing keywords: :b, :c")
end
- ruby_version_is ""...'3.0' do
- it "calls #to_hash on the argument but ignores result when optional argument and keyword argument accepted" do
- obj = mock("coerce block keyword arguments")
- obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})
+ it "assigns elements to mixed argument types" do
+ result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
+ result.should == [1, 2, [3], {x: 9}, 2, {}]
+ end
- result = m([obj]) { |a=nil, **b| [a, b] }
- result.should == [obj, {}]
- end
+ it "does not treat final Hash as keyword arguments and does not autosplat" do
+ result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] }
+ result.should == [[{"a" => 1, a: 10}], {}]
end
- ruby_version_is "3.0" do
- it "does not call #to_hash on the argument when optional argument and keyword argument accepted and does not autosplat" do
+ it "does not call #to_hash on final argument to get keyword arguments and does not autosplat" do
+ suppress_keyword_warning do
obj = mock("coerce block keyword arguments")
obj.should_not_receive(:to_hash)
@@ -121,102 +96,42 @@ describe "A block yielded a single" do
end
end
- describe "when non-symbol keys are in a keyword arguments Hash" do
- ruby_version_is ""..."3.0" do
- it "separates non-symbol keys and symbol keys" do
- suppress_keyword_warning do
- result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
- result.should == [{"a" => 10}, {b: 2}]
- end
- end
- end
- ruby_version_is "3.0" do
- it "does not separate non-symbol keys and symbol keys and does not autosplat" do
- suppress_keyword_warning do
- result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
- result.should == [[{"a" => 10, b: 2}], {}]
- end
- end
- end
- end
-
- ruby_version_is ""..."3.0" do
- it "does not treat hashes with string keys as keyword arguments" do
- result = m(["a" => 10]) { |a = nil, **b| [a, b] }
- result.should == [{"a" => 10}, {}]
- end
- end
+ it "does not call #to_hash on the argument when optional argument and keyword argument accepted and does not autosplat" do
+ obj = mock("coerce block keyword arguments")
+ obj.should_not_receive(:to_hash)
- ruby_version_is "3.0" do
- it "does not treat hashes with string keys as keyword arguments and does not autosplat" do
- result = m(["a" => 10]) { |a = nil, **b| [a, b] }
- result.should == [[{"a" => 10}], {}]
- end
+ result = m([obj]) { |a=nil, **b| [a, b] }
+ result.should == [[obj], {}]
end
- ruby_version_is ''...'3.0' do
- it "calls #to_hash on the last element if keyword arguments are present" do
- suppress_keyword_warning do
- obj = mock("destructure block keyword arguments")
- obj.should_receive(:to_hash).and_return({x: 9})
-
- result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
- result.should == [1, [2], 3, {x: 9}]
- end
- end
-
- it "assigns the last element to a non-keyword argument if #to_hash returns nil" do
- suppress_keyword_warning do
- obj = mock("destructure block keyword arguments")
- obj.should_receive(:to_hash).and_return(nil)
-
- result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
- result.should == [1, [2, 3], obj, {}]
- end
- end
-
- it "calls #to_hash on the last element when there are more arguments than parameters" do
+ describe "when non-symbol keys are in a keyword arguments Hash" do
+ it "does not separate non-symbol keys and symbol keys and does not autosplat" do
suppress_keyword_warning do
- x = mock("destructure matching block keyword argument")
- x.should_receive(:to_hash).and_return({x: 9})
-
- result = m([1, 2, 3, {y: 9}, 4, 5, x]) { |a, b=5, c, **k| [a, b, c, k] }
- result.should == [1, 2, 3, {x: 9}]
+ result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
+ result.should == [[{"a" => 10, b: 2}], {}]
end
end
+ end
- it "raises a TypeError if #to_hash does not return a Hash" do
- obj = mock("destructure block keyword arguments")
- obj.should_receive(:to_hash).and_return(1)
-
- -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(TypeError)
- end
-
- it "raises the error raised inside #to_hash" do
- obj = mock("destructure block keyword arguments")
- error = RuntimeError.new("error while converting to a hash")
- obj.should_receive(:to_hash).and_raise(error)
-
- -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(error)
- end
+ it "does not treat hashes with string keys as keyword arguments and does not autosplat" do
+ result = m(["a" => 10]) { |a = nil, **b| [a, b] }
+ result.should == [[{"a" => 10}], {}]
end
- ruby_version_is '3.0' do
- it "does not call #to_hash on the last element if keyword arguments are present" do
- obj = mock("destructure block keyword arguments")
- obj.should_not_receive(:to_hash)
+ it "does not call #to_hash on the last element if keyword arguments are present" do
+ obj = mock("destructure block keyword arguments")
+ obj.should_not_receive(:to_hash)
- result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
- result.should == [1, [2, 3], obj, {}]
- end
+ result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
+ result.should == [1, [2, 3], obj, {}]
+ end
- it "does not call #to_hash on the last element when there are more arguments than parameters" do
- x = mock("destructure matching block keyword argument")
- x.should_not_receive(:to_hash)
+ it "does not call #to_hash on the last element when there are more arguments than parameters" do
+ x = mock("destructure matching block keyword argument")
+ x.should_not_receive(:to_hash)
- result = m([1, 2, 3, {y: 9}, 4, 5, x]) { |a, b=5, c, **k| [a, b, c, k] }
- result.should == [1, 2, 3, {}]
- end
+ result = m([1, 2, 3, {y: 9}, 4, 5, x]) { |a, b=5, c, **k| [a, b, c, k] }
+ result.should == [1, 2, 3, {}]
end
it "does not call #to_ary on the Array" do
@@ -263,11 +178,70 @@ describe "A block yielded a single" do
m(obj) { |a, b, c| [a, b, c] }.should == [obj, nil, nil]
end
+ it "receives the object if it does not respond to #to_ary" do
+ obj = Object.new
+
+ m(obj) { |a, b, c| [a, b, c] }.should == [obj, nil, nil]
+ end
+
+ it "calls #respond_to? to check if object has method #to_ary" do
+ obj = mock("destructure block arguments")
+ obj.should_receive(:respond_to?).with(:to_ary, true).and_return(true)
+ obj.should_receive(:to_ary).and_return([1, 2])
+
+ m(obj) { |a, b, c| [a, b, c] }.should == [1, 2, nil]
+ end
+
+ it "calls #respond_to? on a BasicObject to check if object has method #to_ary" do
+ ScratchPad.record []
+ obj = BasicObject.new
+ def obj.respond_to?(name, *)
+ ScratchPad << [:respond_to?, name]
+ name == :to_ary ? true : super
+ end
+ def obj.to_ary
+ ScratchPad << :to_ary
+ [1, 2]
+ end
+
+ m(obj) { |a, b, c| [a, b, c] }.should == [1, 2, nil]
+ ScratchPad.recorded.should == [[:respond_to?, :to_ary], :to_ary]
+ end
+
+ it "receives the object if it does not respond to #respond_to?" do
+ obj = BasicObject.new
+
+ m(obj) { |a, b, c| [a, b, c] }.should == [obj, nil, nil]
+ end
+
+ it "calls #to_ary on the object when it is defined dynamically" do
+ obj = Object.new
+ def obj.method_missing(name, *args, &block)
+ if name == :to_ary
+ [1, 2]
+ else
+ super
+ end
+ end
+ def obj.respond_to_missing?(name, include_private)
+ name == :to_ary
+ end
+
+ m(obj) { |a, b, c| [a, b, c] }.should == [1, 2, nil]
+ end
+
it "raises a TypeError if #to_ary does not return an Array" do
obj = mock("destructure block arguments")
obj.should_receive(:to_ary).and_return(1)
- -> { m(obj) { |a, b| } }.should raise_error(TypeError)
+ -> { m(obj) { |a, b| } }.should.raise(TypeError)
+ end
+
+ it "raises error transparently if #to_ary raises error on its own" do
+ obj = Object.new
+ def obj.to_ary; raise "Exception raised in #to_ary" end
+
+ -> { m(obj) { |a, b| } }.should.raise(RuntimeError, "Exception raised in #to_ary")
end
end
end
@@ -317,7 +291,7 @@ describe "A block" do
end
it "may include a rescue clause" do
- eval("@y.z do raise ArgumentError; rescue ArgumentError; 7; end").should == 7
+ @y.z do raise ArgumentError; rescue ArgumentError; 7; end.should == 7
end
end
@@ -331,13 +305,13 @@ describe "A block" do
end
it "may include a rescue clause" do
- eval('@y.z do || raise ArgumentError; rescue ArgumentError; 7; end').should == 7
+ @y.z do || raise ArgumentError; rescue ArgumentError; 7; end.should == 7
end
end
describe "taking |a| arguments" do
it "assigns nil to the argument when no values are yielded" do
- @y.z { |a| a }.should be_nil
+ @y.z { |a| a }.should == nil
end
it "assigns the value yielded to the argument" do
@@ -348,7 +322,7 @@ describe "A block" do
obj = mock("block yield to_ary")
obj.should_not_receive(:to_ary)
- @y.s(obj) { |a| a }.should equal(obj)
+ @y.s(obj) { |a| a }.should.equal?(obj)
end
it "assigns the first value yielded to the argument" do
@@ -360,7 +334,7 @@ describe "A block" do
end
it "may include a rescue clause" do
- eval('@y.s(1) do |x| raise ArgumentError; rescue ArgumentError; 7; end').should == 7
+ @y.s(1) do |x| raise ArgumentError; rescue ArgumentError; 7; end.should == 7
end
end
@@ -424,16 +398,15 @@ describe "A block" do
obj = mock("block yield to_ary invalid")
obj.should_receive(:to_ary).and_return(1)
- -> { @y.s(obj) { |a, b| } }.should raise_error(TypeError)
+ -> { @y.s(obj) { |a, b| } }.should.raise(TypeError)
end
it "raises the original exception if #to_ary raises an exception" do
obj = mock("block yield to_ary raising an exception")
obj.should_receive(:to_ary).and_raise(ZeroDivisionError)
- -> { @y.s(obj) { |a, b| } }.should raise_error(ZeroDivisionError)
+ -> { @y.s(obj) { |a, b| } }.should.raise(ZeroDivisionError)
end
-
end
describe "taking |a, *b| arguments" do
@@ -488,7 +461,7 @@ describe "A block" do
obj = mock("block yield to_ary invalid")
obj.should_receive(:to_ary).and_return(1)
- -> { @y.s(obj) { |a, *b| } }.should raise_error(TypeError)
+ -> { @y.s(obj) { |a, *b| } }.should.raise(TypeError)
end
end
@@ -566,7 +539,7 @@ describe "A block" do
describe "taking |a, | arguments" do
it "assigns nil to the argument when no values are yielded" do
- @y.z { |a, | a }.should be_nil
+ @y.z { |a, | a }.should == nil
end
it "assigns the argument a single value yielded" do
@@ -582,7 +555,7 @@ describe "A block" do
end
it "assigns nil to the argument when passed an empty Array" do
- @y.s([]) { |a, | a }.should be_nil
+ @y.s([]) { |a, | a }.should == nil
end
it "assigns the argument the first element of the Array when passed a single Array" do
@@ -613,7 +586,7 @@ describe "A block" do
obj = mock("block yield to_ary invalid")
obj.should_receive(:to_ary).and_return(1)
- -> { @y.s(obj) { |a, | } }.should raise_error(TypeError)
+ -> { @y.s(obj) { |a, | } }.should.raise(TypeError)
end
end
@@ -655,7 +628,7 @@ describe "A block" do
obj = mock("block yield to_ary invalid")
obj.should_receive(:to_ary).and_return(1)
- -> { @y.s(obj) { |(a, b)| } }.should raise_error(TypeError)
+ -> { @y.s(obj) { |(a, b)| } }.should.raise(TypeError)
end
end
@@ -696,7 +669,7 @@ describe "A block" do
obj = mock("block yield to_ary invalid")
obj.should_receive(:to_ary).and_return(1)
- -> { @y.s(obj) { |(a, b), c| } }.should raise_error(TypeError)
+ -> { @y.s(obj) { |(a, b), c| } }.should.raise(TypeError)
end
end
@@ -755,15 +728,51 @@ describe "A block" do
describe "taking identically-named arguments" do
it "raises a SyntaxError for standard arguments" do
- -> { eval "lambda { |x,x| }" }.should raise_error(SyntaxError)
- -> { eval "->(x,x) {}" }.should raise_error(SyntaxError)
- -> { eval "Proc.new { |x,x| }" }.should raise_error(SyntaxError)
+ -> { eval "lambda { |x,x| }" }.should.raise(SyntaxError)
+ -> { eval "->(x,x) {}" }.should.raise(SyntaxError)
+ -> { eval "Proc.new { |x,x| }" }.should.raise(SyntaxError)
end
it "accepts unnamed arguments" do
- eval("lambda { |_,_| }").should be_an_instance_of(Proc)
- eval("->(_,_) {}").should be_an_instance_of(Proc)
- eval("Proc.new { |_,_| }").should be_an_instance_of(Proc)
+ lambda { |_,_| }.should.instance_of?(Proc) # rubocop:disable Style/Lambda
+ -> _,_ {}.should.instance_of?(Proc)
+ Proc.new { |_,_| }.should.instance_of?(Proc)
+ end
+ end
+
+ describe 'pre and post parameters' do
+ it "assigns nil to unassigned required arguments" do
+ proc { |a, *b, c, d| [a, b, c, d] }.call(1, 2).should == [1, [], 2, nil]
+ end
+
+ it "assigns elements to optional arguments" do
+ proc { |a=5, b=4, c=3| [a, b, c] }.call(1, 2).should == [1, 2, 3]
+ end
+
+ it "assigns elements to post arguments" do
+ proc { |a=5, b, c, d| [a, b, c, d] }.call(1, 2).should == [5, 1, 2, nil]
+ end
+
+ it "assigns elements to pre arguments" do
+ proc { |a, b, c, d=5| [a, b, c, d] }.call(1, 2).should == [1, 2, nil, 5]
+ end
+
+ it "assigns elements to pre and post arguments" do
+ proc { |a, b=5, c=6, d, e| [a, b, c, d, e] }.call(1 ).should == [1, 5, 6, nil, nil]
+ proc { |a, b=5, c=6, d, e| [a, b, c, d, e] }.call(1, 2 ).should == [1, 5, 6, 2, nil]
+ proc { |a, b=5, c=6, d, e| [a, b, c, d, e] }.call(1, 2, 3 ).should == [1, 5, 6, 2, 3]
+ proc { |a, b=5, c=6, d, e| [a, b, c, d, e] }.call(1, 2, 3, 4 ).should == [1, 2, 6, 3, 4]
+ proc { |a, b=5, c=6, d, e| [a, b, c, d, e] }.call(1, 2, 3, 4, 5 ).should == [1, 2, 3, 4, 5]
+ proc { |a, b=5, c=6, d, e| [a, b, c, d, e] }.call(1, 2, 3, 4, 5, 6).should == [1, 2, 3, 4, 5]
+ end
+
+ it "assigns elements to pre and post arguments when *rest is present" do
+ proc { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.call(1 ).should == [1, 5, 6, [], nil, nil]
+ proc { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.call(1, 2 ).should == [1, 5, 6, [], 2, nil]
+ proc { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.call(1, 2, 3 ).should == [1, 5, 6, [], 2, 3]
+ proc { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.call(1, 2, 3, 4 ).should == [1, 2, 6, [], 3, 4]
+ proc { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.call(1, 2, 3, 4, 5 ).should == [1, 2, 3, [], 4, 5]
+ proc { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.call(1, 2, 3, 4, 5, 6).should == [1, 2, 3, [4], 5, 6]
end
end
end
@@ -778,29 +787,29 @@ describe "Block-local variables" do
end
it "can not have the same name as one of the standard parameters" do
- -> { eval "[1].each {|foo; foo| }" }.should raise_error(SyntaxError)
- -> { eval "[1].each {|foo, bar; glark, bar| }" }.should raise_error(SyntaxError)
+ -> { eval "[1].each {|foo; foo| }" }.should.raise(SyntaxError)
+ -> { eval "[1].each {|foo, bar; glark, bar| }" }.should.raise(SyntaxError)
end
it "can not be prefixed with an asterisk" do
- -> { eval "[1].each {|foo; *bar| }" }.should raise_error(SyntaxError)
+ -> { eval "[1].each {|foo; *bar| }" }.should.raise(SyntaxError)
-> do
eval "[1].each {|foo, bar; glark, *fnord| }"
- end.should raise_error(SyntaxError)
+ end.should.raise(SyntaxError)
end
it "can not be prefixed with an ampersand" do
- -> { eval "[1].each {|foo; &bar| }" }.should raise_error(SyntaxError)
+ -> { eval "[1].each {|foo; &bar| }" }.should.raise(SyntaxError)
-> do
eval "[1].each {|foo, bar; glark, &fnord| }"
- end.should raise_error(SyntaxError)
+ end.should.raise(SyntaxError)
end
it "can not be assigned default values" do
- -> { eval "[1].each {|foo; bar=1| }" }.should raise_error(SyntaxError)
+ -> { eval "[1].each {|foo; bar=1| }" }.should.raise(SyntaxError)
-> do
eval "[1].each {|foo, bar; glark, fnord=:fnord| }"
- end.should raise_error(SyntaxError)
+ end.should.raise(SyntaxError)
end
it "need not be preceded by standard parameters" do
@@ -809,8 +818,8 @@ describe "Block-local variables" do
end
it "only allow a single semi-colon in the parameter list" do
- -> { eval "[1].each {|foo; bar; glark| }" }.should raise_error(SyntaxError)
- -> { eval "[1].each {|; bar; glark| }" }.should raise_error(SyntaxError)
+ -> { eval "[1].each {|foo; bar; glark| }" }.should.raise(SyntaxError)
+ -> { eval "[1].each {|; bar; glark| }" }.should.raise(SyntaxError)
end
it "override shadowed variables from the outer scope" do
@@ -835,21 +844,21 @@ describe "Block-local variables" do
end
it "are not automatically instantiated in the outer scope" do
- defined?(glark).should be_nil
+ defined?(glark).should == nil
[1].each {|;glark| 1}
- defined?(glark).should be_nil
+ defined?(glark).should == nil
end
it "are automatically instantiated in the block" do
[1].each do |;glark|
- glark.should be_nil
+ glark.should == nil
end
end
it "are visible in deeper scopes before initialization" do
[1].each {|;glark|
[1].each {
- defined?(glark).should_not be_nil
+ defined?(glark).should_not == nil
glark = 1
}
glark.should == 1
@@ -877,7 +886,7 @@ describe "Post-args" do
-> *a, b do
[a, b]
end.call
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "are assigned to nil when not enough arguments are given to a proc" do
@@ -948,24 +957,27 @@ describe "Post-args" do
end
describe "with a circular argument reference" do
- it "raises a SyntaxError if using an existing local with the same name as the argument" do
- a = 1
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should raise_error(SyntaxError)
+ ruby_version_is ""..."3.4" do
+ it "raises a SyntaxError if using the argument in its default value" do
+ a = 1
+ -> {
+ eval "proc { |a=a| a }"
+ }.should.raise(SyntaxError)
+ end
end
- it "raises a SyntaxError if there is an existing method with the same name as the argument" do
- def a; 1; end
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should raise_error(SyntaxError)
+ ruby_version_is "3.4" do
+ it "is nil if using the argument in its default value" do
+ -> {
+ eval "proc { |a=a| a }.call"
+ }.call.should == nil
+ end
end
+ end
- it "calls an existing method with the same name as the argument if explicitly using ()" do
- def a; 1; end
- proc { |a=a()| a }.call.should == 1
- end
+ it "calls an existing method with the same name as the argument if explicitly using ()" do
+ def a; 1; end
+ proc { |a=a()| a }.call.should == 1
end
end
@@ -983,3 +995,154 @@ describe "Post-args" do
end
end
end
+
+# tested more thoroughly in language/delegation_spec.rb
+describe "Anonymous block forwarding" do
+ it "forwards blocks to other method that formally declares anonymous block" do
+ def b(&); c(&) end
+ def c(&); yield :non_null end
+
+ b { |c| c }.should == :non_null
+ end
+
+ it "requires the anonymous block parameter to be declared if directly passing a block" do
+ -> { eval "def a; b(&); end; def b; end" }.should.raise(SyntaxError)
+ end
+
+ it "works when it's the only declared parameter" do
+ def inner; yield end
+ def block_only(&); inner(&) end
+
+ block_only { 1 }.should == 1
+ end
+
+ it "works alongside positional parameters" do
+ def inner; yield end
+ def pos(arg1, &); inner(&) end
+
+ pos(:a) { 1 }.should == 1
+ end
+
+ it "works alongside positional arguments and splatted keyword arguments" do
+ def inner; yield end
+ def pos_kwrest(arg1, **kw, &); inner(&) end
+
+ pos_kwrest(:a, arg: 3) { 1 }.should == 1
+ end
+
+ it "works alongside positional arguments and disallowed keyword arguments" do
+ def inner; yield end
+ def no_kw(arg1, **nil, &); inner(&) end
+
+ no_kw(:a) { 1 }.should == 1
+ end
+
+ it "works alongside explicit keyword arguments" do
+ eval <<-EOF
+ def inner; yield end
+ def rest_kw(*a, kwarg: 1, &); inner(&) end
+ def kw(kwarg: 1, &); inner(&) end
+ def pos_kw_kwrest(arg1, kwarg: 1, **kw, &); inner(&) end
+ def pos_rkw(arg1, kwarg1:, &); inner(&) end
+ def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &); inner(&) end
+ def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &); inner(&) end
+ EOF
+
+ rest_kw { 1 }.should == 1
+ kw { 1 }.should == 1
+ pos_kw_kwrest(:a) { 1 }.should == 1
+ pos_rkw(:a, kwarg1: 3) { 1 }.should == 1
+ all(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1
+ all_kwrest(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1
+ end
+end
+
+describe "`it` calls without arguments in a block" do
+ ruby_version_is ""..."3.4" do
+ it "emits a deprecation warning" do
+ -> {
+ eval "proc { it }"
+ }.should complain(/warning: `it` calls without arguments will refer to the first block param in Ruby 3.4; use it\(\) or self.it/)
+ end
+
+ it "emits a deprecation warning if numbered parameters are used" do
+ -> {
+ eval "proc { it; _1 }"
+ }.should complain(/warning: `it` calls without arguments will refer to the first block param in Ruby 3.4; use it\(\) or self.it/)
+ end
+
+ it "does not emit a deprecation warning when a block has parameters" do
+ -> { eval "proc { |a, b| it }" }.should_not complain
+ -> { eval "proc { |*rest| it }" }.should_not complain
+ -> { eval "proc { |*| it }" }.should_not complain
+ -> { eval "proc { |a:, b:| it }" }.should_not complain
+ -> { eval "proc { |**kw| it }" }.should_not complain
+ -> { eval "proc { |**| it }" }.should_not complain
+ -> { eval "proc { |&block| it }" }.should_not complain
+ -> { eval "proc { |&| it }" }.should_not complain
+ -> { eval "proc { || it }" }.should_not complain
+ end
+
+ it "does not emit a deprecation warning when `it` calls with arguments" do
+ -> { eval "proc { it(42) }" }.should_not complain
+ -> { eval "proc { it 42 }" }.should_not complain
+ end
+
+ it "does not emit a deprecation warning when `it` calls with a block" do
+ -> { eval "proc { it {} }" }.should_not complain
+ end
+
+ it "does not emit a deprecation warning when a local variable inside the block named `it` exists" do
+ -> { eval "proc { it = 42; it }" }.should_not complain
+ end
+
+ it "does not emit a deprecation warning when `it` calls with explicit empty arguments list" do
+ -> { eval "proc { it() }" }.should_not complain
+ end
+
+ it "calls the method `it` if defined" do
+ o = Object.new
+ def o.it
+ 21
+ end
+ suppress_warning do
+ o.instance_eval("proc { it * 2 }").call(1).should == 42
+ end
+ end
+ end
+
+ ruby_version_is "4.1" do
+ it "works alongside disallowed block argument" do
+ no_block = eval <<-EOF
+ proc {|arg1, &nil| arg1}
+ EOF
+
+ no_block.call(:a).should == :a
+ -> { no_block.call(:a) {} }.should.raise(ArgumentError, 'no block accepted')
+ end
+ end
+end
+
+# Duplicates specs in language/it_parameter_spec.rb
+# Need them here to run on Ruby versions prior 3.4
+# TODO: remove when the minimal supported Ruby version is 3.4
+describe "if `it` is defined as a variable" do
+ it "treats `it` as a captured variable if defined outside of a block" do
+ it = 5
+ proc { it }.call(0).should == 5
+ end
+
+ it "treats `it` as a local variable if defined inside of a block" do
+ proc { it = 5; it }.call(0).should == 5
+ end
+end
+
+describe "Block-parameter destructuring" do
+ it "does not warn about unused inner names in verbose mode" do
+ -> {
+ eval <<~RUBY, binding, __FILE__, __LINE__ + 1
+ proc { |key, (val1, val2)| [key, val2] }
+ RUBY
+ }.should_not complain(verbose: true)
+ end
+end
diff --git a/spec/ruby/language/break_spec.rb b/spec/ruby/language/break_spec.rb
index 627cb4a071..5c9b8060c3 100644
--- a/spec/ruby/language/break_spec.rb
+++ b/spec/ruby/language/break_spec.rb
@@ -52,29 +52,29 @@ describe "The break statement in a captured block" do
describe "when the invocation of the scope creating the block is still active" do
it "raises a LocalJumpError when invoking the block from the scope creating the block" do
- -> { @program.break_in_method }.should raise_error(LocalJumpError)
+ -> { @program.break_in_method }.should.raise(LocalJumpError)
ScratchPad.recorded.should == [:a, :xa, :d, :b]
end
it "raises a LocalJumpError when invoking the block from a method" do
- -> { @program.break_in_nested_method }.should raise_error(LocalJumpError)
+ -> { @program.break_in_nested_method }.should.raise(LocalJumpError)
ScratchPad.recorded.should == [:a, :xa, :cc, :aa, :b]
end
it "raises a LocalJumpError when yielding to the block" do
- -> { @program.break_in_yielding_method }.should raise_error(LocalJumpError)
+ -> { @program.break_in_yielding_method }.should.raise(LocalJumpError)
ScratchPad.recorded.should == [:a, :xa, :cc, :aa, :b]
end
end
describe "from a scope that has returned" do
it "raises a LocalJumpError when calling the block from a method" do
- -> { @program.break_in_method_captured }.should raise_error(LocalJumpError)
+ -> { @program.break_in_method_captured }.should.raise(LocalJumpError)
ScratchPad.recorded.should == [:a, :za, :xa, :zd, :zb]
end
it "raises a LocalJumpError when yielding to the block" do
- -> { @program.break_in_yield_captured }.should raise_error(LocalJumpError)
+ -> { @program.break_in_yield_captured }.should.raise(LocalJumpError)
ScratchPad.recorded.should == [:a, :za, :xa, :zd, :aa, :zb]
end
end
@@ -88,7 +88,7 @@ describe "The break statement in a captured block" do
e
end
end
- thread_with_break.value.should be_an_instance_of(LocalJumpError)
+ thread_with_break.value.should.instance_of?(LocalJumpError)
end
end
end
@@ -252,6 +252,25 @@ describe "Break inside a while loop" do
end
end
+describe "The break statement in a method" do
+ it "is invalid and raises a SyntaxError" do
+ -> {
+ eval("def m; break; end")
+ }.should.raise(SyntaxError)
+ end
+end
+
+describe "The break statement in a module literal" do
+ it "is invalid and raises a SyntaxError" do
+ code = <<~RUBY
+ module BreakSpecs:ModuleWithBreak
+ break
+ end
+ RUBY
+
+ -> { eval(code) }.should.raise(SyntaxError)
+ end
+end
# TODO: Rewrite all the specs from here to the end of the file in the style
# above.
@@ -369,15 +388,15 @@ describe "Executing break from within a block" do
-> do
cls2.new.foo.should == 1
- end.should_not raise_error
+ end.should_not.raise
end
- it "raises LocalJumpError when converted into a proc during a a super call" do
+ it "raises LocalJumpError when converted into a proc during a super call" do
cls1 = Class.new { def foo(&b); b; end }
cls2 = Class.new(cls1) { def foo; super { break 1 }.call; end }
-> do
cls2.new.foo
- end.should raise_error(LocalJumpError)
+ end.should.raise(LocalJumpError)
end
end
diff --git a/spec/ruby/language/case_spec.rb b/spec/ruby/language/case_spec.rb
index bf06803764..41881bf20a 100644
--- a/spec/ruby/language/case_spec.rb
+++ b/spec/ruby/language/case_spec.rb
@@ -27,6 +27,41 @@ describe "The 'case'-construct" do
@calls.should == [:foo, :bar]
end
+ it "matches an Integer literal whose value does not fit in a 32-bit int" do
+ big = 10_000_000_000
+ case big
+ when 10_000_000_000; true
+ else false
+ end.should == true
+
+ case -3_000_000_000
+ when -3_000_000_000; true
+ else false
+ end.should == true
+ end
+
+ it "matches an arbitrary-precision Integer literal" do
+ huge = 1267650600228229401496703205376
+ case huge
+ when 1267650600228229401496703205376; true
+ else false
+ end.should == true
+ end
+
+ it "dispatches correctly with mixed small and large Integer literals" do
+ pick = -> x {
+ case x
+ when 1267650600228229401496703205376 then :beyond_long
+ when 10_000_000_000 then :beyond_int
+ when 1 then :fits_int
+ else :other
+ end
+ }
+
+ [1267650600228229401496703205376, 10_000_000_000, 1, :nope].map(&pick).should ==
+ [:beyond_long, :beyond_int, :fits_int, :other]
+ end
+
it "evaluates the body of the when clause whose range expression includes the case target expression" do
case 5
when 21..30; false
@@ -94,38 +129,38 @@ describe "The 'case'-construct" do
it "tests with matching regexps and sets $~ and captures" do
case "foo42"
when /oo(\d+)/
- $~.should be_kind_of(MatchData)
+ $~.should.is_a?(MatchData)
$1.should == "42"
else
flunk
end
- $~.should be_kind_of(MatchData)
+ $~.should.is_a?(MatchData)
$1.should == "42"
end
- it "tests with a regexp interpolated within another regexp" do
+ it "tests with a string interpolated in a regexp" do
digits = '\d+'
case "foo44"
when /oo(#{digits})/
- $~.should be_kind_of(MatchData)
+ $~.should.is_a?(MatchData)
$1.should == "44"
else
flunk
end
- $~.should be_kind_of(MatchData)
+ $~.should.is_a?(MatchData)
$1.should == "44"
end
- it "tests with a string interpolated in a regexp" do
+ it "tests with a regexp interpolated within another regexp" do
digits_regexp = /\d+/
case "foo43"
when /oo(#{digits_regexp})/
- $~.should be_kind_of(MatchData)
+ $~.should.is_a?(MatchData)
$1.should == "43"
else
flunk
end
- $~.should be_kind_of(MatchData)
+ $~.should.is_a?(MatchData)
$1.should == "43"
end
@@ -268,7 +303,7 @@ describe "The 'case'-construct" do
true
end
CODE
- }.should raise_error(SyntaxError)
+ }.should.raise(SyntaxError)
end
it "raises a SyntaxError when 'else' is used before a 'when' was given" do
@@ -280,7 +315,7 @@ describe "The 'case'-construct" do
when 4; false
end
CODE
- }.should raise_error(SyntaxError)
+ }.should.raise(SyntaxError)
end
it "supports nested case statements" do
@@ -329,49 +364,6 @@ describe "The 'case'-construct" do
100
end.should == 100
end
-end
-
-describe "The 'case'-construct with no target expression" do
- it "evaluates the body of the first clause when at least one of its condition expressions is true" do
- case
- when true, false; 'foo'
- end.should == 'foo'
- end
-
- it "evaluates the body of the first when clause that is not false/nil" do
- case
- when false; 'foo'
- when 2; 'bar'
- when 1 == 1; 'baz'
- end.should == 'bar'
-
- case
- when false; 'foo'
- when nil; 'foo'
- when 1 == 1; 'bar'
- end.should == 'bar'
- end
-
- it "evaluates the body of the else clause if all when clauses are false/nil" do
- case
- when false; 'foo'
- when nil; 'foo'
- when 1 == 2; 'bar'
- else 'baz'
- end.should == 'baz'
- end
-
- it "evaluates multiple conditional expressions as a boolean disjunction" do
- case
- when true, false; 'foo'
- else 'bar'
- end.should == 'foo'
-
- case
- when false, true; 'foo'
- else 'bar'
- end.should == 'foo'
- end
it "evaluates true as only 'true' when true is the first clause" do
case 1
@@ -434,6 +426,104 @@ describe "The 'case'-construct with no target expression" do
end.should == :called
end
+ it "only matches last value in complex expressions within ()" do
+ case 'a'
+ when ('a'; 'b')
+ :wrong_called
+ when ('b'; 'a')
+ :called
+ end.should == :called
+ end
+
+ it "supports declaring variables in the case target expression" do
+ def test(v)
+ case new_variable_in_expression = v
+ when true
+ # This extra block is a test that `new_variable_in_expression` is declared outside of it and not inside
+ self.then { new_variable_in_expression }
+ else
+ # Same
+ self.then { new_variable_in_expression.casecmp?("foo") }
+ end
+ end
+
+ self.test("bar").should == false
+ self.test(true).should == true
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "warns if there are identical when clauses" do
+ -> {
+ eval <<~RUBY
+ case 1
+ when 2
+ :foo
+ when 2
+ :bar
+ end
+ RUBY
+ }.should complain(/warning: (duplicated .when' clause with line \d+ is ignored|'when' clause on line \d+ duplicates 'when' clause on line \d+ and is ignored)/, verbose: true)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "warns if there are identical when clauses" do
+ -> {
+ eval <<~RUBY
+ case 1
+ when 2
+ :foo
+ when 2
+ :bar
+ end
+ RUBY
+ }.should complain(/warning: 'when' clause on line \d+ duplicates 'when' clause on line \d+ and is ignored/, verbose: true)
+ end
+ end
+end
+
+describe "The 'case'-construct with no target expression" do
+ it "evaluates the body of the first clause when at least one of its condition expressions is true" do
+ case
+ when true, false; 'foo'
+ end.should == 'foo'
+ end
+
+ it "evaluates the body of the first when clause that is not false/nil" do
+ case
+ when false; 'foo'
+ when 2; 'bar'
+ when 1 == 1; 'baz'
+ end.should == 'bar'
+
+ case
+ when false; 'foo'
+ when nil; 'foo'
+ when 1 == 1; 'bar'
+ end.should == 'bar'
+ end
+
+ it "evaluates the body of the else clause if all when clauses are false/nil" do
+ case
+ when false; 'foo'
+ when nil; 'foo'
+ when 1 == 2; 'bar'
+ else 'baz'
+ end.should == 'baz'
+ end
+
+ it "evaluates multiple conditional expressions as a boolean disjunction" do
+ case
+ when true, false; 'foo'
+ else 'bar'
+ end.should == 'foo'
+
+ case
+ when false, true; 'foo'
+ else 'bar'
+ end.should == 'foo'
+ end
+
# Homogeneous cases are often optimized to avoid === using a jump table, and should be tested separately.
# See https://github.com/jruby/jruby/issues/6440
it "handles homogeneous cases" do
@@ -442,4 +532,13 @@ describe "The 'case'-construct with no target expression" do
when 2; 'bar'
end.should == 'foo'
end
+
+ it "expands arrays to lists of values" do
+ case
+ when *[false]
+ "foo"
+ when *[true]
+ "bar"
+ end.should == "bar"
+ end
end
diff --git a/spec/ruby/language/class_spec.rb b/spec/ruby/language/class_spec.rb
index 877895bf15..7ea4857514 100644
--- a/spec/ruby/language/class_spec.rb
+++ b/spec/ruby/language/class_spec.rb
@@ -10,23 +10,23 @@ end
describe "The class keyword" do
it "creates a new class with semicolon" do
class ClassSpecsKeywordWithSemicolon; end
- ClassSpecsKeywordWithSemicolon.should be_an_instance_of(Class)
+ ClassSpecsKeywordWithSemicolon.should.instance_of?(Class)
end
it "does not raise a SyntaxError when opening a class without a semicolon" do
eval "class ClassSpecsKeywordWithoutSemicolon end"
- ClassSpecsKeywordWithoutSemicolon.should be_an_instance_of(Class)
+ ClassSpecsKeywordWithoutSemicolon.should.instance_of?(Class)
end
it "can redefine a class when called from a block" do
ClassSpecs::DEFINE_CLASS.call
- A.should be_an_instance_of(Class)
+ A.should.instance_of?(Class)
Object.send(:remove_const, :A)
- defined?(A).should be_nil
+ defined?(A).should == nil
ClassSpecs::DEFINE_CLASS.call
- A.should be_an_instance_of(Class)
+ A.should.instance_of?(Class)
ensure
Object.send(:remove_const, :A) if defined?(::A)
end
@@ -34,8 +34,8 @@ end
describe "A class definition" do
it "creates a new class" do
- ClassSpecs::A.should be_kind_of(Class)
- ClassSpecs::A.new.should be_kind_of(ClassSpecs::A)
+ ClassSpecs::A.should.is_a?(Class)
+ ClassSpecs::A.new.should.is_a?(ClassSpecs::A)
end
it "has no class variables" do
@@ -46,7 +46,14 @@ describe "A class definition" do
-> {
class ClassSpecsNumber
end
- }.should raise_error(TypeError)
+ }.should.raise(TypeError, /\AClassSpecsNumber is not a class/)
+ end
+
+ it "raises TypeError if constant given as class name exists and is a Module but not a Class" do
+ -> {
+ class ClassSpecs
+ end
+ }.should.raise(TypeError, /\AClassSpecs is not a class/)
end
# test case known to be detecting bugs (JRuby, MRI)
@@ -54,19 +61,19 @@ describe "A class definition" do
-> {
class nil::Foo
end
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises TypeError if any constant qualifying the class is not a Module" do
-> {
class ClassSpecs::Number::MyClass
end
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
-> {
class ClassSpecsNumber::MyClass
end
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "inherits from Object by default" do
@@ -80,7 +87,7 @@ describe "A class definition" do
-> {
class SuperclassResetToSubclass < M
end
- }.should raise_error(TypeError, /superclass mismatch/)
+ }.should.raise(TypeError, /superclass mismatch/)
end
end
@@ -93,7 +100,7 @@ describe "A class definition" do
-> {
class SuperclassReopenedBasicObject < BasicObject
end
- }.should raise_error(TypeError, /superclass mismatch/)
+ }.should.raise(TypeError, /superclass mismatch/)
SuperclassReopenedBasicObject.superclass.should == A
end
end
@@ -108,7 +115,7 @@ describe "A class definition" do
-> {
class SuperclassReopenedObject < Object
end
- }.should raise_error(TypeError, /superclass mismatch/)
+ }.should.raise(TypeError, /superclass mismatch/)
SuperclassReopenedObject.superclass.should == A
end
end
@@ -133,7 +140,7 @@ describe "A class definition" do
-> {
class NoSuperclassSet < String
end
- }.should raise_error(TypeError, /superclass mismatch/)
+ }.should.raise(TypeError, /superclass mismatch/)
end
end
@@ -142,7 +149,7 @@ describe "A class definition" do
-> {
class ShouldNotWork < self; end
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "first evaluates the superclass before checking if the class already exists" do
@@ -161,7 +168,7 @@ describe "A class definition" do
it "raises a TypeError if inheriting from a metaclass" do
obj = mock("metaclass super")
meta = obj.singleton_class
- -> { class ClassSpecs::MetaclassSuper < meta; end }.should raise_error(TypeError)
+ -> { class ClassSpecs::MetaclassSuper < meta; end }.should.raise(TypeError)
end
it "allows the declaration of class variables in the body" do
@@ -170,7 +177,7 @@ describe "A class definition" do
end
it "stores instance variables defined in the class body in the class object" do
- ClassSpecs.string_instance_variables(ClassSpecs::B).should include("@ivar")
+ ClassSpecs.string_instance_variables(ClassSpecs::B).should.include?("@ivar")
ClassSpecs::B.instance_variable_get(:@ivar).should == :ivar
end
@@ -182,9 +189,9 @@ describe "A class definition" do
end
it "allows the definition of class-level instance variables in a class method" do
- ClassSpecs.string_instance_variables(ClassSpecs::C).should_not include("@civ")
+ ClassSpecs.string_instance_variables(ClassSpecs::C).should_not.include?("@civ")
ClassSpecs::C.make_class_instance_variable
- ClassSpecs.string_instance_variables(ClassSpecs::C).should include("@civ")
+ ClassSpecs.string_instance_variables(ClassSpecs::C).should.include?("@civ")
ClassSpecs::C.remove_instance_variable :@civ
end
@@ -271,13 +278,16 @@ describe "A class definition" do
AnonWithConstant.name.should == 'AnonWithConstant'
klass.get_class_name.should == 'AnonWithConstant'
+ ensure
+ Object.send(:remove_const, :AnonWithConstant)
end
end
end
describe "An outer class definition" do
it "contains the inner classes" do
- ClassSpecs::Container.constants.should include(:A, :B)
+ ClassSpecs::Container.constants.should.include?(:A)
+ ClassSpecs::Container.constants.should.include?(:B)
end
end
@@ -295,33 +305,23 @@ describe "A class definition extending an object (sclass)" do
end
end
CODE
- }.should raise_error(TypeError)
+ }.should.raise(TypeError)
end
it "raises a TypeError when trying to extend non-Class" do
error_msg = /superclass must be a.* Class/
- -> { class TestClass < ""; end }.should raise_error(TypeError, error_msg)
- -> { class TestClass < 1; end }.should raise_error(TypeError, error_msg)
- -> { class TestClass < :symbol; end }.should raise_error(TypeError, error_msg)
- -> { class TestClass < mock('o'); end }.should raise_error(TypeError, error_msg)
- -> { class TestClass < Module.new; end }.should raise_error(TypeError, error_msg)
- -> { class TestClass < BasicObject.new; end }.should raise_error(TypeError, error_msg)
- end
-
- ruby_version_is ""..."3.0" do
- it "allows accessing the block of the original scope" do
- suppress_warning do
- ClassSpecs.sclass_with_block { 123 }.should == 123
- end
- end
+ -> { class TestClass < ""; end }.should.raise(TypeError, error_msg)
+ -> { class TestClass < 1; end }.should.raise(TypeError, error_msg)
+ -> { class TestClass < :symbol; end }.should.raise(TypeError, error_msg)
+ -> { class TestClass < mock('o'); end }.should.raise(TypeError, error_msg)
+ -> { class TestClass < Module.new; end }.should.raise(TypeError, error_msg)
+ -> { class TestClass < BasicObject.new; end }.should.raise(TypeError, error_msg)
end
- ruby_version_is "3.0" do
- it "does not allow accessing the block of the original scope" do
- -> {
- ClassSpecs.sclass_with_block { 123 }
- }.should raise_error(SyntaxError)
- end
+ it "does not allow accessing the block of the original scope" do
+ -> {
+ ClassSpecs.sclass_with_block { 123 }
+ }.should.raise(SyntaxError)
end
it "can use return to cause the enclosing method to return" do
@@ -341,11 +341,11 @@ describe "Reopening a class" do
end
it "raises a TypeError when superclasses mismatch" do
- -> { class ClassSpecs::A < Array; end }.should raise_error(TypeError)
+ -> { class ClassSpecs::A < Array; end }.should.raise(TypeError)
end
it "adds new methods to subclasses" do
- -> { ClassSpecs::M.m }.should raise_error(NoMethodError)
+ -> { ClassSpecs::M.m }.should.raise(NoMethodError)
class ClassSpecs::L
def self.m
1
@@ -354,6 +354,39 @@ describe "Reopening a class" do
ClassSpecs::M.m.should == 1
ClassSpecs::L.singleton_class.send(:remove_method, :m)
end
+
+ it "does not reopen a class included in Object" do
+ ruby_exe(<<~RUBY).should == "false"
+ module IncludedInObject
+ class IncludedClass
+ end
+ end
+ class Object
+ include IncludedInObject
+ end
+ class IncludedClass
+ end
+ print IncludedInObject::IncludedClass == Object::IncludedClass
+ RUBY
+ end
+
+ it "does not reopen a class included in non-Object modules" do
+ ruby_exe(<<~RUBY).should == "false/false"
+ module Included
+ module IncludedClass; end
+ end
+ module M
+ include Included
+ module IncludedClass; end
+ end
+ class C
+ include Included
+ module IncludedClass; end
+ end
+ print Included::IncludedClass == M::IncludedClass, "/",
+ Included::IncludedClass == C::IncludedClass
+ RUBY
+ end
end
describe "class provides hooks" do
diff --git a/spec/ruby/language/class_variable_spec.rb b/spec/ruby/language/class_variable_spec.rb
index f98deaa081..84a7684c6d 100644
--- a/spec/ruby/language/class_variable_spec.rb
+++ b/spec/ruby/language/class_variable_spec.rb
@@ -30,19 +30,19 @@ describe "A class variable defined in a module" do
end
it "is not defined in these classes" do
- ClassVariablesSpec::ClassC.cvar_defined?.should be_false
+ ClassVariablesSpec::ClassC.cvar_defined?.should == false
end
it "is only updated in the module a method defined in the module is used" do
ClassVariablesSpec::ClassC.cvar_m = "new value"
ClassVariablesSpec::ClassC.cvar_m.should == "new value"
- ClassVariablesSpec::ClassC.cvar_defined?.should be_false
+ ClassVariablesSpec::ClassC.cvar_defined?.should == false
end
it "is updated in the class when a Method defined in the class is used" do
ClassVariablesSpec::ClassC.cvar_c = "new value"
- ClassVariablesSpec::ClassC.cvar_defined?.should be_true
+ ClassVariablesSpec::ClassC.cvar_defined?.should == true
end
it "can be accessed inside the class using the module methods" do
@@ -55,11 +55,11 @@ describe "A class variable defined in a module" do
end
it "is defined in the extended module" do
- ClassVariablesSpec::ModuleN.class_variable_defined?(:@@cvar_n).should be_true
+ ClassVariablesSpec::ModuleN.class_variable_defined?(:@@cvar_n).should == true
end
it "is not defined in the extending module" do
- ClassVariablesSpec::ModuleO.class_variable_defined?(:@@cvar_n).should be_false
+ ClassVariablesSpec::ModuleO.class_variable_defined?(:@@cvar_n).should == false
end
end
@@ -70,47 +70,45 @@ describe 'A class variable definition' do
c = Class.new(b)
b.class_variable_set(:@@cv, :value)
- -> { a.class_variable_get(:@@cv) }.should raise_error(NameError)
+ -> { a.class_variable_get(:@@cv) }.should.raise(NameError)
b.class_variable_get(:@@cv).should == :value
c.class_variable_get(:@@cv).should == :value
# updates the same variable
c.class_variable_set(:@@cv, :next)
- -> { a.class_variable_get(:@@cv) }.should raise_error(NameError)
+ -> { a.class_variable_get(:@@cv) }.should.raise(NameError)
b.class_variable_get(:@@cv).should == :next
c.class_variable_get(:@@cv).should == :next
end
end
-ruby_version_is "3.0" do
- describe 'Accessing a class variable' do
- it "raises a RuntimeError when accessed from the toplevel scope (not in some module or class)" do
- -> {
- eval "@@cvar_toplevel1"
- }.should raise_error(RuntimeError, 'class variable access from toplevel')
- -> {
- eval "@@cvar_toplevel2 = 2"
- }.should raise_error(RuntimeError, 'class variable access from toplevel')
- end
-
- it "does not raise an error when checking if defined from the toplevel scope" do
- -> {
- eval "defined?(@@cvar_toplevel1)"
- }.should_not raise_error
- end
-
- it "raises a RuntimeError when a class variable is overtaken in an ancestor class" do
- parent = Class.new()
- subclass = Class.new(parent)
- subclass.class_variable_set(:@@cvar_overtaken, :subclass)
- parent.class_variable_set(:@@cvar_overtaken, :parent)
-
- -> {
- subclass.class_variable_get(:@@cvar_overtaken)
- }.should raise_error(RuntimeError, /class variable @@cvar_overtaken of .+ is overtaken by .+/)
-
- parent.class_variable_get(:@@cvar_overtaken).should == :parent
- end
+describe 'Accessing a class variable' do
+ it "raises a RuntimeError when accessed from the toplevel scope (not in some module or class)" do
+ -> {
+ eval "@@cvar_toplevel1"
+ }.should.raise(RuntimeError, 'class variable access from toplevel')
+ -> {
+ eval "@@cvar_toplevel2 = 2"
+ }.should.raise(RuntimeError, 'class variable access from toplevel')
+ end
+
+ it "does not raise an error when checking if defined from the toplevel scope" do
+ -> {
+ eval "defined?(@@cvar_toplevel1)"
+ }.should_not.raise
+ end
+
+ it "raises a RuntimeError when a class variable is overtaken in an ancestor class" do
+ parent = Class.new()
+ subclass = Class.new(parent)
+ subclass.class_variable_set(:@@cvar_overtaken, :subclass)
+ parent.class_variable_set(:@@cvar_overtaken, :parent)
+
+ -> {
+ subclass.class_variable_get(:@@cvar_overtaken)
+ }.should.raise(RuntimeError, /class variable @@cvar_overtaken of .+ is overtaken by .+/)
+
+ parent.class_variable_get(:@@cvar_overtaken).should == :parent
end
end
diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb
index 8586e46158..0880230a36 100644
--- a/spec/ruby/language/constants_spec.rb
+++ b/spec/ruby/language/constants_spec.rb
@@ -51,8 +51,8 @@ describe "Literal (A::X) constant resolution" do
it "does not search the singleton class of the class or module" do
-> do
ConstantSpecs::ContainerA::ChildA::CS_CONST14
- end.should raise_error(NameError)
- -> { ConstantSpecs::CS_CONST14 }.should raise_error(NameError)
+ end.should.raise(NameError)
+ -> { ConstantSpecs::CS_CONST14 }.should.raise(NameError)
end
end
@@ -72,39 +72,60 @@ describe "Literal (A::X) constant resolution" do
ConstantSpecs::ModuleA::CS_CONST101 = :const101_5
ConstantSpecs::ModuleA::CS_CONST101.should == :const101_5
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST101)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST101)
+ ConstantSpecs::ContainerB.send(:remove_const, :CS_CONST101)
+ ConstantSpecs::ContainerB::ChildB.send(:remove_const, :CS_CONST101)
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST101)
end
it "searches a module included in the immediate class before the superclass" do
ConstantSpecs::ParentB::CS_CONST102 = :const102_1
ConstantSpecs::ModuleF::CS_CONST102 = :const102_2
ConstantSpecs::ContainerB::ChildB::CS_CONST102.should == :const102_2
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST102)
+ ConstantSpecs::ModuleF.send(:remove_const, :CS_CONST102)
end
it "searches the superclass before a module included in the superclass" do
ConstantSpecs::ModuleE::CS_CONST103 = :const103_1
ConstantSpecs::ParentB::CS_CONST103 = :const103_2
ConstantSpecs::ContainerB::ChildB::CS_CONST103.should == :const103_2
+ ensure
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST103)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST103)
end
it "searches a module included in the superclass" do
ConstantSpecs::ModuleA::CS_CONST104 = :const104_1
ConstantSpecs::ModuleE::CS_CONST104 = :const104_2
ConstantSpecs::ContainerB::ChildB::CS_CONST104.should == :const104_2
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST104)
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST104)
end
it "searches the superclass chain" do
ConstantSpecs::ModuleA::CS_CONST105 = :const105
ConstantSpecs::ContainerB::ChildB::CS_CONST105.should == :const105
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST105)
end
it "searches Object if no class or module qualifier is given" do
CS_CONST106 = :const106
CS_CONST106.should == :const106
+ ensure
+ Object.send(:remove_const, :CS_CONST106)
end
it "searches Object if a toplevel qualifier (::X) is given" do
::CS_CONST107 = :const107
::CS_CONST107.should == :const107
+ ensure
+ Object.send(:remove_const, :CS_CONST107)
end
it "does not search the singleton class of the class or module" do
@@ -114,7 +135,7 @@ describe "Literal (A::X) constant resolution" do
-> do
ConstantSpecs::ContainerB::ChildB::CS_CONST108
- end.should raise_error(NameError)
+ end.should.raise(NameError)
module ConstantSpecs
class << self
@@ -122,7 +143,10 @@ describe "Literal (A::X) constant resolution" do
end
end
- -> { ConstantSpecs::CS_CONST108 }.should raise_error(NameError)
+ -> { ConstantSpecs::CS_CONST108 }.should.raise(NameError)
+ ensure
+ ConstantSpecs::ContainerB::ChildB.singleton_class.send(:remove_const, :CS_CONST108)
+ ConstantSpecs.singleton_class.send(:remove_const, :CS_CONST108)
end
it "returns the updated value when a constant is reassigned" do
@@ -133,71 +157,53 @@ describe "Literal (A::X) constant resolution" do
ConstantSpecs::ClassB::CS_CONST109 = :const109_2
}.should complain(/already initialized constant/)
ConstantSpecs::ClassB::CS_CONST109.should == :const109_2
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST109)
end
- ruby_version_is "3.2" do
- it "evaluates left-to-right" do
- mod = Module.new
+ it "evaluates left-to-right" do
+ mod = Module.new
- mod.module_eval <<-EOC
- order = []
- ConstantSpecsRHS = Module.new
- (order << :lhs; ConstantSpecsRHS)::B = (order << :rhs)
- EOC
+ mod.module_eval <<-EOC
+ order = []
+ ConstantSpecsRHS = Module.new
+ (order << :lhs; ConstantSpecsRHS)::B = (order << :rhs)
+ EOC
- mod::ConstantSpecsRHS::B.should == [:lhs, :rhs]
- end
- end
-
- ruby_version_is ""..."3.2" do
- it "evaluates the right hand side before evaluating a constant path" do
- mod = Module.new
-
- mod.module_eval <<-EOC
- ConstantSpecsRHS::B = begin
- module ConstantSpecsRHS; end
-
- "hello"
- end
- EOC
-
- mod::ConstantSpecsRHS::B.should == 'hello'
- end
+ mod::ConstantSpecsRHS::B.should == [:lhs, :rhs]
end
end
it "raises a NameError if no constant is defined in the search path" do
- -> { ConstantSpecs::ParentA::CS_CONSTX }.should raise_error(NameError)
+ -> { ConstantSpecs::ParentA::CS_CONSTX }.should.raise(NameError)
end
- ruby_version_is "3.0" do
- it "uses the module or class #name to craft the error message" do
- mod = Module.new do
- def self.name
- "ModuleName"
- end
-
- def self.inspect
- "<unusable info>"
- end
+ it "uses the module or class #name to craft the error message" do
+ mod = Module.new do
+ def self.name
+ "ModuleName"
end
- -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant ModuleName::DOES_NOT_EXIST/)
+ def self.inspect
+ "<unusable info>"
+ end
end
- it "uses the module or class #inspect to craft the error message if they are anonymous" do
- mod = Module.new do
- def self.name
- nil
- end
+ -> { mod::DOES_NOT_EXIST }.should.raise(NameError, /uninitialized constant ModuleName::DOES_NOT_EXIST/)
+ end
- def self.inspect
- "<unusable info>"
- end
+ it "uses the module or class #inspect to craft the error message if they are anonymous" do
+ mod = Module.new do
+ def self.name
+ nil
end
- -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant <unusable info>::DOES_NOT_EXIST/)
+ def self.inspect
+ "<unusable info>"
+ end
end
+
+ -> { mod::DOES_NOT_EXIST }.should.raise(NameError, /uninitialized constant <unusable info>::DOES_NOT_EXIST/)
end
it "sends #const_missing to the original class or module scope" do
@@ -209,10 +215,10 @@ describe "Literal (A::X) constant resolution" do
end
it "raises a TypeError if a non-class or non-module qualifier is given" do
- -> { CS_CONST1::CS_CONST }.should raise_error(TypeError)
- -> { 1::CS_CONST }.should raise_error(TypeError)
- -> { "mod"::CS_CONST }.should raise_error(TypeError)
- -> { false::CS_CONST }.should raise_error(TypeError)
+ -> { CS_CONST1::CS_CONST }.should.raise(TypeError)
+ -> { 1::CS_CONST }.should.raise(TypeError)
+ -> { "mod"::CS_CONST }.should.raise(TypeError)
+ -> { false::CS_CONST }.should.raise(TypeError)
end
end
@@ -258,7 +264,7 @@ describe "Constant resolution within methods" do
end
it "does not search the lexical scope of the caller" do
- -> { ConstantSpecs::ClassA.const16 }.should raise_error(NameError)
+ -> { ConstantSpecs::ClassA.const16 }.should.raise(NameError)
end
it "searches the lexical scope of a block" do
@@ -273,7 +279,7 @@ describe "Constant resolution within methods" do
it "does not search the lexical scope of qualifying modules" do
-> do
ConstantSpecs::ContainerA::ChildA.const23
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
end
@@ -294,6 +300,12 @@ describe "Constant resolution within methods" do
ConstantSpecs::ClassB.new.const201.should == :const201_2
ConstantSpecs::ParentB.new.const201.should == :const201_3
ConstantSpecs::ContainerB::ChildB.new.const201.should == :const201_5
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST201)
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST201)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST201)
+ ConstantSpecs::ContainerB.send(:remove_const, :CS_CONST201)
+ ConstantSpecs::ContainerB::ChildB.send(:remove_const, :CS_CONST201)
end
it "searches a module included in the immediate class before the superclass" do
@@ -302,6 +314,9 @@ describe "Constant resolution within methods" do
ConstantSpecs::ContainerB::ChildB.const202.should == :const202_1
ConstantSpecs::ContainerB::ChildB.new.const202.should == :const202_1
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST202)
+ ConstantSpecs::ContainerB::ChildB.send(:remove_const, :CS_CONST202)
end
it "searches the superclass before a module included in the superclass" do
@@ -310,6 +325,9 @@ describe "Constant resolution within methods" do
ConstantSpecs::ContainerB::ChildB.const203.should == :const203_1
ConstantSpecs::ContainerB::ChildB.new.const203.should == :const203_1
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST203)
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST203)
end
it "searches a module included in the superclass" do
@@ -318,6 +336,9 @@ describe "Constant resolution within methods" do
ConstantSpecs::ContainerB::ChildB.const204.should == :const204_1
ConstantSpecs::ContainerB::ChildB.new.const204.should == :const204_1
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST204)
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST204)
end
it "searches the superclass chain" do
@@ -325,6 +346,8 @@ describe "Constant resolution within methods" do
ConstantSpecs::ContainerB::ChildB.const205.should == :const205
ConstantSpecs::ContainerB::ChildB.new.const205.should == :const205
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST205)
end
it "searches the lexical scope of the method not the receiver's immediate class" do
@@ -336,6 +359,9 @@ describe "Constant resolution within methods" do
end
ConstantSpecs::ContainerB::ChildB.const206.should == :const206_1
+ ensure
+ ConstantSpecs::ContainerB::ChildB.send(:remove_const, :CS_CONST206)
+ ConstantSpecs::ContainerB::ChildB.singleton_class.send(:remove_const, :CS_CONST206)
end
it "searches the lexical scope of a singleton method" do
@@ -343,12 +369,17 @@ describe "Constant resolution within methods" do
ConstantSpecs::ClassB::CS_CONST207 = :const207_2
ConstantSpecs::CS_CONST208.const207.should == :const207_1
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST207)
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST207)
end
it "does not search the lexical scope of the caller" do
ConstantSpecs::ClassB::CS_CONST209 = :const209
- -> { ConstantSpecs::ClassB.const209 }.should raise_error(NameError)
+ -> { ConstantSpecs::ClassB.const209 }.should.raise(NameError)
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST209)
end
it "searches the lexical scope of a block" do
@@ -356,6 +387,9 @@ describe "Constant resolution within methods" do
ConstantSpecs::ParentB::CS_CONST210 = :const210_2
ConstantSpecs::ClassB.const210.should == :const210_1
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST210)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST210)
end
it "searches Object as a lexical scope only if Object is explicitly opened" do
@@ -366,6 +400,11 @@ describe "Constant resolution within methods" do
Object::CS_CONST212 = :const212_2
ConstantSpecs::ParentB::CS_CONST212 = :const212_1
ConstantSpecs::ContainerB::ChildB.const212.should == :const212_1
+ ensure
+ Object.send(:remove_const, :CS_CONST211)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST211)
+ Object.send(:remove_const, :CS_CONST212)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST212)
end
it "returns the updated value when a constant is reassigned" do
@@ -378,6 +417,8 @@ describe "Constant resolution within methods" do
}.should complain(/already initialized constant/)
ConstantSpecs::ContainerB::ChildB.const213.should == :const213_2
ConstantSpecs::ContainerB::ChildB.new.const213.should == :const213_2
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST213)
end
it "does not search the lexical scope of qualifying modules" do
@@ -385,12 +426,14 @@ describe "Constant resolution within methods" do
-> do
ConstantSpecs::ContainerB::ChildB.const214
- end.should raise_error(NameError)
+ end.should.raise(NameError)
+ ensure
+ ConstantSpecs::ContainerB.send(:remove_const, :CS_CONST214)
end
end
it "raises a NameError if no constant is defined in the search path" do
- -> { ConstantSpecs::ParentA.constx }.should raise_error(NameError)
+ -> { ConstantSpecs::ParentA.constx }.should.raise(NameError)
end
it "sends #const_missing to the original class or module scope" do
@@ -413,7 +456,7 @@ describe "Constant resolution within a singleton class (class << obj)" do
it "uses its own namespace for nested modules" do
a = ConstantSpecs::CS_SINGLETON3[0].x
b = ConstantSpecs::CS_SINGLETON3[1].x
- a.should_not equal(b)
+ a.should_not.equal?(b)
end
it "allows nested modules to have proper resolution" do
@@ -426,12 +469,12 @@ end
describe "top-level constant lookup" do
context "on a class" do
it "does not search Object after searching other scopes" do
- -> { String::Hash }.should raise_error(NameError)
+ -> { String::Hash }.should.raise(NameError)
end
end
it "searches Object unsuccessfully when searches on a module" do
- -> { Enumerable::Hash }.should raise_error(NameError)
+ -> { Enumerable::Hash }.should.raise(NameError)
end
end
@@ -445,7 +488,7 @@ describe "Module#private_constant marked constants" do
mod.const_set :Foo, false
}.should complain(/already initialized constant/)
- -> {mod::Foo}.should raise_error(NameError)
+ -> {mod::Foo}.should.raise(NameError)
end
it "sends #const_missing to the original class or module" do
@@ -463,19 +506,19 @@ describe "Module#private_constant marked constants" do
it "cannot be accessed from outside the module" do
-> do
ConstantVisibility::PrivConstModule::PRIVATE_CONSTANT_MODULE
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "cannot be reopened as a module from scope where constant would be private" do
-> do
module ConstantVisibility::ModuleContainer::PrivateModule; end
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "cannot be reopened as a class from scope where constant would be private" do
-> do
class ConstantVisibility::ModuleContainer::PrivateClass; end
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "can be reopened as a module where constant is not private" do
@@ -486,6 +529,10 @@ describe "Module#private_constant marked constants" do
PrivateModule::X.should == 1
end
+ ensure
+ module ::ConstantVisibility::ModuleContainer
+ PrivateModule.send(:remove_const, :X)
+ end
end
it "can be reopened as a class where constant is not private" do
@@ -496,6 +543,10 @@ describe "Module#private_constant marked constants" do
PrivateClass::X.should == 1
end
+ ensure
+ module ::ConstantVisibility::ModuleContainer
+ PrivateClass.send(:remove_const, :X)
+ end
end
it "is not defined? with A::B form" do
@@ -503,7 +554,7 @@ describe "Module#private_constant marked constants" do
end
it "can be accessed from the module itself" do
- ConstantVisibility::PrivConstModule.private_constant_from_self.should be_true
+ ConstantVisibility::PrivConstModule.private_constant_from_self.should == true
end
it "is defined? from the module itself" do
@@ -511,7 +562,7 @@ describe "Module#private_constant marked constants" do
end
it "can be accessed from lexical scope" do
- ConstantVisibility::PrivConstModule::Nested.private_constant_from_scope.should be_true
+ ConstantVisibility::PrivConstModule::Nested.private_constant_from_scope.should == true
end
it "is defined? from lexical scope" do
@@ -519,20 +570,20 @@ describe "Module#private_constant marked constants" do
end
it "can be accessed from classes that include the module" do
- ConstantVisibility::ClassIncludingPrivConstModule.new.private_constant_from_include.should be_true
+ ConstantVisibility::ClassIncludingPrivConstModule.new.private_constant_from_include.should == true
end
it "can be accessed from modules that include the module" do
- ConstantVisibility::ModuleIncludingPrivConstModule.private_constant_from_include.should be_true
+ ConstantVisibility::ModuleIncludingPrivConstModule.private_constant_from_include.should == true
end
it "raises a NameError when accessed directly from modules that include the module" do
-> do
ConstantVisibility::ModuleIncludingPrivConstModule.private_constant_self_from_include
- end.should raise_error(NameError)
+ end.should.raise(NameError)
-> do
ConstantVisibility::ModuleIncludingPrivConstModule.private_constant_named_from_include
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "is defined? from classes that include the module" do
@@ -544,19 +595,19 @@ describe "Module#private_constant marked constants" do
it "cannot be accessed from outside the class" do
-> do
ConstantVisibility::PrivConstClass::PRIVATE_CONSTANT_CLASS
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "cannot be reopened as a module" do
-> do
module ConstantVisibility::ClassContainer::PrivateModule; end
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "cannot be reopened as a class" do
-> do
class ConstantVisibility::ClassContainer::PrivateClass; end
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "can be reopened as a module where constant is not private" do
@@ -567,6 +618,10 @@ describe "Module#private_constant marked constants" do
PrivateModule::X.should == 1
end
+ ensure
+ class ::ConstantVisibility::ClassContainer
+ PrivateModule.send(:remove_const, :X)
+ end
end
it "can be reopened as a class where constant is not private" do
@@ -577,6 +632,10 @@ describe "Module#private_constant marked constants" do
PrivateClass::X.should == 1
end
+ ensure
+ class ::ConstantVisibility::ClassContainer
+ PrivateClass.send(:remove_const, :X)
+ end
end
it "is not defined? with A::B form" do
@@ -584,7 +643,7 @@ describe "Module#private_constant marked constants" do
end
it "can be accessed from the class itself" do
- ConstantVisibility::PrivConstClass.private_constant_from_self.should be_true
+ ConstantVisibility::PrivConstClass.private_constant_from_self.should == true
end
it "is defined? from the class itself" do
@@ -592,7 +651,7 @@ describe "Module#private_constant marked constants" do
end
it "can be accessed from lexical scope" do
- ConstantVisibility::PrivConstClass::Nested.private_constant_from_scope.should be_true
+ ConstantVisibility::PrivConstClass::Nested.private_constant_from_scope.should == true
end
it "is defined? from lexical scope" do
@@ -600,7 +659,7 @@ describe "Module#private_constant marked constants" do
end
it "can be accessed from subclasses" do
- ConstantVisibility::PrivConstClassChild.new.private_constant_from_subclass.should be_true
+ ConstantVisibility::PrivConstClassChild.new.private_constant_from_subclass.should == true
end
it "is defined? from subclasses" do
@@ -612,7 +671,7 @@ describe "Module#private_constant marked constants" do
it "cannot be accessed using ::Const form" do
-> do
::PRIVATE_CONSTANT_IN_OBJECT
- end.should raise_error(NameError)
+ end.should.raise(NameError)
end
it "is not defined? using ::Const form" do
@@ -632,14 +691,14 @@ describe "Module#private_constant marked constants" do
it "has :receiver and :name attributes" do
-> do
ConstantVisibility::PrivConstClass::PRIVATE_CONSTANT_CLASS
- end.should raise_error(NameError) {|e|
+ end.should.raise(NameError) {|e|
e.receiver.should == ConstantVisibility::PrivConstClass
e.name.should == :PRIVATE_CONSTANT_CLASS
}
-> do
ConstantVisibility::PrivConstModule::PRIVATE_CONSTANT_MODULE
- end.should raise_error(NameError) {|e|
+ end.should.raise(NameError) {|e|
e.receiver.should == ConstantVisibility::PrivConstModule
e.name.should == :PRIVATE_CONSTANT_MODULE
}
@@ -648,14 +707,14 @@ describe "Module#private_constant marked constants" do
it "has the defined class as the :name attribute" do
-> do
ConstantVisibility::PrivConstClassChild::PRIVATE_CONSTANT_CLASS
- end.should raise_error(NameError) {|e|
+ end.should.raise(NameError) {|e|
e.receiver.should == ConstantVisibility::PrivConstClass
e.name.should == :PRIVATE_CONSTANT_CLASS
}
-> do
ConstantVisibility::ClassIncludingPrivConstModule::PRIVATE_CONSTANT_MODULE
- end.should raise_error(NameError) {|e|
+ end.should.raise(NameError) {|e|
e.receiver.should == ConstantVisibility::PrivConstModule
e.name.should == :PRIVATE_CONSTANT_MODULE
}
@@ -724,7 +783,7 @@ describe 'Allowed characters' do
it 'does not allow not ASCII characters that cannot be upcased or lowercased at the beginning' do
-> do
Module.new.const_set("થBB", 1)
- end.should raise_error(NameError, /wrong constant name/)
+ end.should.raise(NameError, /wrong constant name/)
end
it 'allows not ASCII upcased characters at the beginning' do
@@ -744,7 +803,7 @@ describe 'Assignment' do
B = 1
end
CODE
- end.should raise_error(SyntaxError, /dynamic constant assignment/)
+ end.should.raise(SyntaxError, /dynamic constant assignment/)
end
end
end
diff --git a/spec/ruby/language/def_spec.rb b/spec/ruby/language/def_spec.rb
index c8531343c0..82c89a0d08 100644
--- a/spec/ruby/language/def_spec.rb
+++ b/spec/ruby/language/def_spec.rb
@@ -14,11 +14,11 @@ end
describe "Defining a method at the top-level" do
it "defines it on Object with private visibility by default" do
- Object.should have_private_instance_method(:some_toplevel_method, false)
+ Object.private_instance_methods(false).should.include?(:some_toplevel_method)
end
it "defines it on Object with public visibility after calling public" do
- Object.should have_public_instance_method(:public_toplevel_method, false)
+ Object.public_instance_methods(false).should.include?(:public_toplevel_method)
end
end
@@ -28,7 +28,7 @@ describe "Defining an 'initialize' method" do
def initialize
end
end
- DefInitializeSpec.should have_private_instance_method(:initialize, false)
+ DefInitializeSpec.private_instance_methods(false).should.include?(:initialize)
end
end
@@ -38,7 +38,7 @@ describe "Defining an 'initialize_copy' method" do
def initialize_copy
end
end
- DefInitializeCopySpec.should have_private_instance_method(:initialize_copy, false)
+ DefInitializeCopySpec.private_instance_methods(false).should.include?(:initialize_copy)
end
end
@@ -48,7 +48,7 @@ describe "Defining an 'initialize_dup' method" do
def initialize_dup
end
end
- DefInitializeDupSpec.should have_private_instance_method(:initialize_dup, false)
+ DefInitializeDupSpec.private_instance_methods(false).should.include?(:initialize_dup)
end
end
@@ -58,7 +58,7 @@ describe "Defining an 'initialize_clone' method" do
def initialize_clone
end
end
- DefInitializeCloneSpec.should have_private_instance_method(:initialize_clone, false)
+ DefInitializeCloneSpec.private_instance_methods(false).should.include?(:initialize_clone)
end
end
@@ -68,7 +68,7 @@ describe "Defining a 'respond_to_missing?' method" do
def respond_to_missing?
end
end
- DefRespondToMissingPSpec.should have_private_instance_method(:respond_to_missing?, false)
+ DefRespondToMissingPSpec.private_instance_methods(false).should.include?(:respond_to_missing?)
end
end
@@ -82,12 +82,12 @@ end
describe "An instance method" do
it "raises an error with too few arguments" do
def foo(a, b); end
- -> { foo 1 }.should raise_error(ArgumentError, 'wrong number of arguments (given 1, expected 2)')
+ -> { foo 1 }.should.raise(ArgumentError, 'wrong number of arguments (given 1, expected 2)')
end
it "raises an error with too many arguments" do
def foo(a); end
- -> { foo 1, 2 }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
+ -> { foo 1, 2 }.should.raise(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
end
it "raises FrozenError with the correct class name" do
@@ -96,8 +96,9 @@ describe "An instance method" do
self.freeze
def foo; end
end
- }.should raise_error(FrozenError) { |e|
- e.message.should.start_with? "can't modify frozen module"
+ }.should.raise(FrozenError) { |e|
+ msg_class = ruby_version_is("4.0") ? "Module" : "module"
+ e.message.should == "can't modify frozen #{msg_class}: #{e.receiver}"
}
-> {
@@ -105,8 +106,9 @@ describe "An instance method" do
self.freeze
def foo; end
end
- }.should raise_error(FrozenError){ |e|
- e.message.should.start_with? "can't modify frozen class"
+ }.should.raise(FrozenError){ |e|
+ msg_class = ruby_version_is("4.0") ? "Class" : "class"
+ e.message.should == "can't modify frozen #{msg_class}: #{e.receiver}"
}
end
end
@@ -133,12 +135,12 @@ describe "An instance method definition with a splat" do
end
it "allows only a single * argument" do
- -> { eval 'def foo(a, *b, *c); end' }.should raise_error(SyntaxError)
+ -> { eval 'def foo(a, *b, *c); end' }.should.raise(SyntaxError)
end
it "requires the presence of any arguments that precede the *" do
def foo(a, b, *c); end
- -> { foo 1 }.should raise_error(ArgumentError, 'wrong number of arguments (given 1, expected 2+)')
+ -> { foo 1 }.should.raise(ArgumentError, 'wrong number of arguments (given 1, expected 2+)')
end
end
@@ -171,7 +173,7 @@ describe "An instance method with a default argument" do
def foo(a, b = 2)
[a,b]
end
- -> { foo }.should raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1..2)')
+ -> { foo }.should.raise(ArgumentError, 'wrong number of arguments (given 0, expected 1..2)')
foo(1).should == [1, 2]
end
@@ -179,7 +181,7 @@ describe "An instance method with a default argument" do
def foo(a, b = 2, *c)
[a,b,c]
end
- -> { foo }.should raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1+)')
+ -> { foo }.should.raise(ArgumentError, 'wrong number of arguments (given 0, expected 1+)')
foo(1).should == [1,2,[]]
end
@@ -197,15 +199,25 @@ describe "An instance method with a default argument" do
foo(2,3,3).should == [2,3,[3]]
end
- it "raises a SyntaxError when there is an existing method with the same name as the local variable" do
- def bar
- 1
+ ruby_version_is ""..."3.4" do
+ it "raises a SyntaxError if using the argument in its default value" do
+ -> {
+ eval "def foo(bar = bar)
+ bar
+ end"
+ }.should.raise(SyntaxError)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "is nil if using the argument in its default value" do
+ -> {
+ eval "def foo(bar = bar)
+ bar
+ end
+ foo"
+ }.call.should == nil
end
- -> {
- eval "def foo(bar = bar)
- bar
- end"
- }.should raise_error(SyntaxError)
end
it "calls a method with the same name as the local when explicitly using ()" do
@@ -238,7 +250,7 @@ describe "A singleton method definition" do
end
it "can be declared for a global variable" do
- $__a__ = "hi"
+ $__a__ = +"hi"
def $__a__.foo
7
end
@@ -267,26 +279,27 @@ describe "A singleton method definition" do
it "raises FrozenError if frozen" do
obj = Object.new
obj.freeze
- -> { def obj.foo; end }.should raise_error(FrozenError)
+ -> { def obj.foo; end }.should.raise(FrozenError)
end
it "raises FrozenError with the correct class name" do
obj = Object.new
obj.freeze
- -> { def obj.foo; end }.should raise_error(FrozenError){ |e|
- e.message.should.start_with? "can't modify frozen object"
- }
+ msg_class = ruby_version_is("4.0") ? "Object" : "object"
+ -> { def obj.foo; end }.should.raise(FrozenError, "can't modify frozen #{msg_class}: #{obj}")
+ obj = Object.new
c = obj.singleton_class
- -> { def c.foo; end }.should raise_error(FrozenError){ |e|
- e.message.should.start_with? "can't modify frozen Class"
- }
+ c.singleton_class.freeze
+ -> { def c.foo; end }.should.raise(FrozenError, "can't modify frozen Class: #{c}")
+
+ c = Class.new
+ c.freeze
+ -> { def c.foo; end }.should.raise(FrozenError, "can't modify frozen Class: #{c}")
m = Module.new
m.freeze
- -> { def m.foo; end }.should raise_error(FrozenError){ |e|
- e.message.should.start_with? "can't modify frozen Module"
- }
+ -> { def m.foo; end }.should.raise(FrozenError, "can't modify frozen Module: #{m}")
end
end
@@ -421,7 +434,7 @@ describe "A method definition inside a metaclass scope" do
end
DefSpecSingleton.a_class_method.should == DefSpecSingleton
- -> { Object.a_class_method }.should raise_error(NoMethodError)
+ -> { Object.a_class_method }.should.raise(NoMethodError)
end
it "can create a singleton method" do
@@ -431,7 +444,7 @@ describe "A method definition inside a metaclass scope" do
end
obj.a_singleton_method.should == obj
- -> { Object.new.a_singleton_method }.should raise_error(NoMethodError)
+ -> { Object.new.a_singleton_method }.should.raise(NoMethodError)
end
it "raises FrozenError if frozen" do
@@ -439,7 +452,7 @@ describe "A method definition inside a metaclass scope" do
obj.freeze
class << obj
- -> { def foo; end }.should raise_error(FrozenError)
+ -> { def foo; end }.should.raise(FrozenError)
end
end
end
@@ -460,7 +473,7 @@ describe "A nested method definition" do
other = DefSpecNested.new
other.an_instance_method.should == other
- DefSpecNested.should have_instance_method(:an_instance_method)
+ DefSpecNested.should.method_defined?(:an_instance_method, false)
end
it "creates a class method when evaluated in a class method" do
@@ -475,11 +488,11 @@ describe "A nested method definition" do
end
end
- -> { DefSpecNested.a_class_method }.should raise_error(NoMethodError)
+ -> { DefSpecNested.a_class_method }.should.raise(NoMethodError)
DefSpecNested.create_class_method.should == DefSpecNested
DefSpecNested.a_class_method.should == DefSpecNested
- -> { Object.a_class_method }.should raise_error(NoMethodError)
- -> { DefSpecNested.new.a_class_method }.should raise_error(NoMethodError)
+ -> { Object.a_class_method }.should.raise(NoMethodError)
+ -> { DefSpecNested.new.a_class_method }.should.raise(NoMethodError)
end
it "creates a singleton method when evaluated in the metaclass of an instance" do
@@ -497,7 +510,7 @@ describe "A nested method definition" do
obj.a_singleton_method.should == obj
other = DefSpecNested.new
- -> { other.a_singleton_method }.should raise_error(NoMethodError)
+ -> { other.a_singleton_method }.should.raise(NoMethodError)
end
it "creates a method in the surrounding context when evaluated in a def expr.method" do
@@ -509,11 +522,13 @@ describe "A nested method definition" do
end
DefSpecNested::TARGET.defs_method
- DefSpecNested.should have_instance_method :inherited_method
- DefSpecNested::TARGET.should_not have_method :inherited_method
+ DefSpecNested.should.method_defined?(:inherited_method, false)
+ DefSpecNested::TARGET.should_not.respond_to? :inherited_method
obj = DefSpecNested.new
obj.inherited_method.should == obj
+ ensure
+ DefSpecNested.send(:remove_const, :TARGET)
end
# See http://yugui.jp/articles/846#label-3
@@ -530,11 +545,13 @@ describe "A nested method definition" do
obj = DefSpecNested::OBJ
obj.create_method_in_instance_eval
- obj.should have_method :arg_method
- obj.should have_method :body_method
+ obj.should.respond_to? :arg_method
+ obj.should.respond_to? :body_method
- DefSpecNested.should_not have_instance_method :arg_method
- DefSpecNested.should_not have_instance_method :body_method
+ DefSpecNested.should_not.method_defined? :arg_method
+ DefSpecNested.should_not.method_defined? :body_method
+ ensure
+ DefSpecNested.send(:remove_const, :OBJ)
end
it "creates an instance method inside Class.new" do
@@ -552,7 +569,7 @@ describe "A nested method definition" do
cls.new.new_def.should == 1
- -> { Object.new.new_def }.should raise_error(NoMethodError)
+ -> { Object.new.new_def }.should.raise(NoMethodError)
end
end
@@ -568,18 +585,18 @@ describe "A method definition always resets the visibility to public for nested
end
obj = cls.new
- -> { obj.do_def }.should raise_error(NoMethodError, /private/)
+ -> { obj.do_def }.should.raise(NoMethodError, /private/)
obj.send :do_def
obj.new_def.should == 1
cls.new.new_def.should == 1
- -> { Object.new.new_def }.should raise_error(NoMethodError)
+ -> { Object.new.new_def }.should.raise(NoMethodError)
end
it "at the toplevel" do
obj = Object.new
- -> { obj.toplevel_define_other_method }.should raise_error(NoMethodError, /private/)
+ -> { obj.toplevel_define_other_method }.should.raise(NoMethodError, /private/)
toplevel_define_other_method
nested_method_in_toplevel_method.should == 42
@@ -596,7 +613,7 @@ describe "A method definition inside an instance_eval" do
obj.an_instance_eval_method.should == obj
other = Object.new
- -> { other.an_instance_eval_method }.should raise_error(NoMethodError)
+ -> { other.an_instance_eval_method }.should.raise(NoMethodError)
end
it "creates a singleton method when evaluated inside a metaclass" do
@@ -609,7 +626,7 @@ describe "A method definition inside an instance_eval" do
obj.a_metaclass_eval_method.should == obj
other = Object.new
- -> { other.a_metaclass_eval_method }.should raise_error(NoMethodError)
+ -> { other.a_metaclass_eval_method }.should.raise(NoMethodError)
end
it "creates a class method when the receiver is a class" do
@@ -618,7 +635,7 @@ describe "A method definition inside an instance_eval" do
end
DefSpecNested.an_instance_eval_class_method.should == DefSpecNested
- -> { Object.an_instance_eval_class_method }.should raise_error(NoMethodError)
+ -> { Object.an_instance_eval_class_method }.should.raise(NoMethodError)
end
it "creates a class method when the receiver is an anonymous class" do
@@ -630,7 +647,7 @@ describe "A method definition inside an instance_eval" do
end
m.klass_method.should == :test
- -> { Object.klass_method }.should raise_error(NoMethodError)
+ -> { Object.klass_method }.should.raise(NoMethodError)
end
it "creates a class method when instance_eval is within class" do
@@ -643,7 +660,7 @@ describe "A method definition inside an instance_eval" do
end
m.klass_method.should == :test
- -> { Object.klass_method }.should raise_error(NoMethodError)
+ -> { Object.klass_method }.should.raise(NoMethodError)
end
end
@@ -656,7 +673,7 @@ describe "A method definition inside an instance_exec" do
end
DefSpecNested.an_instance_exec_class_method.should == 1
- -> { Object.an_instance_exec_class_method }.should raise_error(NoMethodError)
+ -> { Object.an_instance_exec_class_method }.should.raise(NoMethodError)
end
it "creates a class method when the receiver is an anonymous class" do
@@ -670,7 +687,7 @@ describe "A method definition inside an instance_exec" do
end
m.klass_method.should == 1
- -> { Object.klass_method }.should raise_error(NoMethodError)
+ -> { Object.klass_method }.should.raise(NoMethodError)
end
it "creates a class method when instance_exec is within class" do
@@ -685,7 +702,7 @@ describe "A method definition inside an instance_exec" do
end
m.klass_method.should == 2
- -> { Object.klass_method }.should raise_error(NoMethodError)
+ -> { Object.klass_method }.should.raise(NoMethodError)
end
end
@@ -705,7 +722,7 @@ describe "A method definition in an eval" do
other = DefSpecNested.new
other.an_eval_instance_method.should == other
- -> { Object.new.an_eval_instance_method }.should raise_error(NoMethodError)
+ -> { Object.new.an_eval_instance_method }.should.raise(NoMethodError)
end
it "creates a class method" do
@@ -721,8 +738,8 @@ describe "A method definition in an eval" do
DefSpecNestedB.eval_class_method.should == DefSpecNestedB
DefSpecNestedB.an_eval_class_method.should == DefSpecNestedB
- -> { Object.an_eval_class_method }.should raise_error(NoMethodError)
- -> { DefSpecNestedB.new.an_eval_class_method}.should raise_error(NoMethodError)
+ -> { Object.an_eval_class_method }.should.raise(NoMethodError)
+ -> { DefSpecNestedB.new.an_eval_class_method}.should.raise(NoMethodError)
end
it "creates a singleton method" do
@@ -740,7 +757,7 @@ describe "A method definition in an eval" do
obj.an_eval_singleton_method.should == obj
other = DefSpecNested.new
- -> { other.an_eval_singleton_method }.should raise_error(NoMethodError)
+ -> { other.an_eval_singleton_method }.should.raise(NoMethodError)
end
end
@@ -751,8 +768,8 @@ describe "a method definition that sets more than one default parameter all to t
it "assigns them all the same object by default" do
foo.should == [{},{},{}]
a, b, c = foo
- a.should eql(b)
- a.should eql(c)
+ a.should.eql?(b)
+ a.should.eql?(c)
end
it "allows the first argument to be given, and sets the rest to null" do
@@ -762,11 +779,11 @@ describe "a method definition that sets more than one default parameter all to t
it "assigns the parameters different objects across different default calls" do
a, _b, _c = foo
d, _e, _f = foo
- a.should_not equal(d)
+ a.should_not.equal?(d)
end
it "only allows overriding the default value of the first such parameter in each set" do
- -> { foo(1,2) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 0..1)')
+ -> { foo(1,2) }.should.raise(ArgumentError, 'wrong number of arguments (given 2, expected 0..1)')
end
def bar(a=b=c=1,d=2)
@@ -777,7 +794,7 @@ describe "a method definition that sets more than one default parameter all to t
bar.should == [1,1,1,2]
bar(3).should == [3,nil,nil,2]
bar(3,4).should == [3,nil,nil,4]
- -> { bar(3,4,5) }.should raise_error(ArgumentError, 'wrong number of arguments (given 3, expected 0..2)')
+ -> { bar(3,4,5) }.should.raise(ArgumentError, 'wrong number of arguments (given 3, expected 0..2)')
end
end
@@ -792,7 +809,7 @@ describe "The def keyword" do
}.call
end
- DefSpecsLambdaVisibility.should have_private_instance_method("some_method")
+ DefSpecsLambdaVisibility.private_instance_methods(false).should.include?(:some_method)
end
end
end
diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb
index ae2bf45bda..6846179a7c 100644
--- a/spec/ruby/language/defined_spec.rb
+++ b/spec/ruby/language/defined_spec.rb
@@ -70,7 +70,7 @@ describe "The defined? keyword when called with a method name" do
end
it "returns nil if the method is not defined" do
- defined?(defined_specs_undefined_method).should be_nil
+ defined?(defined_specs_undefined_method).should == nil
end
it "returns 'method' if the method is defined and private" do
@@ -90,23 +90,23 @@ describe "The defined? keyword when called with a method name" do
end
it "returns nil if the method is private" do
- defined?(Object.print).should be_nil
+ defined?(Object.print).should == nil
end
it "returns nil if the method is protected" do
- defined?(DefinedSpecs::Basic.new.protected_method).should be_nil
+ defined?(DefinedSpecs::Basic.new.protected_method).should == nil
end
it "returns nil if the method is not defined" do
- defined?(Kernel.defined_specs_undefined_method).should be_nil
+ defined?(Kernel.defined_specs_undefined_method).should == nil
end
it "returns nil if the class is not defined" do
- defined?(DefinedSpecsUndefined.puts).should be_nil
+ defined?(DefinedSpecsUndefined.puts).should == nil
end
it "returns nil if the subclass is not defined" do
- defined?(DefinedSpecs::Undefined.puts).should be_nil
+ defined?(DefinedSpecs::Undefined.puts).should == nil
end
end
@@ -116,13 +116,18 @@ describe "The defined? keyword when called with a method name" do
defined?(obj.a_defined_method).should == "method"
end
+ it "returns 'method' for []=" do
+ a = []
+ defined?(a[0] = 1).should == "method"
+ end
+
it "returns nil if the method is not defined" do
obj = DefinedSpecs::Basic.new
- defined?(obj.an_undefined_method).should be_nil
+ defined?(obj.an_undefined_method).should == nil
end
it "returns nil if the variable does not exist" do
- defined?(nonexistent_local_variable.some_method).should be_nil
+ defined?(nonexistent_local_variable.some_method).should == nil
end
it "calls #respond_to_missing?" do
@@ -140,11 +145,11 @@ describe "The defined? keyword when called with a method name" do
it "returns nil if the method is not defined" do
@defined_specs_obj = DefinedSpecs::Basic.new
- defined?(@defined_specs_obj.an_undefined_method).should be_nil
+ defined?(@defined_specs_obj.an_undefined_method).should == nil
end
it "returns nil if the variable does not exist" do
- defined?(@nonexistent_instance_variable.some_method).should be_nil
+ defined?(@nonexistent_instance_variable.some_method).should == nil
end
end
@@ -156,22 +161,22 @@ describe "The defined? keyword when called with a method name" do
it "returns nil if the method is not defined" do
$defined_specs_obj = DefinedSpecs::Basic.new
- defined?($defined_specs_obj.an_undefined_method).should be_nil
+ defined?($defined_specs_obj.an_undefined_method).should == nil
end
it "returns nil if the variable does not exist" do
- defined?($nonexistent_global_variable.some_method).should be_nil
+ defined?($nonexistent_global_variable.some_method).should == nil
end
end
describe "having a method call as a receiver" do
it "returns nil if evaluating the receiver raises an exception" do
- defined?(DefinedSpecs.exception_method / 2).should be_nil
+ defined?(DefinedSpecs.exception_method / 2).should == nil
ScratchPad.recorded.should == :defined_specs_exception
end
it "returns nil if the method is not defined on the object the receiver returns" do
- defined?(DefinedSpecs.side_effects / 2).should be_nil
+ defined?(DefinedSpecs.side_effects / 2).should == nil
ScratchPad.recorded.should == :defined_specs_side_effects
end
@@ -180,6 +185,48 @@ describe "The defined? keyword when called with a method name" do
ScratchPad.recorded.should == :defined_specs_fixnum_method
end
end
+
+ describe "having a throw in the receiver" do
+ it "escapes defined? and performs the throw semantics as normal" do
+ defined_returned = false
+ catch(:out) {
+ # NOTE: defined? behaves differently if it is called in a void context, see below
+ defined?(throw(:out, 42).foo).should == :unreachable
+ defined_returned = true
+ }.should == 42
+ defined_returned.should == false
+ end
+ end
+
+ describe "in a void context" do
+ it "does not execute the receiver" do
+ ScratchPad.record :not_executed
+ defined?(DefinedSpecs.side_effects / 2)
+ ScratchPad.recorded.should == :not_executed
+ end
+
+ it "warns about the void context when parsing it" do
+ -> {
+ eval "defined?(DefinedSpecs.side_effects / 2); 42"
+ }.should complain(/warning: possibly useless use of defined\? in void context/, verbose: true)
+ end
+ end
+
+ describe "for a protected method" do
+ it "returns 'method' when the receiver is a subclass instance" do
+ DefinedSpecs::ProtectedBase.new.defined_on(DefinedSpecs::ProtectedSubclass.new).should == "method"
+ end
+
+ it "returns 'method' when the receiver is the base class instance" do
+ DefinedSpecs::ProtectedSubclass.new.defined_on(DefinedSpecs::ProtectedBase.new).should == "method"
+ end
+
+ ruby_bug "#22076", ""..."4.1" do
+ it "returns 'method' when the receiver is a sibling class instance via a shared included module" do
+ DefinedSpecs::ProtectedIncluderA.new.defined_on(DefinedSpecs::ProtectedIncluderB.new).should == "method"
+ end
+ end
+ end
end
describe "The defined? keyword for an expression" do
@@ -205,6 +252,14 @@ describe "The defined? keyword for an expression" do
defined?(@@defined_specs_x = 2).should == "assignment"
end
+ it "returns 'assignment' for assigning a constant" do
+ defined?(A = 2).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning a fully qualified constant" do
+ defined?(Object::A = 2).should == "assignment"
+ end
+
it "returns 'assignment' for assigning multiple variables" do
defined?((a, b = 1, 2)).should == "assignment"
end
@@ -222,7 +277,27 @@ describe "The defined? keyword for an expression" do
end
it "returns 'assignment' for an expression with '+='" do
- defined?(x += 2).should == "assignment"
+ defined?(a += 1).should == "assignment"
+ defined?(@a += 1).should == "assignment"
+ defined?(@@a += 1).should == "assignment"
+ defined?($a += 1).should == "assignment"
+ defined?(A += 1).should == "assignment"
+ # fully qualified constant check is moved out into a separate test case
+ defined?(a.b += 1).should == "assignment"
+ defined?(a[:b] += 1).should == "assignment"
+ end
+
+ # https://bugs.ruby-lang.org/issues/20111
+ ruby_version_is ""..."3.4" do
+ it "returns 'expression' for an assigning a fully qualified constant with '+='" do
+ defined?(Object::A += 1).should == "expression"
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "returns 'assignment' for an assigning a fully qualified constant with '+='" do
+ defined?(Object::A += 1).should == "assignment"
+ end
end
it "returns 'assignment' for an expression with '*='" do
@@ -253,12 +328,90 @@ describe "The defined? keyword for an expression" do
defined?(x >>= 2).should == "assignment"
end
- it "returns 'assignment' for an expression with '||='" do
- defined?(x ||= 2).should == "assignment"
+ context "||=" do
+ it "returns 'assignment' for assigning a local variable with '||='" do
+ defined?(a ||= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning an instance variable with '||='" do
+ defined?(@a ||= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning a class variable with '||='" do
+ defined?(@@a ||= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning a global variable with '||='" do
+ defined?($a ||= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning a constant with '||='" do
+ defined?(A ||= true).should == "assignment"
+ end
+
+ # https://bugs.ruby-lang.org/issues/20111
+ ruby_version_is ""..."3.4" do
+ it "returns 'expression' for assigning a fully qualified constant with '||='" do
+ defined?(Object::A ||= true).should == "expression"
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "returns 'assignment' for assigning a fully qualified constant with '||='" do
+ defined?(Object::A ||= true).should == "assignment"
+ end
+ end
+
+ it "returns 'assignment' for assigning an attribute with '||='" do
+ defined?(a.b ||= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning a referenced element with '||='" do
+ defined?(a[:b] ||= true).should == "assignment"
+ end
end
- it "returns 'assignment' for an expression with '&&='" do
- defined?(x &&= 2).should == "assignment"
+ context "&&=" do
+ it "returns 'assignment' for assigning a local variable with '&&='" do
+ defined?(a &&= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning an instance variable with '&&='" do
+ defined?(@a &&= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning a class variable with '&&='" do
+ defined?(@@a &&= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning a global variable with '&&='" do
+ defined?($a &&= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning a constant with '&&='" do
+ defined?(A &&= true).should == "assignment"
+ end
+
+ # https://bugs.ruby-lang.org/issues/20111
+ ruby_version_is ""..."3.4" do
+ it "returns 'expression' for assigning a fully qualified constant with '&&='" do
+ defined?(Object::A &&= true).should == "expression"
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "returns 'assignment' for assigning a fully qualified constant with '&&='" do
+ defined?(Object::A &&= true).should == "assignment"
+ end
+ end
+
+ it "returns 'assignment' for assigning an attribute with '&&='" do
+ defined?(a.b &&= true).should == "assignment"
+ end
+
+ it "returns 'assignment' for assigning a referenced element with '&&='" do
+ defined?(a[:b] &&= true).should == "assignment"
+ end
end
it "returns 'assignment' for an expression with '**='" do
@@ -266,15 +419,15 @@ describe "The defined? keyword for an expression" do
end
it "returns nil for an expression with == and an undefined method" do
- defined?(defined_specs_undefined_method == 2).should be_nil
+ defined?(defined_specs_undefined_method == 2).should == nil
end
it "returns nil for an expression with != and an undefined method" do
- defined?(defined_specs_undefined_method != 2).should be_nil
+ defined?(defined_specs_undefined_method != 2).should == nil
end
it "returns nil for an expression with !~ and an undefined method" do
- defined?(defined_specs_undefined_method !~ 2).should be_nil
+ defined?(defined_specs_undefined_method !~ 2).should == nil
end
it "returns 'method' for an expression with '=='" do
@@ -294,25 +447,25 @@ describe "The defined? keyword for an expression" do
describe "with logical connectives" do
it "returns nil for an expression with '!' and an undefined method" do
- defined?(!defined_specs_undefined_method).should be_nil
+ defined?(!defined_specs_undefined_method).should == nil
end
it "returns nil for an expression with '!' and an unset class variable" do
@result = eval("class singleton_class::A; defined?(!@@doesnt_exist) end", binding, __FILE__, __LINE__)
- @result.should be_nil
+ @result.should == nil
end
it "returns nil for an expression with 'not' and an undefined method" do
- defined?(not defined_specs_undefined_method).should be_nil
+ defined?(not defined_specs_undefined_method).should == nil
end
it "returns nil for an expression with 'not' and an unset class variable" do
@result = eval("class singleton_class::A; defined?(not @@doesnt_exist) end", binding, __FILE__, __LINE__)
- @result.should be_nil
+ @result.should == nil
end
it "does not propagate an exception raised by a method in a 'not' expression" do
- defined?(not DefinedSpecs.exception_method).should be_nil
+ defined?(not DefinedSpecs.exception_method).should == nil
ScratchPad.recorded.should == :defined_specs_exception
end
@@ -351,11 +504,11 @@ describe "The defined? keyword for an expression" do
end
it "returns nil for an expression with '!' and an unset global variable" do
- defined?(!$defined_specs_undefined_global_variable).should be_nil
+ defined?(!$defined_specs_undefined_global_variable).should == nil
end
it "returns nil for an expression with '!' and an unset instance variable" do
- defined?(!@defined_specs_undefined_instance_variable).should be_nil
+ defined?(!@defined_specs_undefined_instance_variable).should == nil
end
it "returns 'method' for a 'not' expression with a method" do
@@ -368,11 +521,11 @@ describe "The defined? keyword for an expression" do
end
it "returns nil for an expression with 'not' and an unset global variable" do
- defined?(not $defined_specs_undefined_global_variable).should be_nil
+ defined?(not $defined_specs_undefined_global_variable).should == nil
end
it "returns nil for an expression with 'not' and an unset instance variable" do
- defined?(not @defined_specs_undefined_instance_variable).should be_nil
+ defined?(not @defined_specs_undefined_instance_variable).should == nil
end
it "returns 'expression' for an expression with '&&/and' and an undefined method" do
@@ -387,12 +540,12 @@ describe "The defined? keyword for an expression" do
it "does not call a method in an '&&' expression and returns 'expression'" do
defined?(DefinedSpecs.side_effects && true).should == "expression"
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
it "does not call a method in an 'and' expression and returns 'expression'" do
defined?(DefinedSpecs.side_effects and true).should == "expression"
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
it "returns 'expression' for an expression with '||/or' and an undefined method" do
@@ -407,12 +560,12 @@ describe "The defined? keyword for an expression" do
it "does not call a method in an '||' expression and returns 'expression'" do
defined?(DefinedSpecs.side_effects || true).should == "expression"
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
it "does not call a method in an 'or' expression and returns 'expression'" do
defined?(DefinedSpecs.side_effects or true).should == "expression"
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
end
@@ -435,7 +588,7 @@ describe "The defined? keyword for an expression" do
it "does not call the method in the String" do
defined?("garble #{DefinedSpecs.dynamic_string}").should == "expression"
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
end
@@ -454,7 +607,7 @@ describe "The defined? keyword for an expression" do
it "does not call the method in the Regexp" do
defined?(/garble #{DefinedSpecs.dynamic_string}/).should == "expression"
- ScratchPad.recorded.should be_nil
+ ScratchPad.recorded.should == nil
end
end
@@ -503,11 +656,11 @@ describe "The defined? keyword for variables" do
end
it "returns nil for an instance variable that has not been read" do
- DefinedSpecs::Basic.new.instance_variable_undefined.should be_nil
+ DefinedSpecs::Basic.new.instance_variable_undefined.should == nil
end
it "returns nil for an instance variable that has been read but not assigned to" do
- DefinedSpecs::Basic.new.instance_variable_read.should be_nil
+ DefinedSpecs::Basic.new.instance_variable_read.should == nil
end
it "returns 'instance-variable' for an instance variable that has been assigned" do
@@ -521,11 +674,11 @@ describe "The defined? keyword for variables" do
end
it "returns nil for a global variable that has not been read" do
- DefinedSpecs::Basic.new.global_variable_undefined.should be_nil
+ DefinedSpecs::Basic.new.global_variable_undefined.should == nil
end
it "returns nil for a global variable that has been read but not assigned to" do
- DefinedSpecs::Basic.new.global_variable_read.should be_nil
+ DefinedSpecs::Basic.new.global_variable_read.should == nil
end
it "returns 'global-variable' for a global variable that has been assigned nil" do
@@ -557,27 +710,27 @@ describe "The defined? keyword for variables" do
end
it "returns nil for $&" do
- defined?($&).should be_nil
+ defined?($&).should == nil
end
it "returns nil for $`" do
- defined?($`).should be_nil
+ defined?($`).should == nil
end
it "returns nil for $'" do
- defined?($').should be_nil
+ defined?($').should == nil
end
it "returns nil for $+" do
- defined?($+).should be_nil
+ defined?($+).should == nil
end
it "returns nil for any last match global" do
- defined?($1).should be_nil
- defined?($4).should be_nil
- defined?($7).should be_nil
- defined?($10).should be_nil
- defined?($200).should be_nil
+ defined?($1).should == nil
+ defined?($4).should == nil
+ defined?($7).should == nil
+ defined?($10).should == nil
+ defined?($200).should == nil
end
end
@@ -612,10 +765,10 @@ describe "The defined? keyword for variables" do
end
it "returns nil for non-captures" do
- defined?($4).should be_nil
- defined?($7).should be_nil
- defined?($10).should be_nil
- defined?($200).should be_nil
+ defined?($4).should == nil
+ defined?($7).should == nil
+ defined?($10).should == nil
+ defined?($200).should == nil
end
end
@@ -629,27 +782,27 @@ describe "The defined? keyword for variables" do
end
it "returns nil for $&" do
- defined?($&).should be_nil
+ defined?($&).should == nil
end
it "returns nil for $`" do
- defined?($`).should be_nil
+ defined?($`).should == nil
end
it "returns nil for $'" do
- defined?($').should be_nil
+ defined?($').should == nil
end
it "returns nil for $+" do
- defined?($+).should be_nil
+ defined?($+).should == nil
end
it "returns nil for any last match global" do
- defined?($1).should be_nil
- defined?($4).should be_nil
- defined?($7).should be_nil
- defined?($10).should be_nil
- defined?($200).should be_nil
+ defined?($1).should == nil
+ defined?($4).should == nil
+ defined?($7).should == nil
+ defined?($10).should == nil
+ defined?($200).should == nil
end
end
@@ -684,10 +837,10 @@ describe "The defined? keyword for variables" do
end
it "returns nil for non-captures" do
- defined?($4).should be_nil
- defined?($7).should be_nil
- defined?($10).should be_nil
- defined?($200).should be_nil
+ defined?($4).should == nil
+ defined?($7).should == nil
+ defined?($10).should == nil
+ defined?($200).should == nil
end
end
it "returns 'global-variable' for a global variable that has been assigned" do
@@ -695,7 +848,7 @@ describe "The defined? keyword for variables" do
end
it "returns nil for a class variable that has not been read" do
- DefinedSpecs::Basic.new.class_variable_undefined.should be_nil
+ DefinedSpecs::Basic.new.class_variable_undefined.should == nil
end
# There is no spec for a class variable that is read before being assigned
@@ -722,12 +875,12 @@ describe "The defined? keyword for a simple constant" do
end
it "returns nil when the constant is not defined" do
- defined?(DefinedSpecsUndefined).should be_nil
+ defined?(DefinedSpecsUndefined).should == nil
end
it "does not call Object.const_missing if the constant is not defined" do
Object.should_not_receive(:const_missing)
- defined?(DefinedSpecsUndefined).should be_nil
+ defined?(DefinedSpecsUndefined).should == nil
end
it "returns 'constant' for an included module" do
@@ -745,12 +898,12 @@ describe "The defined? keyword for a top-level constant" do
end
it "returns nil if the constant is not defined" do
- defined?(::DefinedSpecsUndefined).should be_nil
+ defined?(::DefinedSpecsUndefined).should == nil
end
it "does not call Object.const_missing if the constant is not defined" do
Object.should_not_receive(:const_missing)
- defined?(::DefinedSpecsUndefined).should be_nil
+ defined?(::DefinedSpecsUndefined).should == nil
end
end
@@ -760,33 +913,37 @@ describe "The defined? keyword for a scoped constant" do
end
it "returns nil when the scoped constant is not defined" do
- defined?(DefinedSpecs::Undefined).should be_nil
+ defined?(DefinedSpecs::Undefined).should == nil
+ end
+
+ it "returns nil when the constant is not defined and the outer module implements .const_missing" do
+ defined?(DefinedSpecs::ModuleWithConstMissing::Undefined).should == nil
end
it "does not call .const_missing if the constant is not defined" do
DefinedSpecs.should_not_receive(:const_missing)
- defined?(DefinedSpecs::UnknownChild).should be_nil
+ defined?(DefinedSpecs::UnknownChild).should == nil
end
it "returns nil when an undefined constant is scoped to a defined constant" do
- defined?(DefinedSpecs::Child::Undefined).should be_nil
+ defined?(DefinedSpecs::Child::Undefined).should == nil
end
it "returns nil when a constant is scoped to an undefined constant" do
Object.should_not_receive(:const_missing)
- defined?(Undefined::Object).should be_nil
+ defined?(Undefined::Object).should == nil
end
it "returns nil when the undefined constant is scoped to an undefined constant" do
- defined?(DefinedSpecs::Undefined::Undefined).should be_nil
+ defined?(DefinedSpecs::Undefined::Undefined).should == nil
end
it "returns nil when a constant is defined on top-level but not on the module" do
- defined?(DefinedSpecs::String).should be_nil
+ defined?(DefinedSpecs::String).should == nil
end
it "returns nil when a constant is defined on top-level but not on the class" do
- defined?(DefinedSpecs::Basic::String).should be_nil
+ defined?(DefinedSpecs::Basic::String).should == nil
end
it "returns 'constant' if the scoped-scoped constant is defined" do
@@ -800,15 +957,15 @@ describe "The defined? keyword for a top-level scoped constant" do
end
it "returns nil when the scoped constant is not defined" do
- defined?(::DefinedSpecs::Undefined).should be_nil
+ defined?(::DefinedSpecs::Undefined).should == nil
end
it "returns nil when an undefined constant is scoped to a defined constant" do
- defined?(::DefinedSpecs::Child::Undefined).should be_nil
+ defined?(::DefinedSpecs::Child::Undefined).should == nil
end
it "returns nil when the undefined constant is scoped to an undefined constant" do
- defined?(::DefinedSpecs::Undefined::Undefined).should be_nil
+ defined?(::DefinedSpecs::Undefined::Undefined).should == nil
end
it "returns 'constant' if the scoped-scoped constant is defined" do
@@ -818,7 +975,7 @@ end
describe "The defined? keyword for a self-send method call scoped constant" do
it "returns nil if the constant is not defined in the scope of the method's value" do
- defined?(defined_specs_method::Undefined).should be_nil
+ defined?(defined_specs_method::Undefined).should == nil
end
it "returns 'constant' if the constant is defined in the scope of the method's value" do
@@ -826,11 +983,11 @@ describe "The defined? keyword for a self-send method call scoped constant" do
end
it "returns nil if the last constant is not defined in the scope chain" do
- defined?(defined_specs_method::Basic::Undefined).should be_nil
+ defined?(defined_specs_method::Basic::Undefined).should == nil
end
it "returns nil if the middle constant is not defined in the scope chain" do
- defined?(defined_specs_method::Undefined::Undefined).should be_nil
+ defined?(defined_specs_method::Undefined::Undefined).should == nil
end
it "returns 'constant' if all the constants in the scope chain are defined" do
@@ -840,7 +997,7 @@ end
describe "The defined? keyword for a receiver method call scoped constant" do
it "returns nil if the constant is not defined in the scope of the method's value" do
- defined?(defined_specs_receiver.defined_method::Undefined).should be_nil
+ defined?(defined_specs_receiver.defined_method::Undefined).should == nil
end
it "returns 'constant' if the constant is defined in the scope of the method's value" do
@@ -848,11 +1005,11 @@ describe "The defined? keyword for a receiver method call scoped constant" do
end
it "returns nil if the last constant is not defined in the scope chain" do
- defined?(defined_specs_receiver.defined_method::Basic::Undefined).should be_nil
+ defined?(defined_specs_receiver.defined_method::Basic::Undefined).should == nil
end
it "returns nil if the middle constant is not defined in the scope chain" do
- defined?(defined_specs_receiver.defined_method::Undefined::Undefined).should be_nil
+ defined?(defined_specs_receiver.defined_method::Undefined::Undefined).should == nil
end
it "returns 'constant' if all the constants in the scope chain are defined" do
@@ -862,7 +1019,7 @@ end
describe "The defined? keyword for a module method call scoped constant" do
it "returns nil if the constant is not defined in the scope of the method's value" do
- defined?(DefinedSpecs.defined_method::Undefined).should be_nil
+ defined?(DefinedSpecs.defined_method::Undefined).should == nil
end
it "returns 'constant' if the constant scoped by the method's value is defined" do
@@ -870,11 +1027,11 @@ describe "The defined? keyword for a module method call scoped constant" do
end
it "returns nil if the last constant in the scope chain is not defined" do
- defined?(DefinedSpecs.defined_method::Basic::Undefined).should be_nil
+ defined?(DefinedSpecs.defined_method::Basic::Undefined).should == nil
end
it "returns nil if the middle constant in the scope chain is not defined" do
- defined?(DefinedSpecs.defined_method::Undefined::Undefined).should be_nil
+ defined?(DefinedSpecs.defined_method::Undefined::Undefined).should == nil
end
it "returns 'constant' if all the constants in the scope chain are defined" do
@@ -882,11 +1039,11 @@ describe "The defined? keyword for a module method call scoped constant" do
end
it "returns nil if the outer scope constant in the receiver is not defined" do
- defined?(Undefined::DefinedSpecs.defined_method::Basic).should be_nil
+ defined?(Undefined::DefinedSpecs.defined_method::Basic).should == nil
end
it "returns nil if the scoped constant in the receiver is not defined" do
- defined?(DefinedSpecs::Undefined.defined_method::Basic).should be_nil
+ defined?(DefinedSpecs::Undefined.defined_method::Basic).should == nil
end
it "returns 'constant' if all the constants in the receiver are defined" do
@@ -907,7 +1064,7 @@ describe "The defined? keyword for a variable scoped constant" do
it "returns nil if the instance scoped constant is not defined" do
@defined_specs_obj = DefinedSpecs::Basic
- defined?(@defined_specs_obj::Undefined).should be_nil
+ defined?(@defined_specs_obj::Undefined).should == nil
end
it "returns 'constant' if the constant is defined in the scope of the instance variable" do
@@ -917,7 +1074,7 @@ describe "The defined? keyword for a variable scoped constant" do
it "returns nil if the global scoped constant is not defined" do
$defined_specs_obj = DefinedSpecs::Basic
- defined?($defined_specs_obj::Undefined).should be_nil
+ defined?($defined_specs_obj::Undefined).should == nil
end
it "returns 'constant' if the constant is defined in the scope of the global variable" do
@@ -929,7 +1086,7 @@ describe "The defined? keyword for a variable scoped constant" do
eval(<<-END, binding, __FILE__, __LINE__)
class singleton_class::A
@@defined_specs_obj = DefinedSpecs::Basic
- defined?(@@defined_specs_obj::Undefined).should be_nil
+ defined?(@@defined_specs_obj::Undefined).should == nil
end
END
end
@@ -945,7 +1102,7 @@ describe "The defined? keyword for a variable scoped constant" do
it "returns nil if the local scoped constant is not defined" do
defined_specs_obj = DefinedSpecs::Basic
- defined?(defined_specs_obj::Undefined).should be_nil
+ defined?(defined_specs_obj::Undefined).should == nil
end
it "returns 'constant' if the constant is defined in the scope of the local variable" do
@@ -966,11 +1123,11 @@ end
describe "The defined? keyword for yield" do
it "returns nil if no block is passed to a method not taking a block parameter" do
- DefinedSpecs::Basic.new.no_yield_block.should be_nil
+ DefinedSpecs::Basic.new.no_yield_block.should == nil
end
it "returns nil if no block is passed to a method taking a block parameter" do
- DefinedSpecs::Basic.new.no_yield_block_parameter.should be_nil
+ DefinedSpecs::Basic.new.no_yield_block_parameter.should == nil
end
it "returns 'yield' if a block is passed to a method not taking a block parameter" do
@@ -998,24 +1155,24 @@ end
describe "The defined? keyword for super" do
it "returns nil when a superclass undef's the method" do
- DefinedSpecs::ClassWithoutMethod.new.test.should be_nil
+ DefinedSpecs::ClassWithoutMethod.new.test.should == nil
end
describe "for a method taking no arguments" do
it "returns nil when no superclass method exists" do
- DefinedSpecs::Super.new.no_super_method_no_args.should be_nil
+ DefinedSpecs::Super.new.no_super_method_no_args.should == nil
end
it "returns nil from a block when no superclass method exists" do
- DefinedSpecs::Super.new.no_super_method_block_no_args.should be_nil
+ DefinedSpecs::Super.new.no_super_method_block_no_args.should == nil
end
it "returns nil from a #define_method when no superclass method exists" do
- DefinedSpecs::Super.new.no_super_define_method_no_args.should be_nil
+ DefinedSpecs::Super.new.no_super_define_method_no_args.should == nil
end
it "returns nil from a block in a #define_method when no superclass method exists" do
- DefinedSpecs::Super.new.no_super_define_method_block_no_args.should be_nil
+ DefinedSpecs::Super.new.no_super_define_method_block_no_args.should == nil
end
it "returns 'super' when a superclass method exists" do
@@ -1043,19 +1200,19 @@ describe "The defined? keyword for super" do
describe "for a method taking arguments" do
it "returns nil when no superclass method exists" do
- DefinedSpecs::Super.new.no_super_method_args.should be_nil
+ DefinedSpecs::Super.new.no_super_method_args.should == nil
end
it "returns nil from a block when no superclass method exists" do
- DefinedSpecs::Super.new.no_super_method_block_args.should be_nil
+ DefinedSpecs::Super.new.no_super_method_block_args.should == nil
end
it "returns nil from a #define_method when no superclass method exists" do
- DefinedSpecs::Super.new.no_super_define_method_args.should be_nil
+ DefinedSpecs::Super.new.no_super_define_method_args.should == nil
end
it "returns nil from a block in a #define_method when no superclass method exists" do
- DefinedSpecs::Super.new.no_super_define_method_block_args.should be_nil
+ DefinedSpecs::Super.new.no_super_define_method_block_args.should == nil
end
it "returns 'super' when a superclass method exists" do
@@ -1090,7 +1247,7 @@ describe "The defined? keyword for instance variables" do
end
it "returns nil if not assigned" do
- defined?(@unassigned_ivar).should be_nil
+ defined?(@unassigned_ivar).should == nil
end
end
diff --git a/spec/ruby/language/delegation_spec.rb b/spec/ruby/language/delegation_spec.rb
index 3f24a79d5c..3d917993f5 100644
--- a/spec/ruby/language/delegation_spec.rb
+++ b/spec/ruby/language/delegation_spec.rb
@@ -1,6 +1,7 @@
require_relative '../spec_helper'
require_relative 'fixtures/delegation'
+# Forwarding anonymous parameters
describe "delegation with def(...)" do
it "delegates rest and kwargs" do
a = Class.new(DelegationSpecs::Target)
@@ -10,10 +11,10 @@ describe "delegation with def(...)" do
end
RUBY
- a.new.delegate(1, b: 2).should == [[1], {b: 2}]
+ a.new.delegate(1, b: 2).should == [[1], {b: 2}, nil]
end
- it "delegates block" do
+ it "delegates a block literal" do
a = Class.new(DelegationSpecs::Target)
a.class_eval(<<-RUBY)
def delegate_block(...)
@@ -24,6 +25,28 @@ describe "delegation with def(...)" do
a.new.delegate_block(1, b: 2) { |x| x }.should == [{b: 2}, [1]]
end
+ it "delegates a block argument" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(...)
+ target(...)
+ end
+ RUBY
+
+ block = proc {}
+ a.new.delegate(1, b: 2, &block).should == [[1], {b: 2}, block]
+ end
+
+ it "delegates with additional arguments" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(...)
+ target(:first, :second, ...)
+ end
+ RUBY
+ a.new.delegate(1, b: 2).should == [[:first, :second, 1], {b: 2}, nil]
+ end
+
it "parses as open endless Range when brackets are omitted" do
a = Class.new(DelegationSpecs::Target)
suppress_warning do
@@ -31,35 +54,109 @@ describe "delegation with def(...)" do
def delegate(...)
target ...
end
- RUBY
- end
+ RUBY
+ end
- a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true)
+ a.new.delegate(1, b: 2).should == Range.new([[], {}, nil], nil, true)
end
end
-ruby_version_is "2.7.3" do
- describe "delegation with def(x, ...)" do
- it "delegates rest and kwargs" do
- a = Class.new(DelegationSpecs::Target)
- a.class_eval(<<-RUBY)
- def delegate(x, ...)
- target(...)
- end
- RUBY
+describe "delegation with def(x, ...)" do
+ it "delegates rest and kwargs" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(x, ...)
+ target(...)
+ end
+ RUBY
+
+ a.new.delegate(0, 1, b: 2).should == [[1], {b: 2}, nil]
+ end
+
+ it "delegates a block literal" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate_block(x, ...)
+ target_block(...)
+ end
+ RUBY
+
+ a.new.delegate_block(0, 1, b: 2) { |x| x }.should == [{b: 2}, [1]]
+ end
+
+ it "delegates a block argument" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(...)
+ target(...)
+ end
+ RUBY
- a.new.delegate(0, 1, b: 2).should == [[1], {b: 2}]
+ block = proc {}
+ a.new.delegate(1, b: 2, &block).should == [[1], {b: 2}, block]
+ end
+end
+
+describe "delegation with def(*)" do
+ it "delegates rest" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(*)
+ target(*)
end
+ RUBY
- it "delegates block" do
- a = Class.new(DelegationSpecs::Target)
- a.class_eval(<<-RUBY)
- def delegate_block(x, ...)
- target_block(...)
- end
- RUBY
+ a.new.delegate(0, 1).should == [[0, 1], {}, nil]
+ end
+
+ context "within a block that accepts anonymous rest within a method that accepts anonymous rest" do
+ it "does not allow delegating rest" do
+ -> {
+ eval "def m(*); proc { |*| n(*) } end"
+ }.should.raise(SyntaxError, /anonymous rest parameter is also used within block/)
+ end
+ end
+end
+
+describe "delegation with def(**)" do
+ it "delegates kwargs" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(**)
+ target(**)
+ end
+ RUBY
+
+ a.new.delegate(a: 1) { |x| x }.should == [[], {a: 1}, nil]
+ end
+
+ context "within a block that accepts anonymous kwargs within a method that accepts anonymous kwargs" do
+ it "does not allow delegating kwargs" do
+ -> {
+ eval "def m(**); proc { |**| n(**) } end"
+ }.should.raise(SyntaxError, /anonymous keyword rest parameter is also used within block/)
+ end
+ end
+end
+
+describe "delegation with def(&)" do
+ it "delegates an anonymous block parameter" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(&)
+ target(&)
+ end
+ RUBY
+
+ block = proc {}
+ a.new.delegate(&block).should == [[], {}, block]
+ end
- a.new.delegate_block(0, 1, b: 2) { |x| x }.should == [{b: 2}, [1]]
+ context "within a block that accepts anonymous block within a method that accepts anonymous block" do
+ it "does not allow delegating a block" do
+ -> {
+ eval "def m(&); proc { |&| n(&) } end"
+ }.should.raise(SyntaxError, /anonymous block parameter is also used within block/)
end
end
end
diff --git a/spec/ruby/language/encoding_spec.rb b/spec/ruby/language/encoding_spec.rb
index 5430c9cb98..116f53a77d 100644
--- a/spec/ruby/language/encoding_spec.rb
+++ b/spec/ruby/language/encoding_spec.rb
@@ -5,7 +5,7 @@ require_relative 'fixtures/coding_utf_8'
describe "The __ENCODING__ pseudo-variable" do
it "is an instance of Encoding" do
- __ENCODING__.should be_kind_of(Encoding)
+ __ENCODING__.should.is_a?(Encoding)
end
it "is US-ASCII by default" do
@@ -13,15 +13,15 @@ describe "The __ENCODING__ pseudo-variable" do
end
it "is the evaluated strings's one inside an eval" do
- eval("__ENCODING__".force_encoding("US-ASCII")).should == Encoding::US_ASCII
- eval("__ENCODING__".force_encoding("BINARY")).should == Encoding::BINARY
+ eval("__ENCODING__".dup.force_encoding("US-ASCII")).should == Encoding::US_ASCII
+ eval("__ENCODING__".dup.force_encoding("BINARY")).should == Encoding::BINARY
end
it "is the encoding specified by a magic comment inside an eval" do
- code = "# encoding: BINARY\n__ENCODING__".force_encoding("US-ASCII")
+ code = "# encoding: BINARY\n__ENCODING__".dup.force_encoding("US-ASCII")
eval(code).should == Encoding::BINARY
- code = "# encoding: us-ascii\n__ENCODING__".force_encoding("BINARY")
+ code = "# encoding: us-ascii\n__ENCODING__".dup.force_encoding("BINARY")
eval(code).should == Encoding::US_ASCII
end
@@ -31,6 +31,6 @@ describe "The __ENCODING__ pseudo-variable" do
end
it "raises a SyntaxError if assigned to" do
- -> { eval("__ENCODING__ = 1") }.should raise_error(SyntaxError)
+ -> { eval("__ENCODING__ = 1") }.should.raise(SyntaxError)
end
end
diff --git a/spec/ruby/language/ensure_spec.rb b/spec/ruby/language/ensure_spec.rb