summaryrefslogtreecommitdiff
path: root/spec/ruby/core
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core')
-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/codepoints_spec.rb16
-rw-r--r--spec/ruby/core/argf/lines_spec.rb16
-rw-r--r--spec/ruby/core/argf/readpartial_spec.rb4
-rw-r--r--spec/ruby/core/argf/shared/getc.rb2
-rw-r--r--spec/ruby/core/argf/shared/read.rb4
-rw-r--r--spec/ruby/core/array/assoc_spec.rb12
-rw-r--r--spec/ruby/core/array/bsearch_index_spec.rb4
-rw-r--r--spec/ruby/core/array/drop_spec.rb12
-rw-r--r--spec/ruby/core/array/drop_while_spec.rb12
-rw-r--r--spec/ruby/core/array/fill_spec.rb2
-rw-r--r--spec/ruby/core/array/fixtures/encoded_strings.rb18
-rw-r--r--spec/ruby/core/array/flatten_spec.rb24
-rw-r--r--spec/ruby/core/array/multiply_spec.rb18
-rw-r--r--spec/ruby/core/array/pack/buffer_spec.rb12
-rw-r--r--spec/ruby/core/array/pack/shared/string.rb2
-rw-r--r--spec/ruby/core/array/rassoc_spec.rb14
-rw-r--r--spec/ruby/core/array/shared/inspect.rb6
-rw-r--r--spec/ruby/core/array/shared/slice.rb400
-rw-r--r--spec/ruby/core/array/slice_spec.rb60
-rw-r--r--spec/ruby/core/array/take_spec.rb12
-rw-r--r--spec/ruby/core/array/take_while_spec.rb12
-rw-r--r--spec/ruby/core/array/uniq_spec.rb12
-rw-r--r--spec/ruby/core/basicobject/instance_eval_spec.rb7
-rw-r--r--spec/ruby/core/basicobject/singleton_method_added_spec.rb8
-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.rb99
-rw-r--r--spec/ruby/core/binding/fixtures/irbrc1
-rw-r--r--spec/ruby/core/binding/irb_spec.rb15
-rw-r--r--spec/ruby/core/binding/shared/clone.rb22
-rw-r--r--spec/ruby/core/class/attached_object_spec.rb8
-rw-r--r--spec/ruby/core/class/dup_spec.rb3
-rw-r--r--spec/ruby/core/class/subclasses_spec.rb29
-rw-r--r--spec/ruby/core/complex/inspect_spec.rb6
-rw-r--r--spec/ruby/core/complex/to_r_spec.rb12
-rw-r--r--spec/ruby/core/complex/to_s_spec.rb3
-rw-r--r--spec/ruby/core/conditionvariable/broadcast_spec.rb1
-rw-r--r--spec/ruby/core/conditionvariable/marshal_dump_spec.rb1
-rw-r--r--spec/ruby/core/conditionvariable/signal_spec.rb1
-rw-r--r--spec/ruby/core/conditionvariable/wait_spec.rb1
-rw-r--r--spec/ruby/core/data/constants_spec.rb16
-rw-r--r--spec/ruby/core/data/fixtures/classes.rb2
-rw-r--r--spec/ruby/core/data/initialize_spec.rb7
-rw-r--r--spec/ruby/core/data/with_spec.rb35
-rw-r--r--spec/ruby/core/dir/children_spec.rb17
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb13
-rw-r--r--spec/ruby/core/dir/each_spec.rb11
-rw-r--r--spec/ruby/core/dir/entries_spec.rb2
-rw-r--r--spec/ruby/core/dir/exist_spec.rb8
-rw-r--r--spec/ruby/core/dir/glob_spec.rb12
-rw-r--r--spec/ruby/core/dir/home_spec.rb27
-rw-r--r--spec/ruby/core/dir/shared/chroot.rb4
-rw-r--r--spec/ruby/core/dir/shared/exist.rb8
-rw-r--r--spec/ruby/core/dir/shared/glob.rb28
-rw-r--r--spec/ruby/core/encoding/compatible_spec.rb74
-rw-r--r--spec/ruby/core/encoding/converter/convert_spec.rb15
-rw-r--r--spec/ruby/core/encoding/converter/finish_spec.rb4
-rw-r--r--spec/ruby/core/encoding/converter/last_error_spec.rb16
-rw-r--r--spec/ruby/core/encoding/converter/new_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/primitive_convert_spec.rb5
-rw-r--r--spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb1
-rw-r--r--spec/ruby/core/encoding/converter/putback_spec.rb14
-rw-r--r--spec/ruby/core/encoding/converter/replacement_spec.rb20
-rw-r--r--spec/ruby/core/encoding/default_external_spec.rb8
-rw-r--r--spec/ruby/core/encoding/inspect_spec.rb20
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb4
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb4
-rw-r--r--spec/ruby/core/encoding/replicate_spec.rb23
-rw-r--r--spec/ruby/core/enumerable/fixtures/classes.rb6
-rw-r--r--spec/ruby/core/enumerable/grep_spec.rb49
-rw-r--r--spec/ruby/core/enumerable/grep_v_spec.rb49
-rw-r--r--spec/ruby/core/enumerable/to_set_spec.rb29
-rw-r--r--spec/ruby/core/enumerator/chain/initialize_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/each_spec.rb18
-rw-r--r--spec/ruby/core/enumerator/generator/initialize_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/initialize_spec.rb12
-rw-r--r--spec/ruby/core/enumerator/lazy/initialize_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/new_spec.rb47
-rw-r--r--spec/ruby/core/enumerator/next_values_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/peek_values_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/product/each_spec.rb73
-rw-r--r--spec/ruby/core/enumerator/product/initialize_copy_spec.rb54
-rw-r--r--spec/ruby/core/enumerator/product/initialize_spec.rb33
-rw-r--r--spec/ruby/core/enumerator/product/inspect_spec.rb22
-rw-r--r--spec/ruby/core/enumerator/product/rewind_spec.rb64
-rw-r--r--spec/ruby/core/enumerator/product/size_spec.rb56
-rw-r--r--spec/ruby/core/enumerator/product_spec.rb7
-rw-r--r--spec/ruby/core/enumerator/rewind_spec.rb4
-rw-r--r--spec/ruby/core/env/delete_spec.rb16
-rw-r--r--spec/ruby/core/env/except_spec.rb44
-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/key_spec.rb32
-rw-r--r--spec/ruby/core/env/shared/include.rb7
-rw-r--r--spec/ruby/core/env/shared/key.rb31
-rw-r--r--spec/ruby/core/env/shared/value.rb7
-rw-r--r--spec/ruby/core/env/slice_spec.rb10
-rw-r--r--spec/ruby/core/env/to_a_spec.rb5
-rw-r--r--spec/ruby/core/exception/backtrace_spec.rb27
-rw-r--r--spec/ruby/core/exception/case_compare_spec.rb2
-rw-r--r--spec/ruby/core/exception/detailed_message_spec.rb12
-rw-r--r--spec/ruby/core/exception/equal_value_spec.rb14
-rw-r--r--spec/ruby/core/exception/fixtures/syntax_error.rb3
-rw-r--r--spec/ruby/core/exception/frozen_error_spec.rb16
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb89
-rw-r--r--spec/ruby/core/exception/interrupt_spec.rb2
-rw-r--r--spec/ruby/core/exception/no_method_error_spec.rb28
-rw-r--r--spec/ruby/core/exception/set_backtrace_spec.rb28
-rw-r--r--spec/ruby/core/exception/syntax_error_spec.rb27
-rw-r--r--spec/ruby/core/exception/to_s_spec.rb2
-rw-r--r--spec/ruby/core/exception/top_level_spec.rb30
-rw-r--r--spec/ruby/core/false/singleton_method_spec.rb15
-rw-r--r--spec/ruby/core/fiber/blocking_spec.rb68
-rw-r--r--spec/ruby/core/fiber/inspect_spec.rb8
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb56
-rw-r--r--spec/ruby/core/fiber/resume_spec.rb15
-rw-r--r--spec/ruby/core/fiber/storage_spec.rb88
-rw-r--r--spec/ruby/core/file/absolute_path_spec.rb2
-rw-r--r--spec/ruby/core/file/atime_spec.rb3
-rw-r--r--spec/ruby/core/file/ctime_spec.rb3
-rw-r--r--spec/ruby/core/file/exist_spec.rb8
-rw-r--r--spec/ruby/core/file/expand_path_spec.rb2
-rw-r--r--spec/ruby/core/file/flock_spec.rb4
-rw-r--r--spec/ruby/core/file/lutime_spec.rb9
-rw-r--r--spec/ruby/core/file/mtime_spec.rb3
-rw-r--r--spec/ruby/core/file/new_spec.rb24
-rw-r--r--spec/ruby/core/file/open_spec.rb22
-rw-r--r--spec/ruby/core/file/realpath_spec.rb4
-rw-r--r--spec/ruby/core/file/shared/fnmatch.rb47
-rw-r--r--spec/ruby/core/file/shared/path.rb4
-rw-r--r--spec/ruby/core/file/shared/update_time.rb105
-rw-r--r--spec/ruby/core/file/utime_spec.rb100
-rw-r--r--spec/ruby/core/filetest/exist_spec.rb8
-rw-r--r--spec/ruby/core/gc/auto_compact_spec.rb36
-rw-r--r--spec/ruby/core/hash/assoc_spec.rb6
-rw-r--r--spec/ruby/core/hash/compare_by_identity_spec.rb19
-rw-r--r--spec/ruby/core/hash/delete_spec.rb18
-rw-r--r--spec/ruby/core/hash/element_reference_spec.rb2
-rw-r--r--spec/ruby/core/hash/except_spec.rb50
-rw-r--r--spec/ruby/core/hash/hash_spec.rb2
-rw-r--r--spec/ruby/core/hash/index_spec.rb9
-rw-r--r--spec/ruby/core/hash/rehash_spec.rb30
-rw-r--r--spec/ruby/core/hash/shared/each.rb37
-rw-r--r--spec/ruby/core/hash/shared/equal.rb90
-rw-r--r--spec/ruby/core/hash/shared/store.rb8
-rw-r--r--spec/ruby/core/hash/shared/to_s.rb4
-rw-r--r--spec/ruby/core/hash/to_a_spec.rb10
-rw-r--r--spec/ruby/core/hash/to_proc_spec.rb16
-rw-r--r--spec/ruby/core/hash/transform_keys_spec.rb32
-rw-r--r--spec/ruby/core/integer/coerce_spec.rb13
-rw-r--r--spec/ruby/core/integer/div_spec.rb8
-rw-r--r--spec/ruby/core/integer/shared/arithmetic_coerce.rb20
-rw-r--r--spec/ruby/core/integer/zero_spec.rb12
-rw-r--r--spec/ruby/core/io/binread_spec.rb10
-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_read_spec.rb3
-rw-r--r--spec/ruby/core/io/close_write_spec.rb14
-rw-r--r--spec/ruby/core/io/codepoints_spec.rb38
-rw-r--r--spec/ruby/core/io/copy_stream_spec.rb33
-rw-r--r--spec/ruby/core/io/eof_spec.rb2
-rw-r--r--spec/ruby/core/io/foreach_spec.rb19
-rw-r--r--spec/ruby/core/io/getbyte_spec.rb16
-rw-r--r--spec/ruby/core/io/gets_spec.rb18
-rw-r--r--spec/ruby/core/io/initialize_spec.rb16
-rw-r--r--spec/ruby/core/io/ioctl_spec.rb2
-rw-r--r--spec/ruby/core/io/lineno_spec.rb6
-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.rb13
-rw-r--r--spec/ruby/core/io/pread_spec.rb88
-rw-r--r--spec/ruby/core/io/puts_spec.rb2
-rw-r--r--spec/ruby/core/io/pwrite_spec.rb30
-rw-r--r--spec/ruby/core/io/read_nonblock_spec.rb8
-rw-r--r--spec/ruby/core/io/read_spec.rb135
-rw-r--r--spec/ruby/core/io/readline_spec.rb12
-rw-r--r--spec/ruby/core/io/readlines_spec.rb33
-rw-r--r--spec/ruby/core/io/readpartial_spec.rb9
-rw-r--r--spec/ruby/core/io/select_spec.rb48
-rw-r--r--spec/ruby/core/io/shared/binwrite.rb12
-rw-r--r--spec/ruby/core/io/shared/each.rb20
-rw-r--r--spec/ruby/core/io/shared/new.rb55
-rw-r--r--spec/ruby/core/io/shared/readlines.rb22
-rw-r--r--spec/ruby/core/io/stat_spec.rb3
-rw-r--r--spec/ruby/core/io/sysread_spec.rb23
-rw-r--r--spec/ruby/core/io/ungetc_spec.rb16
-rw-r--r--spec/ruby/core/io/write_spec.rb67
-rw-r--r--spec/ruby/core/kernel/Float_spec.rb2
-rw-r--r--spec/ruby/core/kernel/Integer_spec.rb27
-rw-r--r--spec/ruby/core/kernel/String_spec.rb2
-rw-r--r--spec/ruby/core/kernel/__dir___spec.rb16
-rw-r--r--spec/ruby/core/kernel/caller_locations_spec.rb30
-rw-r--r--spec/ruby/core/kernel/caller_spec.rb10
-rw-r--r--spec/ruby/core/kernel/catch_spec.rb2
-rw-r--r--spec/ruby/core/kernel/class_spec.rb2
-rw-r--r--spec/ruby/core/kernel/clone_spec.rb86
-rw-r--r--spec/ruby/core/kernel/eval_spec.rb86
-rw-r--r--spec/ruby/core/kernel/exec_spec.rb4
-rw-r--r--spec/ruby/core/kernel/initialize_clone_spec.rb10
-rw-r--r--spec/ruby/core/kernel/initialize_copy_spec.rb9
-rw-r--r--spec/ruby/core/kernel/iterator_spec.rb14
-rw-r--r--spec/ruby/core/kernel/lambda_spec.rb74
-rw-r--r--spec/ruby/core/kernel/not_match_spec.rb14
-rw-r--r--spec/ruby/core/kernel/open_spec.rb78
-rw-r--r--spec/ruby/core/kernel/printf_spec.rb7
-rw-r--r--spec/ruby/core/kernel/proc_spec.rb18
-rw-r--r--spec/ruby/core/kernel/public_send_spec.rb4
-rw-r--r--spec/ruby/core/kernel/require_relative_spec.rb8
-rw-r--r--spec/ruby/core/kernel/require_spec.rb2
-rw-r--r--spec/ruby/core/kernel/shared/load.rb38
-rw-r--r--spec/ruby/core/kernel/shared/require.rb68
-rw-r--r--spec/ruby/core/kernel/shared/sprintf.rb4
-rw-r--r--spec/ruby/core/kernel/shared/sprintf_encoding.rb8
-rw-r--r--spec/ruby/core/kernel/singleton_class_spec.rb29
-rw-r--r--spec/ruby/core/kernel/sleep_spec.rb1
-rw-r--r--spec/ruby/core/kernel/sprintf_spec.rb16
-rw-r--r--spec/ruby/core/kernel/system_spec.rb17
-rw-r--r--spec/ruby/core/kernel/taint_spec.rb8
-rw-r--r--spec/ruby/core/kernel/tainted_spec.rb12
-rw-r--r--spec/ruby/core/kernel/test_spec.rb4
-rw-r--r--spec/ruby/core/kernel/trust_spec.rb10
-rw-r--r--spec/ruby/core/kernel/untaint_spec.rb10
-rw-r--r--spec/ruby/core/kernel/untrust_spec.rb8
-rw-r--r--spec/ruby/core/kernel/untrusted_spec.rb10
-rw-r--r--spec/ruby/core/kernel/warn_spec.rb141
-rw-r--r--spec/ruby/core/main/private_spec.rb12
-rw-r--r--spec/ruby/core/main/public_spec.rb12
-rw-r--r--spec/ruby/core/marshal/dump_spec.rb68
-rw-r--r--spec/ruby/core/marshal/fixtures/marshal_data.rb8
-rw-r--r--spec/ruby/core/marshal/shared/load.rb96
-rw-r--r--spec/ruby/core/matchdata/begin_spec.rb28
-rw-r--r--spec/ruby/core/matchdata/byteoffset_spec.rb4
-rw-r--r--spec/ruby/core/matchdata/element_reference_spec.rb10
-rw-r--r--spec/ruby/core/matchdata/post_match_spec.rb12
-rw-r--r--spec/ruby/core/matchdata/pre_match_spec.rb12
-rw-r--r--spec/ruby/core/matchdata/shared/captures.rb8
-rw-r--r--spec/ruby/core/matchdata/string_spec.rb5
-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.rb4
-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/dup_spec.rb15
-rw-r--r--spec/ruby/core/method/parameters_spec.rb47
-rw-r--r--spec/ruby/core/method/shared/dup.rb32
-rw-r--r--spec/ruby/core/method/shared/to_s.rb30
-rw-r--r--spec/ruby/core/method/source_location_spec.rb2
-rw-r--r--spec/ruby/core/method/super_method_spec.rb10
-rw-r--r--spec/ruby/core/method/to_proc_spec.rb2
-rw-r--r--spec/ruby/core/module/alias_method_spec.rb14
-rw-r--r--spec/ruby/core/module/attr_accessor_spec.rb19
-rw-r--r--spec/ruby/core/module/attr_reader_spec.rb17
-rw-r--r--spec/ruby/core/module/attr_spec.rb23
-rw-r--r--spec/ruby/core/module/attr_writer_spec.rb17
-rw-r--r--spec/ruby/core/module/autoload_spec.rb103
-rw-r--r--spec/ruby/core/module/const_added_spec.rb35
-rw-r--r--spec/ruby/core/module/const_get_spec.rb2
-rw-r--r--spec/ruby/core/module/const_set_spec.rb18
-rw-r--r--spec/ruby/core/module/const_source_location_spec.rb12
-rw-r--r--spec/ruby/core/module/define_method_spec.rb46
-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/module.rb4
-rw-r--r--spec/ruby/core/module/include_spec.rb28
-rw-r--r--spec/ruby/core/module/module_function_spec.rb136
-rw-r--r--spec/ruby/core/module/name_spec.rb54
-rw-r--r--spec/ruby/core/module/prepend_spec.rb131
-rw-r--r--spec/ruby/core/module/private_class_method_spec.rb14
-rw-r--r--spec/ruby/core/module/public_class_method_spec.rb20
-rw-r--r--spec/ruby/core/module/ruby2_keywords_spec.rb24
-rw-r--r--spec/ruby/core/module/set_temporary_name_spec.rb68
-rw-r--r--spec/ruby/core/module/shared/attr_added.rb34
-rw-r--r--spec/ruby/core/module/shared/class_eval.rb6
-rw-r--r--spec/ruby/core/module/shared/set_visibility.rb28
-rw-r--r--spec/ruby/core/module/undef_method_spec.rb10
-rw-r--r--spec/ruby/core/module/using_spec.rb2
-rw-r--r--spec/ruby/core/mutex/lock_spec.rb4
-rw-r--r--spec/ruby/core/mutex/owned_spec.rb18
-rw-r--r--spec/ruby/core/nil/singleton_method_spec.rb15
-rw-r--r--spec/ruby/core/numeric/clone_spec.rb10
-rw-r--r--spec/ruby/core/numeric/fdiv_spec.rb1
-rw-r--r--spec/ruby/core/numeric/quo_spec.rb1
-rw-r--r--spec/ruby/core/numeric/shared/quo.rb7
-rw-r--r--spec/ruby/core/numeric/shared/step.rb8
-rw-r--r--spec/ruby/core/numeric/step_spec.rb85
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb86
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb2
-rw-r--r--spec/ruby/core/proc/arity_spec.rb16
-rw-r--r--spec/ruby/core/proc/clone_spec.rb9
-rw-r--r--spec/ruby/core/proc/compose_spec.rb46
-rw-r--r--spec/ruby/core/proc/dup_spec.rb7
-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/proc_aref.rb1
-rw-r--r--spec/ruby/core/proc/lambda_spec.rb8
-rw-r--r--spec/ruby/core/proc/new_spec.rb35
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb43
-rw-r--r--spec/ruby/core/proc/ruby2_keywords_spec.rb22
-rw-r--r--spec/ruby/core/proc/shared/dup.rb23
-rw-r--r--spec/ruby/core/proc/shared/equal.rb17
-rw-r--r--spec/ruby/core/proc/shared/to_s.rb14
-rw-r--r--spec/ruby/core/proc/source_location_spec.rb8
-rw-r--r--spec/ruby/core/process/argv0_spec.rb2
-rw-r--r--spec/ruby/core/process/constants_spec.rb8
-rw-r--r--spec/ruby/core/process/detach_spec.rb14
-rw-r--r--spec/ruby/core/process/exec_spec.rb44
-rw-r--r--spec/ruby/core/process/fixtures/kill.rb2
-rw-r--r--spec/ruby/core/process/spawn_spec.rb2
-rw-r--r--spec/ruby/core/process/status/termsig_spec.rb2
-rw-r--r--spec/ruby/core/process/status/wait_spec.rb158
-rw-r--r--spec/ruby/core/process/times_spec.rb27
-rw-r--r--spec/ruby/core/process/waitpid_spec.rb3
-rw-r--r--spec/ruby/core/process/warmup_spec.rb11
-rw-r--r--spec/ruby/core/queue/deq_spec.rb7
-rw-r--r--spec/ruby/core/queue/pop_spec.rb7
-rw-r--r--spec/ruby/core/queue/shift_spec.rb7
-rw-r--r--spec/ruby/core/random/bytes_spec.rb1
-rw-r--r--spec/ruby/core/random/default_spec.rb24
-rw-r--r--spec/ruby/core/range/bsearch_spec.rb44
-rw-r--r--spec/ruby/core/range/cover_spec.rb4
-rw-r--r--spec/ruby/core/range/frozen_spec.rb34
-rw-r--r--spec/ruby/core/range/include_spec.rb4
-rw-r--r--spec/ruby/core/range/initialize_spec.rb15
-rw-r--r--spec/ruby/core/range/max_spec.rb18
-rw-r--r--spec/ruby/core/range/minmax_spec.rb24
-rw-r--r--spec/ruby/core/range/new_spec.rb14
-rw-r--r--spec/ruby/core/range/shared/cover_and_include.rb1
-rw-r--r--spec/ruby/core/range/size_spec.rb62
-rw-r--r--spec/ruby/core/range/step_spec.rb45
-rw-r--r--spec/ruby/core/rational/coerce_spec.rb6
-rw-r--r--spec/ruby/core/refinement/extend_object_spec.rb6
-rw-r--r--spec/ruby/core/refinement/import_methods_spec.rb4
-rw-r--r--spec/ruby/core/refinement/refined_class_spec.rb2
-rw-r--r--spec/ruby/core/regexp/initialize_spec.rb12
-rw-r--r--spec/ruby/core/regexp/shared/new.rb44
-rw-r--r--spec/ruby/core/regexp/shared/quote.rb10
-rw-r--r--spec/ruby/core/regexp/union_spec.rb51
-rw-r--r--spec/ruby/core/signal/signame_spec.rb12
-rw-r--r--spec/ruby/core/signal/trap_spec.rb31
-rw-r--r--spec/ruby/core/sizedqueue/append_spec.rb7
-rw-r--r--spec/ruby/core/sizedqueue/deq_spec.rb7
-rw-r--r--spec/ruby/core/sizedqueue/enq_spec.rb7
-rw-r--r--spec/ruby/core/sizedqueue/pop_spec.rb7
-rw-r--r--spec/ruby/core/sizedqueue/push_spec.rb7
-rw-r--r--spec/ruby/core/sizedqueue/shift_spec.rb7
-rw-r--r--spec/ruby/core/string/ascii_only_spec.rb23
-rw-r--r--spec/ruby/core/string/b_spec.rb1
-rw-r--r--spec/ruby/core/string/byteindex_spec.rb304
-rw-r--r--spec/ruby/core/string/byterindex_spec.rb359
-rw-r--r--spec/ruby/core/string/bytes_spec.rb2
-rw-r--r--spec/ruby/core/string/bytesize_spec.rb10
-rw-r--r--spec/ruby/core/string/byteslice_spec.rb8
-rw-r--r--spec/ruby/core/string/bytesplice_spec.rb1
-rw-r--r--spec/ruby/core/string/capitalize_spec.rb39
-rw-r--r--spec/ruby/core/string/center_spec.rb29
-rw-r--r--spec/ruby/core/string/chilled_string_spec.rb71
-rw-r--r--spec/ruby/core/string/chomp_spec.rb16
-rw-r--r--spec/ruby/core/string/chop_spec.rb13
-rw-r--r--spec/ruby/core/string/clear_spec.rb1
-rw-r--r--spec/ruby/core/string/codepoints_spec.rb2
-rw-r--r--spec/ruby/core/string/comparison_spec.rb8
-rw-r--r--spec/ruby/core/string/concat_spec.rb6
-rw-r--r--spec/ruby/core/string/delete_prefix_spec.rb16
-rw-r--r--spec/ruby/core/string/delete_spec.rb13
-rw-r--r--spec/ruby/core/string/delete_suffix_spec.rb16
-rw-r--r--spec/ruby/core/string/downcase_spec.rb13
-rw-r--r--spec/ruby/core/string/dump_spec.rb12
-rw-r--r--spec/ruby/core/string/dup_spec.rb2
-rw-r--r--spec/ruby/core/string/each_byte_spec.rb16
-rw-r--r--spec/ruby/core/string/each_grapheme_cluster_spec.rb10
-rw-r--r--spec/ruby/core/string/element_set_spec.rb1
-rw-r--r--spec/ruby/core/string/encode_spec.rb26
-rw-r--r--spec/ruby/core/string/encoding_spec.rb24
-rw-r--r--spec/ruby/core/string/fixtures/utf-8-encoding.rb7
-rw-r--r--spec/ruby/core/string/force_encoding_spec.rb1
-rw-r--r--spec/ruby/core/string/freeze_spec.rb1
-rw-r--r--spec/ruby/core/string/gsub_spec.rb22
-rw-r--r--spec/ruby/core/string/include_spec.rb12
-rw-r--r--spec/ruby/core/string/index_spec.rb33
-rw-r--r--spec/ruby/core/string/insert_spec.rb2
-rw-r--r--spec/ruby/core/string/inspect_spec.rb2
-rw-r--r--spec/ruby/core/string/ljust_spec.rb29
-rw-r--r--spec/ruby/core/string/lstrip_spec.rb19
-rw-r--r--spec/ruby/core/string/modulo_spec.rb65
-rw-r--r--spec/ruby/core/string/ord_spec.rb2
-rw-r--r--spec/ruby/core/string/partition_spec.rb4
-rw-r--r--spec/ruby/core/string/prepend_spec.rb1
-rw-r--r--spec/ruby/core/string/reverse_spec.rb19
-rw-r--r--spec/ruby/core/string/rindex_spec.rb14
-rw-r--r--spec/ruby/core/string/rjust_spec.rb29
-rw-r--r--spec/ruby/core/string/rpartition_spec.rb4
-rw-r--r--spec/ruby/core/string/rstrip_spec.rb11
-rw-r--r--spec/ruby/core/string/scan_spec.rb10
-rw-r--r--spec/ruby/core/string/scrub_spec.rb37
-rw-r--r--spec/ruby/core/string/setbyte_spec.rb1
-rw-r--r--spec/ruby/core/string/shared/byte_index_common.rb63
-rw-r--r--spec/ruby/core/string/shared/chars.rb12
-rw-r--r--spec/ruby/core/string/shared/codepoints.rb6
-rw-r--r--spec/ruby/core/string/shared/concat.rb1
-rw-r--r--spec/ruby/core/string/shared/dedup.rb9
-rw-r--r--spec/ruby/core/string/shared/each_codepoint_without_block.rb4
-rw-r--r--spec/ruby/core/string/shared/each_line.rb20
-rw-r--r--spec/ruby/core/string/shared/encode.rb1
-rw-r--r--spec/ruby/core/string/shared/eql.rb8
-rw-r--r--spec/ruby/core/string/shared/length.rb10
-rw-r--r--spec/ruby/core/string/shared/partition.rb34
-rw-r--r--spec/ruby/core/string/shared/replace.rb1
-rw-r--r--spec/ruby/core/string/shared/slice.rb118
-rw-r--r--spec/ruby/core/string/shared/strip.rb18
-rw-r--r--spec/ruby/core/string/shared/succ.rb19
-rw-r--r--spec/ruby/core/string/shared/to_a.rb9
-rw-r--r--spec/ruby/core/string/shared/to_sym.rb4
-rw-r--r--spec/ruby/core/string/slice_spec.rb95
-rw-r--r--spec/ruby/core/string/split_spec.rb120
-rw-r--r--spec/ruby/core/string/squeeze_spec.rb13
-rw-r--r--spec/ruby/core/string/start_with_spec.rb17
-rw-r--r--spec/ruby/core/string/strip_spec.rb17
-rw-r--r--spec/ruby/core/string/sub_spec.rb22
-rw-r--r--spec/ruby/core/string/swapcase_spec.rb16
-rw-r--r--spec/ruby/core/string/to_i_spec.rb12
-rw-r--r--spec/ruby/core/string/tr_s_spec.rb22
-rw-r--r--spec/ruby/core/string/tr_spec.rb22
-rw-r--r--spec/ruby/core/string/unicode_normalize_spec.rb1
-rw-r--r--spec/ruby/core/string/unicode_normalized_spec.rb1
-rw-r--r--spec/ruby/core/string/unpack/a_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/b_spec.rb4
-rw-r--r--spec/ruby/core/string/unpack/u_spec.rb2
-rw-r--r--spec/ruby/core/string/upcase_spec.rb13
-rw-r--r--spec/ruby/core/string/uplus_spec.rb4
-rw-r--r--spec/ruby/core/string/upto_spec.rb6
-rw-r--r--spec/ruby/core/string/valid_encoding_spec.rb30
-rw-r--r--spec/ruby/core/struct/constants_spec.rb15
-rw-r--r--spec/ruby/core/struct/new_spec.rb2
-rw-r--r--spec/ruby/core/symbol/name_spec.rb24
-rw-r--r--spec/ruby/core/symbol/to_proc_spec.rb47
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/label_spec.rb10
-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_locations_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace_spec.rb2
-rw-r--r--spec/ruby/core/thread/each_caller_location_spec.rb49
-rw-r--r--spec/ruby/core/thread/exclusive_spec.rb49
-rw-r--r--spec/ruby/core/thread/fetch_spec.rb30
-rw-r--r--spec/ruby/core/thread/ignore_deadlock_spec.rb26
-rw-r--r--spec/ruby/core/thread/native_thread_id_spec.rb9
-rw-r--r--spec/ruby/core/thread/report_on_exception_spec.rb50
-rw-r--r--spec/ruby/core/thread/thread_variable_get_spec.rb2
-rw-r--r--spec/ruby/core/time/_load_spec.rb3
-rw-r--r--spec/ruby/core/time/at_spec.rb9
-rw-r--r--spec/ruby/core/time/deconstruct_keys_spec.rb5
-rw-r--r--spec/ruby/core/time/fixtures/classes.rb1
-rw-r--r--spec/ruby/core/time/new_spec.rb24
-rw-r--r--spec/ruby/core/time/succ_spec.rb40
-rw-r--r--spec/ruby/core/tracepoint/enable_spec.rb8
-rw-r--r--spec/ruby/core/tracepoint/inspect_spec.rb14
-rw-r--r--spec/ruby/core/tracepoint/path_spec.rb31
-rw-r--r--spec/ruby/core/true/singleton_method_spec.rb15
-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/shared/dup.rb32
-rw-r--r--spec/ruby/core/unboundmethod/source_location_spec.rb2
-rw-r--r--spec/ruby/core/unboundmethod/super_method_spec.rb10
-rw-r--r--spec/ruby/core/warning/element_reference_spec.rb12
-rw-r--r--spec/ruby/core/warning/element_set_spec.rb20
-rw-r--r--spec/ruby/core/warning/performance_warning_spec.rb28
-rw-r--r--spec/ruby/core/warning/warn_spec.rb145
471 files changed, 6294 insertions, 4423 deletions
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/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/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/readpartial_spec.rb b/spec/ruby/core/argf/readpartial_spec.rb
index 5e284b3423..ea4301f25c 100644
--- a/spec/ruby/core/argf/readpartial_spec.rb
+++ b/spec/ruby/core/argf/readpartial_spec.rb
@@ -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
@@ -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/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/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/array/assoc_spec.rb b/spec/ruby/core/array/assoc_spec.rb
index af95528281..f0be3de795 100644
--- a/spec/ruby/core/array/assoc_spec.rb
+++ b/spec/ruby/core/array/assoc_spec.rb
@@ -37,4 +37,16 @@ describe "Array#assoc" do
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/bsearch_index_spec.rb b/spec/ruby/core/array/bsearch_index_spec.rb
index df2c7c098e..94d85b37f3 100644
--- a/spec/ruby/core/array/bsearch_index_spec.rb
+++ b/spec/ruby/core/array/bsearch_index_spec.rb
@@ -63,10 +63,6 @@ describe "Array#bsearch_index" do
@array.bsearch_index { |x| -1 }.should be_nil
end
- it "returns the middle element when block always returns zero" do
- @array.bsearch_index { |x| 0 }.should == 2
- end
-
context "magnitude does not effect the result" do
it "returns the index of any matched elements where element is between 4n <= xn < 8n" do
[1, 2].should include(@array.bsearch_index { |x| (1 - x / 4) * (2**100) })
diff --git a/spec/ruby/core/array/drop_spec.rb b/spec/ruby/core/array/drop_spec.rb
index f911fd9018..0ea748e47d 100644
--- a/spec/ruby/core/array/drop_spec.rb
+++ b/spec/ruby/core/array/drop_spec.rb
@@ -50,15 +50,7 @@ describe "Array#drop" do
-> { [1, 2].drop(obj) }.should raise_error(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 be_an_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 94064528aa..bd46e8b882 100644
--- a/spec/ruby/core/array/drop_while_spec.rb
+++ b/spec/ruby/core/array/drop_while_spec.rb
@@ -18,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 be_an_instance_of(Array)
end
end
diff --git a/spec/ruby/core/array/fill_spec.rb b/spec/ruby/core/array/fill_spec.rb
index 02360e550d..2c3b5d9e84 100644
--- a/spec/ruby/core/array/fill_spec.rb
+++ b/spec/ruby/core/array/fill_spec.rb
@@ -21,7 +21,7 @@ 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]
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..8c97000c79 100644
--- a/spec/ruby/core/array/flatten_spec.rb
+++ b/spec/ruby/core/array/flatten_spec.rb
@@ -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 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 "is not destructive" do
diff --git a/spec/ruby/core/array/multiply_spec.rb b/spec/ruby/core/array/multiply_spec.rb
index 23d5c99f3a..eca51142fb 100644
--- a/spec/ruby/core/array/multiply_spec.rb
+++ b/spec/ruby/core/array/multiply_spec.rb
@@ -76,20 +76,10 @@ 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 be_an_instance_of(Array)
+ (@array * 1).should be_an_instance_of(Array)
+ (@array * 2).should be_an_instance_of(Array)
end
it "does not call #initialize on the subclass instance" do
diff --git a/spec/ruby/core/array/pack/buffer_spec.rb b/spec/ruby/core/array/pack/buffer_spec.rb
index ecb40bfd06..f1206efb3e 100644
--- a/spec/ruby/core/array/pack/buffer_spec.rb
+++ b/spec/ruby/core/array/pack/buffer_spec.rb
@@ -13,13 +13,13 @@ describe "Array#pack with :buffer option" do
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
@@ -31,19 +31,19 @@ describe "Array#pack with :buffer option" do
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/shared/string.rb b/spec/ruby/core/array/pack/shared/string.rb
index 8c82e8c617..2f70dc3951 100644
--- a/spec/ruby/core/array/pack/shared/string.rb
+++ b/spec/ruby/core/array/pack/shared/string.rb
@@ -40,7 +40,7 @@ describe :array_pack_string, shared: true 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/rassoc_spec.rb b/spec/ruby/core/array/rassoc_spec.rb
index 62fbd40611..632a05e8b3 100644
--- a/spec/ruby/core/array/rassoc_spec.rb
+++ b/spec/ruby/core/array/rassoc_spec.rb
@@ -35,4 +35,18 @@ describe "Array#rassoc" do
[[1, :foobar, o], [2, o, 1], [3, mock('foo')]].rassoc(key).should == [2, o, 1]
end
+
+ ruby_version_is "3.3" do
+ 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
end
diff --git a/spec/ruby/core/array/shared/inspect.rb b/spec/ruby/core/array/shared/inspect.rb
index a2b43d4959..af5128c645 100644
--- a/spec/ruby/core/array/shared/inspect.rb
+++ b/spec/ruby/core/array/shared/inspect.rb
@@ -19,7 +19,7 @@ describe :array_inspect, shared: true do
end
it "does not call #to_s on a String returned from #inspect" do
- str = "abc"
+ str = +"abc"
str.should_not_receive(:to_s)
[str].send(@method).should == '["abc"]'
@@ -98,8 +98,8 @@ describe :array_inspect, shared: true do
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 = 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
diff --git a/spec/ruby/core/array/shared/slice.rb b/spec/ruby/core/array/shared/slice.rb
index 8fb33738b9..d2866970a5 100644
--- a/spec/ruby/core/array/shared/slice.rb
+++ b/spec/ruby/core/array/shared/slice.rb
@@ -397,56 +397,28 @@ describe :array_slice, shared: true 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.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
+ it "returns a Array instance with [n, m]" do
+ @array.send(@method, 0, 2).should be_an_instance_of(Array)
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, -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, 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
- 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
it "returns an empty array when m == n with [m...n]" do
@@ -534,239 +506,237 @@ describe :array_slice, shared: true do
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
+ 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]
+ 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("(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
+ @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 == []
+ 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(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 == []
+ @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]
+ # 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(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]
+ @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]
+ # 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(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
+ @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]
+ 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("(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
+ @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 == []
+ 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(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 == []
+ @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]
+ # 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(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]
+ @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]
+ # 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(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]
+ @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]
+ # 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(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]
+ @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]
+ # 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(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
+ @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 == []
+ 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(-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 == []
+ @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 == []
+ # 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(-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 == []
+ @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 == []
+ # 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(-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 == []
+ @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 == []
+ # 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(-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 == []
+ @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 == []
+ # 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(-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
+ @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 == []
+ 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(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 == []
+ @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 == []
+ # 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(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 == []
+ @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 == []
+ # 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(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 == []
+ @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 == []
+ # 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(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
+ @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)
+ 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)
+ # 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
+ # 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
+ 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
+ @array.send(@method, eval("(6..).step(2)")).should == []
+ -> { @array.send(@method, eval("(7..).step(2)")) }.should raise_error(RangeError)
end
end
diff --git a/spec/ruby/core/array/slice_spec.rb b/spec/ruby/core/array/slice_spec.rb
index 8e1499855a..731c129251 100644
--- a/spec/ruby/core/array/slice_spec.rb
+++ b/spec/ruby/core/array/slice_spec.rb
@@ -187,56 +187,28 @@ 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 be_an_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 be_an_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 be_an_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 be_an_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 be_an_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 be_an_instance_of(Array)
end
end
end
diff --git a/spec/ruby/core/array/take_spec.rb b/spec/ruby/core/array/take_spec.rb
index 4fb6f0ce75..c4f0ac9aa4 100644
--- a/spec/ruby/core/array/take_spec.rb
+++ b/spec/ruby/core/array/take_spec.rb
@@ -26,15 +26,7 @@ describe "Array#take" do
->{ [1].take(-3) }.should raise_error(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 be_an_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 73f25493c8..8f50260b42 100644
--- a/spec/ruby/core/array/take_while_spec.rb
+++ b/spec/ruby/core/array/take_while_spec.rb
@@ -15,16 +15,8 @@ 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
- 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
+ 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
diff --git a/spec/ruby/core/array/uniq_spec.rb b/spec/ruby/core/array/uniq_spec.rb
index 905ab59634..d5d826db15 100644
--- a/spec/ruby/core/array/uniq_spec.rb
+++ b/spec/ruby/core/array/uniq_spec.rb
@@ -85,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 be_an_instance_of(Array)
end
it "properly handles an identical item even when its #eql? isn't reflexive" do
diff --git a/spec/ruby/core/basicobject/instance_eval_spec.rb b/spec/ruby/core/basicobject/instance_eval_spec.rb
index 699c965171..1f3a43f341 100644
--- a/spec/ruby/core/basicobject/instance_eval_spec.rb
+++ b/spec/ruby/core/basicobject/instance_eval_spec.rb
@@ -84,6 +84,13 @@ describe "BasicObject#instance_eval" do
end
+ ruby_version_is "3.3" do
+ it "uses the caller location as default location" do
+ f = Object.new
+ f.instance_eval("[__FILE__, __LINE__]").should == ["(eval at #{__FILE__}:#{__LINE__})", 1]
+ end
+ 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
diff --git a/spec/ruby/core/basicobject/singleton_method_added_spec.rb b/spec/ruby/core/basicobject/singleton_method_added_spec.rb
index ab6b2a2d10..fc65a091aa 100644
--- a/spec/ruby/core/basicobject/singleton_method_added_spec.rb
+++ b/spec/ruby/core/basicobject/singleton_method_added_spec.rb
@@ -94,7 +94,7 @@ describe "BasicObject#singleton_method_added" do
-> {
def self.foo
end
- }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for/)
+ }.should raise_error(NoMethodError, /undefined method [`']singleton_method_added' for/)
end
end
@@ -106,16 +106,16 @@ describe "BasicObject#singleton_method_added" do
-> {
def foo
end
- }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for #<Object:/)
+ }.should raise_error(NoMethodError, /undefined method [`']singleton_method_added' for #<Object:/)
-> {
define_method(:bar) {}
- }.should raise_error(NoMethodError, /undefined method `singleton_method_added' for #<Object:/)
+ }.should raise_error(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_error(NoMethodError, /undefined method [`']singleton_method_added' for #<Object:/)
end
it "calls #method_missing" 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..4eff66bd9a 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_error(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..bb2036f739 100644
--- a/spec/ruby/core/binding/eval_spec.rb
+++ b/spec/ruby/core/binding/eval_spec.rb
@@ -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,18 @@ 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
+ ruby_version_is ""..."3.3" 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
+ 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 +106,10 @@ describe "Binding#eval" do
bind.eval("'bar'.foo").should == "foo"
end
+
+ ruby_version_is "3.3" do
+ it "uses the caller location as default filename" do
+ binding.eval("[__FILE__, __LINE__]").should == ["(eval at #{__FILE__}:#{__LINE__})", 1]
+ end
+ end
end
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
index b3bc274f78..2607c7ef33 100644
--- a/spec/ruby/core/binding/irb_spec.rb
+++ b/spec/ruby/core/binding/irb_spec.rb
@@ -1,16 +1,19 @@
require_relative '../../spec_helper'
+require 'tmpdir'
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"
+ envs = %w[IRBRC HOME XDG_CONFIG_HOME].to_h {|e| [e, nil]}
- out = IO.popen([{"IRBRC"=>irbrc_fixture}, *ruby_exe, irb_fixture], "r+") do |pipe|
- pipe.puts "a ** 2"
- pipe.puts "exit"
- pipe.readlines.map(&:chomp)
+ out = Dir.mktmpdir do |dir|
+ IO.popen([envs, *ruby_exe, irb_fixture, chdir: dir], "r+") do |pipe|
+ pipe.puts "a ** 2"
+ pipe.puts "exit"
+ pipe.readlines.map(&:chomp).reject(&:empty?)
+ end
end
- out[-3..-1].should == ["a ** 2", "100", "exit"]
+ out.last(3).should == ["a ** 2", "100", "exit"]
end
end
diff --git a/spec/ruby/core/binding/shared/clone.rb b/spec/ruby/core/binding/shared/clone.rb
index 0e934ac1b5..1224b8ec7d 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/class/attached_object_spec.rb b/spec/ruby/core/class/attached_object_spec.rb
index 115d5fa563..f1c0f63a44 100644
--- a/spec/ruby/core/class/attached_object_spec.rb
+++ b/spec/ruby/core/class/attached_object_spec.rb
@@ -19,13 +19,13 @@ ruby_version_is '3.2' do
it "raises TypeError if the class is not a singleton class" do
a = Class.new
- -> { a.attached_object }.should raise_error(TypeError)
+ -> { a.attached_object }.should raise_error(TypeError, /is not a singleton class/)
end
it "raises TypeError for special singleton classes" do
- -> { nil.singleton_class.attached_object }.should raise_error(TypeError)
- -> { true.singleton_class.attached_object }.should raise_error(TypeError)
- -> { false.singleton_class.attached_object }.should raise_error(TypeError)
+ -> { nil.singleton_class.attached_object }.should raise_error(TypeError, /[`']NilClass' is not a singleton class/)
+ -> { true.singleton_class.attached_object }.should raise_error(TypeError, /[`']TrueClass' is not a singleton class/)
+ -> { false.singleton_class.attached_object }.should raise_error(TypeError, /[`']FalseClass' is not a singleton class/)
end
end
end
diff --git a/spec/ruby/core/class/dup_spec.rb b/spec/ruby/core/class/dup_spec.rb
index 701fd72e19..c09ed71b31 100644
--- a/spec/ruby/core/class/dup_spec.rb
+++ b/spec/ruby/core/class/dup_spec.rb
@@ -61,4 +61,7 @@ describe "Class#dup" do
CoreClassSpecs::RecordCopy.name.should == "CoreClassSpecs::RecordCopy"
end
+ it "raises TypeError if called on BasicObject" do
+ -> { BasicObject.dup }.should raise_error(TypeError, "can't copy the root class")
+ end
end
diff --git a/spec/ruby/core/class/subclasses_spec.rb b/spec/ruby/core/class/subclasses_spec.rb
index a16b934d4f..50eb5358d9 100644
--- a/spec/ruby/core/class/subclasses_spec.rb
+++ b/spec/ruby/core/class/subclasses_spec.rb
@@ -7,7 +7,7 @@ ruby_version_is '3.1' do
assert_subclasses(ModuleSpecs::Parent, [ModuleSpecs::Child, ModuleSpecs::Child2])
end
- it "does not return included modules" do
+ it "does not return included modules from the parent" do
parent = Class.new
child = Class.new(parent)
mod = Module.new
@@ -16,6 +16,33 @@ ruby_version_is '3.1' do
assert_subclasses(parent, [child])
end
+ it "does not return included modules from the child" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.include(mod)
+
+ assert_subclasses(parent, [child])
+ 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 "does not return singleton classes" do
a = Class.new
diff --git a/spec/ruby/core/complex/inspect_spec.rb b/spec/ruby/core/complex/inspect_spec.rb
index 7a89ec6854..045be94b22 100644
--- a/spec/ruby/core/complex/inspect_spec.rb
+++ b/spec/ruby/core/complex/inspect_spec.rb
@@ -17,7 +17,8 @@ describe "Complex#inspect" do
it "calls #inspect on real and imaginary" do
real = NumericSpecs::Subclass.new
- real.should_receive(:inspect).and_return("1")
+ # + 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)
@@ -26,7 +27,8 @@ describe "Complex#inspect" do
it "adds an `*' before the `i' if the last character of the imaginary part is not numeric" do
real = NumericSpecs::Subclass.new
- real.should_receive(:inspect).and_return("(1)")
+ # + 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)
diff --git a/spec/ruby/core/complex/to_r_spec.rb b/spec/ruby/core/complex/to_r_spec.rb
index 4559921492..788027a500 100644
--- a/spec/ruby/core/complex/to_r_spec.rb
+++ b/spec/ruby/core/complex/to_r_spec.rb
@@ -34,8 +34,16 @@ describe "Complex#to_r" do
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_error(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 7677dcd0b5..ceccffe470 100644
--- a/spec/ruby/core/complex/to_s_spec.rb
+++ b/spec/ruby/core/complex/to_s_spec.rb
@@ -45,7 +45,8 @@ describe "Complex#to_s" do
it "treats real and imaginary parts as strings" do
real = NumericSpecs::Subclass.new
- real.should_receive(:to_s).and_return("1")
+ # + 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)
diff --git a/spec/ruby/core/conditionvariable/broadcast_spec.rb b/spec/ruby/core/conditionvariable/broadcast_spec.rb
index d88159df23..55a7b89c72 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
diff --git a/spec/ruby/core/conditionvariable/marshal_dump_spec.rb b/spec/ruby/core/conditionvariable/marshal_dump_spec.rb
index f951a13e28..88b1cc38c1 100644
--- a/spec/ruby/core/conditionvariable/marshal_dump_spec.rb
+++ b/spec/ruby/core/conditionvariable/marshal_dump_spec.rb
@@ -1,5 +1,4 @@
require_relative '../../spec_helper'
-require 'thread'
describe "ConditionVariable#marshal_dump" do
it "raises a TypeError" do
diff --git a/spec/ruby/core/conditionvariable/signal_spec.rb b/spec/ruby/core/conditionvariable/signal_spec.rb
index 86383073f1..43a9cc611b 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
diff --git a/spec/ruby/core/conditionvariable/wait_spec.rb b/spec/ruby/core/conditionvariable/wait_spec.rb
index 9a68c2b5a1..fe73e513c0 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
diff --git a/spec/ruby/core/data/constants_spec.rb b/spec/ruby/core/data/constants_spec.rb
index d9d55b50f9..2eb43d501e 100644
--- a/spec/ruby/core/data/constants_spec.rb
+++ b/spec/ruby/core/data/constants_spec.rb
@@ -1,20 +1,6 @@
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
- end
-end
-
-ruby_version_is '3.0'...'3.2' do
+ruby_version_is ''...'3.2' do
describe "Data" do
it "does not exist anymore" do
Object.should_not have_constant(:Data)
diff --git a/spec/ruby/core/data/fixtures/classes.rb b/spec/ruby/core/data/fixtures/classes.rb
index d1e10e02ed..46a6b48bb2 100644
--- a/spec/ruby/core/data/fixtures/classes.rb
+++ b/spec/ruby/core/data/fixtures/classes.rb
@@ -1,5 +1,5 @@
module DataSpecs
- ruby_version_is "3.2" do
+ guard -> { ruby_version_is "3.2" and Data.respond_to?(:define) } do
Measure = Data.define(:amount, :unit)
end
end
diff --git a/spec/ruby/core/data/initialize_spec.rb b/spec/ruby/core/data/initialize_spec.rb
index 94470cd108..2c36bd3ac4 100644
--- a/spec/ruby/core/data/initialize_spec.rb
+++ b/spec/ruby/core/data/initialize_spec.rb
@@ -31,6 +31,13 @@ ruby_version_is "3.2" do
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 "raises ArgumentError if no arguments are given" do
-> {
DataSpecs::Measure.new
diff --git a/spec/ruby/core/data/with_spec.rb b/spec/ruby/core/data/with_spec.rb
new file mode 100644
index 0000000000..97e34c951f
--- /dev/null
+++ b/spec/ruby/core/data/with_spec.rb
@@ -0,0 +1,35 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.2" do
+ 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_error(ArgumentError, "wrong number of arguments (given 2, expected 0)")
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/children_spec.rb b/spec/ruby/core/dir/children_spec.rb
index 03698cc246..0ad3df4669 100644
--- a/spec/ruby/core/dir/children_spec.rb
+++ b/spec/ruby/core/dir/children_spec.rb
@@ -47,7 +47,7 @@ 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"))
end
@@ -113,7 +113,7 @@ 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"))
end
@@ -131,4 +131,17 @@ describe "Dir#children" do
children = @dir.children.sort
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/each_child_spec.rb b/spec/ruby/core/dir/each_child_spec.rb
index 520186e79e..7194273b95 100644
--- a/spec/ruby/core/dir/each_child_spec.rb
+++ b/spec/ruby/core/dir/each_child_spec.rb
@@ -86,6 +86,19 @@ 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)
diff --git a/spec/ruby/core/dir/each_spec.rb b/spec/ruby/core/dir/each_spec.rb
index 8c69a7212b..7674663d82 100644
--- a/spec/ruby/core/dir/each_spec.rb
+++ b/spec/ruby/core/dir/each_spec.rb
@@ -35,6 +35,17 @@ describe "Dir#each" do
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)
diff --git a/spec/ruby/core/dir/entries_spec.rb b/spec/ruby/core/dir/entries_spec.rb
index 91c30fccae..7462542acf 100644
--- a/spec/ruby/core/dir/entries_spec.rb
+++ b/spec/ruby/core/dir/entries_spec.rb
@@ -47,7 +47,7 @@ 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"))
end
diff --git a/spec/ruby/core/dir/exist_spec.rb b/spec/ruby/core/dir/exist_spec.rb
index 43987b0f32..9023de533f 100644
--- a/spec/ruby/core/dir/exist_spec.rb
+++ b/spec/ruby/core/dir/exist_spec.rb
@@ -13,3 +13,11 @@ describe "Dir.exist?" do
it_behaves_like :dir_exist, :exist?
end
+
+ruby_version_is "3.2" do
+ describe "Dir.exists?" do
+ it "has been removed" do
+ Dir.should_not.respond_to?(:exists?)
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/glob_spec.rb b/spec/ruby/core/dir/glob_spec.rb
index 72d6337e15..32f515c81d 100644
--- a/spec/ruby/core/dir/glob_spec.rb
+++ b/spec/ruby/core/dir/glob_spec.rb
@@ -106,11 +106,11 @@ describe "Dir.glob" do
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
- ]
+ nested/.
+ nested/.dotsubir
+ nested/.dotsubir/.dotfile
+ nested/.dotsubir/nondotfile
+ ]
Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort
end
@@ -260,7 +260,7 @@ describe "Dir.glob" do
Dir.glob('**/.*', base: "deeply/nested").sort.should == expected
end
- # 2.7 and 3.0 include a "." entry for every dir: ["directory/.", "directory/structure/.", ...]
+ # < 3.1 include a "." entry for every dir: ["directory/.", "directory/structure/.", ...]
ruby_version_is '3.1' do
it "handles **/.* with base keyword argument and FNM_DOTMATCH" do
expected = %w[
diff --git a/spec/ruby/core/dir/home_spec.rb b/spec/ruby/core/dir/home_spec.rb
index 90a008faf1..3cf745ab46 100644
--- a/spec/ruby/core/dir/home_spec.rb
+++ b/spec/ruby/core/dir/home_spec.rb
@@ -40,22 +40,21 @@ describe "Dir.home" do
home.should == "C:/rubyspäc/home"
home.encoding.should == Encoding::UTF_8
end
- 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')]
+ 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"
- # https://bugs.ruby-lang.org/issues/19244
- # 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
+ 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
end
diff --git a/spec/ruby/core/dir/shared/chroot.rb b/spec/ruby/core/dir/shared/chroot.rb
index 8c0599fe3f..a8f7c10a19 100644
--- a/spec/ruby/core/dir/shared/chroot.rb
+++ b/spec/ruby/core/dir/shared/chroot.rb
@@ -2,7 +2,7 @@ describe :dir_chroot_as_root, shared: true do
before :all do
DirSpecs.create_mock_dirs
- @real_root = "../" * (File.dirname(__FILE__).count('/') - 1)
+ @real_root = "../" * (__dir__.count('/') - 1)
@ref_dir = File.join("/", File.basename(Dir["/*"].first))
end
@@ -18,7 +18,7 @@ describe :dir_chroot_as_root, shared: true do
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_error
File.should.exist?("/#{File.basename(__FILE__)}")
end unless compilations_ci
diff --git a/spec/ruby/core/dir/shared/exist.rb b/spec/ruby/core/dir/shared/exist.rb
index 765d1b656c..2ea4f88a80 100644
--- a/spec/ruby/core/dir/shared/exist.rb
+++ b/spec/ruby/core/dir/shared/exist.rb
@@ -1,6 +1,6 @@
describe :dir_exist, shared: true do
it "returns true if the given directory exists" do
- Dir.send(@method, File.dirname(__FILE__)).should be_true
+ Dir.send(@method, __dir__).should be_true
end
it "returns true for '.'" do
@@ -20,7 +20,7 @@ describe :dir_exist, shared: true do
end
it "understands relative paths" do
- Dir.send(@method, File.dirname(__FILE__) + '/../').should be_true
+ Dir.send(@method, __dir__ + '/../').should be_true
end
it "returns false if the given directory doesn't exist" do
@@ -28,7 +28,7 @@ describe :dir_exist, shared: true do
end
it "doesn't require the name to have a trailing slash" do
- dir = File.dirname(__FILE__)
+ dir = __dir__
dir.sub!(/\/$/,'')
Dir.send(@method, dir).should be_true
end
@@ -50,7 +50,7 @@ describe :dir_exist, shared: true do
it "calls #to_path on non String arguments" do
p = mock('path')
- p.should_receive(:to_path).and_return(File.dirname(__FILE__))
+ p.should_receive(:to_path).and_return(__dir__)
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 33b2828c27..745f02d46b 100644
--- a/spec/ruby/core/dir/shared/glob.rb
+++ b/spec/ruby/core/dir/shared/glob.rb
@@ -12,7 +12,7 @@ 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
+ pattern = "file*".dup.force_encoding Encoding::UTF_16BE
-> { Dir.send(@method, pattern) }.should raise_error(Encoding::CompatibilityError)
end
@@ -27,24 +27,22 @@ describe :dir_glob, shared: true do
-> {Dir.send(@method, "file_o*\0file_t*")}.should raise_error 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 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 "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 "sort: false returns same files" do
+ result = Dir.send(@method,'*', sort: false)
+ result.sort.should == Dir.send(@method, '*').sort
end
- ruby_version_is "3.0"..."3.1" do
+ ruby_version_is ""..."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
diff --git a/spec/ruby/core/encoding/compatible_spec.rb b/spec/ruby/core/encoding/compatible_spec.rb
index 80ecab6155..f18d8680a9 100644
--- a/spec/ruby/core/encoding/compatible_spec.rb
+++ b/spec/ruby/core/encoding/compatible_spec.rb
@@ -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,28 +33,28 @@ 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")
+ a = "abc".dup.force_encoding("UTF-8")
+ b = "1234".dup.force_encoding("UTF-16LE")
Encoding.compatible?(a, b).should be_nil
end
end
@@ -75,7 +75,7 @@ describe "Encoding.compatible? String, String" do
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
@@ -91,14 +91,14 @@ describe "Encoding.compatible? String, String" do
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
@@ -114,11 +114,11 @@ describe "Encoding.compatible? String, String" do
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".dup.force_encoding("utf-16be")).should be_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".dup.force_encoding("utf-16be")).should be_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,7 +154,7 @@ 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
@@ -165,7 +165,7 @@ 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 +180,15 @@ 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
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,8 +203,8 @@ 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
@@ -221,8 +221,8 @@ describe "Encoding.compatible? String, Encoding" do
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
@@ -242,7 +242,7 @@ 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
@@ -256,8 +256,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 +270,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 +291,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 +310,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
diff --git a/spec/ruby/core/encoding/converter/convert_spec.rb b/spec/ruby/core/encoding/converter/convert_spec.rb
index 95a9e0b758..7f249d90a3 100644
--- a/spec/ruby/core/encoding/converter/convert_spec.rb
+++ b/spec/ruby/core/encoding/converter/convert_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: binary -*-
+# frozen_string_literal: true
require_relative '../../../spec_helper'
describe "Encoding::Converter#convert" do
@@ -9,31 +10,31 @@ describe "Encoding::Converter#convert" do
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 \
+ -> { ec.convert("\u{6543}".dup.force_encoding('UTF-8')) }.should \
raise_error(Encoding::UndefinedConversionError)
end
diff --git a/spec/ruby/core/encoding/converter/finish_spec.rb b/spec/ruby/core/encoding/converter/finish_spec.rb
index 11ca7e8510..239243430b 100644
--- a/spec/ruby/core/encoding/converter/finish_spec.rb
+++ b/spec/ruby/core/encoding/converter/finish_spec.rb
@@ -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..78779be70b 100644
--- a/spec/ruby/core/encoding/converter/last_error_spec.rb
+++ b/spec/ruby/core/encoding/converter/last_error_spec.rb
@@ -9,45 +9,45 @@ describe "Encoding::Converter#last_error" do
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.convert('a'.dup.force_encoding('ascii'))
ec.last_error.should be_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
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.primitive_convert("glark".dup.force_encoding('utf-8'), +"").should == :finished
ec.last_error.should be_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.primitive_convert(+"\xf1abcd", +"").should == :invalid_byte_sequence
+ ec.primitive_convert("glark".dup.force_encoding('utf-8'), +"").should == :finished
ec.last_error.should be_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.primitive_convert(+"\xf1abcd", +"").should == :invalid_byte_sequence
ec.last_error.should be_an_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.primitive_convert(+"\u{9876}", +"").should == :undefined_conversion
ec.last_error.should be_an_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.primitive_convert(+"\xa4", +"", nil, 10).should == :incomplete_input
ec.last_error.should be_an_instance_of(Encoding::InvalidByteSequenceError)
end
diff --git a/spec/ruby/core/encoding/converter/new_spec.rb b/spec/ruby/core/encoding/converter/new_spec.rb
index 1f7affc72b..db9c3364d7 100644
--- a/spec/ruby/core/encoding/converter/new_spec.rb
+++ b/spec/ruby/core/encoding/converter/new_spec.rb
@@ -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..63f25eddef 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 -*-
+# frozen_string_literal: false
require_relative '../../../spec_helper'
describe "Encoding::Converter#primitive_convert" do
@@ -14,6 +15,10 @@ describe "Encoding::Converter#primitive_convert" do
-> { @ec.primitive_convert("","") }.should_not raise_error
end
+ it "raises FrozenError when the destination buffer is a frozen String" do
+ -> { @ec.primitive_convert("", "".freeze) }.should raise_error(FrozenError)
+ end
+
it "accepts nil for the destination byte offset" do
-> { @ec.primitive_convert("","", nil) }.should_not raise_error
end
diff --git a/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb b/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
index 1f836b259f..668eb9a924 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 -*-
+# frozen_string_literal: false
require_relative '../../../spec_helper'
describe "Encoding::Converter#primitive_errinfo" do
diff --git a/spec/ruby/core/encoding/converter/putback_spec.rb b/spec/ruby/core/encoding/converter/putback_spec.rb
index c4e0a5da21..e19fe6c314 100644
--- a/spec/ruby/core/encoding/converter/putback_spec.rb
+++ b/spec/ruby/core/encoding/converter/putback_spec.rb
@@ -4,7 +4,7 @@ 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
@@ -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..ea514ca8dd 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
@@ -38,33 +38,33 @@ describe "Encoding::Converter#replacement=" do
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
+ utf8_q = "\u{986}".dup.force_encoding('utf-8')
+ ec.primitive_convert(utf8_q.dup, +"").should == :undefined_conversion
-> { ec.replacement = utf8_q }.should \
raise_error(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
+ utf8_q = "\u{986}".dup.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')
+ 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/default_external_spec.rb b/spec/ruby/core/encoding/default_external_spec.rb
index 682d49d37c..9aae4976e0 100644
--- a/spec/ruby/core/encoding/default_external_spec.rb
+++ b/spec/ruby/core/encoding/default_external_spec.rb
@@ -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
diff --git a/spec/ruby/core/encoding/inspect_spec.rb b/spec/ruby/core/encoding/inspect_spec.rb
index 9a930b2a77..df96141db9 100644
--- a/spec/ruby/core/encoding/inspect_spec.rb
+++ b/spec/ruby/core/encoding/inspect_spec.rb
@@ -5,9 +5,23 @@ describe "Encoding#inspect" do
Encoding::UTF_8.inspect.should be_an_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/incomplete_input_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb
index 94201a9b15..8a3f3de69a 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
@@ -8,7 +8,7 @@ describe "Encoding::InvalidByteSequenceError#incomplete_input?" do
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
@@ -18,7 +18,7 @@ describe "Encoding::InvalidByteSequenceError#incomplete_input?" do
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
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 9866310c25..a5e2824984 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
@@ -15,11 +15,11 @@ describe "Encoding::InvalidByteSequenceError#readagain_bytes" do
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/replicate_spec.rb b/spec/ruby/core/encoding/replicate_spec.rb
index 498d03581a..e22673db7d 100644
--- a/spec/ruby/core/encoding/replicate_spec.rb
+++ b/spec/ruby/core/encoding/replicate_spec.rb
@@ -18,8 +18,8 @@ describe "Encoding#replicate" do
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
+ "a".dup.force_encoding(e).valid_encoding?.should be_true
+ "\x80".dup.force_encoding(e).valid_encoding?.should be_false
end
it "returns a replica of UTF-8" do
@@ -28,9 +28,9 @@ describe "Encoding#replicate" do
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
+ "a".dup.force_encoding(e).valid_encoding?.should be_true
+ "\u3042".dup.force_encoding(e).valid_encoding?.should be_true
+ "\x80".dup.force_encoding(e).valid_encoding?.should be_false
end
it "returns a replica of UTF-16BE" do
@@ -39,9 +39,9 @@ describe "Encoding#replicate" do
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
+ "a".dup.force_encoding(e).valid_encoding?.should be_false
+ "\x30\x42".dup.force_encoding(e).valid_encoding?.should be_true
+ "\x80".dup.force_encoding(e).valid_encoding?.should be_false
end
it "returns a replica of ISO-2022-JP" do
@@ -61,7 +61,7 @@ describe "Encoding#replicate" do
e.name.should == name
Encoding.find(name).should == e
- s = "abc".force_encoding(e)
+ s = "abc".dup.force_encoding(e)
s.encoding.should == e
s.encoding.name.should == name
end
@@ -73,6 +73,11 @@ describe "Encoding#replicate" do
Encoding::US_ASCII.replicate('MY-US-ASCII')
}.should complain(/warning: Encoding#replicate is deprecated and will be removed in Ruby 3.3; use the original encoding instead/)
end
+
+ it "raises EncodingError if too many encodings" do
+ code = '1_000.times {|i| Encoding::US_ASCII.replicate("R_#{i}") }'
+ ruby_exe(code, args: "2>&1", exit_status: 1).should.include?('too many encoding (> 256) (EncodingError)')
+ end
end
ruby_version_is "3.3" do
diff --git a/spec/ruby/core/enumerable/fixtures/classes.rb b/spec/ruby/core/enumerable/fixtures/classes.rb
index fb4951c6e6..2701c6999c 100644
--- a/spec/ruby/core/enumerable/fixtures/classes.rb
+++ b/spec/ruby/core/enumerable/fixtures/classes.rb
@@ -342,4 +342,10 @@ module EnumerableSpecs
@block.call(*args)
end
end
+
+ # Set is a core class since Ruby 3.2
+ ruby_version_is '3.2' do
+ class SetSubclass < Set
+ end
+ end
end # EnumerableSpecs utility classes
diff --git a/spec/ruby/core/enumerable/grep_spec.rb b/spec/ruby/core/enumerable/grep_spec.rb
index b81075291f..989358f01b 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
diff --git a/spec/ruby/core/enumerable/grep_v_spec.rb b/spec/ruby/core/enumerable/grep_v_spec.rb
index 35fde27eb6..ba19216968 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
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..c21a2772c4
--- /dev/null
+++ b/spec/ruby/core/enumerable/to_set_spec.rb
@@ -0,0 +1,29 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.2" do
+ 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
+
+ it "instantiates an object of provided as the first argument set class" do
+ set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)
+ set.should be_kind_of(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
+ end
+
+ it "does not need explicit `require 'set'`" do
+ output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1')
+ puts [1, 2, 3].to_set
+ RUBY
+
+ output.chomp.should == "#<Set: {1, 2, 3}>"
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/chain/initialize_spec.rb b/spec/ruby/core/enumerator/chain/initialize_spec.rb
index 69484dfcb4..daa30351d7 100644
--- a/spec/ruby/core/enumerator/chain/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/chain/initialize_spec.rb
@@ -22,10 +22,10 @@ describe "Enumerator::Chain#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_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/enumerator/each_spec.rb b/spec/ruby/core/enumerator/each_spec.rb
index 99ac3120af..3af16e5587 100644
--- a/spec/ruby/core/enumerator/each_spec.rb
+++ b/spec/ruby/core/enumerator/each_spec.rb
@@ -10,41 +10,41 @@ 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
diff --git a/spec/ruby/core/enumerator/generator/initialize_spec.rb b/spec/ruby/core/enumerator/generator/initialize_spec.rb
index f75c7d6f26..acc1174253 100644
--- a/spec/ruby/core/enumerator/generator/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/generator/initialize_spec.rb
@@ -17,10 +17,10 @@ describe "Enumerator::Generator#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_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/enumerator/initialize_spec.rb b/spec/ruby/core/enumerator/initialize_spec.rb
index 217af1d3bc..5e0256ca46 100644
--- a/spec/ruby/core/enumerator/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/initialize_spec.rb
@@ -11,14 +11,6 @@ describe "Enumerator#initialize" 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
- end
-
it "returns self when given a block" do
@uninitialized.send(:initialize) {}.should equal(@uninitialized)
end
@@ -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_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/enumerator/lazy/initialize_spec.rb b/spec/ruby/core/enumerator/lazy/initialize_spec.rb
index f23018d010..e1e0b1d608 100644
--- a/spec/ruby/core/enumerator/lazy/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/initialize_spec.rb
@@ -56,8 +56,8 @@ describe "Enumerator::Lazy#initialize" do
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_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/enumerator/new_spec.rb b/spec/ruby/core/enumerator/new_spec.rb
index c439469525..671912224f 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_error(ArgumentError)
end
end
diff --git a/spec/ruby/core/enumerator/next_values_spec.rb b/spec/ruby/core/enumerator/next_values_spec.rb
index 201b5d323f..2202700c58 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 == [[:f1, :f2]]
+ end
+
+ it "raises StopIteration if called on a finished enumerator" do
+ 8.times { @e.next }
-> { @e.next_values }.should raise_error(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..8b84fc8afc 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 == [[:f1, :f2]]
+ end
+
+ it "raises StopIteration if called on a finished enumerator" do
+ 8.times { @e.next }
-> { @e.peek_values }.should raise_error(StopIteration)
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..cabeb9d93a
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/each_spec.rb
@@ -0,0 +1,73 @@
+require_relative '../../../spec_helper'
+require_relative '../../enumerable/shared/enumeratorized'
+
+ruby_version_is "3.2" do
+ 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_error(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
+ 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..46e8421322
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/initialize_copy_spec.rb
@@ -0,0 +1,54 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "3.2" do
+ 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.should have_private_instance_method(:initialize_copy, false)
+ 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_error(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_error(TypeError, 'initialize_copy should take same class object')
+ -> { enum2.send(:initialize_copy, enum) }.should raise_error(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_error(ArgumentError, 'uninitialized product')
+ end
+ 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..4b60564240
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/initialize_spec.rb
@@ -0,0 +1,33 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "3.2" do
+ describe "Enumerator::Product#initialize" do
+ before :each do
+ @uninitialized = Enumerator::Product.allocate
+ end
+
+ it "is a private method" do
+ Enumerator::Product.should have_private_instance_method(:initialize, false)
+ 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_error(FrozenError)
+ end
+ 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..1ea8e9c49b
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/inspect_spec.rb
@@ -0,0 +1,22 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "3.2" do
+ 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
+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..e8ee730239
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/rewind_spec.rb
@@ -0,0 +1,64 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "3.2" do
+ 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
+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..46958b1a22
--- /dev/null
+++ b/spec/ruby/core/enumerator/product/size_spec.rb
@@ -0,0 +1,56 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "3.2" do
+ 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
+ end
+end
diff --git a/spec/ruby/core/enumerator/product_spec.rb b/spec/ruby/core/enumerator/product_spec.rb
index 44fc6441e1..0acca6690e 100644
--- a/spec/ruby/core/enumerator/product_spec.rb
+++ b/spec/ruby/core/enumerator/product_spec.rb
@@ -44,6 +44,11 @@ ruby_version_is "3.2" do
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)
@@ -64,7 +69,7 @@ ruby_version_is "3.2" do
it "raises NoMethodError when argument doesn't respond to #each_entry" do
-> {
Enumerator.product(Object.new).to_a
- }.should raise_error(NoMethodError, /undefined method `each_entry' for/)
+ }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/)
end
it "calls #each_entry lazily" do
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/env/delete_spec.rb b/spec/ruby/core/env/delete_spec.rb
index 5e7891f74d..f28ac97911 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,6 +41,14 @@ 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")
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/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/key_spec.rb b/spec/ruby/core/env/key_spec.rb
index 82cfbefa39..cf70286409 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 be_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_error(TypeError, "no implicit conversion of Object into String")
+ end
end
diff --git a/spec/ruby/core/env/shared/include.rb b/spec/ruby/core/env/shared/include.rb
index 3efcd523d6..70aa555301 100644
--- a/spec/ruby/core/env/shared/include.rb
+++ b/spec/ruby/core/env/shared/include.rb
@@ -17,6 +17,13 @@ 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")
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/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/slice_spec.rb b/spec/ruby/core/env/slice_spec.rb
index e3b6020391..959239d2b2 100644
--- a/spec/ruby/core/env/slice_spec.rb
+++ b/spec/ruby/core/env/slice_spec.rb
@@ -21,6 +21,16 @@ 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")
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/exception/backtrace_spec.rb b/spec/ruby/core/exception/backtrace_spec.rb
index 3f74c4cefe..9a65ea3820 100644
--- a/spec/ruby/core/exception/backtrace_spec.rb
+++ b/spec/ruby/core/exception/backtrace_spec.rb
@@ -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
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/detailed_message_spec.rb b/spec/ruby/core/exception/detailed_message_spec.rb
index bd85927dbe..fbe4443daa 100644
--- a/spec/ruby/core/exception/detailed_message_spec.rb
+++ b/spec/ruby/core/exception/detailed_message_spec.rb
@@ -7,6 +7,14 @@ describe "Exception#detailed_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 "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
@@ -23,13 +31,13 @@ describe "Exception#detailed_message" do
RuntimeError.new("").detailed_message.should == "unhandled exception"
end
- it "returns just class name for an instance of RuntimeError sublass with empty message" do
+ it "returns just class name for an instance of RuntimeError subclass with empty message" do
DetailedMessageSpec::C.new("").detailed_message.should == "DetailedMessageSpec::C"
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/
+ klass.new("").detailed_message.should =~ /\A#<Class:0x\h+>\z/
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..e8f3ce0f8d 100644
--- a/spec/ruby/core/exception/equal_value_spec.rb
+++ b/spec/ruby/core/exception/equal_value_spec.rb
@@ -22,18 +22,18 @@ 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.set_backtrace [__dir__]
one.should be_kind_of(Exception)
two = TypeError.new("message")
- two.set_backtrace [File.dirname(__FILE__)]
+ two.set_backtrace [__dir__]
two.should be_kind_of(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/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/frozen_error_spec.rb b/spec/ruby/core/exception/frozen_error_spec.rb
index 2efdc239d8..979ec2ff98 100644
--- a/spec/ruby/core/exception/frozen_error_spec.rb
+++ b/spec/ruby/core/exception/frozen_error_spec.rb
@@ -20,3 +20,19 @@ describe "FrozenError#receiver" do
end
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_error(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 ee66582022..5154354555 100644
--- a/spec/ruby/core/exception/full_message_spec.rb
+++ b/spec/ruby/core/exception/full_message_spec.rb
@@ -42,16 +42,59 @@ 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
+ 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 +105,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"
@@ -107,21 +150,49 @@ describe "Exception#full_message" do
ruby_version_is "3.2" do
it "relies on #detailed_message" do
e = RuntimeError.new("new error")
- e.define_singleton_method(:detailed_message) { |**opt| "DETAILED MESSAGE" }
+ e.define_singleton_method(:detailed_message) { |**| "DETAILED MESSAGE" }
e.full_message.lines.first.should =~ /DETAILED MESSAGE/
end
- it "passes all its own keyword arguments to #detailed_message" do
+ 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")
- opt_ = nil
- e.define_singleton_method(:detailed_message) do |**opt|
- opt_ = opt
+ options_passed = nil
+ e.define_singleton_method(:detailed_message) do |**options|
+ options_passed = options
"DETAILED MESSAGE"
end
e.full_message(foo: "bar")
- opt_.should == { foo: "bar", highlight: Exception.to_tty? }
+ 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
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/no_method_error_spec.rb b/spec/ruby/core/exception/no_method_error_spec.rb
index f84f3418a4..26df3338e9 100644
--- a/spec/ruby/core/exception/no_method_error_spec.rb
+++ b/spec/ruby/core/exception/no_method_error_spec.rb
@@ -62,7 +62,7 @@ describe "NoMethodError#message" do
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 /
+ e.message.lines[0].should =~ /private method [`']a_private_method' called for /
end
end
@@ -125,21 +125,19 @@ describe "NoMethodError#message" do
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 /
- end
+ 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 /
+ end
- mod = Module.new { def self.name; "MyModule"; end }
- begin
- mod.foo
- rescue NoMethodError => error
- error.message.lines.first.chomp.should =~ /^undefined method `foo' for /
- end
+ mod = Module.new { def self.name; "MyModule"; end }
+ begin
+ mod.foo
+ rescue NoMethodError => error
+ error.message.lines.first.chomp.should =~ /^undefined method [`']foo' for /
end
end
end
diff --git a/spec/ruby/core/exception/set_backtrace_spec.rb b/spec/ruby/core/exception/set_backtrace_spec.rb
index ba2e1bf7aa..12c1da919c 100644
--- a/spec/ruby/core/exception/set_backtrace_spec.rb
+++ b/spec/ruby/core/exception/set_backtrace_spec.rb
@@ -11,9 +11,37 @@ describe "Exception#set_backtrace" do
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
+ err.backtrace_locations.should == nil
+ 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 = RuntimeError.new
+ err.backtrace.should == nil
+ err.backtrace_locations.should == nil
+
+ err.set_backtrace 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
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..6cc8522de3
--- /dev/null
+++ b/spec/ruby/core/exception/syntax_error_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.2" do
+ describe "SyntaxError#path" do
+ it "returns the file path provided to eval" do
+ filename = "speccing.rb"
+
+ -> {
+ eval("if true", TOPLEVEL_BINDING, filename)
+ }.should raise_error(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_error(SyntaxError) { |e| e.path.should == expected_path }
+ end
+
+ it "returns nil when constructed directly" do
+ SyntaxError.new.path.should == nil
+ end
+ end
+end
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 bcd09205b6..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
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..738794b46c
--- /dev/null
+++ b/spec/ruby/core/false/singleton_method_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+describe "FalseClass#singleton_method" do
+ ruby_version_is '3.3' do
+ it "raises regardless of whether FalseClass defines the method" do
+ -> { false.singleton_method(:foo) }.should raise_error(NameError)
+ begin
+ def (false).foo; end
+ -> { false.singleton_method(:foo) }.should raise_error(NameError)
+ ensure
+ FalseClass.send(:remove_method, :foo)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/fiber/blocking_spec.rb b/spec/ruby/core/fiber/blocking_spec.rb
index eeee5a71c1..ebefa116af 100644
--- a/spec/ruby/core/fiber/blocking_spec.rb
+++ b/spec/ruby/core/fiber/blocking_spec.rb
@@ -1,61 +1,59 @@
require_relative '../../spec_helper'
require_relative 'shared/blocking'
-ruby_version_is "3.0" do
- require "fiber"
+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
+ 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
+
+ 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
+ thread.join
end
end
end
diff --git a/spec/ruby/core/fiber/inspect_spec.rb b/spec/ruby/core/fiber/inspect_spec.rb
index ee53af3a39..f20a153fc2 100644
--- a/spec/ruby/core/fiber/inspect_spec.rb
+++ b/spec/ruby/core/fiber/inspect_spec.rb
@@ -18,11 +18,9 @@ describe "Fiber#inspect" do
inspected.should =~ /\A#<Fiber:0x\h+ .+ \(resumed\)>\z/
end
- ruby_version_is "3.0" do
- 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 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
diff --git a/spec/ruby/core/fiber/raise_spec.rb b/spec/ruby/core/fiber/raise_spec.rb
index 09c4c1b524..b3e021e636 100644
--- a/spec/ruby/core/fiber/raise_spec.rb
+++ b/spec/ruby/core/fiber/raise_spec.rb
@@ -91,29 +91,49 @@ 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
+
+ -> do
+ f2.raise(RuntimeError, "Expected error")
+ end.should raise_error(RuntimeError, "Expected error")
+ end
-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")
+ it "raises on itself" do
+ -> do
+ Fiber.current.raise(RuntimeError, "Expected error")
+ end.should raise_error(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_error(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")
- end
+
+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")
end
end
diff --git a/spec/ruby/core/fiber/resume_spec.rb b/spec/ruby/core/fiber/resume_spec.rb
index 273bc866af..ab9a6799ab 100644
--- a/spec/ruby/core/fiber/resume_spec.rb
+++ b/spec/ruby/core/fiber/resume_spec.rb
@@ -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_error(FiberError, /current fiber/)
end
it "returns control to the calling Fiber if called from one" do
diff --git a/spec/ruby/core/fiber/storage_spec.rb b/spec/ruby/core/fiber/storage_spec.rb
index e99fe6e4df..5c87ed5d41 100644
--- a/spec/ruby/core/fiber/storage_spec.rb
+++ b/spec/ruby/core/fiber/storage_spec.rb
@@ -1,9 +1,7 @@
require_relative '../../spec_helper'
-require 'fiber'
-
-describe "Fiber.new(storage:)" do
- ruby_version_is "3.2" do
+ruby_version_is "3.2" do
+ 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 }
@@ -24,11 +22,26 @@ describe "Fiber.new(storage:)" do
it "cannot create a fiber with non-hash storage" do
-> { Fiber.new(storage: 42) {} }.should raise_error(TypeError)
end
+
+ it "cannot create a fiber with a frozen hash as storage" do
+ -> { Fiber.new(storage: {life: 43}.freeze) {} }.should raise_error(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_error(TypeError)
+ end
end
-end
-describe "Fiber#storage=" do
- ruby_version_is "3.2" do
+ describe "Fiber#storage" do
+ it "cannot be accessed from a different fiber" do
+ f = Fiber.new(storage: {life: 42}) { nil }
+ -> {
+ f.storage
+ }.should raise_error(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
@@ -58,10 +71,8 @@ describe "Fiber#storage=" do
-> { Fiber.current.storage = {life: 43, Object.new => 44} }.should raise_error(TypeError)
end
end
-end
-describe "Fiber.[]" do
- ruby_version_is "3.2" do
+ 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
@@ -73,11 +84,34 @@ describe "Fiber.[]" do
it "returns nil if the current fiber has no storage" do
Fiber.new { Fiber[:life] }.resume.should be_nil
end
+
+ ruby_version_is "3.2.3" do
+ 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, "Foo", 12]
+ invalid_keys.each do |key|
+ -> { Fiber[key] }.should raise_error(TypeError)
+ end
+ end
+ 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_error(TypeError)
+ end
end
-end
-describe "Fiber.[]=" do
- ruby_version_is "3.2" do
+ 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
@@ -89,17 +123,31 @@ describe "Fiber.[]=" do
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
- end
- ruby_version_is "3.3" do
- it "deletes the fiber storage key when assigning nil" do
- Fiber.new(storage: {life: 42}) { Fiber[:life] = nil; Fiber.current.storage }.resume.should == {}
+ 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_error(TypeError)
+ end
+
+ ruby_version_is "3.3" do
+ 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
end
-end
-describe "Thread.new" do
- ruby_version_is "3.2" do
+ 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
diff --git a/spec/ruby/core/file/absolute_path_spec.rb b/spec/ruby/core/file/absolute_path_spec.rb
index e35c80ec3c..315eead34f 100644
--- a/spec/ruby/core/file/absolute_path_spec.rb
+++ b/spec/ruby/core/file/absolute_path_spec.rb
@@ -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 1b47576e6b..e47e70e5ac 100644
--- a/spec/ruby/core/file/atime_spec.rb
+++ b/spec/ruby/core/file/atime_spec.rb
@@ -27,6 +27,9 @@ 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
diff --git a/spec/ruby/core/file/ctime_spec.rb b/spec/ruby/core/file/ctime_spec.rb
index d17ba1a77f..718f26d5cc 100644
--- a/spec/ruby/core/file/ctime_spec.rb
+++ b/spec/ruby/core/file/ctime_spec.rb
@@ -22,6 +22,9 @@ describe "File.ctime" do
else
File.ctime(__FILE__).usec.should == 0
end
+ rescue Errno::ENOENT => e
+ # Windows don't have stat command.
+ skip e.message
end
end
diff --git a/spec/ruby/core/file/exist_spec.rb b/spec/ruby/core/file/exist_spec.rb
index ddb5febcba..2633376880 100644
--- a/spec/ruby/core/file/exist_spec.rb
+++ b/spec/ruby/core/file/exist_spec.rb
@@ -4,3 +4,11 @@ require_relative '../../shared/file/exist'
describe "File.exist?" do
it_behaves_like :file_exist, :exist?, File
end
+
+ruby_version_is "3.2" do
+ describe "File.exists?" do
+ it "has been removed" do
+ File.should_not.respond_to?(:exists?)
+ end
+ end
+end
diff --git a/spec/ruby/core/file/expand_path_spec.rb b/spec/ruby/core/file/expand_path_spec.rb
index c31f885b92..1abcf93900 100644
--- a/spec/ruby/core/file/expand_path_spec.rb
+++ b/spec/ruby/core/file/expand_path_spec.rb
@@ -137,7 +137,7 @@ 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
+ path = "./a".dup.force_encoding Encoding::CP1251
File.expand_path(path).encoding.should equal(Encoding::CP1251)
weird_path = [222, 173, 190, 175].pack('C*')
diff --git a/spec/ruby/core/file/flock_spec.rb b/spec/ruby/core/file/flock_spec.rb
index 751e99d994..070d830bc4 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
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/mtime_spec.rb b/spec/ruby/core/file/mtime_spec.rb
index 5304bbf057..0e9c95caee 100644
--- a/spec/ruby/core/file/mtime_spec.rb
+++ b/spec/ruby/core/file/mtime_spec.rb
@@ -26,6 +26,9 @@ describe "File.mtime" do
else
File.mtime(__FILE__).usec.should == 0
end
+ rescue Errno::ENOENT => e
+ # Windows don't have stat command.
+ skip e.message
end
end
end
diff --git a/spec/ruby/core/file/new_spec.rb b/spec/ruby/core/file/new_spec.rb
index a1ca46979e..1e82a070b1 100644
--- a/spec/ruby/core/file/new_spec.rb
+++ b/spec/ruby/core/file/new_spec.rb
@@ -100,7 +100,7 @@ describe "File.new" do
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
+ 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_error(Errno::EEXIST)
end
@@ -168,16 +168,14 @@ describe "File.new" do
File.should.exist?(@file)
end
- ruby_version_is "3.0" do
- it "accepts options as a keyword argument" do
- @fh = File.new(@file, 'w', 0755, flags: @flags)
- @fh.should be_kind_of(File)
- @fh.close
+ it "accepts options as a keyword argument" do
+ @fh = File.new(@file, 'w', 0755, flags: @flags)
+ @fh.should be_kind_of(File)
+ @fh.close
- -> {
- @fh = File.new(@file, 'w', 0755, {flags: @flags})
- }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
- end
+ -> {
+ @fh = File.new(@file, 'w', 0755, {flags: @flags})
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
it "bitwise-ORs mode and flags option" do
@@ -190,6 +188,12 @@ describe "File.new" do
}.should raise_error(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)
diff --git a/spec/ruby/core/file/open_spec.rb b/spec/ruby/core/file/open_spec.rb
index 0c6d6cd19c..6bfc16bbf9 100644
--- a/spec/ruby/core/file/open_spec.rb
+++ b/spec/ruby/core/file/open_spec.rb
@@ -314,7 +314,7 @@ describe "File.open" do
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")
@@ -354,7 +354,7 @@ 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")
@@ -423,7 +423,7 @@ describe "File.open" do
}.should raise_error(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
@@ -441,7 +441,7 @@ describe "File.open" do
}.should raise_error(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
@@ -565,15 +565,13 @@ describe "File.open" do
File.open(@file, 'wb+') {|f| f.external_encoding.should == Encoding::BINARY}
end
- ruby_version_is "3.0" do
- it "accepts options as a keyword argument" do
- @fh = File.open(@file, 'w', 0755, flags: File::CREAT)
- @fh.should be_an_instance_of(File)
+ it "accepts options as a keyword argument" do
+ @fh = File.open(@file, 'w', 0755, flags: File::CREAT)
+ @fh.should be_an_instance_of(File)
- -> {
- File.open(@file, 'w', 0755, {flags: File::CREAT})
- }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
- end
+ -> {
+ File.open(@file, 'w', 0755, {flags: File::CREAT})
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
it "uses the second argument as an options Hash" do
diff --git a/spec/ruby/core/file/realpath_spec.rb b/spec/ruby/core/file/realpath_spec.rb
index bd27e09da6..bd25bfdecf 100644
--- a/spec/ruby/core/file/realpath_spec.rb
+++ b/spec/ruby/core/file/realpath_spec.rb
@@ -54,6 +54,10 @@ 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)
diff --git a/spec/ruby/core/file/shared/fnmatch.rb b/spec/ruby/core/file/shared/fnmatch.rb
index 94f22144b0..db4b5c5d8c 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
@@ -221,6 +239,33 @@ describe :file_fnmatch, shared: true do
File.send(@method, pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true
end
+ it "has special handling for ./ when using * and FNM_PATHNAME" do
+ File.send(@method, './*', '.', File::FNM_PATHNAME).should be_false
+ File.send(@method, './*', './', File::FNM_PATHNAME).should be_true
+ File.send(@method, './*/', './', File::FNM_PATHNAME).should be_false
+ File.send(@method, './**', './', File::FNM_PATHNAME).should be_true
+ File.send(@method, './**/', './', File::FNM_PATHNAME).should be_true
+ File.send(@method, './*', '.', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_false
+ File.send(@method, './*', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true
+ File.send(@method, './*/', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_false
+ File.send(@method, './**', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true
+ File.send(@method, './**/', './', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true
+ end
+
+ it "matches **/* with FNM_PATHNAME to recurse directories" do
+ File.send(@method, 'nested/**/*', 'nested/subdir', File::FNM_PATHNAME).should be_true
+ File.send(@method, 'nested/**/*', 'nested/subdir/file', File::FNM_PATHNAME).should be_true
+ File.send(@method, 'nested/**/*', 'nested/.dotsubdir', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true
+ File.send(@method, 'nested/**/*', 'nested/.dotsubir/.dotfile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true
+ end
+
+ it "matches ** with FNM_PATHNAME only in current directory" do
+ File.send(@method, 'nested/**', 'nested/subdir', File::FNM_PATHNAME).should be_true
+ File.send(@method, 'nested/**', 'nested/subdir/file', File::FNM_PATHNAME).should be_false
+ File.send(@method, 'nested/**', 'nested/.dotsubdir', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_true
+ File.send(@method, 'nested/**', 'nested/.dotsubir/.dotfile', File::FNM_PATHNAME | File::FNM_DOTMATCH).should be_false
+ end
+
it "accepts an object that has a #to_path method" do
File.send(@method, '\*', mock_to_path('a')).should == false
end
diff --git a/spec/ruby/core/file/shared/path.rb b/spec/ruby/core/file/shared/path.rb
index ee8109ba05..aa2a64cf25 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
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..9c063a8e93
--- /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 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 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/utime_spec.rb b/spec/ruby/core/file/utime_spec.rb
index 0b0e4f979c..d87626be50 100644
--- a/spec/ruby/core/file/utime_spec.rb
+++ b/spec/ruby/core/file/utime_spec.rb
@@ -1,102 +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 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.utime(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
+ it_behaves_like :update_time, :utime
end
diff --git a/spec/ruby/core/filetest/exist_spec.rb b/spec/ruby/core/filetest/exist_spec.rb
index 4d14bea231..a95d3f91a1 100644
--- a/spec/ruby/core/filetest/exist_spec.rb
+++ b/spec/ruby/core/filetest/exist_spec.rb
@@ -4,3 +4,11 @@ require_relative '../../shared/file/exist'
describe "FileTest.exist?" do
it_behaves_like :file_exist, :exist?, FileTest
end
+
+ruby_version_is "3.2" do
+ describe "FileTest.exists?" do
+ it "has been removed" do
+ FileTest.should_not.respond_to?(:exists?)
+ end
+ 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/hash/assoc_spec.rb b/spec/ruby/core/hash/assoc_spec.rb
index 64442918d1..62b2a11b30 100644
--- a/spec/ruby/core/hash/assoc_spec.rb
+++ b/spec/ruby/core/hash/assoc_spec.rb
@@ -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
diff --git a/spec/ruby/core/hash/compare_by_identity_spec.rb b/spec/ruby/core/hash/compare_by_identity_spec.rb
index 874cd46eb7..2975526a97 100644
--- a/spec/ruby/core/hash/compare_by_identity_spec.rb
+++ b/spec/ruby/core/hash/compare_by_identity_spec.rb
@@ -85,19 +85,21 @@ describe "Hash#compare_by_identity" do
-> { @h.compare_by_identity }.should raise_error(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
@@ -108,9 +110,16 @@ describe "Hash#compare_by_identity" do
@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
diff --git a/spec/ruby/core/hash/delete_spec.rb b/spec/ruby/core/hash/delete_spec.rb
index b262e8846b..3e3479c69c 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.frozen_hash.delete("foo") }.should raise_error(FrozenError)
-> { HashSpecs.empty_frozen_hash.delete("foo") }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/element_reference_spec.rb b/spec/ruby/core/hash/element_reference_spec.rb
index e271f37ea6..94e8237839 100644
--- a/spec/ruby/core/hash/element_reference_spec.rb
+++ b/spec/ruby/core/hash/element_reference_spec.rb
@@ -30,7 +30,7 @@ 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]
diff --git a/spec/ruby/core/hash/except_spec.rb b/spec/ruby/core/hash/except_spec.rb
index 82cfced72f..ac84f9975c 100644
--- a/spec/ruby/core/hash/except_spec.rb
+++ b/spec/ruby/core/hash/except_spec.rb
@@ -1,34 +1,32 @@
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 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 hash without the requested subset" do
+ @hash.except(:c, :a).should == { b: 2 }
+ end
- it "ignores keys not present in the original hash" do
- @hash.except(:a, :chunky_bacon).should == { b: 2, c: 3 }
- end
+ it "ignores keys not present in the original hash" do
+ @hash.except(:a, :chunky_bacon).should == { b: 2, c: 3 }
+ 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 "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
end
diff --git a/spec/ruby/core/hash/hash_spec.rb b/spec/ruby/core/hash/hash_spec.rb
index 2ccb483120..19eb806dc4 100644
--- a/spec/ruby/core/hash/hash_spec.rb
+++ b/spec/ruby/core/hash/hash_spec.rb
@@ -43,7 +43,7 @@ describe "Hash#hash" do
end
ruby_version_is "3.1" do
- it "allows ommiting values" do
+ it "allows omitting values" do
a = 1
b = 2
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/rehash_spec.rb b/spec/ruby/core/hash/rehash_spec.rb
index 0049080456..db3e91b166 100644
--- a/spec/ruby/core/hash/rehash_spec.rb
+++ b/spec/ruby/core/hash/rehash_spec.rb
@@ -77,6 +77,36 @@ 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)
diff --git a/spec/ruby/core/hash/shared/each.rb b/spec/ruby/core/hash/shared/each.rb
index b2483c8116..f9839ff58f 100644
--- a/spec/ruby/core/hash/shared/each.rb
+++ b/spec/ruby/core/hash/shared/each.rb
@@ -21,37 +21,18 @@ describe :hash_each, shared: true do
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]
+ 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
- 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, &obj.method(:foo))
+ }.should raise_error(ArgumentError)
- -> {
- { "a" => 1 }.send(@method, &-> key, value { })
- }.should raise_error(ArgumentError)
- end
+ -> {
+ { "a" => 1 }.send(@method, &-> key, value { })
+ }.should raise_error(ArgumentError)
end
it "yields an Array of 2 elements when given a callable of arity 1" do
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/store.rb b/spec/ruby/core/hash/shared/store.rb
index b823ea45ca..dd1bb52bac 100644
--- a/spec/ruby/core/hash/shared/store.rb
+++ b/spec/ruby/core/hash/shared/store.rb
@@ -9,7 +9,7 @@ describe :hash_store, shared: true do
it "duplicates string keys using dup semantics" do
# dup doesn't copy singleton methods
- key = "foo"
+ key = +"foo"
def key.reverse() "bar" end
h = {}
h.send(@method, key, 0)
@@ -44,7 +44,7 @@ describe :hash_store, shared: true do
end
it "duplicates and freezes string keys" do
- key = "foo"
+ key = +"foo"
h = {}
h.send(@method, key, 0)
key << "bar"
@@ -75,8 +75,8 @@ describe :hash_store, shared: true do
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 = "foo".dup
+ key2 = "foo".dup
key1.should_not equal(key2)
h[key1] = 41
frozen_key = h.keys.last
diff --git a/spec/ruby/core/hash/shared/to_s.rb b/spec/ruby/core/hash/shared/to_s.rb
index 2db3a96583..7864d7cd4c 100644
--- a/spec/ruby/core/hash/shared/to_s.rb
+++ b/spec/ruby/core/hash/shared/to_s.rb
@@ -24,7 +24,7 @@ describe :hash_to_s, shared: true do
end
it "does not call #to_s on a String returned from #inspect" do
- str = "abc"
+ str = +"abc"
str.should_not_receive(:to_s)
{ a: str }.send(@method).should == '{:a=>"abc"}'
@@ -78,7 +78,7 @@ describe :hash_to_s, shared: true do
it "does not raise if inspected result is not default external encoding" do
utf_16be = mock("utf_16be")
- utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
+ utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode(Encoding::UTF_16BE))
{a: utf_16be}.send(@method).should == '{:a=>"utf_16be \u3042"}'
end
diff --git a/spec/ruby/core/hash/to_a_spec.rb b/spec/ruby/core/hash/to_a_spec.rb
index 8b7894a2ba..5baf677929 100644
--- a/spec/ruby/core/hash/to_a_spec.rb
+++ b/spec/ruby/core/hash/to_a_spec.rb
@@ -26,14 +26,4 @@ describe "Hash#to_a" do
ent.should be_kind_of(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_proc_spec.rb b/spec/ruby/core/hash/to_proc_spec.rb
index 8f5d21beb5..9dbc79e5eb 100644
--- a/spec/ruby/core/hash/to_proc_spec.rb
+++ b/spec/ruby/core/hash/to_proc_spec.rb
@@ -19,20 +19,12 @@ 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
diff --git a/spec/ruby/core/hash/transform_keys_spec.rb b/spec/ruby/core/hash/transform_keys_spec.rb
index 361089ca97..2fbb17a8e2 100644
--- a/spec/ruby/core/hash/transform_keys_spec.rb
+++ b/spec/ruby/core/hash/transform_keys_spec.rb
@@ -43,18 +43,16 @@ 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
end
@@ -111,11 +109,9 @@ describe "Hash#transform_keys!" do
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
@@ -132,10 +128,8 @@ describe "Hash#transform_keys!" do
@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_error(FrozenError)
end
context "when no block is given" do
diff --git a/spec/ruby/core/integer/coerce_spec.rb b/spec/ruby/core/integer/coerce_spec.rb
index f1f3256032..1d6dc9713f 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
@@ -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/div_spec.rb b/spec/ruby/core/integer/div_spec.rb
index 344e095179..2eb9c0623b 100644
--- a/spec/ruby/core/integer/div_spec.rb
+++ b/spec/ruby/core/integer/div_spec.rb
@@ -143,4 +143,12 @@ describe "Integer#div" do
-> { @bignum.div(-0) }.should raise_error(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/shared/arithmetic_coerce.rb b/spec/ruby/core/integer/shared/arithmetic_coerce.rb
index 4c0cbcb999..1260192df1 100644
--- a/spec/ruby/core/integer/shared/arithmetic_coerce.rb
+++ b/spec/ruby/core/integer/shared/arithmetic_coerce.rb
@@ -1,25 +1,5 @@
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")
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/binread_spec.rb b/spec/ruby/core/io/binread_spec.rb
index a3f752d8f9..418e89213b 100644
--- a/spec/ruby/core/io/binread_spec.rb
+++ b/spec/ruby/core/io/binread_spec.rb
@@ -44,4 +44,14 @@ describe "IO.binread" do
it "raises an Errno::EINVAL when not passed a valid offset" do
-> { IO.binread @fname, 0, -1 }.should raise_error(Errno::EINVAL)
end
+
+ ruby_version_is "3.3" 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/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_read_spec.rb b/spec/ruby/core/io/close_read_spec.rb
index 26454bfddd..e700e85bd9 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
diff --git a/spec/ruby/core/io/close_write_spec.rb b/spec/ruby/core/io/close_write_spec.rb
index 14835e4e2c..70610a3e9d 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
@@ -48,12 +49,15 @@ 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
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..ffa2ea992c 100644
--- a/spec/ruby/core/io/copy_stream_spec.rb
+++ b/spec/ruby/core/io/copy_stream_spec.rb
@@ -69,9 +69,12 @@ 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_error(IOError)
+ ensure
+ to_io.close
+ end
end
it "does not close the destination IO" 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
@@ -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
@@ -277,10 +300,8 @@ describe "IO.copy_stream" do
@io.should_not_receive(:pos)
IO.copy_stream(@io, @to_name)
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/eof_spec.rb b/spec/ruby/core/io/eof_spec.rb
index 315345d942..b4850df437 100644
--- a/spec/ruby/core/io/eof_spec.rb
+++ b/spec/ruby/core/io/eof_spec.rb
@@ -76,7 +76,7 @@ describe "IO#eof?" do
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/foreach_spec.rb b/spec/ruby/core/io/foreach_spec.rb
index c2276cf544..c361d27879 100644
--- a/spec/ruby/core/io/foreach_spec.rb
+++ b/spec/ruby/core/io/foreach_spec.rb
@@ -20,7 +20,10 @@ describe "IO.foreach" do
platform_is :windows do
cmd = "|cmd.exe /C echo hello&echo line2"
end
- IO.foreach(cmd) { |l| ScratchPad << l }
+
+ 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
@@ -28,7 +31,9 @@ describe "IO.foreach" 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"]
@@ -39,6 +44,16 @@ describe "IO.foreach" do
end
end
end
+
+ ruby_version_is "3.3" do
+ # 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
end
diff --git a/spec/ruby/core/io/getbyte_spec.rb b/spec/ruby/core/io/getbyte_spec.rb
index 6ba8f0a3e0..b4351160e6 100644
--- a/spec/ruby/core/io/getbyte_spec.rb
+++ b/spec/ruby/core/io/getbyte_spec.rb
@@ -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_error(IOError)
+ end
+end
diff --git a/spec/ruby/core/io/gets_spec.rb b/spec/ruby/core/io/gets_spec.rb
index f38e3d3974..ca64bf860e 100644
--- a/spec/ruby/core/io/gets_spec.rb
+++ b/spec/ruby/core/io/gets_spec.rb
@@ -24,6 +24,12 @@ describe "IO#gets" do
end
end
+ it "sets $_ to nil after the last line has been read" do
+ while @io.gets
+ end
+ $_.should be_nil
+ end
+
it "returns nil if called at the end of the stream" do
IOSpecs.lines.length.times { @io.gets }
@io.gets.should == nil
@@ -149,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_error(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_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
end
end
end
diff --git a/spec/ruby/core/io/initialize_spec.rb b/spec/ruby/core/io/initialize_spec.rb
index 28fd7af7ab..026252a13d 100644
--- a/spec/ruby/core/io/initialize_spec.rb
+++ b/spec/ruby/core/io/initialize_spec.rb
@@ -27,17 +27,15 @@ describe "IO#initialize" do
@io.fileno.should == fd
end
- ruby_version_is "3.0" do
- it "accepts options as keyword arguments" do
- fd = new_fd @name, "w:utf-8"
+ 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)
+ @io.fileno.should == fd
- -> {
- @io.send(:initialize, fd, "w", {flags: File::CREAT})
- }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 1..2)")
- end
+ -> {
+ @io.send(:initialize, fd, "w", {flags: File::CREAT})
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 1..2)")
end
it "raises a TypeError when passed an IO" do
diff --git a/spec/ruby/core/io/ioctl_spec.rb b/spec/ruby/core/io/ioctl_spec.rb
index 8dcd9eb2c6..3f7b5ad5d7 100644
--- a/spec/ruby/core/io/ioctl_spec.rb
+++ b/spec/ruby/core/io/ioctl_spec.rb
@@ -12,7 +12,7 @@ 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)
diff --git a/spec/ruby/core/io/lineno_spec.rb b/spec/ruby/core/io/lineno_spec.rb
index 9a4ad90880..e82cdd9f17 100644
--- a/spec/ruby/core/io/lineno_spec.rb
+++ b/spec/ruby/core/io/lineno_spec.rb
@@ -26,7 +26,8 @@ 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)
end
@@ -70,7 +71,8 @@ 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)
end
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 0ef30991fd..979ac0efcb 100644
--- a/spec/ruby/core/io/new_spec.rb
+++ b/spec/ruby/core/io/new_spec.rb
@@ -1,10 +1,16 @@
require_relative '../../spec_helper'
require_relative 'shared/new'
-# NOTE: should be syncronized with library/stringio/initialize_spec.rb
+# 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..d151da9ce5 100644
--- a/spec/ruby/core/io/open_spec.rb
+++ b/spec/ruby/core/io/open_spec.rb
@@ -37,6 +37,19 @@ describe "IO.open" do
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_error(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|
diff --git a/spec/ruby/core/io/pread_spec.rb b/spec/ruby/core/io/pread_spec.rb
index fb0645dec6..6d93b432c2 100644
--- a/spec/ruby/core/io/pread_spec.rb
+++ b/spec/ruby/core/io/pread_spec.rb
@@ -21,16 +21,100 @@ guard -> { platform_is_not :windows or ruby_version_is "3.3" } do
end
it "accepts a length, an offset, and an output buffer" do
- buffer = "foo"
- @file.pread(3, 4, buffer)
+ buffer = +"foo"
+ @file.pread(3, 4, buffer).should.equal?(buffer)
buffer.should == "567"
end
+ it "shrinks the buffer in case of less bytes read" do
+ buffer = +"foo"
+ @file.pread(1, 0, buffer)
+ buffer.should == "1"
+ end
+
+ it "grows the buffer in case of more bytes read" do
+ buffer = +"foo"
+ @file.pread(5, 0, buffer)
+ buffer.should == "12345"
+ 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 "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_error(TypeError, 'no implicit conversion of Object into Integer')
+ end
+
+ 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_error(TypeError, 'no implicit conversion of Object into Integer')
+ end
+
+ it "raises ArgumentError for negative values of maxlen" do
+ -> { @file.pread(-4, 0) }.should raise_error(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_error(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_error(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_error(EOFError)
end
diff --git a/spec/ruby/core/io/puts_spec.rb b/spec/ruby/core/io/puts_spec.rb
index 9a708fffef..9ed343c94c 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
diff --git a/spec/ruby/core/io/pwrite_spec.rb b/spec/ruby/core/io/pwrite_spec.rb
index c10578a8eb..2bc508b37d 100644
--- a/spec/ruby/core/io/pwrite_spec.rb
+++ b/spec/ruby/core/io/pwrite_spec.rb
@@ -28,16 +28,42 @@ guard -> { platform_is_not :windows or ruby_version_is "3.3" } do
@file.pread(6, 0).should == "foobar"
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 "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_error(IOError)
+ -> { file.pwrite("foo", 1) }.should raise_error(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_error(IOError)
+ -> { file.pwrite("foo", 1) }.should raise_error(IOError, "closed stream")
+ end
+
+ it "raises a NoMethodError if object does not respond to #to_s" do
+ -> {
+ @file.pwrite(BasicObject.new, 0)
+ }.should raise_error(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_error(TypeError, "no implicit conversion of Object into Integer")
end
end
end
diff --git a/spec/ruby/core/io/read_nonblock_spec.rb b/spec/ruby/core/io/read_nonblock_spec.rb
index a62b75274c..51e7cd6bd2 100644
--- a/spec/ruby/core/io/read_nonblock_spec.rb
+++ b/spec/ruby/core/io/read_nonblock_spec.rb
@@ -96,21 +96,21 @@ describe "IO#read_nonblock" do
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)
end
it "discards the existing buffer content upon successful read" do
- buffer = "existing content"
+ buffer = +"existing content"
@write.write("hello world")
@write.close
@read.read_nonblock(11, buffer)
@@ -118,7 +118,7 @@ describe "IO#read_nonblock" do
end
it "discards the existing buffer content upon error" do
- buffer = "existing content"
+ buffer = +"existing content"
@write.close
-> { @read.read_nonblock(1, buffer) }.should raise_error(EOFError)
buffer.should be_empty
diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb
index 8bffd50876..8741d9f017 100644
--- a/spec/ruby/core/io/read_spec.rb
+++ b/spec/ruby/core/io/read_spec.rb
@@ -23,15 +23,13 @@ describe "IO.read" do
IO.read(p)
end
- ruby_version_is "3.0" do
- # 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]
+ # 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_error(ArgumentError, /wrong number of arguments/)
- end
+ -> {
+ IO.read(@fname, 3, 0, {mode: "r+"})
+ }.should raise_error(ArgumentError, /wrong number of arguments/)
end
it "accepts an empty options Hash" do
@@ -115,6 +113,15 @@ 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)
@@ -167,12 +174,19 @@ describe "IO.read from a pipe" do
platform_is :windows do
cmd = "|cmd.exe /C echo hello"
end
- IO.read(cmd).should == "hello\n"
+
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ 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("|-")
+ 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
@@ -187,13 +201,18 @@ describe "IO.read from a pipe" do
platform_is :windows do
cmd = "|cmd.exe /C echo hello"
end
- IO.read(cmd, 1).should == "h"
+
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read(cmd, 1).should == "h"
+ end
end
platform_is_not :windows do
it "raises Errno::ESPIPE if passed an offset" do
-> {
- IO.read("|sh -c 'echo hello'", 1, 1)
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read("|sh -c 'echo hello'", 1, 1)
+ end
}.should raise_error(Errno::ESPIPE)
end
end
@@ -204,11 +223,23 @@ quarantine! do # The process tried to write to a nonexistent pipe.
# once https://bugs.ruby-lang.org/issues/12230 is fixed.
it "raises Errno::EINVAL if passed an offset" do
-> {
- IO.read("|cmd.exe /C echo hello", 1, 1)
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read("|cmd.exe /C echo hello", 1, 1)
+ end
}.should raise_error(Errno::EINVAL)
end
end
end
+
+ ruby_version_is "3.3" do
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation given a path with a pipe" do
+ cmd = "|echo ok"
+ -> {
+ IO.read(cmd)
+ }.should complain(/IO process creation with a leading '\|'/)
+ end
+ end
end
describe "IO.read on an empty file" do
@@ -252,21 +283,55 @@ 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_error(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_error(FrozenError)
+ -> { @io.read(1, 'frozen-string'.freeze) }.should raise_error(FrozenError)
+ -> { @io.read(nil, 'frozen-string'.freeze) }.should raise_error(FrozenError)
+ end
+
+ ruby_bug "", ""..."3.3" do
+ it "raise FrozenError if the output buffer is frozen (2)" do
+ @io.read
+ -> { @io.read(1, ''.freeze) }.should raise_error(FrozenError)
+ end
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
@@ -279,53 +344,68 @@ 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
end
it "returns the given buffer when there is nothing to read" do
- buf = ""
+ 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)
@@ -523,13 +603,13 @@ describe :io_read_internal_encoding, shared: true do
describe "when passed nil for limit" do
it "sets the buffer to a transcoded String" do
- result = @io.read(nil, buf = "")
+ 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)
end
@@ -543,17 +623,18 @@ describe :io_read_size_internal_encoding, shared: true do
it "returns a String in BINARY when passed a size" do
@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)
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
diff --git a/spec/ruby/core/io/readline_spec.rb b/spec/ruby/core/io/readline_spec.rb
index cf9f0dfc11..a814c1be90 100644
--- a/spec/ruby/core/io/readline_spec.rb
+++ b/spec/ruby/core/io/readline_spec.rb
@@ -73,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_error(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_error(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 43d0750a72..3a6ff3d0f3 100644
--- a/spec/ruby/core/io/readlines_spec.rb
+++ b/spec/ruby/core/io/readlines_spec.rb
@@ -117,14 +117,12 @@ 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_error(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_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
end
end
@@ -182,13 +180,20 @@ describe "IO.readlines" do
platform_is :windows do
cmd = "|cmd.exe /C echo hello&echo line2"
end
- lines = IO.readlines(cmd)
+
+ lines = nil
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ lines = IO.readlines(cmd)
+ end
lines.should == ["hello\n", "line2\n"]
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("|-")
+ end
if lines # parent
lines.should == ["hello\n", "from a fork\n"]
@@ -201,6 +206,16 @@ describe "IO.readlines" do
end
end
+ ruby_version_is "3.3" do
+ # 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
it_behaves_like :io_readlines_options_19, :readlines
end
diff --git a/spec/ruby/core/io/readpartial_spec.rb b/spec/ruby/core/io/readpartial_spec.rb
index 2901b429c2..0852f20b2d 100644
--- a/spec/ruby/core/io/readpartial_spec.rb
+++ b/spec/ruby/core/io/readpartial_spec.rb
@@ -59,10 +59,10 @@ describe "IO#readpartial" do
end
it "discards the existing buffer content upon successful read" do
- buffer = "existing content"
+ 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
@@ -74,7 +74,7 @@ describe "IO#readpartial" do
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
@@ -95,7 +95,7 @@ describe "IO#readpartial" do
ruby_bug "#18421", ""..."3.0.4" do
it "clears and returns the given buffer if the length argument is 0" do
- buffer = "existing content"
+ buffer = +"existing content"
@rd.readpartial(0, buffer).should == buffer
buffer.should == ""
end
@@ -106,6 +106,7 @@ describe "IO#readpartial" do
@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/select_spec.rb b/spec/ruby/core/io/select_spec.rb
index 4603c1fbbc..3893e7620f 100644
--- a/spec/ruby/core/io/select_spec.rb
+++ b/spec/ruby/core/io/select_spec.rb
@@ -55,8 +55,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 +64,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")
@@ -103,6 +114,39 @@ describe "IO.select" do
it "raises an ArgumentError when passed a negative timeout" do
-> { IO.select(nil, nil, nil, -5)}.should raise_error(ArgumentError)
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
diff --git a/spec/ruby/core/io/shared/binwrite.rb b/spec/ruby/core/io/shared/binwrite.rb
index 950a6f51ab..e51093329b 100644
--- a/spec/ruby/core/io/shared/binwrite.rb
+++ b/spec/ruby/core/io/shared/binwrite.rb
@@ -21,14 +21,12 @@ describe :io_binwrite, shared: true do
IO.send(@method, @filename, "abcde").should == 5
end
- ruby_version_is "3.0" do
- it "accepts options as a keyword argument" do
- IO.send(@method, @filename, "hi", 0, flags: File::CREAT).should == 2
+ 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_error(ArgumentError, "wrong number of arguments (given 4, expected 2..3)")
- end
+ -> {
+ IO.send(@method, @filename, "hi", 0, {flags: File::CREAT})
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 2..3)")
end
it "creates a file if missing" do
diff --git a/spec/ruby/core/io/shared/each.rb b/spec/ruby/core/io/shared/each.rb
index 02bbe19c1a..aca622834f 100644
--- a/spec/ruby/core/io/shared/each.rb
+++ b/spec/ruby/core/io/shared/each.rb
@@ -33,10 +33,6 @@ 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)
end
@@ -180,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_error(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_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
end
end
diff --git a/spec/ruby/core/io/shared/new.rb b/spec/ruby/core/io/shared/new.rb
index da4c0af7a9..cba5f33ebf 100644
--- a/spec/ruby/core/io/shared/new.rb
+++ b/spec/ruby/core/io/shared/new.rb
@@ -1,6 +1,6 @@
require_relative '../fixtures/classes'
-# NOTE: should be syncronized with library/stringio/initialize_spec.rb
+# 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.
@@ -64,15 +64,13 @@ describe :io_new, shared: true do
@io.should be_an_instance_of(IO)
end
- ruby_version_is "3.0" do
- it "accepts options as keyword arguments" do
- @io = IO.send(@method, @fd, "w", flags: File::CREAT)
- @io.write("foo").should == 3
+ 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_error(ArgumentError, "wrong number of arguments (given 3, expected 1..2)")
- end
+ -> {
+ IO.send(@method, @fd, "w", {flags: File::CREAT})
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 1..2)")
end
it "accepts a :mode option" do
@@ -210,21 +208,10 @@ 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
- 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 "raises ArgumentError for nil options" do
+ -> {
+ IO.send(@method, @fd, 'w', nil)
+ }.should raise_error(ArgumentError)
end
it "coerces mode with #to_str" do
@@ -395,21 +382,9 @@ describe :io_new_errors, shared: true do
}.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
- 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_error(ArgumentError)
end
end
diff --git a/spec/ruby/core/io/shared/readlines.rb b/spec/ruby/core/io/shared/readlines.rb
index 7681e1b5c1..6c1fa11a59 100644
--- a/spec/ruby/core/io/shared/readlines.rb
+++ b/spec/ruby/core/io/shared/readlines.rb
@@ -99,18 +99,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_error(TypeError)
end
end
@@ -179,12 +177,10 @@ describe :io_readlines_options_19, shared: true do
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_error(TypeError)
end
end
end
diff --git a/spec/ruby/core/io/stat_spec.rb b/spec/ruby/core/io/stat_spec.rb
index 58eba02b8f..717c45d0a3 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
diff --git a/spec/ruby/core/io/sysread_spec.rb b/spec/ruby/core/io/sysread_spec.rb
index e7f63cefec..8851214283 100644
--- a/spec/ruby/core/io/sysread_spec.rb
+++ b/spec/ruby/core/io/sysread_spec.rb
@@ -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"
@@ -90,23 +90,30 @@ describe "IO#sysread on a file" do
end
it "immediately returns the given buffer if the length argument is 0" do
- buffer = "existing content"
+ 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)
+ 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"
+ buffer = +"existing content"
@file.seek(0, :END)
-> { @file.sysread(1, buffer) }.should raise_error(EOFError)
buffer.should be_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
describe "IO#sysread" do
diff --git a/spec/ruby/core/io/ungetc_spec.rb b/spec/ruby/core/io/ungetc_spec.rb
index 41a455c836..47a4e99ebf 100644
--- a/spec/ruby/core/io/ungetc_spec.rb
+++ b/spec/ruby/core/io/ungetc_spec.rb
@@ -103,19 +103,9 @@ describe "IO#ungetc" do
-> { @io.sysread(1) }.should raise_error(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_error(TypeError)
end
it "puts one or more characters back in the stream" do
diff --git a/spec/ruby/core/io/write_spec.rb b/spec/ruby/core/io/write_spec.rb
index bf23634372..4a26f8dbaf 100644
--- a/spec/ruby/core/io/write_spec.rb
+++ b/spec/ruby/core/io/write_spec.rb
@@ -203,18 +203,33 @@ 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 "3.3" 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
@@ -259,25 +274,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/Float_spec.rb b/spec/ruby/core/kernel/Float_spec.rb
index 015bcb33d6..0f83cb5824 100644
--- a/spec/ruby/core/kernel/Float_spec.rb
+++ b/spec/ruby/core/kernel/Float_spec.rb
@@ -41,7 +41,7 @@ describe :kernel_float, shared: true do
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
diff --git a/spec/ruby/core/kernel/Integer_spec.rb b/spec/ruby/core/kernel/Integer_spec.rb
index c691cb4c41..74dd3e0dd2 100644
--- a/spec/ruby/core/kernel/Integer_spec.rb
+++ b/spec/ruby/core/kernel/Integer_spec.rb
@@ -145,7 +145,7 @@ 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)
end
@@ -348,7 +348,7 @@ describe "Integer() given a String", shared: true do
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)
end
@@ -586,6 +586,21 @@ describe "Integer() given a String and base", shared: true do
Integer("777", obj).should == 0777
end
+ # https://bugs.ruby-lang.org/issues/19349
+ ruby_version_is ''...'3.3' do
+ it "ignores the base if it is not an integer and does not respond to #to_i" do
+ Integer("777", "8").should == 777
+ end
+ end
+
+ ruby_version_is '3.3' do
+ it "raises a TypeError if it is not an integer and does not respond to #to_i" do
+ -> {
+ Integer("777", "8")
+ }.should raise_error(TypeError, "no implicit conversion of String into Integer")
+ end
+ end
+
describe "when passed exception: false" do
describe "and valid argument" do
it "returns an Integer number" do
@@ -784,9 +799,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
@@ -798,9 +813,9 @@ 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)
diff --git a/spec/ruby/core/kernel/String_spec.rb b/spec/ruby/core/kernel/String_spec.rb
index 47ee797be5..7caec6eda5 100644
--- a/spec/ruby/core/kernel/String_spec.rb
+++ b/spec/ruby/core/kernel/String_spec.rb
@@ -78,7 +78,7 @@ describe :kernel_String, shared: true do
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)
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/caller_locations_spec.rb b/spec/ruby/core/kernel/caller_locations_spec.rb
index 5994b28fa3..aaacd9a910 100644
--- a/spec/ruby/core/kernel/caller_locations_spec.rb
+++ b/spec/ruby/core/kernel/caller_locations_spec.rb
@@ -71,14 +71,28 @@ 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" 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
end
end
diff --git a/spec/ruby/core/kernel/caller_spec.rb b/spec/ruby/core/kernel/caller_spec.rb
index f1ff7044b8..c3d63ccb00 100644
--- a/spec/ruby/core/kernel/caller_spec.rb
+++ b/spec/ruby/core/kernel/caller_spec.rb
@@ -38,10 +38,9 @@ describe 'Kernel#caller' do
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 "works with endless ranges" do
@@ -63,8 +62,7 @@ describe 'Kernel#caller' do
loc = nil
tap { loc = caller(1, 1)[0] }
- loc.should.end_with? "in `tap'"
- loc.should.start_with? "<internal:"
+ loc.should =~ /\A<internal:.*in [`'](?:Kernel#)?tap'\z/
end
end
end
diff --git a/spec/ruby/core/kernel/catch_spec.rb b/spec/ruby/core/kernel/catch_spec.rb
index 4060172429..9f59d3b384 100644
--- a/spec/ruby/core/kernel/catch_spec.rb
+++ b/spec/ruby/core/kernel/catch_spec.rb
@@ -35,7 +35,7 @@ describe "Kernel.catch" do
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_error(ArgumentError)
end
it "catches a Symbol when thrown a matching Symbol" do
diff --git a/spec/ruby/core/kernel/class_spec.rb b/spec/ruby/core/kernel/class_spec.rb
index 2725bde19b..b1d9df1671 100644
--- a/spec/ruby/core/kernel/class_spec.rb
+++ b/spec/ruby/core/kernel/class_spec.rb
@@ -19,7 +19,7 @@ describe "Kernel#class" do
end
it "returns the first non-singleton class" do
- a = "hello"
+ a = +"hello"
def a.my_singleton_method; end
a.class.should equal(String)
end
diff --git a/spec/ruby/core/kernel/clone_spec.rb b/spec/ruby/core/kernel/clone_spec.rb
index a87c7544fe..5adcbbe603 100644
--- a/spec/ruby/core/kernel/clone_spec.rb
+++ b/spec/ruby/core/kernel/clone_spec.rb
@@ -45,26 +45,18 @@ describe "Kernel#clone" do
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 be_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_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
end
end
@@ -114,25 +92,15 @@ 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_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
end
end
diff --git a/spec/ruby/core/kernel/eval_spec.rb b/spec/ruby/core/kernel/eval_spec.rb
index 9be0f2dfd3..454bc4a58e 100644
--- a/spec/ruby/core/kernel/eval_spec.rb
+++ b/spec/ruby/core/kernel/eval_spec.rb
@@ -135,7 +135,7 @@ describe "Kernel#eval" do
it "includes file and line information in syntax error" do
expected = 'speccing.rb'
-> {
- eval('if true',TOPLEVEL_BINDING, expected)
+ eval('if true', TOPLEVEL_BINDING, expected)
}.should raise_error(SyntaxError) { |e|
e.message.should =~ /#{expected}:1:.+/
}
@@ -144,7 +144,7 @@ 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)
+ eval('if true', TOPLEVEL_BINDING, expected_file, -100)
}.should raise_error(SyntaxError) { |e|
e.message.should =~ /#{expected_file}:-100:.+/
}
@@ -159,24 +159,7 @@ 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'
- end
-
- it 'uses the given binding file and line for __FILE__ and __LINE__' do
- suppress_warning {
- eval("[__FILE__, __LINE__]", binding).should == [__FILE__, __LINE__]
- }
- end
- end
-
- ruby_version_is "3.0" do
+ ruby_version_is ""..."3.3" do
it "uses (eval) filename if none is provided" do
eval("__FILE__").should == "(eval)"
eval("__FILE__", binding).should == "(eval)"
@@ -192,6 +175,21 @@ describe "Kernel#eval" do
end
end
+ ruby_version_is "3.3" do
+ 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
+ end
# Found via Rubinius bug github:#149
it "does not alter the value of __FILE__ in the binding" do
first_time = EvalSpecs.call_eval
@@ -228,6 +226,20 @@ describe "Kernel#eval" 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"
@@ -249,6 +261,19 @@ describe "Kernel#eval" do
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
+
# See language/magic_comment_spec.rb for more magic comments specs
describe "with a magic encoding comment" do
it "uses the magic comment encoding for the encoding of literal strings" do
@@ -325,12 +350,11 @@ CODE
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
@@ -340,7 +364,7 @@ CODE
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
end
it "allows a magic encoding comment and a frozen_string_literal magic comment on the same line in emacs style" do
@@ -359,8 +383,9 @@ CODE
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"
@@ -374,23 +399,24 @@ CODE
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
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..3d9520ad67 100644
--- a/spec/ruby/core/kernel/exec_spec.rb
+++ b/spec/ruby/core/kernel/exec_spec.rb
@@ -7,12 +7,12 @@ describe "Kernel#exec" do
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/initialize_clone_spec.rb b/spec/ruby/core/kernel/initialize_clone_spec.rb
index 2d889f5aad..21a90c19f0 100644
--- a/spec/ruby/core/kernel/initialize_clone_spec.rb
+++ b/spec/ruby/core/kernel/initialize_clone_spec.rb
@@ -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..d71ca9f60f 100644
--- a/spec/ruby/core/kernel/initialize_copy_spec.rb
+++ b/spec/ruby/core/kernel/initialize_copy_spec.rb
@@ -1,11 +1,18 @@
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
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/lambda_spec.rb b/spec/ruby/core/kernel/lambda_spec.rb
index 2aa4d4f2fb..565536ac0d 100644
--- a/spec/ruby/core/kernel/lambda_spec.rb
+++ b/spec/ruby/core/kernel/lambda_spec.rb
@@ -26,42 +26,44 @@ describe "Kernel.lambda" do
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
+ ruby_version_is ""..."3.3" do
+ 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
- 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 "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
+ 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)
+ lambda { l.call(:extra) }.should raise_error(ArgumentError)
+ end
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 "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
+ 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
+ end
end
it "checks the arity of the call when no args are specified" do
@@ -136,15 +138,21 @@ describe "Kernel.lambda" do
klass.new.ret.should == 1
end
- ruby_version_is "3.0" do
- context "when called without a literal block" do
+ context "when called without a literal block" do
+ ruby_version_is ""..."3.3" 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
+ end
- it "doesn't warn when proc is lambda" do
- -> { lambda(&lambda{}) }.should_not complain(verbose: true)
+ ruby_version_is "3.3" do
+ it "raises when proc isn't a lambda" do
+ -> { lambda(&proc{}) }.should raise_error(ArgumentError, /the lambda method requires a literal block/)
end
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/not_match_spec.rb b/spec/ruby/core/kernel/not_match_spec.rb
index 906f18df2c..f8dd82fad8 100644
--- a/spec/ruby/core/kernel/not_match_spec.rb
+++ b/spec/ruby/core/kernel/not_match_spec.rb
@@ -14,6 +14,20 @@ describe "Kernel#!~" do
(obj !~ :foo).should == false
end
+ ruby_version_is ""..."3.2" do
+ it "returns true if self does not respond to #=~" do
+ suppress_warning do
+ (Object.new !~ :foo).should == true
+ end
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "raises NoMethodError if self does not respond to #=~" do
+ -> { Object.new !~ :foo }.should raise_error(NoMethodError)
+ end
+ 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 bad2ae9d2c..bb42c31f31 100644
--- a/spec/ruby/core/kernel/open_spec.rb
+++ b/spec/ruby/core/kernel/open_spec.rb
@@ -29,7 +29,9 @@ describe "Kernel#open" do
platform_is_not :windows, :wasi do
it "opens an io when path starts with a pipe" do
- @io = open("|date")
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @io = open("|date")
+ end
begin
@io.should be_kind_of(IO)
@io.read
@@ -39,21 +41,27 @@ describe "Kernel#open" do
end
it "opens an io when called with a block" do
- @output = open("|date") { |f| f.read }
+ 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(".")
+ 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
platform_is :windows do
it "opens an io when path starts with a pipe" do
- @io = open("|date /t")
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @io = open("|date /t")
+ end
begin
@io.should be_kind_of(IO)
@io.read
@@ -63,24 +71,34 @@ describe "Kernel#open" do
end
it "opens an io when called with a block" do
- @output = open("|date /t") { |f| f.read }
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @output = open("|date /t") { |f| f.read }
+ end
@output.should_not == ''
end
end
+ ruby_version_is "3.3" do
+ # 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)
end
- ruby_version_is "3.0" do
- it "accepts options as keyword arguments" do
- @file = open(@name, "r", 0666, flags: File::CREAT)
- @file.should be_kind_of(File)
+ it "accepts options as keyword arguments" do
+ @file = open(@name, "r", 0666, flags: File::CREAT)
+ @file.should be_kind_of(File)
- -> {
- open(@name, "r", 0666, {flags: File::CREAT})
- }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
- end
+ -> {
+ open(@name, "r", 0666, {flags: File::CREAT})
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
describe "when given an object that responds to to_open" do
@@ -158,28 +176,14 @@ describe "Kernel#open" 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/printf_spec.rb b/spec/ruby/core/kernel/printf_spec.rb
index d8f93ce429..61bf955c25 100644
--- a/spec/ruby/core/kernel/printf_spec.rb
+++ b/spec/ruby/core/kernel/printf_spec.rb
@@ -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/proc_spec.rb b/spec/ruby/core/kernel/proc_spec.rb
index 231c1f0dfb..6553b8fd04 100644
--- a/spec/ruby/core/kernel/proc_spec.rb
+++ b/spec/ruby/core/kernel/proc_spec.rb
@@ -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_error(ArgumentError, 'tried to create Proc object without a block')
end
end
diff --git a/spec/ruby/core/kernel/public_send_spec.rb b/spec/ruby/core/kernel/public_send_spec.rb
index 4dae419ff9..b684b1729c 100644
--- a/spec/ruby/core/kernel/public_send_spec.rb
+++ b/spec/ruby/core/kernel/public_send_spec.rb
@@ -105,11 +105,11 @@ describe "Kernel#public_send" do
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_error(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_error(TypeError) { |e| e.backtrace[0].should =~ /[`'](?:Kernel#)?public_send'/ }
end
it_behaves_like :basicobject_send, :public_send
diff --git a/spec/ruby/core/kernel/require_relative_spec.rb b/spec/ruby/core/kernel/require_relative_spec.rb
index 5999855de6..6188d13a4e 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
@@ -92,7 +92,7 @@ describe "Kernel#require_relative with a relative path" do
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__))
+ expanded_missing_path = File.expand_path(missing_path, __dir__)
-> { require_relative(missing_path) }.should raise_error(LoadError) { |e|
e.message.should include(expanded_missing_path)
e.path.should == expanded_missing_path
@@ -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
diff --git a/spec/ruby/core/kernel/require_spec.rb b/spec/ruby/core/kernel/require_spec.rb
index 896afb840a..4029e68725 100644
--- a/spec/ruby/core/kernel/require_spec.rb
+++ b/spec/ruby/core/kernel/require_spec.rb
@@ -26,7 +26,7 @@ describe "Kernel#require" do
features = out.lines.map { |line| File.basename(line.chomp, '.*') }
# Ignore CRuby internals
- features -= %w[encdb transdb windows_1252]
+ features -= %w[encdb transdb windows_1252 windows_31j]
features.reject! { |feature| feature.end_with?('-fake') }
features.sort.should == provided.sort
diff --git a/spec/ruby/core/kernel/shared/load.rb b/spec/ruby/core/kernel/shared/load.rb
index 5c41c19bf6..0fe2d5ce16 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,22 +11,31 @@ 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 be_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 be_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 be_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_error(LoadError)
end
end
diff --git a/spec/ruby/core/kernel/shared/require.rb b/spec/ruby/core/kernel/shared/require.rb
index 5cbc11c9ec..250813191b 100644
--- a/spec/ruby/core/kernel/shared/require.rb
+++ b/spec/ruby/core/kernel/shared/require.rb
@@ -212,6 +212,34 @@ 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 be_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_error(Exception, /file too short|not a mach-o file/)
+ 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_error(Exception, /load_fixture\.bundle.+(file too short|not a mach-o file)/)
+ 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_error(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
@@ -262,13 +290,11 @@ describe :kernel_require, shared: true do
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 be_true
+ $LOAD_PATH.replace [File.expand_path("b", CODE_LOADING_DIR), CODE_LOADING_DIR]
+ @object.require("load_fixture").should be_false
end
end
@@ -566,23 +592,21 @@ describe :kernel_require, shared: true do
-> { @object.require("unicode_normalize") }.should raise_error(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 be_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 be_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 be_false
+ ScratchPad.recorded.should == [:loaded, :loaded]
end
end
diff --git a/spec/ruby/core/kernel/shared/sprintf.rb b/spec/ruby/core/kernel/shared/sprintf.rb
index 2db50bd686..13dc6e97f0 100644
--- a/spec/ruby/core/kernel/shared/sprintf.rb
+++ b/spec/ruby/core/kernel/shared/sprintf.rb
@@ -356,13 +356,13 @@ describe :kernel_sprintf, shared: true do
it "raises TypeError if converting to Integer with to_int returns non-Integer" do
obj = BasicObject.new
- def obj.to_str
+ def obj.to_int
:foo
end
-> {
@method.call("%c", obj)
- }.should raise_error(TypeError, /can't convert BasicObject to String/)
+ }.should raise_error(TypeError, /can't convert BasicObject to Integer/)
end
end
diff --git a/spec/ruby/core/kernel/shared/sprintf_encoding.rb b/spec/ruby/core/kernel/shared/sprintf_encoding.rb
index 9cedb8b662..7ec0fe4c48 100644
--- a/spec/ruby/core/kernel/shared/sprintf_encoding.rb
+++ b/spec/ruby/core/kernel/shared/sprintf_encoding.rb
@@ -14,14 +14,14 @@ describe :kernel_sprintf_encoding, shared: true do
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)
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)
@@ -56,7 +56,7 @@ describe :kernel_sprintf_encoding, shared: true do
end
it "uses the encoding of the format string to interpret codepoints" do
- format = "%c".force_encoding("euc-jp")
+ format = "%c".dup.force_encoding("euc-jp")
result = @method.call(format, 9415601)
result.encoding.should == Encoding::EUC_JP
diff --git a/spec/ruby/core/kernel/singleton_class_spec.rb b/spec/ruby/core/kernel/singleton_class_spec.rb
index 4865e29c10..23c400f9bd 100644
--- a/spec/ruby/core/kernel/singleton_class_spec.rb
+++ b/spec/ruby/core/kernel/singleton_class_spec.rb
@@ -1,3 +1,4 @@
+# truffleruby_primitives: true
require_relative '../../spec_helper'
describe "Kernel#singleton_class" do
@@ -42,4 +43,32 @@ describe "Kernel#singleton_class" do
obj.freeze
obj.singleton_class.frozen?.should be_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/sleep_spec.rb b/spec/ruby/core/kernel/sleep_spec.rb
index 44b417a92e..0570629723 100644
--- a/spec/ruby/core/kernel/sleep_spec.rb
+++ b/spec/ruby/core/kernel/sleep_spec.rb
@@ -1,5 +1,4 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
describe "Kernel#sleep" do
it "is a private method" do
diff --git a/spec/ruby/core/kernel/sprintf_spec.rb b/spec/ruby/core/kernel/sprintf_spec.rb
index 7adf71be76..9ef7f86f16 100644
--- a/spec/ruby/core/kernel/sprintf_spec.rb
+++ b/spec/ruby/core/kernel/sprintf_spec.rb
@@ -3,6 +3,14 @@ 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)
@@ -11,6 +19,10 @@ describe "Kernel#sprintf" do
it_behaves_like :kernel_sprintf_encoding, -> format, *args {
sprintf(format, *args)
}
+
+ it_behaves_like :kernel_sprintf_to_str, -> format, *args {
+ sprintf(format, *args)
+ }
end
describe "Kernel.sprintf" do
@@ -21,4 +33,8 @@ describe "Kernel.sprintf" do
it_behaves_like :kernel_sprintf_encoding, -> format, *args {
Kernel.sprintf(format, *args)
}
+
+ it_behaves_like :kernel_sprintf_to_str, -> format, *args {
+ Kernel.sprintf(format, *args)
+ }
end
diff --git a/spec/ruby/core/kernel/system_spec.rb b/spec/ruby/core/kernel/system_spec.rb
index 9671a650cc..9bc03924dd 100644
--- a/spec/ruby/core/kernel/system_spec.rb
+++ b/spec/ruby/core/kernel/system_spec.rb
@@ -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'
diff --git a/spec/ruby/core/kernel/taint_spec.rb b/spec/ruby/core/kernel/taint_spec.rb
index eff9b4a450..0c16b1dbbf 100644
--- a/spec/ruby/core/kernel/taint_spec.rb
+++ b/spec/ruby/core/kernel/taint_spec.rb
@@ -4,9 +4,11 @@ require_relative 'fixtures/classes'
describe "Kernel#taint" do
ruby_version_is ""..."3.2" do
it "is a no-op" do
- o = Object.new
- o.taint
- o.should_not.tainted?
+ suppress_warning do
+ o = Object.new
+ o.taint
+ o.should_not.tainted?
+ end
end
it "warns in verbose mode" do
diff --git a/spec/ruby/core/kernel/tainted_spec.rb b/spec/ruby/core/kernel/tainted_spec.rb
index 4e81971e58..fcae433069 100644
--- a/spec/ruby/core/kernel/tainted_spec.rb
+++ b/spec/ruby/core/kernel/tainted_spec.rb
@@ -4,11 +4,13 @@ require_relative 'fixtures/classes'
describe "Kernel#tainted?" do
ruby_version_is ""..."3.2" do
it "is a no-op" do
- o = mock('o')
- p = mock('p')
- p.taint
- o.should_not.tainted?
- p.should_not.tainted?
+ suppress_warning do
+ o = mock('o')
+ p = mock('p')
+ p.taint
+ o.should_not.tainted?
+ p.should_not.tainted?
+ end
end
it "warns in verbose mode" do
diff --git a/spec/ruby/core/kernel/test_spec.rb b/spec/ruby/core/kernel/test_spec.rb
index abb365aed2..d26dc06361 100644
--- a/spec/ruby/core/kernel/test_spec.rb
+++ b/spec/ruby/core/kernel/test_spec.rb
@@ -3,8 +3,8 @@ 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
diff --git a/spec/ruby/core/kernel/trust_spec.rb b/spec/ruby/core/kernel/trust_spec.rb
index 3a49ab3085..db6f17e0fb 100644
--- a/spec/ruby/core/kernel/trust_spec.rb
+++ b/spec/ruby/core/kernel/trust_spec.rb
@@ -4,10 +4,12 @@ require_relative 'fixtures/classes'
describe "Kernel#trust" do
ruby_version_is ""..."3.2" do
it "is a no-op" do
- o = Object.new.untrust
- o.should_not.untrusted?
- o.trust
- o.should_not.untrusted?
+ suppress_warning do
+ o = Object.new.untrust
+ o.should_not.untrusted?
+ o.trust
+ o.should_not.untrusted?
+ end
end
it "warns in verbose mode" do
diff --git a/spec/ruby/core/kernel/untaint_spec.rb b/spec/ruby/core/kernel/untaint_spec.rb
index a543025c5d..26b2aabbe9 100644
--- a/spec/ruby/core/kernel/untaint_spec.rb
+++ b/spec/ruby/core/kernel/untaint_spec.rb
@@ -4,10 +4,12 @@ require_relative 'fixtures/classes'
describe "Kernel#untaint" do
ruby_version_is ""..."3.2" do
it "is a no-op" do
- o = Object.new.taint
- o.should_not.tainted?
- o.untaint
- o.should_not.tainted?
+ suppress_warning do
+ o = Object.new.taint
+ o.should_not.tainted?
+ o.untaint
+ o.should_not.tainted?
+ end
end
it "warns in verbose mode" do
diff --git a/spec/ruby/core/kernel/untrust_spec.rb b/spec/ruby/core/kernel/untrust_spec.rb
index 6eefb624c0..5310cd8eb4 100644
--- a/spec/ruby/core/kernel/untrust_spec.rb
+++ b/spec/ruby/core/kernel/untrust_spec.rb
@@ -4,9 +4,11 @@ require_relative 'fixtures/classes'
describe "Kernel#untrust" do
ruby_version_is ""..."3.2" do
it "is a no-op" do
- o = Object.new
- o.untrust
- o.should_not.untrusted?
+ suppress_warning do
+ o = Object.new
+ o.untrust
+ o.should_not.untrusted?
+ end
end
it "warns in verbose mode" do
diff --git a/spec/ruby/core/kernel/untrusted_spec.rb b/spec/ruby/core/kernel/untrusted_spec.rb
index bd0bf154ed..ea36d6c98c 100644
--- a/spec/ruby/core/kernel/untrusted_spec.rb
+++ b/spec/ruby/core/kernel/untrusted_spec.rb
@@ -4,10 +4,12 @@ require_relative 'fixtures/classes'
describe "Kernel#untrusted?" do
ruby_version_is ""..."3.2" do
it "is a no-op" do
- o = mock('o')
- o.should_not.untrusted?
- o.untrust
- o.should_not.untrusted?
+ suppress_warning do
+ o = mock('o')
+ o.should_not.untrusted?
+ o.untrust
+ o.should_not.untrusted?
+ end
end
it "warns in verbose mode" do
diff --git a/spec/ruby/core/kernel/warn_spec.rb b/spec/ruby/core/kernel/warn_spec.rb
index 7df6fa72d1..00164ad90b 100644
--- a/spec/ruby/core/kernel/warn_spec.rb
+++ b/spec/ruby/core/kernel/warn_spec.rb
@@ -128,36 +128,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_error(TypeError)
end
it "converts first arg using to_s" do
@@ -212,67 +210,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/private_spec.rb b/spec/ruby/core/main/private_spec.rb
index cac0645b40..e8c1f3f44c 100644
--- a/spec/ruby/core/main/private_spec.rb
+++ b/spec/ruby/core/main/private_spec.rb
@@ -22,13 +22,11 @@ describe "main#private" do
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
+ 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
diff --git a/spec/ruby/core/main/public_spec.rb b/spec/ruby/core/main/public_spec.rb
index 91f045dbab..31baad4583 100644
--- a/spec/ruby/core/main/public_spec.rb
+++ b/spec/ruby/core/main/public_spec.rb
@@ -22,13 +22,11 @@ describe "main#public" do
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
+ 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
diff --git a/spec/ruby/core/marshal/dump_spec.rb b/spec/ruby/core/marshal/dump_spec.rb
index f38250b513..0f77279a4f 100644
--- a/spec/ruby/core/marshal/dump_spec.rb
+++ b/spec/ruby/core/marshal/dump_spec.rb
@@ -76,7 +76,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
@@ -85,8 +85,8 @@ 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}"
@@ -150,7 +150,7 @@ describe "Marshal.dump" do
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 = +"<dump>"
s.instance_variable_set(:@foo, "bar")
s
end
@@ -194,7 +194,7 @@ describe "Marshal.dump" do
end
it "dumps a class with multibyte characters in name" do
- source_object = eval("MarshalSpec::MultibyteぁあぃいClass".force_encoding(Encoding::UTF_8))
+ source_object = eval("MarshalSpec::MultibyteぁあぃいClass".dup.force_encoding(Encoding::UTF_8))
Marshal.dump(source_object).should == "\x04\bc,MarshalSpec::Multibyte\xE3\x81\x81\xE3\x81\x82\xE3\x81\x83\xE3\x81\x84Class"
end
@@ -217,7 +217,7 @@ describe "Marshal.dump" do
end
it "dumps a module with multibyte characters in name" do
- source_object = eval("MarshalSpec::MultibyteけげこごModule".force_encoding(Encoding::UTF_8))
+ source_object = eval("MarshalSpec::MultibyteけげこごModule".dup.force_encoding(Encoding::UTF_8))
Marshal.dump(source_object).should == "\x04\bm-MarshalSpec::Multibyte\xE3\x81\x91\xE3\x81\x92\xE3\x81\x93\xE3\x81\x94Module"
end
@@ -271,13 +271,25 @@ describe "Marshal.dump" do
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
+ end
+
+ describe "with a Complex" do
+ it "dumps a Complex" do
+ Marshal.dump(Complex(2, 3)).should == "\x04\bU:\fComplex[\ai\ai\b"
+ 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
@@ -285,7 +297,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
@@ -302,23 +314,23 @@ describe "Marshal.dump" do
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
@@ -352,7 +364,7 @@ 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
@@ -371,18 +383,18 @@ describe "Marshal.dump" do
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".force_encoding("utf-8"), Regexp::FIXEDENCODING)
+ 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".force_encoding("utf-8"), Regexp::FIXEDENCODING)
+ 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)
@@ -541,7 +553,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
@@ -626,17 +638,6 @@ describe "Marshal.dump" do
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
- end
-
it "raises TypeError with an anonymous Range subclass" do
-> { Marshal.dump(Class.new(Range).new(1, 2)) }.should raise_error(TypeError, /can't dump anonymous class/)
end
@@ -684,7 +685,7 @@ describe "Marshal.dump" do
end
it "dumps a Time subclass with multibyte characters in name" do
- source_object = eval("MarshalSpec::MultibyteぁあぃいTime".force_encoding(Encoding::UTF_8))
+ source_object = eval("MarshalSpec::MultibyteぁあぃいTime".dup.force_encoding(Encoding::UTF_8))
Marshal.dump(source_object).should == "\x04\bc+MarshalSpec::Multibyte\xE3\x81\x81\xE3\x81\x82\xE3\x81\x83\xE3\x81\x84Time"
end
@@ -739,7 +740,7 @@ describe "Marshal.dump" do
rescue => e
end
- Marshal.dump(e).should =~ /undefined method `foo' for ("":String|an instance of String)/
+ Marshal.dump(e).should =~ /undefined method [`']foo' for ("":String|an instance of String)/
end
it "raises TypeError if an Object is an instance of an anonymous class" do
@@ -780,7 +781,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)
@@ -803,8 +803,6 @@ describe "Marshal.dump" do
obj.should_receive(:binmode).at_least(1)
Marshal.dump("test", obj)
end
-
-
end
describe "when passed a StringIO" do
diff --git a/spec/ruby/core/marshal/fixtures/marshal_data.rb b/spec/ruby/core/marshal/fixtures/marshal_data.rb
index 680cb08ac7..a508b6bea1 100644
--- a/spec/ruby/core/marshal/fixtures/marshal_data.rb
+++ b/spec/ruby/core/marshal/fixtures/marshal_data.rb
@@ -38,7 +38,7 @@ class UserDefinedWithIvar
attr_reader :a, :b, :c
def initialize
- @a = 'stuff'
+ @a = +'stuff'
@a.instance_variable_set :@foo, :UserDefinedWithIvar
@b = 'more'
@c = @b
@@ -267,7 +267,7 @@ module MarshalSpec
end
end
- module_eval(<<~ruby.force_encoding(Encoding::UTF_8))
+ module_eval(<<~ruby.dup.force_encoding(Encoding::UTF_8))
class MultibyteぁあぃいClass
end
@@ -313,7 +313,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"],
@@ -420,7 +420,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"],
diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb
index bc094f28f2..f599042529 100644
--- a/spec/ruby/core/marshal/shared/load.rb
+++ b/spec/ruby/core/marshal/shared/load.rb
@@ -183,7 +183,7 @@ describe :marshal_load, shared: true do
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')
@@ -268,7 +268,7 @@ describe :marshal_load, shared: true do
it "loads an Array with proc" do
arr = []
- s = 'hi'
+ s = +'hi'
s.instance_variable_set(:@foo, 5)
st = Struct.new("Brittle", :a).new
st.instance_variable_set(:@clue, 'none')
@@ -413,13 +413,13 @@ 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_data = '\xff\xff'
+ marshal_data = +'\xff\xff'
marshal_data[0] = (Marshal::MAJOR_VERSION - 1).chr
marshal_data[1] = (Marshal::MINOR_VERSION).chr
@@ -470,7 +470,7 @@ 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)
@@ -516,7 +516,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'
@@ -600,7 +600,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
@@ -614,8 +614,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
@@ -623,11 +623,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_error(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
@@ -655,7 +663,7 @@ describe :marshal_load, shared: true do
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
@@ -663,7 +671,7 @@ describe :marshal_load, shared: true do
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
@@ -671,7 +679,7 @@ describe :marshal_load, shared: true do
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
@@ -679,12 +687,20 @@ describe :marshal_load, shared: true do
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_error(ArgumentError, "marshal data too short")
+ end
end
describe "for a Struct" do
@@ -807,7 +823,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
@@ -819,6 +835,14 @@ describe :marshal_load, shared: true do
Marshal.send(@method, "\x04\bo:\tFile\001\001:\001\005@path\"\x10/etc/passwd")
end.should raise_error(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_error(ArgumentError, "marshal data too short")
+ end
end
describe "for an object responding to #marshal_dump and #marshal_load" do
@@ -908,6 +932,14 @@ describe :marshal_load, shared: true do
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_error(ArgumentError, "marshal data too short")
+ end
end
describe "for a Float" do
@@ -929,6 +961,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_error(ArgumentError, "marshal data too short")
+ end
end
describe "for an Integer" do
@@ -994,13 +1034,17 @@ 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
@@ -1114,6 +1158,14 @@ describe :marshal_load, shared: true do
it "raises ArgumentError if given a nonexistent class" do
-> { Marshal.send(@method, "\x04\bc\vStrung") }.should raise_error(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_error(ArgumentError, "marshal data too short")
+ end
end
describe "for a Module" do
@@ -1128,6 +1180,14 @@ describe :marshal_load, shared: true do
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_error(ArgumentError, "marshal data too short")
+ end
end
describe "for a wrapped C pointer" do
diff --git a/spec/ruby/core/matchdata/begin_spec.rb b/spec/ruby/core/matchdata/begin_spec.rb
index 85c454da56..54b4e0a33f 100644
--- a/spec/ruby/core/matchdata/begin_spec.rb
+++ b/spec/ruby/core/matchdata/begin_spec.rb
@@ -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_error(IndexError, "index -1 out of matches")
+
+ -> {
+ match_data.begin(3)
+ }.should raise_error(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_error(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_error(IndexError, "undefined group name reference: y")
+ end
end
end
diff --git a/spec/ruby/core/matchdata/byteoffset_spec.rb b/spec/ruby/core/matchdata/byteoffset_spec.rb
index 6036097834..b27267fd0e 100644
--- a/spec/ruby/core/matchdata/byteoffset_spec.rb
+++ b/spec/ruby/core/matchdata/byteoffset_spec.rb
@@ -60,7 +60,7 @@ describe "MatchData#byteoffset" do
m.byteoffset(obj).should == [3, 6]
end
- it "raises IndexError if there is no group with provided name" do
+ it "raises IndexError if there is no group with the provided name" do
m = /(?<f>foo)(?<b>bar)/.match("foobar")
-> {
@@ -72,7 +72,7 @@ describe "MatchData#byteoffset" do
}.should raise_error(IndexError, "undefined group name reference: y")
end
- it "raises IndexError if index is out of matches" do
+ it "raises IndexError if index is out of bounds" do
m = /(?<f>foo)(?<b>bar)/.match("foobar")
-> {
diff --git a/spec/ruby/core/matchdata/element_reference_spec.rb b/spec/ruby/core/matchdata/element_reference_spec.rb
index 0e0d3991cb..806db2d7b5 100644
--- a/spec/ruby/core/matchdata/element_reference_spec.rb
+++ b/spec/ruby/core/matchdata/element_reference_spec.rb
@@ -48,11 +48,9 @@ describe "MatchData#[]" 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 be_an_instance_of(String) }
end
end
@@ -115,7 +113,7 @@ describe "MatchData#[Symbol]" do
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/post_match_spec.rb b/spec/ruby/core/matchdata/post_match_spec.rb
index d3aa4c8900..7bfe6df119 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 = "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 = "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 be_an_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..2f1ba9b8f6 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 = "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 = "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 be_an_instance_of(String)
end
end
diff --git a/spec/ruby/core/matchdata/shared/captures.rb b/spec/ruby/core/matchdata/shared/captures.rb
index d2c85ece5a..33f834561a 100644
--- a/spec/ruby/core/matchdata/shared/captures.rb
+++ b/spec/ruby/core/matchdata/shared/captures.rb
@@ -6,10 +6,8 @@ describe :matchdata_captures, shared: true do
/(.)(.)(\d+)(\d)/.match("THX1138.").send(@method).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).send(@method).each { |c| c.should be_an_instance_of(String) }
- 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 be_an_instance_of(String) }
end
end
diff --git a/spec/ruby/core/matchdata/string_spec.rb b/spec/ruby/core/matchdata/string_spec.rb
index 420233e1f3..952e953318 100644
--- a/spec/ruby/core/matchdata/string_spec.rb
+++ b/spec/ruby/core/matchdata/string_spec.rb
@@ -17,8 +17,9 @@ describe "MatchData#string" do
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..4fa11ff604 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 be_an_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..cd1c4dbca2 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 be_an_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 4fd0bfc42a..535719a2ee 100644
--- a/spec/ruby/core/matchdata/values_at_spec.rb
+++ b/spec/ruby/core/matchdata/values_at_spec.rb
@@ -1,6 +1,6 @@
require_relative '../../spec_helper'
-describe "Struct#values_at" do
+describe "MatchData#values_at" do
# 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"]
@@ -34,7 +34,7 @@ describe "Struct#values_at" do
end
it "supports beginningless Range" do
- /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..2).should == ["HX1138", "H", "X"]
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(..2).should == ["HX1138", "H", "X"]
end
it "returns an empty Array when Range is empty" 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/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/parameters_spec.rb b/spec/ruby/core/method/parameters_spec.rb
index 0f730fe013..8495aef4d2 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,14 @@ 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
+ def forward_parameters(...) end
+
def underscore_parameters(_, _, _ = 1, *_, _:, _: 2, **_, &_); end
define_method(:one_optional_defined_method) {|x = 1|}
@@ -178,6 +182,11 @@ 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
+
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]]
@@ -225,10 +234,15 @@ describe "Method#parameters" do
end
ruby_version_is '3.2' do
- it "adds * rest arg for \"star\" argument" do
+ it "adds rest arg with name * for \"star\" argument" do
m = MethodSpecs::Methods.new
m.method(:one_unnamed_splat).parameters.should == [[:rest, :*]]
end
+
+ 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
end
ruby_version_is ''...'3.2' do
@@ -236,6 +250,37 @@ describe "Method#parameters" do
m = MethodSpecs::Methods.new
m.method(:one_unnamed_splat).parameters.should == [[:rest]]
end
+
+ it "adds nameless keyrest arg for \"double star\" argument" do
+ m = MethodSpecs::Methods.new
+ m.method(:one_unnamed_keyrest).parameters.should == [[:keyrest]]
+ end
+ end
+
+ ruby_version_is '3.1' do
+ it "adds block arg with name & for anonymous block argument" do
+ object = Object.new
+
+ eval(<<~RUBY).should == [[:block, :&]]
+ def object.foo(&)
+ end
+ object.method(:foo).parameters
+ RUBY
+ end
+ end
+
+ ruby_version_is ""..."3.1" do
+ it "returns [:rest, :*], [:block, :&] for forward parameters operator" do
+ m = MethodSpecs::Methods.new
+ m.method(:forward_parameters).parameters.should == [[:rest, :*], [:block, :&]]
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "returns [:rest, :*], [:keyrest, :**], [:block, :&] for forward parameters operator" do
+ m = MethodSpecs::Methods.new
+ m.method(:forward_parameters).parameters.should == [[:rest, :*], [:keyrest, :**], [:block, :&]]
+ end
end
it "returns the args and block for a splat and block argument" 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..1a10b90689
--- /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/to_s.rb b/spec/ruby/core/method/shared/to_s.rb
index 6fdeaaf99c..b2d27d370f 100644
--- a/spec/ruby/core/method/shared/to_s.rb
+++ b/spec/ruby/core/method/shared/to_s.rb
@@ -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 4cfb21c5d0..c5b296f6e2 100644
--- a/spec/ruby/core/method/source_location_spec.rb
+++ b/spec/ruby/core/method/source_location_spec.rb
@@ -13,7 +13,7 @@ describe "Method#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 == 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
diff --git a/spec/ruby/core/method/super_method_spec.rb b/spec/ruby/core/method/super_method_spec.rb
index f9a18f3878..c63a7aaa0f 100644
--- a/spec/ruby/core/method/super_method_spec.rb
+++ b/spec/ruby/core/method/super_method_spec.rb
@@ -55,12 +55,10 @@ describe "Method#super_method" do
end
end
- ruby_version_is "2.7.3" do
- 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
+ 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/module/alias_method_spec.rb b/spec/ruby/core/module/alias_method_spec.rb
index 391efa227a..c36dedd2d8 100644
--- a/spec/ruby/core/module/alias_method_spec.rb
+++ b/spec/ruby/core/module/alias_method_spec.rb
@@ -92,17 +92,9 @@ describe "Module#alias_method" do
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
diff --git a/spec/ruby/core/module/attr_accessor_spec.rb b/spec/ruby/core/module/attr_accessor_spec.rb
index ba5289cbea..503dccc61e 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
@@ -80,19 +81,9 @@ describe "Module#attr_accessor" do
Module.should have_public_instance_method(:attr_accessor, false)
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
@@ -116,4 +107,6 @@ describe "Module#attr_accessor" do
1.foobar.should be_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..37fd537ff5 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
@@ -62,19 +63,11 @@ describe "Module#attr_reader" do
Module.should have_public_instance_method(:attr_reader, false)
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..2f9f4e26dc 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
@@ -146,23 +147,13 @@ describe "Module#attr" do
Module.should have_public_instance_method(:attr, false)
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..5b863ef88c 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
@@ -72,19 +73,11 @@ describe "Module#attr_writer" do
Module.should have_public_instance_method(:attr_writer, false)
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_spec.rb b/spec/ruby/core/module/autoload_spec.rb
index af04ab26c8..45d18b8608 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
@@ -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,58 +373,83 @@ 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
diff --git a/spec/ruby/core/module/const_added_spec.rb b/spec/ruby/core/module/const_added_spec.rb
index 31ac6eb105..f9edda3a07 100644
--- a/spec/ruby/core/module/const_added_spec.rb
+++ b/spec/ruby/core/module/const_added_spec.rb
@@ -121,5 +121,40 @@ describe "Module#const_added" do
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 = 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 []
+
+ 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
end
diff --git a/spec/ruby/core/module/const_get_spec.rb b/spec/ruby/core/module/const_get_spec.rb
index 69f181cf51..0233118f4b 100644
--- a/spec/ruby/core/module/const_get_spec.rb
+++ b/spec/ruby/core/module/const_get_spec.rb
@@ -105,7 +105,7 @@ describe "Module#const_get" do
-> { ConstantSpecs.const_get("CS_CONST1", false) }.should raise_error(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
diff --git a/spec/ruby/core/module/const_set_spec.rb b/spec/ruby/core/module/const_set_spec.rb
index ba7810d17b..5bdfd7b68f 100644
--- a/spec/ruby/core/module/const_set_spec.rb
+++ b/spec/ruby/core/module/const_set_spec.rb
@@ -20,20 +20,10 @@ describe "Module#const_set" do
m.name.should == "ConstantSpecs::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
diff --git a/spec/ruby/core/module/const_source_location_spec.rb b/spec/ruby/core/module/const_source_location_spec.rb
index ded2aa51d7..c194c9113f 100644
--- a/spec/ruby/core/module/const_source_location_spec.rb
+++ b/spec/ruby/core/module/const_source_location_spec.rb
@@ -233,5 +233,17 @@ 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
+ end
+ end
end
end
diff --git a/spec/ruby/core/module/define_method_spec.rb b/spec/ruby/core/module/define_method_spec.rb
index ce94436bfd..e04bb87ceb 100644
--- a/spec/ruby/core/module/define_method_spec.rb
+++ b/spec/ruby/core/module/define_method_spec.rb
@@ -133,6 +133,17 @@ describe "Module#define_method when name is not a special private name" do
klass.should have_public_instance_method(: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
@@ -488,6 +499,33 @@ describe "Module#define_method" do
Class.new { define_method :bar, m }
}.should raise_error(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_error(NoMethodError)
+ end
end
describe "Module#define_method" do
@@ -686,7 +724,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)
@@ -711,7 +749,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)
@@ -736,7 +774,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
@@ -761,7 +799,7 @@ describe "Method#define_method when passed a Proc object" do
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/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/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/include_spec.rb b/spec/ruby/core/module/include_spec.rb
index c073bc31ca..78f6b41031 100644
--- a/spec/ruby/core/module/include_spec.rb
+++ b/spec/ruby/core/module/include_spec.rb
@@ -47,6 +47,34 @@ describe "Module#include" do
-> { ModuleSpecs::SubclassSpec.include(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
end
+ ruby_version_is ""..."3.2" do
+ it "raises ArgumentError 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_error(ArgumentError, "refinement module is not allowed")
+ end
+ end
+
+ ruby_version_is "3.2" do
+ 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_error(TypeError, "Cannot include refinement")
+ end
+ 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)
diff --git a/spec/ruby/core/module/module_function_spec.rb b/spec/ruby/core/module/module_function_spec.rb
index 0602e95ca9..1c3ec5471b 100644
--- a/spec/ruby/core/module/module_function_spec.rb
+++ b/spec/ruby/core/module/module_function_spec.rb
@@ -155,15 +155,62 @@ 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
@@ -187,13 +234,13 @@ describe "Module#module_function as a toggle (no arguments) in a Module body" do
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 +249,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 +264,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..0d1f4e24d5 100644
--- a/spec/ruby/core/module/name_spec.rb
+++ b/spec/ruby/core/module/name_spec.rb
@@ -6,20 +6,10 @@ describe "Module#name" do
Module.new.name.should be_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
@@ -42,6 +32,19 @@ describe "Module#name" do
m::N.name.should == "ModuleSpecs::Anonymous::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
module ModuleSpecs
module ModuleToRemove
@@ -69,12 +72,18 @@ 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"
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"
+ end
+
it "is not modified when assigning to a new constant after it has been accessed" do
m = Module.new
ModuleSpecs::Anonymous::B = m
@@ -111,13 +120,26 @@ 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"
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.
+ end
+
it "returns a frozen String" do
ModuleSpecs.name.should.frozen?
end
diff --git a/spec/ruby/core/module/prepend_spec.rb b/spec/ruby/core/module/prepend_spec.rb
index 976b09b105..b40d12f0de 100644
--- a/spec/ruby/core/module/prepend_spec.rb
+++ b/spec/ruby/core/module/prepend_spec.rb
@@ -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
@@ -415,6 +435,34 @@ describe "Module#prepend" do
-> { ModuleSpecs::SubclassSpec.prepend(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
end
+ ruby_version_is ""..."3.2" do
+ it "raises ArgumentError 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_error(ArgumentError, "refinement module is not allowed")
+ end
+ end
+
+ ruby_version_is "3.2" do
+ 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_error(TypeError, "Cannot prepend refinement")
+ end
+ end
+
it "imports constants" do
m1 = Module.new
m1::MY_CONSTANT = 1
@@ -499,34 +547,17 @@ describe "Module#prepend" do
c.dup.new.should be_kind_of(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 be_kind_of(m1)
+ c2.ancestors[0,3].should == [m1,m2dup,c2]
+ c2.new.should be_kind_of(m1)
end
it "depends on prepend_features to add the module" do
@@ -743,6 +774,50 @@ 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
+ ruby_version_is ""..."3.1" do
+ it "does not modify 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(4).should == [b, m, a, Object]
+ end
+ end
+
+ ruby_version_is "3.1" 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
+ end
+
describe "called on a module" do
describe "included into a class"
it "does not obscure the module's methods from reflective access" 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..f899c71a57 100644
--- a/spec/ruby/core/module/private_class_method_spec.rb
+++ b/spec/ruby/core/module/private_class_method_spec.rb
@@ -79,15 +79,13 @@ describe "Module#private_class_method" do
end.should raise_error(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_error(NoMethodError)
end
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..71b20acda5 100644
--- a/spec/ruby/core/module/public_class_method_spec.rb
+++ b/spec/ruby/core/module/public_class_method_spec.rb
@@ -78,19 +78,17 @@ describe "Module#public_class_method" do
end.should raise_error(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/ruby2_keywords_spec.rb b/spec/ruby/core/module/ruby2_keywords_spec.rb
index 80a99e2624..aca419f522 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
@@ -223,25 +220,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 +237,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_error(NameError, /undefined method [`']not_existing'/)
end
it "accepts String as well" do
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..f5886a3398
--- /dev/null
+++ b/spec/ruby/core/module/set_temporary_name_spec.rb
@@ -0,0 +1,68 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.3" do
+ describe "Module#set_temporary_name" do
+ it "can assign a temporary name" do
+ m = Module.new
+ m.name.should be_nil
+
+ m.set_temporary_name("fake_name")
+ m.name.should == "fake_name"
+
+ m.set_temporary_name(nil)
+ m.name.should be_nil
+ end
+
+ it "can assign a temporary name which is not a valid constant path" do
+ m = Module.new
+ m.set_temporary_name("a::B")
+ m.name.should == "a::B"
+
+ m.set_temporary_name("Template['foo.rb']")
+ m.name.should == "Template['foo.rb']"
+ end
+
+ it "can't assign empty string as name" do
+ m = Module.new
+ -> { m.set_temporary_name("") }.should raise_error(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_error(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_error(ArgumentError, "the temporary name must not be a constant path to avoid confusion")
+ -> { m.set_temporary_name("::A") }.should raise_error(ArgumentError, "the temporary name must not be a constant path to avoid confusion")
+ -> { m.set_temporary_name("::A::B") }.should raise_error(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_error(RuntimeError, "can't change permanent name")
+ end
+
+ it "can assign a temporary name to a nested 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 be_nil
+ 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
+ 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 9ef7b5be44..b1d5cb3814 100644
--- a/spec/ruby/core/module/shared/class_eval.rb
+++ b/spec/ruby/core/module/shared/class_eval.rb
@@ -52,6 +52,12 @@ describe :module_class_eval, shared: true do
ModuleSpecs.send(@method, "[__FILE__, __LINE__]", "test", 102).should == ["test", 102]
end
+ ruby_version_is "3.3" do
+ it "uses the caller location as default filename" do
+ ModuleSpecs.send(@method, "[__FILE__, __LINE__]").should == ["(eval at #{__FILE__}:#{__LINE__})", 1]
+ end
+ 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)
diff --git a/spec/ruby/core/module/shared/set_visibility.rb b/spec/ruby/core/module/shared/set_visibility.rb
index 9f31e230ca..a1586dd2bd 100644
--- a/spec/ruby/core/module/shared/set_visibility.rb
+++ b/spec/ruby/core/module/shared/set_visibility.rb
@@ -22,21 +22,19 @@ describe :set_visibility, shared: true do
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.should send(:"have_#{visibility}_instance_method", :test1, false)
+ mod.should send(:"have_#{visibility}_instance_method", :test2, false)
end
end
diff --git a/spec/ruby/core/module/undef_method_spec.rb b/spec/ruby/core/module/undef_method_spec.rb
index c2ad200536..d4efcd51cb 100644
--- a/spec/ruby/core/module/undef_method_spec.rb
+++ b/spec/ruby/core/module/undef_method_spec.rb
@@ -50,7 +50,7 @@ describe "Module#undef_method" do
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_error(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_error(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_error(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_error(NameError, /undefined method [`']not_exist' for class [`']String'/) { |e|
# a NameError and not a NoMethodError
e.class.should == NameError
}
diff --git a/spec/ruby/core/module/using_spec.rb b/spec/ruby/core/module/using_spec.rb
index 4781b99bb7..a908363c96 100644
--- a/spec/ruby/core/module/using_spec.rb
+++ b/spec/ruby/core/module/using_spec.rb
@@ -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..e9d33f5fd9 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
diff --git a/spec/ruby/core/mutex/owned_spec.rb b/spec/ruby/core/mutex/owned_spec.rb
index 1f843cd576..7bfc7d8f83 100644
--- a/spec/ruby/core/mutex/owned_spec.rb
+++ b/spec/ruby/core/mutex/owned_spec.rb
@@ -41,15 +41,13 @@ describe "Mutex#owned?" do
end
end
- ruby_version_is "3.0" do
- 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
+ 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
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..8d898b1cc9
--- /dev/null
+++ b/spec/ruby/core/nil/singleton_method_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+describe "NilClass#singleton_method" do
+ ruby_version_is '3.3' do
+ it "raises regardless of whether NilClass defines the method" do
+ -> { nil.singleton_method(:foo) }.should raise_error(NameError)
+ begin
+ def (nil).foo; end
+ -> { nil.singleton_method(:foo) }.should raise_error(NameError)
+ ensure
+ NilClass.send(:remove_method, :foo)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/clone_spec.rb b/spec/ruby/core/numeric/clone_spec.rb
index c3b06ca0c9..423cec85dd 100644
--- a/spec/ruby/core/numeric/clone_spec.rb
+++ b/spec/ruby/core/numeric/clone_spec.rb
@@ -14,7 +14,7 @@ describe "Numeric#clone" 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)
end
@@ -23,10 +23,8 @@ describe "Numeric#clone" do
-> { 1.clone(freeze: false) }.should raise_error(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/fdiv_spec.rb b/spec/ruby/core/numeric/fdiv_spec.rb
index 907e5d343c..e97fa77f79 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
diff --git a/spec/ruby/core/numeric/quo_spec.rb b/spec/ruby/core/numeric/quo_spec.rb
index 67bacee9b5..6e3ce7a374 100644
--- a/spec/ruby/core/numeric/quo_spec.rb
+++ b/spec/ruby/core/numeric/quo_spec.rb
@@ -1,6 +1,5 @@
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
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/step.rb b/spec/ruby/core/numeric/shared/step.rb
index 8b1a7bf307..977ec6de02 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 }
@@ -258,12 +258,6 @@ describe :numeric_step, :shared => true 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
- @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)
end
diff --git a/spec/ruby/core/numeric/step_spec.rb b/spec/ruby/core/numeric/step_spec.rb
index 095c474fec..1705fb1b4e 100644
--- a/spec/ruby/core/numeric/step_spec.rb
+++ b/spec/ruby/core/numeric/step_spec.rb
@@ -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,24 +80,12 @@ 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_error(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_error(ArgumentError)
end
it "raises a ArgumentError when limit and to are defined" do
@@ -156,26 +96,9 @@ describe "Numeric#step" 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
- 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/objectspace/define_finalizer_spec.rb b/spec/ruby/core/objectspace/define_finalizer_spec.rb
index d9db027e0b..effecc41d0 100644
--- a/spec/ruby/core/objectspace/define_finalizer_spec.rb
+++ b/spec/ruby/core/objectspace/define_finalizer_spec.rb
@@ -52,7 +52,7 @@ 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
@@ -60,60 +60,58 @@ describe "ObjectSpace.define_finalizer" do
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
@@ -143,9 +141,9 @@ describe "ObjectSpace.define_finalizer" do
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
diff --git a/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb b/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
index 689509d820..c427e01ca5 100644
--- a/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
@@ -24,7 +24,7 @@ ruby_version_is "3.3" do
it "requires the keys to implement #hash" do
map = ObjectSpace::WeakKeyMap.new
- -> { map[BasicObject.new] = 1 }.should raise_error(NoMethodError, "undefined method `hash' for an instance of BasicObject")
+ -> { map[BasicObject.new] = 1 }.should raise_error(NoMethodError, /undefined method [`']hash' for an instance of BasicObject/)
end
it "accepts frozen keys or values" do
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/clone_spec.rb b/spec/ruby/core/proc/clone_spec.rb
index a1a1292654..7eca9c561e 100644
--- a/spec/ruby/core/proc/clone_spec.rb
+++ b/spec/ruby/core/proc/clone_spec.rb
@@ -3,4 +3,13 @@ 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.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
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/dup_spec.rb b/spec/ruby/core/proc/dup_spec.rb
index 6da2f3080c..dd19b3c1e9 100644
--- a/spec/ruby/core/proc/dup_spec.rb
+++ b/spec/ruby/core/proc/dup_spec.rb
@@ -3,4 +3,11 @@ 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
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/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/lambda_spec.rb b/spec/ruby/core/proc/lambda_spec.rb
index b2d3f50350..5c3c38fc2a 100644
--- a/spec/ruby/core/proc/lambda_spec.rb
+++ b/spec/ruby/core/proc/lambda_spec.rb
@@ -14,9 +14,11 @@ describe "Proc#lambda?" 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
+ ruby_version_is ""..."3.3" do
+ 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
+ end
end
it "is preserved when passing a Proc with & to the proc keyword" do
diff --git a/spec/ruby/core/proc/new_spec.rb b/spec/ruby/core/proc/new_spec.rb
index cb52e94f44..b2b7387756 100644
--- a/spec/ruby/core/proc/new_spec.rb
+++ b/spec/ruby/core/proc/new_spec.rb
@@ -166,36 +166,13 @@ describe "Proc.new without a block" do
-> { ProcSpecs.new_proc_subclass_in_method }.should raise_error(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_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
end
diff --git a/spec/ruby/core/proc/parameters_spec.rb b/spec/ruby/core/proc/parameters_spec.rb
index 1ffaf17315..972596d2ea 100644
--- a/spec/ruby/core/proc/parameters_spec.rb
+++ b/spec/ruby/core/proc/parameters_spec.rb
@@ -21,7 +21,7 @@ describe "Proc#parameters" do
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
+ 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
@@ -33,6 +33,16 @@ describe "Proc#parameters" do
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
end
it "regards optional keyword parameters in procs as optional" do
@@ -91,19 +101,38 @@ 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
+ 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 * rest arg for \"star\" argument" do
- -> x, * {}.parameters.should == [[:req, :x], [:rest, :*]]
+ 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
end
ruby_version_is ''...'3.2' do
it "adds nameless rest arg for \"star\" argument" do
- -> x, * {}.parameters.should == [[:req, :x], [:rest]]
+ -> * {}.parameters.should == [[:rest]]
+ end
+
+ it "adds nameless keyrest arg for \"double star\" argument" do
+ -> ** {}.parameters.should == [[:keyrest]]
+ end
+ end
+
+ ruby_version_is '3.1' do
+ it "adds block arg with name & for anonymous block argument" do
+ eval('-> & {}.parameters').should == [[:block, :&]]
end
end
@@ -141,4 +170,8 @@ describe "Proc#parameters" do
[:block, :_]
]
end
+
+ it "returns :nokey for **nil parameter" do
+ proc { |**nil| }.parameters.should == [[:nokey]]
+ end
end
diff --git a/spec/ruby/core/proc/ruby2_keywords_spec.rb b/spec/ruby/core/proc/ruby2_keywords_spec.rb
index c6eb03e693..ab67302231 100644
--- a/spec/ruby/core/proc/ruby2_keywords_spec.rb
+++ b/spec/ruby/core/proc/ruby2_keywords_spec.rb
@@ -25,28 +25,6 @@ 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
diff --git a/spec/ruby/core/proc/shared/dup.rb b/spec/ruby/core/proc/shared/dup.rb
index 4480f3d0c9..c419a4078a 100644
--- a/spec/ruby/core/proc/shared/dup.rb
+++ b/spec/ruby/core/proc/shared/dup.rb
@@ -15,4 +15,27 @@ describe :proc_dup, shared: true do
cl.new{}.send(@method).class.should == cl
end
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..d0503fb064 100644
--- a/spec/ruby/core/proc/shared/equal.rb
+++ b/spec/ruby/core/proc/shared/equal.rb
@@ -81,20 +81,3 @@ describe :proc_equal, shared: true do
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
- 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 a5895a7fcb..a8b99287d5 100644
--- a/spec/ruby/core/proc/source_location_spec.rb
+++ b/spec/ruby/core/proc/source_location_spec.rb
@@ -19,19 +19,19 @@ describe "Proc#source_location" do
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 == 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 == 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 == 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 == 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
diff --git a/spec/ruby/core/process/argv0_spec.rb b/spec/ruby/core/process/argv0_spec.rb
index 7c2342f959..f5aba719e9 100644
--- a/spec/ruby/core/process/argv0_spec.rb
+++ b/spec/ruby/core/process/argv0_spec.rb
@@ -8,7 +8,7 @@ describe "Process.argv0" do
it "is the path given as the main script and the same as __FILE__" do
script = "fixtures/argv0.rb"
- Dir.chdir(File.dirname(__FILE__)) do
+ Dir.chdir(__dir__) do
ruby_exe(script).should == "#{script}\n#{script}\nOK"
end
end
diff --git a/spec/ruby/core/process/constants_spec.rb b/spec/ruby/core/process/constants_spec.rb
index 4130bb58a5..616c54b8e1 100644
--- a/spec/ruby/core/process/constants_spec.rb
+++ b/spec/ruby/core/process/constants_spec.rb
@@ -56,12 +56,18 @@ describe "Process::Constants" do
end
platform_is :netbsd, :freebsd do
- it "Process::RLIMIT_SBSIZE" do
+ it "has the correct constant values on NetBSD and FreeBSD" do
Process::RLIMIT_SBSIZE.should == 9 # FIXME: what's it equal?
Process::RLIMIT_AS.should == 10
end
end
+ platform_is :freebsd do
+ it "has the correct constant values on FreeBSD" do
+ Process::RLIMIT_NPTS.should == 11
+ end
+ end
+
platform_is :windows do
it "does not define RLIMIT constants" do
%i[
diff --git a/spec/ruby/core/process/detach_spec.rb b/spec/ruby/core/process/detach_spec.rb
index 91661afcea..f13bda1f5d 100644
--- a/spec/ruby/core/process/detach_spec.rb
+++ b/spec/ruby/core/process/detach_spec.rb
@@ -44,11 +44,17 @@ describe "Process.detach" do
end
it "tolerates not existing child process pid" do
- # ensure there is no child process with this hardcoded pid
- # `kill 0 pid` for existing process returns "1" and raises Errno::ESRCH if process doesn't exist
- -> { Process.kill(0, 100500) }.should raise_error(Errno::ESRCH)
+ # 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)
- thr = Process.detach(100500)
+ # 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_error(Errno::ESRCH)
+
+ thr = Process.detach(pid_not_existing)
thr.join
thr.should be_kind_of(Thread)
diff --git a/spec/ruby/core/process/exec_spec.rb b/spec/ruby/core/process/exec_spec.rb
index deb8913b6b..0f371b39c8 100644
--- a/spec/ruby/core/process/exec_spec.rb
+++ b/spec/ruby/core/process/exec_spec.rb
@@ -30,20 +30,20 @@ describe "Process.exec" do
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_error(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,19 +154,19 @@ 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
@@ -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/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/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb
index c8a58c4d04..283a7f033d 100644
--- a/spec/ruby/core/process/spawn_spec.rb
+++ b/spec/ruby/core/process/spawn_spec.rb
@@ -714,7 +714,7 @@ describe "Process.spawn" do
end
it "raises an Errno::EACCES or Errno::EISDIR when passed a directory" do
- -> { Process.spawn File.dirname(__FILE__) }.should raise_error(SystemCallError) { |e|
+ -> { Process.spawn __dir__ }.should raise_error(SystemCallError) { |e|
[Errno::EACCES, Errno::EISDIR].should include(e.class)
}
end
diff --git a/spec/ruby/core/process/status/termsig_spec.rb b/spec/ruby/core/process/status/termsig_spec.rb
index 5d286950f8..9a22dbea71 100644
--- a/spec/ruby/core/process/status/termsig_spec.rb
+++ b/spec/ruby/core/process/status/termsig_spec.rb
@@ -6,7 +6,7 @@ describe "Process::Status#termsig" do
ruby_exe("exit(0)")
end
- it "returns true" do
+ it "returns nil" do
$?.termsig.should be_nil
end
end
diff --git a/spec/ruby/core/process/status/wait_spec.rb b/spec/ruby/core/process/status/wait_spec.rb
index ee9ea80ebb..57d56209a9 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 rjit
- 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 be_an_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_error(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_error(Errno::ESRCH)
+ -> { Process.kill(0, pid2) }.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_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_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_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 be_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_error(Errno::ESRCH)
end
end
end
diff --git a/spec/ruby/core/process/times_spec.rb b/spec/ruby/core/process/times_spec.rb
index d2610f6415..d3bff2cda9 100644
--- a/spec/ruby/core/process/times_spec.rb
+++ b/spec/ruby/core/process/times_spec.rb
@@ -16,31 +16,4 @@ describe "Process.times" do
Process.times.utime.should > user
end
end
-
- # TODO: The precision of `getrusage` depends on platforms (OpenBSD
- # seems not supporting under-milliseconds in fact); this example is
- # very questionable as an example of Ruby, and it just repeats the
- # guard condition.
- guard -> do
- 1000.times.any? do
- # If getrusage has precision beyond milliseconds, there will be
- # very likely at least one non-zero microsecond results when
- # repeating enough.
- time = Process.clock_gettime(:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
- not ('%.6f' % time).end_with?('000')
- end
- rescue Errno::EINVAL
- false
- end do
- it "uses getrusage when available to improve precision beyond milliseconds" do
- max = 10_000
-
- found = (max * 100).times.find do
- time = Process.times.utime
- !('%.6f' % time).end_with?('000')
- end
-
- found.should_not == nil
- end
- 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..b562d52d22
--- /dev/null
+++ b/spec/ruby/core/process/warmup_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../spec_helper'
+
+describe "Process.warmup" do
+ ruby_version_is "3.3" 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
+end
diff --git a/spec/ruby/core/queue/deq_spec.rb b/spec/ruby/core/queue/deq_spec.rb
index 9510978eac..f84d4220ea 100644
--- a/spec/ruby/core/queue/deq_spec.rb
+++ b/spec/ruby/core/queue/deq_spec.rb
@@ -1,6 +1,13 @@
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
+ ruby_version_is "3.2" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.deq(timeout: v) }
+ end
+end
diff --git a/spec/ruby/core/queue/pop_spec.rb b/spec/ruby/core/queue/pop_spec.rb
index 1ce9231685..d344740834 100644
--- a/spec/ruby/core/queue/pop_spec.rb
+++ b/spec/ruby/core/queue/pop_spec.rb
@@ -1,6 +1,13 @@
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
+ ruby_version_is "3.2" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.pop(timeout: v) }
+ end
+end
diff --git a/spec/ruby/core/queue/shift_spec.rb b/spec/ruby/core/queue/shift_spec.rb
index f84058e1df..64165e0b61 100644
--- a/spec/ruby/core/queue/shift_spec.rb
+++ b/spec/ruby/core/queue/shift_spec.rb
@@ -1,6 +1,13 @@
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
+ ruby_version_is "3.2" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.shift(timeout: v) }
+ end
+end
diff --git a/spec/ruby/core/random/bytes_spec.rb b/spec/ruby/core/random/bytes_spec.rb
index ed1b3a7b41..b42dc61234 100644
--- a/spec/ruby/core/random/bytes_spec.rb
+++ b/spec/ruby/core/random/bytes_spec.rb
@@ -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..01d7430df8 100644
--- a/spec/ruby/core/random/default_spec.rb
+++ b/spec/ruby/core/random/default_spec.rb
@@ -14,26 +14,16 @@ describe "Random::DEFAULT" do
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
+ it "refers to the Random class" do
+ suppress_warning do
+ Random::DEFAULT.should.equal?(Random)
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
+ it "is deprecated" do
+ -> {
+ Random::DEFAULT.should.equal?(Random)
+ }.should complain(/constant Random::DEFAULT is deprecated/)
end
end
diff --git a/spec/ruby/core/range/bsearch_spec.rb b/spec/ruby/core/range/bsearch_spec.rb
index 9c93671d85..5254ab756c 100644
--- a/spec/ruby/core/range/bsearch_spec.rb
+++ b/spec/ruby/core/range/bsearch_spec.rb
@@ -9,22 +9,30 @@ describe "Range#bsearch" do
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_error(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_error(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_error(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_error(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_error(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_error(TypeError, "can't do binary search for String")
end
context "with Integer values" do
@@ -94,6 +102,10 @@ 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
@@ -156,7 +168,6 @@ describe "Range#bsearch" do
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
-
end
it "returns nil if the block never returns zero" 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
@@ -250,6 +265,10 @@ describe "Range#bsearch" do
[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
@@ -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
@@ -361,6 +383,10 @@ describe "Range#bsearch" do
[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
@@ -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/cover_spec.rb b/spec/ruby/core/range/cover_spec.rb
index fa881607e9..eb7cddc967 100644
--- a/spec/ruby/core/range/cover_spec.rb
+++ b/spec/ruby/core/range/cover_spec.rb
@@ -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 be_true
+ 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/include_spec.rb b/spec/ruby/core/range/include_spec.rb
index b2c7a54545..277de205d1 100644
--- a/spec/ruby/core/range/include_spec.rb
+++ b/spec/ruby/core/range/include_spec.rb
@@ -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 be_false
+ end
end
diff --git a/spec/ruby/core/range/initialize_spec.rb b/spec/ruby/core/range/initialize_spec.rb
index 8a6ca65daa..c653caf0c6 100644
--- a/spec/ruby/core/range/initialize_spec.rb
+++ b/spec/ruby/core/range/initialize_spec.rb
@@ -27,18 +27,9 @@ describe "Range#initialize" do
-> { @range.send(:initialize, 1, 3, 5, 7, 9) }.should raise_error(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_error(FrozenError)
+ -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(FrozenError)
end
it "raises an ArgumentError if arguments don't respond to <=>" do
diff --git a/spec/ruby/core/range/max_spec.rb b/spec/ruby/core/range/max_spec.rb
index 6c9ada2a3c..a3bbc31e7d 100644
--- a/spec/ruby/core/range/max_spec.rb
+++ b/spec/ruby/core/range/max_spec.rb
@@ -50,17 +50,15 @@ describe "Range#max" do
-> { eval("(1..)").max }.should raise_error(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
- -> {
- (...1).max
- }.should raise_error(TypeError, 'cannot exclude end value with non Integer begin value')
- end
+ it "raises for an exclusive beginless range" do
+ -> {
+ (...1).max
+ }.should raise_error(TypeError, 'cannot exclude end value with non Integer begin value')
end
end
diff --git a/spec/ruby/core/range/minmax_spec.rb b/spec/ruby/core/range/minmax_spec.rb
index b2b4fd61a1..6651ae3726 100644
--- a/spec/ruby/core/range/minmax_spec.rb
+++ b/spec/ruby/core/range/minmax_spec.rb
@@ -86,24 +86,22 @@ describe 'Range#minmax' do
/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
diff --git a/spec/ruby/core/range/new_spec.rb b/spec/ruby/core/range/new_spec.rb
index 40df914b83..3cab887799 100644
--- a/spec/ruby/core/range/new_spec.rb
+++ b/spec/ruby/core/range/new_spec.rb
@@ -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 "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 "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
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..f36a2cef8b 100644
--- a/spec/ruby/core/range/shared/cover_and_include.rb
+++ b/spec/ruby/core/range/shared/cover_and_include.rb
@@ -57,7 +57,6 @@ describe :range_cover_and_include, shared: true do
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}"
end
it "returns true if argument is sole element in the range" do
diff --git a/spec/ruby/core/range/size_spec.rb b/spec/ruby/core/range/size_spec.rb
index 81ea5a3846..a1fe3ce17d 100644
--- a/spec/ruby/core/range/size_spec.rb
+++ b/spec/ruby/core/range/size_spec.rb
@@ -4,34 +4,22 @@ 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
ruby_version_is ""..."3.2" do
@@ -43,7 +31,7 @@ describe "Range#size" do
end
end
- ruby_version_is "3.2" do
+ ruby_version_is "3.2"..."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
@@ -58,6 +46,54 @@ describe "Range#size" do
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_error(TypeError, /can't iterate from/)
+ -> { (1.0...16.0).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (1.0..15.9).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (1.1..16.0).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (1.1..15.9).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (16.0..0.0).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (Float::INFINITY..0).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (-Float::INFINITY..0).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (-Float::INFINITY..Float::INFINITY).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (..1).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (...0.5).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (..nil).size }.should raise_error(TypeError, /can't iterate from/)
+ -> { (...'o').size }.should raise_error(TypeError, /can't iterate from/)
+ -> { eval("(0.5...)").size }.should raise_error(TypeError, /can't iterate from/)
+ -> { eval("([]...)").size }.should raise_error(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
diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb
index 9024636d55..64ea3de4ed 100644
--- a/spec/ruby/core/range/step_spec.rb
+++ b/spec/ruby/core/range/step_spec.rb
@@ -377,48 +377,21 @@ describe "Range#step" do
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_error(ArgumentError)
end
describe "returned Enumerator" do
describe "size" do
- ruby_version_is ""..."3.0" 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)
- 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)
- end
+ 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_error(TypeError)
end
- ruby_version_is "3.0" do
- 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_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
- 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
it "returns the ceil of range size divided by the number of steps" do
diff --git a/spec/ruby/core/rational/coerce_spec.rb b/spec/ruby/core/rational/coerce_spec.rb
deleted file mode 100644
index 9c0f05829b..0000000000
--- a/spec/ruby/core/rational/coerce_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative "../../spec_helper"
-require_relative '../../shared/rational/coerce'
-
-describe "Rational#coerce" do
- it_behaves_like :rational_coerce, :coerce
-end
diff --git a/spec/ruby/core/refinement/extend_object_spec.rb b/spec/ruby/core/refinement/extend_object_spec.rb
index e44e9f46d8..6c2a0af4f3 100644
--- a/spec/ruby/core/refinement/extend_object_spec.rb
+++ b/spec/ruby/core/refinement/extend_object_spec.rb
@@ -11,8 +11,10 @@ describe "Refinement#extend_object" do
Module.new do
refine c do
called = false
- define_method(:extend_object){called = true}
- proc{c.extend(self)}.should raise_error(TypeError)
+ define_method(:extend_object) { called = true }
+ -> {
+ c.extend(self)
+ }.should raise_error(TypeError)
called.should == false
end
end
diff --git a/spec/ruby/core/refinement/import_methods_spec.rb b/spec/ruby/core/refinement/import_methods_spec.rb
index 05973b2380..614c54dff8 100644
--- a/spec/ruby/core/refinement/import_methods_spec.rb
+++ b/spec/ruby/core/refinement/import_methods_spec.rb
@@ -128,7 +128,7 @@ describe "Refinement#import_methods" do
using self
-> {
"foo".indent(3)
- }.should raise_error(NoMethodError, /undefined method `indent' for ("foo":String|an instance of String)/)
+ }.should raise_error(NoMethodError, /undefined method [`']indent' for ("foo":String|an instance of String)/)
end
end
@@ -214,7 +214,7 @@ describe "Refinement#import_methods" do
using self
-> {
String.indent(3)
- }.should raise_error(NoMethodError, /undefined method `indent' for (String:Class|class String)/)
+ }.should raise_error(NoMethodError, /undefined method [`']indent' for (String:Class|class String)/)
end
end
diff --git a/spec/ruby/core/refinement/refined_class_spec.rb b/spec/ruby/core/refinement/refined_class_spec.rb
index bcf48c4e25..00b65d0895 100644
--- a/spec/ruby/core/refinement/refined_class_spec.rb
+++ b/spec/ruby/core/refinement/refined_class_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Refinement#refined_class" do
- ruby_version_is "3.2" do
+ ruby_version_is "3.2"..."3.3" do
it "returns the class refined by the receiver" do
refinement_int = nil
diff --git a/spec/ruby/core/regexp/initialize_spec.rb b/spec/ruby/core/regexp/initialize_spec.rb
index a1583384af..dd57292242 100644
--- a/spec/ruby/core/regexp/initialize_spec.rb
+++ b/spec/ruby/core/regexp/initialize_spec.rb
@@ -5,16 +5,8 @@ describe "Regexp#initialize" do
Regexp.should have_private_instance_method(:initialize)
end
- ruby_version_is ""..."3.0" do
- it "raises a SecurityError on a Regexp literal" do
- -> { //.send(:initialize, "") }.should raise_error(SecurityError)
- end
- end
-
- ruby_version_is "3.0" do
- it "raises a FrozenError on a Regexp literal" do
- -> { //.send(:initialize, "") }.should raise_error(FrozenError)
- end
+ it "raises a FrozenError on a Regexp literal" do
+ -> { //.send(:initialize, "") }.should raise_error(FrozenError)
end
it "raises a TypeError on an initialized non-literal Regexp" do
diff --git a/spec/ruby/core/regexp/shared/new.rb b/spec/ruby/core/regexp/shared/new.rb
index 773882e495..7c3fabf612 100644
--- a/spec/ruby/core/regexp/shared/new.rb
+++ b/spec/ruby/core/regexp/shared/new.rb
@@ -123,14 +123,30 @@ describe :regexp_new_string, shared: true do
(r.options & Regexp::EXTENDED).should_not == 0
end
- 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
+ ruby_version_is ""..."3.2" 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)
- Regexp.send(@method, "Hi", obj)
+ ScratchPad.recorded.should == nil
+ end
+ end
- ScratchPad.recorded.should == nil
+ ruby_version_is "3.2" 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
end
ruby_version_is ""..."3.2" do
@@ -188,12 +204,12 @@ describe :regexp_new_string, shared: true do
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)
+ -> { Regexp.send(@method, 'Hi', 'e') }.should raise_error(ArgumentError, "unknown regexp option: e")
+ -> { Regexp.send(@method, 'Hi', 'n') }.should raise_error(ArgumentError, "unknown regexp option: n")
+ -> { Regexp.send(@method, 'Hi', 's') }.should raise_error(ArgumentError, "unknown regexp option: s")
+ -> { Regexp.send(@method, 'Hi', 'u') }.should raise_error(ArgumentError, "unknown regexp option: u")
+ -> { Regexp.send(@method, 'Hi', 'j') }.should raise_error(ArgumentError, "unknown regexp option: j")
+ -> { Regexp.send(@method, 'Hi', 'mjx') }.should raise_error(ArgumentError, /unknown regexp option: mjx\b/)
end
end
@@ -473,12 +489,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
diff --git a/spec/ruby/core/regexp/shared/quote.rb b/spec/ruby/core/regexp/shared/quote.rb
index 9533102766..b5ecc35f04 100644
--- a/spec/ruby/core/regexp/shared/quote.rb
+++ b/spec/ruby/core/regexp/shared/quote.rb
@@ -18,23 +18,23 @@ 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 = "ありがとう".dup.force_encoding("utf-8")
str.valid_encoding?.should be_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 = "\xff".dup.force_encoding "us-ascii"
str.valid_encoding?.should be_false
Regexp.send(@method, "\xff").encoding.should == Encoding::BINARY
end
diff --git a/spec/ruby/core/regexp/union_spec.rb b/spec/ruby/core/regexp/union_spec.rb
index 8076836471..ea5a5053f7 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_error(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_error(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_error(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_error(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_error(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_error(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_error(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_error(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_error(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_error(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_error(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_error(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_error(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_error(TypeError, 'no implicit conversion of Array into String')
end
end
diff --git a/spec/ruby/core/signal/signame_spec.rb b/spec/ruby/core/signal/signame_spec.rb
index b66de9fc85..adfe895d97 100644
--- a/spec/ruby/core/signal/signame_spec.rb
+++ b/spec/ruby/core/signal/signame_spec.rb
@@ -9,10 +9,22 @@ 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)
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_error(TypeError)
+ end
+
platform_is_not :windows do
it "the original should take precedence over alias when looked up by number" do
Signal.signame(Signal.list["ABRT"]).should == "ABRT"
diff --git a/spec/ruby/core/signal/trap_spec.rb b/spec/ruby/core/signal/trap_spec.rb
index 10e122e072..6d654a99be 100644
--- a/spec/ruby/core/signal/trap_spec.rb
+++ b/spec/ruby/core/signal/trap_spec.rb
@@ -221,10 +221,29 @@ describe "Signal.trap" do
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_error(ArgumentError, /bad signal type/)
+ end
+
it "raises ArgumentError when passed unknown signal" do
-> { Signal.trap(300) { } }.should raise_error(ArgumentError, "invalid signal number (300)")
- -> { Signal.trap("USR10") { } }.should raise_error(ArgumentError, "unsupported signal `SIGUSR10'")
- -> { Signal.trap("SIGUSR10") { } }.should raise_error(ArgumentError, "unsupported signal `SIGUSR10'")
+ -> { Signal.trap("USR10") { } }.should raise_error(ArgumentError, /\Aunsupported signal [`']SIGUSR10'\z/)
+ -> { Signal.trap("SIGUSR10") { } }.should raise_error(ArgumentError, /\Aunsupported signal [`']SIGUSR10'\z/)
end
it "raises ArgumentError when passed signal is not Integer, String or Symbol" do
@@ -245,6 +264,14 @@ describe "Signal.trap" do
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_error(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..6fffe2f272 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,9 @@ end
describe "SizedQueue#<<" do
it_behaves_like :sizedqueue_enq, :<<, -> n { SizedQueue.new(n) }
end
+
+describe "SizedQueue operations with timeout" do
+ ruby_version_is "3.2" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.send(:<<, 1, timeout: v) }
+ end
+end
diff --git a/spec/ruby/core/sizedqueue/deq_spec.rb b/spec/ruby/core/sizedqueue/deq_spec.rb
index 5e1bd9f746..985d654bb3 100644
--- a/spec/ruby/core/sizedqueue/deq_spec.rb
+++ b/spec/ruby/core/sizedqueue/deq_spec.rb
@@ -1,6 +1,13 @@
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
+ ruby_version_is "3.2" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.deq(timeout: v) }
+ end
+end
diff --git a/spec/ruby/core/sizedqueue/enq_spec.rb b/spec/ruby/core/sizedqueue/enq_spec.rb
index 3821afac95..619373e46b 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,9 @@ end
describe "SizedQueue#enq" do
it_behaves_like :sizedqueue_enq, :enq, -> n { SizedQueue.new(n) }
end
+
+describe "SizedQueue operations with timeout" do
+ ruby_version_is "3.2" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.enq(1, timeout: v) }
+ end
+end
diff --git a/spec/ruby/core/sizedqueue/pop_spec.rb b/spec/ruby/core/sizedqueue/pop_spec.rb
index a0cf6f509c..5e7cfea8fb 100644
--- a/spec/ruby/core/sizedqueue/pop_spec.rb
+++ b/spec/ruby/core/sizedqueue/pop_spec.rb
@@ -1,6 +1,13 @@
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
+ ruby_version_is "3.2" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.pop(timeout: v) }
+ end
+end
diff --git a/spec/ruby/core/sizedqueue/push_spec.rb b/spec/ruby/core/sizedqueue/push_spec.rb
index bba9be9e3f..ce61e89b53 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,9 @@ end
describe "SizedQueue#push" do
it_behaves_like :sizedqueue_enq, :push, -> n { SizedQueue.new(n) }
end
+
+describe "SizedQueue operations with timeout" do
+ ruby_version_is "3.2" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.push(1, timeout: v) }
+ end
+end
diff --git a/spec/ruby/core/sizedqueue/shift_spec.rb b/spec/ruby/core/sizedqueue/shift_spec.rb
index 5138e68258..3220801f3a 100644
--- a/spec/ruby/core/sizedqueue/shift_spec.rb
+++ b/spec/ruby/core/sizedqueue/shift_spec.rb
@@ -1,6 +1,13 @@
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
+ ruby_version_is "3.2" do
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.shift(timeout: v) }
+ end
+end
diff --git a/spec/ruby/core/string/ascii_only_spec.rb b/spec/ruby/core/string/ascii_only_spec.rb
index c7e02fd874..88a0559cfd 100644
--- a/spec/ruby/core/string/ascii_only_spec.rb
+++ b/spec/ruby/core/string/ascii_only_spec.rb
@@ -7,12 +7,12 @@ 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".dup.force_encoding(Encoding::US_ASCII).ascii_only?.should be_true
"hello".encode(Encoding::US_ASCII).ascii_only?.should be_true
end
@@ -34,13 +34,13 @@ describe "String#ascii_only?" 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
@@ -51,17 +51,16 @@ describe "String#ascii_only?" do
end
it "returns false for the empty String with a non-ASCII-compatible encoding" do
- "".force_encoding('UTF-16LE').ascii_only?.should be_false
+ "".dup.force_encoding('UTF-16LE').ascii_only?.should be_false
"".encode('UTF-16BE').ascii_only?.should be_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 be_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
@@ -70,14 +69,14 @@ describe "String#ascii_only?" do
end
it "returns false after appending non ASCII characters to an empty String" do
- ("" << "λ").ascii_only?.should be_false
+ ("".dup << "λ").ascii_only?.should be_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 be_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 be_false
end
end
diff --git a/spec/ruby/core/string/b_spec.rb b/spec/ruby/core/string/b_spec.rb
index 37c7994700..4b1fafff11 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
diff --git a/spec/ruby/core/string/byteindex_spec.rb b/spec/ruby/core/string/byteindex_spec.rb
new file mode 100644
index 0000000000..47c7be1029
--- /dev/null
+++ b/spec/ruby/core/string/byteindex_spec.rb
@@ -0,0 +1,304 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative 'shared/byte_index_common.rb'
+
+describe "String#byteindex" do
+ ruby_version_is "3.2" 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
+end
+
+describe "String#byteindex with String" do
+ ruby_version_is "3.2" 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_error(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
+end
+
+describe "String#byteindex with Regexp" do
+ ruby_version_is "3.2" 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 be_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
+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..150f709b90
--- /dev/null
+++ b/spec/ruby/core/string/byterindex_spec.rb
@@ -0,0 +1,359 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative 'shared/byte_index_common.rb'
+
+describe "String#byterindex with object" do
+ ruby_version_is "3.2" 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
+end
+
+describe "String#byterindex with String" do
+ ruby_version_is "3.2" 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_error(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
+end
+
+describe "String#byterindex with Regexp" do
+ ruby_version_is "3.2" 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_error(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
+end
diff --git a/spec/ruby/core/string/bytes_spec.rb b/spec/ruby/core/string/bytes_spec.rb
index 859b346550..02151eebbc 100644
--- a/spec/ruby/core/string/bytes_spec.rb
+++ b/spec/ruby/core/string/bytes_spec.rb
@@ -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 312229523d..5b1027f4a5 100644
--- a/spec/ruby/core/string/byteslice_spec.rb
+++ b/spec/ruby/core/string/byteslice_spec.rb
@@ -19,10 +19,10 @@ end
describe "String#byteslice on 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
diff --git a/spec/ruby/core/string/bytesplice_spec.rb b/spec/ruby/core/string/bytesplice_spec.rb
index f13024a79b..967edcba29 100644
--- a/spec/ruby/core/string/bytesplice_spec.rb
+++ b/spec/ruby/core/string/bytesplice_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe "String#bytesplice" do
diff --git a/spec/ruby/core/string/capitalize_spec.rb b/spec/ruby/core/string/capitalize_spec.rb
index 3f85cf5ae4..5e59b656c5 100644
--- a/spec/ruby/core/string/capitalize_spec.rb
+++ b/spec/ruby/core/string/capitalize_spec.rb
@@ -78,18 +78,9 @@ describe "String#capitalize" do
-> { "abc".capitalize(: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("hello").capitalize.should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("Hello").capitalize.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").capitalize.should be_an_instance_of(String)
- StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(String)
- end
+ 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
@@ -99,7 +90,7 @@ end
describe "String#capitalize!" do
it "capitalizes self in place" do
- a = "hello"
+ a = +"hello"
a.capitalize!.should equal(a)
a.should == "Hello"
end
@@ -112,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
@@ -130,7 +121,7 @@ describe "String#capitalize!" do
end
it "updates string metadata" do
- capitalized = "ßeT"
+ capitalized = +"ßeT"
capitalized.capitalize!
capitalized.should == "Sset"
@@ -142,7 +133,7 @@ describe "String#capitalize!" do
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
@@ -156,13 +147,13 @@ 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
@@ -174,13 +165,13 @@ describe "String#capitalize!" do
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
@@ -199,12 +190,12 @@ describe "String#capitalize!" do
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
diff --git a/spec/ruby/core/string/center_spec.rb b/spec/ruby/core/string/center_spec.rb
index 76da6e1e09..1667b59327 100644
--- a/spec/ruby/core/string/center_spec.rb
+++ b/spec/ruby/core/string/center_spec.rb
@@ -81,31 +81,18 @@ describe "String#center with length, padding" do
-> { "hello".center(0, "") }.should raise_error(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)
-
- "".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
+ 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)
- 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 be_an_instance_of(String)
+ "foo".center(10, StringSpecs::MyString.new("x")).should be_an_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)
@@ -114,7 +101,7 @@ describe "String#center with length, padding" do
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)
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..9f81b1af6d
--- /dev/null
+++ b/spec/ruby/core/string/chilled_string_spec.rb
@@ -0,0 +1,71 @@
+require_relative '../../spec_helper'
+
+describe "chilled String" do
+ guard -> { ruby_version_is "3.4" and !"test".equal?("test") } 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 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_error(FrozenError)
+ }.should_not complain(/literal string will be frozen in the future/)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/string/chomp_spec.rb b/spec/ruby/core/string/chomp_spec.rb
index d0508d938f..d27c84c6f6 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'
@@ -44,18 +45,9 @@ describe "String#chomp" do
"abc\n\n".encode("US-ASCII").chomp.encoding.should == Encoding::US_ASCII
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
- 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 be_an_instance_of(String)
end
it "removes trailing characters that match $/ when it has been assigned a value" do
diff --git a/spec/ruby/core/string/chop_spec.rb b/spec/ruby/core/string/chop_spec.rb
index f598d34bc8..99c2c82190 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'
@@ -49,16 +50,8 @@ describe "String#chop" do
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
- 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 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
diff --git a/spec/ruby/core/string/clear_spec.rb b/spec/ruby/core/string/clear_spec.rb
index e1d68e03bd..152986fd0f 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
diff --git a/spec/ruby/core/string/codepoints_spec.rb b/spec/ruby/core/string/codepoints_spec.rb
index 0b6cde82f7..b276d0baa8 100644
--- a/spec/ruby/core/string/codepoints_spec.rb
+++ b/spec/ruby/core/string/codepoints_spec.rb
@@ -11,7 +11,7 @@ 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 = "\xDF".dup.force_encoding(Encoding::UTF_8)
s.valid_encoding?.should be_false
-> { s.codepoints }.should raise_error(ArgumentError)
end
diff --git a/spec/ruby/core/string/comparison_spec.rb b/spec/ruby/core/string/comparison_spec.rb
index 91cfdca25a..9db0cff5ee 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
diff --git a/spec/ruby/core/string/concat_spec.rb b/spec/ruby/core/string/concat_spec.rb
index 6f487eaa3a..cbd7df54e2 100644
--- a/spec/ruby/core/string/concat_spec.rb
+++ b/spec/ruby/core/string/concat_spec.rb
@@ -8,19 +8,19 @@ describe "String#concat" do
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 = +"hello"
str.concat.should equal(str)
str.should == "hello"
end
diff --git a/spec/ruby/core/string/delete_prefix_spec.rb b/spec/ruby/core/string/delete_prefix_spec.rb
index 238de85f05..ee7f044905 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'
@@ -38,18 +39,9 @@ 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
- 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 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
diff --git a/spec/ruby/core/string/delete_spec.rb b/spec/ruby/core/string/delete_spec.rb
index 87831a9d19..6d359776e4 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'
@@ -84,16 +85,8 @@ describe "String#delete" do
-> { "hello world".delete(mock('x')) }.should raise_error(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
- 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 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
diff --git a/spec/ruby/core/string/delete_suffix_spec.rb b/spec/ruby/core/string/delete_suffix_spec.rb
index 6883d6938c..1842d75aa5 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'
@@ -38,18 +39,9 @@ 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
- 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 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
diff --git a/spec/ruby/core/string/downcase_spec.rb b/spec/ruby/core/string/downcase_spec.rb
index 153b4ce191..2d260f23f1 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'
@@ -76,16 +77,8 @@ describe "String#downcase" 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
- 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 be_an_instance_of(String)
end
end
diff --git a/spec/ruby/core/string/dump_spec.rb b/spec/ruby/core/string/dump_spec.rb
index 81de0cfae4..cab8beff5a 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 be_an_instance_of(String)
end
it "wraps string with \"" do
diff --git a/spec/ruby/core/string/dup_spec.rb b/spec/ruby/core/string/dup_spec.rb
index 73f71b8ffc..073802d84b 100644
--- a/spec/ruby/core/string/dup_spec.rb
+++ b/spec/ruby/core/string/dup_spec.rb
@@ -51,7 +51,7 @@ 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
diff --git a/spec/ruby/core/string/each_byte_spec.rb b/spec/ruby/core/string/each_byte_spec.rb
index e04dca807f..7b3db265ac 100644
--- a/spec/ruby/core/string/each_byte_spec.rb
+++ b/spec/ruby/core/string/each_byte_spec.rb
@@ -9,26 +9,26 @@ 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
diff --git a/spec/ruby/core/string/each_grapheme_cluster_spec.rb b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
index f28e24000e..e1fa4ae67b 100644
--- a/spec/ruby/core/string/each_grapheme_cluster_spec.rb
+++ b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
@@ -8,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 fa041fa31d..e7599f832c 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'
diff --git a/spec/ruby/core/string/encode_spec.rb b/spec/ruby/core/string/encode_spec.rb
index 5604ab7210..97dd753b62 100644
--- a/spec/ruby/core/string/encode_spec.rb
+++ b/spec/ruby/core/string/encode_spec.rb
@@ -34,8 +34,8 @@ describe "String#encode" do
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 = "#{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
@@ -49,7 +49,7 @@ describe "String#encode" do
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
@@ -79,6 +79,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,8 +122,7 @@ 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)
@@ -151,8 +154,7 @@ describe "String#encode" do
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)
@@ -187,13 +189,13 @@ describe "String#encode!" do
describe "when passed no options" do
it "returns self when Encoding.default_internal is nil" do
Encoding.default_internal = nil
- 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 = +"abc"
str.encode!.should equal(str)
end
end
@@ -201,14 +203,14 @@ describe "String#encode!" do
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 = +"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)
@@ -217,7 +219,7 @@ describe "String#encode!" do
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)
diff --git a/spec/ruby/core/string/encoding_spec.rb b/spec/ruby/core/string/encoding_spec.rb
index 574a1e2f92..f6e8fd3470 100644
--- a/spec/ruby/core/string/encoding_spec.rb
+++ b/spec/ruby/core/string/encoding_spec.rb
@@ -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
@@ -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
@@ -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/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..2259dcf3cf 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
diff --git a/spec/ruby/core/string/freeze_spec.rb b/spec/ruby/core/string/freeze_spec.rb
index 04d1e9513c..2e8e70386d 100644
--- a/spec/ruby/core/string/freeze_spec.rb
+++ b/spec/ruby/core/string/freeze_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe "String#freeze" do
diff --git a/spec/ruby/core/string/gsub_spec.rb b/spec/ruby/core/string/gsub_spec.rb
index c87a566591..0d9f32eca2 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'
@@ -192,22 +193,11 @@ describe "String#gsub with pattern and replacement" do
-> { "hello".gsub(/[aeiou]/, nil) }.should raise_error(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
- 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
+ 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
it "sets $~ to MatchData of last match and nil when there's none" do
diff --git a/spec/ruby/core/string/include_spec.rb b/spec/ruby/core/string/include_spec.rb
index 23e1e134ec..9781140a55 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
diff --git a/spec/ruby/core/string/index_spec.rb b/spec/ruby/core/string/index_spec.rb
index 2eeee9be87..835263a2cd 100644
--- a/spec/ruby/core/string/index_spec.rb
+++ b/spec/ruby/core/string/index_spec.rb
@@ -161,11 +161,18 @@ describe "String#index with String" do
end
it "handles a substring in a superset encoding" do
- 'abc'.force_encoding(Encoding::US_ASCII).index('é').should == nil
+ 'abc'.dup.force_encoding(Encoding::US_ASCII).index('é').should == nil
end
it "handles a substring in a subset encoding" do
- 'été'.index('t'.force_encoding(Encoding::US_ASCII)).should == 1
+ 'é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_error(Encoding::CompatibilityError, "incompatible character encodings: ISO-2022-JP and EUC-JP")
end
end
@@ -224,6 +231,17 @@ describe "String#index with Regexp" do
$~.should == nil
end
+ ruby_bug "#20421", ""..."3.3" do
+ it "always clear $~" do
+ "a".index(/a/)
+ $~.should_not == nil
+
+ string = "blablabla"
+ string.index(/bla/, string.length + 1)
+ $~.should == nil
+ end
+ end
+
it "starts the search at the given offset" do
"blablabla".index(/.{0}/, 5).should == 5
"blablabla".index(/.{1}/, 5).should == 5
@@ -312,6 +330,17 @@ describe "String#index with Regexp" do
"われわわれ".index(/わ/, 3).should == 3
end
+ ruby_bug "#19763", ""..."3.3.0" do
+ it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
+ re = Regexp.new "れ".encode(Encoding::EUC_JP)
+ -> do
+ "あれ".index re
+ end.should raise_error(Encoding::CompatibilityError, "incompatible encoding regexp match (EUC-JP regexp with UTF-8 string)")
+ end
+ end
+
+ # The exception message was incorrectly "incompatible character encodings: UTF-8 and EUC-JP" before 3.3.0
+ # Still test that the right exception class is used before that.
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
re = Regexp.new "れ".encode(Encoding::EUC_JP)
-> do
diff --git a/spec/ruby/core/string/insert_spec.rb b/spec/ruby/core/string/insert_spec.rb
index 0c87df3a95..483f3c9367 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'
diff --git a/spec/ruby/core/string/inspect_spec.rb b/spec/ruby/core/string/inspect_spec.rb
index 8bf3d3161f..15db06c7f5 100644
--- a/spec/ruby/core/string/inspect_spec.rb
+++ b/spec/ruby/core/string/inspect_spec.rb
@@ -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/ljust_spec.rb b/spec/ruby/core/string/ljust_spec.rb
index 9a25d3abd4..47324c59d2 100644
--- a/spec/ruby/core/string/ljust_spec.rb
+++ b/spec/ruby/core/string/ljust_spec.rb
@@ -64,31 +64,18 @@ describe "String#ljust with length, padding" do
-> { "hello".ljust(10, '') }.should raise_error(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)
-
- "".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
+ 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)
- 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 be_an_instance_of(String)
+ "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_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)
@@ -97,7 +84,7 @@ describe "String#ljust with length, padding" do
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)
diff --git a/spec/ruby/core/string/lstrip_spec.rb b/spec/ruby/core/string/lstrip_spec.rb
index 75434613f1..99bab6f349 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'
@@ -20,11 +21,9 @@ 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
@@ -47,12 +46,10 @@ 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
diff --git a/spec/ruby/core/string/modulo_spec.rb b/spec/ruby/core/string/modulo_spec.rb
index bf96a82874..9045afa263 100644
--- a/spec/ruby/core/string/modulo_spec.rb
+++ b/spec/ruby/core/string/modulo_spec.rb
@@ -55,33 +55,48 @@ describe "String#%" do
-> { ("foo%" % [])}.should raise_error(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_error(ArgumentError)
+ -> { ("foo%quux" % []) }.should raise_error(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
+ end
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError if % is not followed by a conversion specifier" do
+ -> { "%" % [] }.should raise_error(ArgumentError)
+ -> { "%\n" % [] }.should raise_error(ArgumentError)
+ -> { "%\0" % [] }.should raise_error(ArgumentError)
+ -> { " % " % [] }.should raise_error(ArgumentError)
-> { "%.\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
end
end
@@ -125,8 +140,16 @@ 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_error(ArgumentError)
+ end
end
it "raises an ArgumentError when given invalid argument specifiers" do
diff --git a/spec/ruby/core/string/ord_spec.rb b/spec/ruby/core/string/ord_spec.rb
index 4cf26990fe..35af3b5458 100644
--- a/spec/ruby/core/string/ord_spec.rb
+++ b/spec/ruby/core/string/ord_spec.rb
@@ -27,7 +27,7 @@ describe "String#ord" do
end
it "raises ArgumentError if the character is broken" do
- s = "©".force_encoding("US-ASCII")
+ s = "©".dup.force_encoding("US-ASCII")
-> { s.ord }.should raise_error(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 9cb3672881..d5370dcc73 100644
--- a/spec/ruby/core/string/partition_spec.rb
+++ b/spec/ruby/core/string/partition_spec.rb
@@ -40,7 +40,7 @@ describe "String#partition with String" do
end
it "handles a pattern in a superset encoding" do
- string = "hello".force_encoding(Encoding::US_ASCII)
+ string = "hello".dup.force_encoding(Encoding::US_ASCII)
result = string.partition("é")
@@ -51,7 +51,7 @@ describe "String#partition with String" do
end
it "handles a pattern in a subset encoding" do
- pattern = "o".force_encoding(Encoding::US_ASCII)
+ pattern = "o".dup.force_encoding(Encoding::US_ASCII)
result = "héllo world".partition(pattern)
diff --git a/spec/ruby/core/string/prepend_spec.rb b/spec/ruby/core/string/prepend_spec.rb
index a0393d4760..5248ea8056 100644
--- a/spec/ruby/core/string/prepend_spec.rb
+++ b/spec/ruby/core/string/prepend_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
diff --git a/spec/ruby/core/string/reverse_spec.rb b/spec/ruby/core/string/reverse_spec.rb
index 73526256ef..aa6abe6036 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 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
it "reverses a string with multi byte characters" do
diff --git a/spec/ruby/core/string/rindex_spec.rb b/spec/ruby/core/string/rindex_spec.rb
index e795105e1d..88ce733583 100644
--- a/spec/ruby/core/string/rindex_spec.rb
+++ b/spec/ruby/core/string/rindex_spec.rb
@@ -1,7 +1,6 @@
# -*- 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
@@ -198,11 +197,18 @@ describe "String#rindex with String" do
end
it "handles a substring in a superset encoding" do
- 'abc'.force_encoding(Encoding::US_ASCII).rindex('é').should == nil
+ 'abc'.dup.force_encoding(Encoding::US_ASCII).rindex('é').should == nil
end
it "handles a substring in a subset encoding" do
- 'été'.rindex('t'.force_encoding(Encoding::US_ASCII)).should == 1
+ 'é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_error(Encoding::CompatibilityError, "incompatible character encodings: ISO-2022-JP and EUC-JP")
end
end
@@ -373,6 +379,6 @@ describe "String#rindex with Regexp" do
re = Regexp.new "れ".encode(Encoding::EUC_JP)
-> do
"あれ".rindex re
- end.should raise_error(Encoding::CompatibilityError)
+ end.should raise_error(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..4ad3e54aea 100644
--- a/spec/ruby/core/string/rjust_spec.rb
+++ b/spec/ruby/core/string/rjust_spec.rb
@@ -64,31 +64,18 @@ describe "String#rjust with length, padding" do
-> { "hello".rjust(10, '') }.should raise_error(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)
-
- "".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
+ 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)
- 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 be_an_instance_of(String)
+ "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_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)
@@ -97,7 +84,7 @@ describe "String#rjust with length, padding" do
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)
diff --git a/spec/ruby/core/string/rpartition_spec.rb b/spec/ruby/core/string/rpartition_spec.rb
index 21e87f530a..cef0384c73 100644
--- a/spec/ruby/core/string/rpartition_spec.rb
+++ b/spec/ruby/core/string/rpartition_spec.rb
@@ -48,7 +48,7 @@ describe "String#rpartition with String" do
end
it "handles a pattern in a superset encoding" do
- string = "hello".force_encoding(Encoding::US_ASCII)
+ string = "hello".dup.force_encoding(Encoding::US_ASCII)
result = string.rpartition("é")
@@ -59,7 +59,7 @@ describe "String#rpartition with String" do
end
it "handles a pattern in a subset encoding" do
- pattern = "o".force_encoding(Encoding::US_ASCII)
+ pattern = "o".dup.force_encoding(Encoding::US_ASCII)
result = "héllo world".rpartition(pattern)
diff --git a/spec/ruby/core/string/rstrip_spec.rb b/spec/ruby/core/string/rstrip_spec.rb
index e96ce4120f..6d46eb590e 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'
@@ -51,12 +52,10 @@ 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
diff --git a/spec/ruby/core/string/scan_spec.rb b/spec/ruby/core/string/scan_spec.rb
index a2d1815132..70c3b7fb7b 100644
--- a/spec/ruby/core/string/scan_spec.rb
+++ b/spec/ruby/core/string/scan_spec.rb
@@ -165,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 a51fbd020a..b9ef0f1a16 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'
@@ -36,18 +37,10 @@ describe "String#scrub with a default replacement" do
"abc\u3042#{x81}".scrub.encoding.should == Encoding::UTF_8
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
- 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 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
end
@@ -97,12 +90,10 @@ describe "String#scrub with a custom replacement" do
block.should raise_error(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 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
end
@@ -129,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 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
end
diff --git a/spec/ruby/core/string/setbyte_spec.rb b/spec/ruby/core/string/setbyte_spec.rb
index 77bff64038..85403ca62c 100644
--- a/spec/ruby/core/string/setbyte_spec.rb
+++ b/spec/ruby/core/string/setbyte_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
describe "String#setbyte" 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..3de1453f4f
--- /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_error(TypeError, "no implicit conversion of nil into String")
+ end
+
+ it "raises a TypeError if passed a boolean" do
+ -> { "abc".send(@method, true) }.should raise_error(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_error(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_error(TypeError, "no implicit conversion of MockObject into String")
+ end
+
+ it "raises a TypeError if passed an Integer" do
+ -> { "abc".send(@method, 97) }.should raise_error(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_error(IndexError, "offset 1 does not land on character boundary")
+ -> { "わ".send(@method, "", 2) }.should raise_error(IndexError, "offset 2 does not land on character boundary")
+ -> { "わ".send(@method, "", -1) }.should raise_error(IndexError, "offset 2 does not land on character boundary")
+ -> { "わ".send(@method, "", -2) }.should raise_error(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_error(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..c730643cf4 100644
--- a/spec/ruby/core/string/shared/chars.rb
+++ b/spec/ruby/core/string/shared/chars.rb
@@ -21,12 +21,12 @@ describe :string_chars, shared: true do
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
@@ -39,14 +39,14 @@ describe :string_chars, shared: true do
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')
diff --git a/spec/ruby/core/string/shared/codepoints.rb b/spec/ruby/core/string/shared/codepoints.rb
index 0b2e078e0a..f71263054a 100644
--- a/spec/ruby/core/string/shared/codepoints.rb
+++ b/spec/ruby/core/string/shared/codepoints.rb
@@ -7,7 +7,7 @@ describe :string_codepoints, shared: true do
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 = "\xDF".dup.force_encoding(Encoding::UTF_8)
s.valid_encoding?.should be_false
-> { s.send(@method).to_a }.should raise_error(ArgumentError)
end
@@ -21,7 +21,7 @@ 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 = "\xDF".dup.force_encoding(Encoding::UTF_8)
s.valid_encoding?.should be_false
-> { s.send(@method) { } }.should raise_error(ArgumentError)
end
@@ -49,7 +49,7 @@ 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
diff --git a/spec/ruby/core/string/shared/concat.rb b/spec/ruby/core/string/shared/concat.rb
index ee5ef2a98f..dded9a69e7 100644
--- a/spec/ruby/core/string/shared/concat.rb
+++ b/spec/ruby/core/string/shared/concat.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
describe :string_concat, shared: true do
it "concatenates the given argument to self and returns self" do
str = 'hello '
diff --git a/spec/ruby/core/string/shared/dedup.rb b/spec/ruby/core/string/shared/dedup.rb
index 6ffcb9b045..97b5df6ed1 100644
--- a/spec/ruby/core/string/shared/dedup.rb
+++ b/spec/ruby/core/string/shared/dedup.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
describe :string_dedup, shared: true do
it 'returns self if the String is frozen' do
input = 'foo'.freeze
@@ -48,10 +49,8 @@ describe :string_dedup, shared: true do
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
+ 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
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..31b4c02c9c 100644
--- a/spec/ruby/core/string/shared/each_codepoint_without_block.rb
+++ b/spec/ruby/core/string/shared/each_codepoint_without_block.rb
@@ -6,7 +6,7 @@ describe :string_each_codepoint_without_block, shared: true do
end
it "returns an Enumerator even when self has an invalid encoding" do
- s = "\xDF".force_encoding(Encoding::UTF_8)
+ s = "\xDF".dup.force_encoding(Encoding::UTF_8)
s.valid_encoding?.should be_false
s.send(@method).should be_an_instance_of(Enumerator)
end
@@ -23,7 +23,7 @@ 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 = "\xDF".dup.force_encoding(Encoding::UTF_8)
s.valid_encoding?.should be_false
s.send(@method).size.should == 1
end
diff --git a/spec/ruby/core/string/shared/each_line.rb b/spec/ruby/core/string/shared/each_line.rb
index df78bd2186..231a6d9d4f 100644
--- a/spec/ruby/core/string/shared/each_line.rb
+++ b/spec/ruby/core/string/shared/each_line.rb
@@ -85,20 +85,10 @@ 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
@@ -116,7 +106,7 @@ 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."]
diff --git a/spec/ruby/core/string/shared/encode.rb b/spec/ruby/core/string/shared/encode.rb
index a73de5b943..3776e0d709 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
diff --git a/spec/ruby/core/string/shared/eql.rb b/spec/ruby/core/string/shared/eql.rb
index 6f268c929c..845b0a3e15 100644
--- a/spec/ruby/core/string/shared/eql.rb
+++ b/spec/ruby/core/string/shared/eql.rb
@@ -13,15 +13,15 @@ describe :string_eql_value, shared: true do
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 be_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 be_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 be_false
end
it "ignores subclass differences" do
@@ -33,6 +33,6 @@ describe :string_eql_value, shared: true do
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/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 41b3c7e0c9..4cac149ce5 100644
--- a/spec/ruby/core/string/shared/partition.rb
+++ b/spec/ruby/core/string/shared/partition.rb
@@ -2,35 +2,17 @@ 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
-
- StringSpecs::MyString.new("hello").send(@method, "x").each do |item|
- item.should be_an_instance_of(String)
- end
-
- 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 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("hello").send(@method, StringSpecs::MyString.new("l")).each do |item|
- item.should be_an_instance_of(StringSpecs::MyString)
- end
-
- StringSpecs::MyString.new("hello").send(@method, "x").each do |item|
- item.should be_an_instance_of(StringSpecs::MyString)
- 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, /l./).each do |item|
- item.should be_an_instance_of(StringSpecs::MyString)
- end
+ StringSpecs::MyString.new("hello").send(@method, /l./).each do |item|
+ item.should be_an_instance_of(String)
end
end
diff --git a/spec/ruby/core/string/shared/replace.rb b/spec/ruby/core/string/shared/replace.rb
index a5108d9e7c..24dac0eb27 100644
--- a/spec/ruby/core/string/shared/replace.rb
+++ b/spec/ruby/core/string/shared/replace.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
describe :string_replace, shared: true do
it "returns self" do
a = "a"
diff --git a/spec/ruby/core/string/shared/slice.rb b/spec/ruby/core/string/shared/slice.rb
index a7c1d05b56..2f69b9ddce 100644
--- a/spec/ruby/core/string/shared/slice.rb
+++ b/spec/ruby/core/string/shared/slice.rb
@@ -84,8 +84,8 @@ describe :string_slice_index_length, shared: true 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
@@ -152,22 +152,11 @@ describe :string_slice_index_length, shared: true do
-> { "hello".send(@method, 0, bignum_value) }.should raise_error(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
- 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 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 "handles repeated application" do
@@ -242,22 +231,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 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 "calls to_int on range arguments" do
@@ -336,20 +314,10 @@ describe :string_slice_regexp, shared: true do
"hello there".encode("US-ASCII").send(@method, /[aeiou](.)\1/).encoding.should == Encoding::US_ASCII
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
- 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 be_an_instance_of(String)
+ s.send(@method, /../).should be_an_instance_of(String)
end
it "sets $~ to MatchData when there is a match and nil when there's none" do
@@ -418,20 +386,10 @@ describe :string_slice_regexp_index, shared: true do
-> { "hello".send(@method, /(.)(.)(.)/, nil) }.should raise_error(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 be_an_instance_of(String)
+ s.send(@method, /(.)(.)/, 1).should be_an_instance_of(String)
end
it "sets $~ to MatchData when there is a match and nil when there's none" do
@@ -470,22 +428,11 @@ describe :string_slice_string, shared: true do
-> { "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
- 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 be_an_instance_of(String)
end
end
@@ -531,18 +478,9 @@ describe :string_slice_regexp_group, shared: true do
-> { "hello".send(@method, /(?<q>)/, '') }.should raise_error(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 be_an_instance_of(String)
end
it "sets $~ to MatchData when there is a match and nil when there's none" do
diff --git a/spec/ruby/core/string/shared/strip.rb b/spec/ruby/core/string/shared/strip.rb
index 0c0aae20f3..3af77b50fe 100644
--- a/spec/ruby/core/string/shared/strip.rb
+++ b/spec/ruby/core/string/shared/strip.rb
@@ -6,19 +6,9 @@ describe :string_strip, shared: true do
" hello ".encode("US-ASCII").send(@method).encoding.should == Encoding::US_ASCII
end
- 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
- 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 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
end
diff --git a/spec/ruby/core/string/shared/succ.rb b/spec/ruby/core/string/shared/succ.rb
index 3605fa99a2..b69a394875 100644
--- a/spec/ruby/core/string/shared/succ.rb
+++ b/spec/ruby/core/string/shared/succ.rb
@@ -59,20 +59,10 @@ 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
- 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 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
@@ -83,6 +73,7 @@ end
describe :string_succ_bang, shared: true do
it "is equivalent to succ, but modifies self in place (still returns self)" do
["", "abcd", "THX1138"].each do |s|
+ s = +s
r = s.dup.send(@method)
s.send(@method).should equal(s)
s.should == r
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_sym.rb b/spec/ruby/core/string/shared/to_sym.rb
index 52d8314211..833eae100e 100644
--- a/spec/ruby/core/string/shared/to_sym.rb
+++ b/spec/ruby/core/string/shared/to_sym.rb
@@ -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
diff --git a/spec/ruby/core/string/slice_spec.rb b/spec/ruby/core/string/slice_spec.rb
index c9e13ed1bc..5aba2d3be0 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'
@@ -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 be_an_instance_of(String)
+ s.slice!(0, 4).should be_an_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 be_an_instance_of(String)
+ s.slice!(0..4).should be_an_instance_of(String)
end
it "calls to_int on range arguments" do
@@ -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 be_an_instance_of(String)
+ s.slice!(/../).should be_an_instance_of(String)
end
it "returns the matching portion of self with a multi byte character" do
@@ -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 be_an_instance_of(String)
+ s.slice!(/(.)(.)/, 1).should be_an_instance_of(String)
end
it "returns the encoding aware capture for the given index" do
@@ -415,22 +375,11 @@ describe "String#slice! with String" do
-> { "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
- 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 be_an_instance_of(String)
end
it "raises a FrozenError if self is frozen" do
diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb
index 519c5d845d..3c6d1864d1 100644
--- a/spec/ruby/core/string/split_spec.rb
+++ b/spec/ruby/core/string/split_spec.rb
@@ -4,7 +4,7 @@ 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)
@@ -12,7 +12,7 @@ describe "String#split with String" do
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)
end
@@ -192,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 be_an_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 be_an_instance_of(String)
end
end
end
@@ -257,7 +229,7 @@ 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)
end
@@ -414,36 +386,12 @@ 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
- 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
+ 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
@@ -461,7 +409,7 @@ describe "String#split with Regexp" do
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')
@@ -569,32 +517,16 @@ 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 be_an_instance_of(String)
+ first.should == "a"
- last.should be_an_instance_of(String)
- last.should == "b"
- end
+ last.should be_an_instance_of(String)
+ last.should == "b"
end
end
diff --git a/spec/ruby/core/string/squeeze_spec.rb b/spec/ruby/core/string/squeeze_spec.rb
index 2f3fa65745..4ea238e6b5 100644
--- a/spec/ruby/core/string/squeeze_spec.rb
+++ b/spec/ruby/core/string/squeeze_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: binary -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -75,16 +76,8 @@ describe "String#squeeze" do
-> { "hello world".squeeze(mock('x')) }.should raise_error(TypeError)
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
- 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 be_an_instance_of(String)
end
end
diff --git a/spec/ruby/core/string/start_with_spec.rb b/spec/ruby/core/string/start_with_spec.rb
index 3833289f96..35e33b46a6 100644
--- a/spec/ruby/core/string/start_with_spec.rb
+++ b/spec/ruby/core/string/start_with_spec.rb
@@ -7,12 +7,21 @@ 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
- "\xe3\x81\x82".size.should == 1
- "\xe3\x81\x82".should.start_with?("\xe3")
+ ruby_version_is ""..."3.3" do
+ it "does not check we are matching only part of a character" do
+ "\xe3\x81\x82".size.should == 1
+ "\xe3\x81\x82".should.start_with?("\xe3")
+ end
+ end
+
+ ruby_version_is "3.3" do # #19784
+ it "checks we are matching only part of a character" do
+ "\xe3\x81\x82".size.should == 1
+ "\xe3\x81\x82".should_not.start_with?("\xe3")
+ end
end
end
diff --git a/spec/ruby/core/string/strip_spec.rb b/spec/ruby/core/string/strip_spec.rb
index 662f13b032..edb6ea3b44 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,10 +12,8 @@ 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
@@ -41,12 +40,10 @@ 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
diff --git a/spec/ruby/core/string/sub_spec.rb b/spec/ruby/core/string/sub_spec.rb
index 99dd7b45a8..4f9f87a433 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'
@@ -170,22 +171,11 @@ describe "String#sub with pattern, replacement" do
-> { "hello".sub(/[aeiou]/, 99) }.should raise_error(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 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 "sets $~ to MatchData of match and nil when there's none" do
diff --git a/spec/ruby/core/string/swapcase_spec.rb b/spec/ruby/core/string/swapcase_spec.rb
index d369ab3e4e..7f4c68366d 100644
--- a/spec/ruby/core/string/swapcase_spec.rb
+++ b/spec/ruby/core/string/swapcase_spec.rb
@@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*-
+# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -74,18 +75,9 @@ describe "String#swapcase" 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
- 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 be_an_instance_of(String)
+ StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(String)
end
end
diff --git a/spec/ruby/core/string/to_i_spec.rb b/spec/ruby/core/string/to_i_spec.rb
index e4fa89aab3..9931502baa 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 underscoes 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|
diff --git a/spec/ruby/core/string/tr_s_spec.rb b/spec/ruby/core/string/tr_s_spec.rb
index e1bb20ce35..dd72da440c 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,15 @@ describe "String#tr_s" do
"hello ^--^".tr_s("---", "_").should == "hello ^_^"
end
+ ruby_bug "#19769", ""..."3.3" do
+ 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
+ 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 +55,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 be_an_instance_of(String)
end
# http://redmine.ruby-lang.org/issues/show/1839
diff --git a/spec/ruby/core/string/tr_spec.rb b/spec/ruby/core/string/tr_spec.rb
index 72adb9f2eb..75841a974f 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,6 +17,15 @@ describe "String#tr" do
"hello ^-^".tr("---", "_").should == "hello ^_^"
end
+ ruby_bug "#19769", ""..."3.3" do
+ 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
+ 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..."
@@ -57,16 +67,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 be_an_instance_of(String)
end
# http://redmine.ruby-lang.org/issues/show/1839
diff --git a/spec/ruby/core/string/unicode_normalize_spec.rb b/spec/ruby/core/string/unicode_normalize_spec.rb
index 6de7533fc7..2e7d22394a 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
diff --git a/spec/ruby/core/string/unicode_normalized_spec.rb b/spec/ruby/core/string/unicode_normalized_spec.rb
index 87f3740459..91cf2086b2 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
diff --git a/spec/ruby/core/string/unpack/a_spec.rb b/spec/ruby/core/string/unpack/a_spec.rb
index 2d83b4c824..4002ece697 100644
--- a/spec/ruby/core/string/unpack/a_spec.rb
+++ b/spec/ruby/core/string/unpack/a_spec.rb
@@ -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/b_spec.rb b/spec/ruby/core/string/unpack/b_spec.rb
index 5c53eff721..23d93a8aea 100644
--- a/spec/ruby/core/string/unpack/b_spec.rb
+++ b/spec/ruby/core/string/unpack/b_spec.rb
@@ -107,7 +107,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
@@ -215,7 +215,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/u_spec.rb b/spec/ruby/core/string/unpack/u_spec.rb
index 7845e6d5f2..456abee784 100644
--- a/spec/ruby/core/string/unpack/u_spec.rb
+++ b/spec/ruby/core/string/unpack/u_spec.rb
@@ -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/upcase_spec.rb b/spec/ruby/core/string/upcase_spec.rb
index 5ce7b0b95f..652de5c2ef 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'
@@ -73,16 +74,8 @@ describe "String#upcase" 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
- 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 be_an_instance_of(String)
end
end
diff --git a/spec/ruby/core/string/uplus_spec.rb b/spec/ruby/core/string/uplus_spec.rb
index 038b283c90..c0b0c49ede 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,6 +8,9 @@ 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
diff --git a/spec/ruby/core/string/upto_spec.rb b/spec/ruby/core/string/upto_spec.rb
index f8529b1d2b..8bc847d5ac 100644
--- a/spec/ruby/core/string/upto_spec.rb
+++ b/spec/ruby/core/string/upto_spec.rb
@@ -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_error(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)
diff --git a/spec/ruby/core/string/valid_encoding_spec.rb b/spec/ruby/core/string/valid_encoding_spec.rb
index be7cef7a8e..375035cd94 100644
--- a/spec/ruby/core/string/valid_encoding_spec.rb
+++ b/spec/ruby/core/string/valid_encoding_spec.rb
@@ -7,13 +7,13 @@ describe "String#valid_encoding?" do
end
it "returns true if self is valid in the current encoding and other encodings" do
- str = "\x77"
+ str = +"\x77"
str.force_encoding('utf-8').valid_encoding?.should be_true
str.force_encoding('binary').valid_encoding?.should be_true
end
it "returns true for all encodings self is valid in" do
- str = "\xE6\x9D\x94"
+ 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
@@ -43,10 +43,10 @@ describe "String#valid_encoding?" do
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
+ "\xD8\x00".dup.force_encoding('UTF-16BE').valid_encoding?.should be_false
+ "\x00\xD8".dup.force_encoding('UTF-16LE').valid_encoding?.should be_false
+ "\x04\x03\x02\x01".dup.force_encoding('UTF-32BE').valid_encoding?.should be_false
+ "\x01\x02\x03\x04".dup.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
@@ -100,27 +100,25 @@ describe "String#valid_encoding?" do
str.force_encoding('UTF8-MAC').valid_encoding?.should be_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 be_true
+ str.force_encoding('CP720').valid_encoding?.should be_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 = +"\u{8765}"
str.valid_encoding?.should be_true
- str = str.force_encoding('ascii')
+ str.force_encoding('ascii')
str.valid_encoding?.should be_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 be_false
end
it "returns false if a valid String had an invalid character appended to it" do
- str = "a"
+ str = +"a"
str.valid_encoding?.should be_true
str << [0xDD].pack('C').force_encoding('utf-8')
str.valid_encoding?.should be_false
diff --git a/spec/ruby/core/struct/constants_spec.rb b/spec/ruby/core/struct/constants_spec.rb
new file mode 100644
index 0000000000..fa61a4b912
--- /dev/null
+++ b/spec/ruby/core/struct/constants_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.2" do
+ 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
+end
diff --git a/spec/ruby/core/struct/new_spec.rb b/spec/ruby/core/struct/new_spec.rb
index 8758051a81..a94eb852e1 100644
--- a/spec/ruby/core/struct/new_spec.rb
+++ b/spec/ruby/core/struct/new_spec.rb
@@ -48,7 +48,7 @@ describe "Struct.new" do
end
it "allows non-ASCII member name" do
- name = "r\xe9sum\xe9".force_encoding(Encoding::ISO_8859_1).to_sym
+ 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
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/to_proc_spec.rb b/spec/ruby/core/symbol/to_proc_spec.rb
index 6d9c4bc622..54eccdba11 100644
--- a/spec/ruby/core/symbol/to_proc_spec.rb
+++ b/spec/ruby/core/symbol/to_proc_spec.rb
@@ -12,38 +12,19 @@ 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 "produces a Proc with arity -1" do
- pr = :to_s.to_proc
- pr.arity.should == -1
- end
-
- it "produces a Proc that always returns [[:rest]] for #parameters" do
- pr = :to_s.to_proc
- pr.parameters.should == [[:rest]]
- end
+ it "returns a Proc with #lambda? true" do
+ pr = :to_s.to_proc
+ pr.should.lambda?
end
- ruby_version_is "3.0" do
- it "returns a Proc with #lambda? true" do
- pr = :to_s.to_proc
- pr.should.lambda?
- end
-
- it "produces a Proc with arity -2" do
- pr = :to_s.to_proc
- pr.arity.should == -2
- 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 [[:req], [:rest]] for #parameters" do
- pr = :to_s.to_proc
- pr.parameters.should == [[:req], [: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.2" do
@@ -58,8 +39,8 @@ describe "Symbol#to_proc" do
@a = []
singleton_class.class_eval(&body)
tap(&:pub)
- proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method `pro' called/)
- proc{tap(&:pri)}.should raise_error(NoMethodError, /private method `pri' called/)
+ proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method [`']pro' called/)
+ proc{tap(&:pri)}.should raise_error(NoMethodError, /private method [`']pri' called/)
@a.should == [:pub]
@a = []
@@ -67,8 +48,8 @@ describe "Symbol#to_proc" do
o = c.new
o.instance_variable_set(:@a, [])
o.tap(&:pub)
- proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method `pro' called/)
- proc{o.tap(&:pri)}.should raise_error(NoMethodError, /private method `pri' called/)
+ proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method [`']pro' called/)
+ proc{o.tap(&:pri)}.should raise_error(NoMethodError, /private method [`']pri' called/)
o.a.should == [:pub]
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 e35e1fc0b4..6e381e4868 100644
--- a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
@@ -59,7 +59,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/label_spec.rb b/spec/ruby/core/thread/backtrace/location/label_spec.rb
index 7312d017e5..85ddccc8e3 100644
--- a/spec/ruby/core/thread/backtrace/location/label_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/label_spec.rb
@@ -7,11 +7,11 @@ describe 'Thread::Backtrace::Location#label' do
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
@@ -22,9 +22,9 @@ describe 'Thread::Backtrace::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
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_locations_spec.rb b/spec/ruby/core/thread/backtrace_locations_spec.rb
index c970ae023b..09fe622e0d 100644
--- a/spec/ruby/core/thread/backtrace_locations_spec.rb
+++ b/spec/ruby/core/thread/backtrace_locations_spec.rb
@@ -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..15bb29a349 100644
--- a/spec/ruby/core/thread/backtrace_spec.rb
+++ b/spec/ruby/core/thread/backtrace_spec.rb
@@ -13,7 +13,7 @@ describe "Thread#backtrace" do
backtrace = t.backtrace
backtrace.should be_kind_of(Array)
- backtrace.first.should =~ /`sleep'/
+ backtrace.first.should =~ /[`'](?:Kernel#)?sleep'/
t.raise 'finish the thread'
t.join
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..29c271789b
--- /dev/null
+++ b/spec/ruby/core/thread/each_caller_location_spec.rb
@@ -0,0 +1,49 @@
+require_relative '../../spec_helper'
+
+describe "Thread.each_caller_location" do
+ ruby_version_is "3.2" 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 be_kind_of(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 be_kind_of(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_error(LocalJumpError, "no block given")
+ end
+
+ it "doesn't accept keyword arguments" do
+ -> {
+ Thread.each_caller_location(12, foo: 10) {}
+ }.should raise_error(ArgumentError);
+ end
+ end
+end
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/fetch_spec.rb b/spec/ruby/core/thread/fetch_spec.rb
index 6b37d4cfc5..85ffb71874 100644
--- a/spec/ruby/core/thread/fetch_spec.rb
+++ b/spec/ruby/core/thread/fetch_spec.rb
@@ -29,6 +29,36 @@ 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)
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/native_thread_id_spec.rb b/spec/ruby/core/thread/native_thread_id_spec.rb
index 8460a1db8c..17a08c8a15 100644
--- a/spec/ruby/core/thread/native_thread_id_spec.rb
+++ b/spec/ruby/core/thread/native_thread_id_spec.rb
@@ -19,8 +19,15 @@ ruby_version_is "3.1" do
main_thread_id = Thread.current.native_thread_id
t_thread_id = t.native_thread_id
- t_thread_id.should be_kind_of(Integer)
+ if ruby_version_is "3.3"
+ # native_thread_id can be nil on a M:N scheduler
+ t_thread_id.should be_kind_of(Integer) if t_thread_id != nil
+ else
+ t_thread_id.should be_kind_of(Integer)
+ end
+
main_thread_id.should_not == t_thread_id
+
t.run
t.join
t.native_thread_id.should == nil
diff --git a/spec/ruby/core/thread/report_on_exception_spec.rb b/spec/ruby/core/thread/report_on_exception_spec.rb
index 9279fa1da5..d9daa041cd 100644
--- a/spec/ruby/core/thread/report_on_exception_spec.rb
+++ b/spec/ruby/core/thread/report_on_exception_spec.rb
@@ -61,34 +61,32 @@ describe "Thread#report_on_exception=" do
}.should raise_error(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
-
- line_call_foo = __LINE__ + 5
- go = false
- t = Thread.new {
- Thread.current.report_on_exception = true
- Thread.pass until go
- foo
- }
+ 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
- -> {
- 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
+ line_call_foo = __LINE__ + 5
+ go = false
+ t = Thread.new {
+ Thread.current.report_on_exception = true
+ Thread.pass until go
+ foo
+ }
- -> {
- t.join
- }.should raise_error(RuntimeError, "Thread#report_on_exception specs backtrace order")
- end
+ -> {
+ 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
it "prints the backtrace even if the thread was killed just after Thread#raise" do
diff --git a/spec/ruby/core/thread/thread_variable_get_spec.rb b/spec/ruby/core/thread/thread_variable_get_spec.rb
index 38f90d5830..0ad19bfd88 100644
--- a/spec/ruby/core/thread/thread_variable_get_spec.rb
+++ b/spec/ruby/core/thread/thread_variable_get_spec.rb
@@ -13,7 +13,7 @@ describe "Thread#thread_variable_get" do
@t.thread_variable_get(:a).should be_nil
end
- it "returns the value previously set by #[]=" do
+ 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
diff --git a/spec/ruby/core/time/_load_spec.rb b/spec/ruby/core/time/_load_spec.rb
index 152934370f..bb0d705bbc 100644
--- a/spec/ruby/core/time/_load_spec.rb
+++ b/spec/ruby/core/time/_load_spec.rb
@@ -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 0459589f01..48fb3c6f52 100644
--- a/spec/ruby/core/time/at_spec.rb
+++ b/spec/ruby/core/time/at_spec.rb
@@ -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))
@@ -203,7 +196,7 @@ describe "Time.at" do
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)
end
diff --git a/spec/ruby/core/time/deconstruct_keys_spec.rb b/spec/ruby/core/time/deconstruct_keys_spec.rb
index fbb0ec2164..ee17e7dbd4 100644
--- a/spec/ruby/core/time/deconstruct_keys_spec.rb
+++ b/spec/ruby/core/time/deconstruct_keys_spec.rb
@@ -37,8 +37,9 @@ ruby_version_is "3.2" do
Time.new(2022, 10, 5, 13, 30).deconstruct_keys(['year', []]).should == {}
end
- it "ignores not existing Symbol keys" do
- Time.new(2022, 10, 5, 13, 30).deconstruct_keys([:year, :a]).should == { year: 2022 }
+ 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
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/new_spec.rb b/spec/ruby/core/time/new_spec.rb
index 3752cd146d..d686355270 100644
--- a/spec/ruby/core/time/new_spec.rb
+++ b/spec/ruby/core/time/new_spec.rb
@@ -58,7 +58,7 @@ 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
- ruby_bug '#13669', '3.0'...'3.1' do
+ ruby_bug '#13669', ''...'3.1' do
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
@@ -200,10 +200,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
@@ -360,7 +358,7 @@ describe "Time.new with a timezone argument" do
-> {
Marshal.dump(time)
- }.should raise_error(NoMethodError, /undefined method `name' for/)
+ }.should raise_error(NoMethodError, /undefined method [`']name' for/)
end
end
@@ -561,15 +559,15 @@ describe "Time.new with a timezone argument" do
-> {
Time.new("2020-012-25 00:56:17 +0900")
- }.should raise_error(ArgumentError, "two digits mon is expected after `-': -012-25 00:")
+ }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -012-25 00:\z/)
-> {
Time.new("2020-2-25 00:56:17 +0900")
- }.should raise_error(ArgumentError, "two digits mon is expected after `-': -2-25 00:56")
+ }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -2-25 00:56\z/)
-> {
Time.new("2020-12-215 00:56:17 +0900")
- }.should raise_error(ArgumentError, "two digits mday is expected after `-': -215 00:56:")
+ }.should raise_error(ArgumentError, /\Atwo digits mday is expected after [`']-': -215 00:56:\z/)
-> {
Time.new("2020-12-25 000:56:17 +0900")
@@ -581,19 +579,19 @@ describe "Time.new with a timezone argument" do
-> {
Time.new("2020-12-25 00:516:17 +0900")
- }.should raise_error(ArgumentError, "two digits min is expected after `:': :516:17 +09")
+ }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :516:17 \+09\z/)
-> {
Time.new("2020-12-25 00:6:17 +0900")
- }.should raise_error(ArgumentError, "two digits min is expected after `:': :6:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :6:17 \+0900\z/)
-> {
Time.new("2020-12-25 00:56:137 +0900")
- }.should raise_error(ArgumentError, "two digits sec is expected after `:': :137 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :137 \+0900\z/)
-> {
Time.new("2020-12-25 00:56:7 +0900")
- }.should raise_error(ArgumentError, "two digits sec is expected after `:': :7 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :7 \+0900\z/)
-> {
Time.new("2020-12-25 00:56. +0900")
diff --git a/spec/ruby/core/time/succ_spec.rb b/spec/ruby/core/time/succ_spec.rb
deleted file mode 100644
index cbf7cf0951..0000000000
--- a/spec/ruby/core/time/succ_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require_relative '../../spec_helper'
-
-ruby_version_is ""..."3.0" do
- 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/tracepoint/enable_spec.rb b/spec/ruby/core/tracepoint/enable_spec.rb
index 24f6070b97..6cc8bb3897 100644
--- a/spec/ruby/core/tracepoint/enable_spec.rb
+++ b/spec/ruby/core/tracepoint/enable_spec.rb
@@ -149,13 +149,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
diff --git a/spec/ruby/core/tracepoint/inspect_spec.rb b/spec/ruby/core/tracepoint/inspect_spec.rb
index 151a08e7b4..cc6bf0f842 100644
--- a/spec/ruby/core/tracepoint/inspect_spec.rb
+++ b/spec/ruby/core/tracepoint/inspect_spec.rb
@@ -3,13 +3,7 @@ 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
@@ -50,7 +44,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
@@ -68,7 +62,7 @@ describe 'TracePoint#inspect' do
trace_point_spec_test_return
end
- 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
@@ -82,7 +76,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
diff --git a/spec/ruby/core/tracepoint/path_spec.rb b/spec/ruby/core/tracepoint/path_spec.rb
index 5b6c6d4cfc..dc2ca840b8 100644
--- a/spec/ruby/core/tracepoint/path_spec.rb
+++ b/spec/ruby/core/tracepoint/path_spec.rb
@@ -13,14 +13,29 @@ describe 'TracePoint#path' do
path.should == "#{__FILE__}"
end
- it 'equals (eval) inside an eval for :end event' do
- path = nil
- TracePoint.new(:end) { |tp|
- next unless TracePointSpec.target_thread?
- path = tp.path
- }.enable do
- eval("module TracePointSpec; end")
+ ruby_version_is ""..."3.3" do
+ it 'equals (eval) inside an eval for :end event' do
+ path = nil
+ TracePoint.new(:end) { |tp|
+ next unless TracePointSpec.target_thread?
+ path = tp.path
+ }.enable do
+ eval("module TracePointSpec; end")
+ end
+ path.should == '(eval)'
+ end
+ end
+
+ ruby_version_is "3.3" 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?
+ path = tp.path
+ }.enable do
+ eval("module TracePointSpec; end")
+ end
+ path.should == "(eval at #{__FILE__}:#{__LINE__ - 2})"
end
- path.should == '(eval)'
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..c06793850f
--- /dev/null
+++ b/spec/ruby/core/true/singleton_method_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+describe "TrueClass#singleton_method" do
+ ruby_version_is '3.3' do
+ it "raises regardless of whether TrueClass defines the method" do
+ -> { true.singleton_method(:foo) }.should raise_error(NameError)
+ begin
+ def (true).foo; end
+ -> { true.singleton_method(:foo) }.should raise_error(NameError)
+ ensure
+ TrueClass.send(:remove_method, :foo)
+ end
+ end
+ 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/shared/dup.rb b/spec/ruby/core/unboundmethod/shared/dup.rb
new file mode 100644
index 0000000000..943a7faaa3
--- /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/source_location_spec.rb b/spec/ruby/core/unboundmethod/source_location_spec.rb
index c6823aa84b..5c2f14362c 100644
--- a/spec/ruby/core/unboundmethod/source_location_spec.rb
+++ b/spec/ruby/core/unboundmethod/source_location_spec.rb
@@ -9,7 +9,7 @@ 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 == 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
diff --git a/spec/ruby/core/unboundmethod/super_method_spec.rb b/spec/ruby/core/unboundmethod/super_method_spec.rb
index 101c83b8b3..aa7c129377 100644
--- a/spec/ruby/core/unboundmethod/super_method_spec.rb
+++ b/spec/ruby/core/unboundmethod/super_method_spec.rb
@@ -40,12 +40,10 @@ describe "UnboundMethod#super_method" do
end
end
- ruby_version_is "2.7.3" do
- 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
+ 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/warning/element_reference_spec.rb b/spec/ruby/core/warning/element_reference_spec.rb
index 41129e533a..c0ed37ef13 100644
--- a/spec/ruby/core/warning/element_reference_spec.rb
+++ b/spec/ruby/core/warning/element_reference_spec.rb
@@ -1,11 +1,13 @@
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
ruby_version_is '3.3' do
diff --git a/spec/ruby/core/warning/element_set_spec.rb b/spec/ruby/core/warning/element_set_spec.rb
index d20ee215ad..d59a7d4c9e 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,6 +17,18 @@ describe "Warning.[]=" do
end
end
+ ruby_version_is '3.3' do
+ it "enables or disables performance warnings" do
+ original = Warning[:performance]
+ begin
+ Warning[:performance] = !original
+ Warning[:performance].should == !original
+ ensure
+ Warning[:performance] = original
+ end
+ end
+ end
+
it "raises for unknown category" do
-> { Warning[:noop] = false }.should raise_error(ArgumentError, /unknown category: noop/)
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 e2fcfbf93f..8f96fe9287 100644
--- a/spec/ruby/core/warning/warn_spec.rb
+++ b/spec/ruby/core/warning/warn_spec.rb
@@ -51,100 +51,85 @@ 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
- 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
+ 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 "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
+ 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 :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
+ 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 "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
+ 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
- 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
+ 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 "prints the message when VERBOSE is false" do
- -> { Warning.warn("foo") }.should complain("foo")
+ 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 "prints the message when VERBOSE is nil" do
- -> { Warning.warn("foo") }.should complain("foo", verbose: nil)
- end
+ it "prints the message when VERBOSE is false" do
+ -> { Warning.warn("foo") }.should complain("foo")
+ end
- it "prints the message when VERBOSE is true" do
- -> { Warning.warn("foo") }.should complain("foo", verbose: true)
- end
+ it "prints the message when VERBOSE is nil" do
+ -> { Warning.warn("foo") }.should complain("foo", verbose: nil)
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
- begin
- Kernel.warn("Chunky bacon!")
- ensure
- $VERBOSE = verbose
- end
- end
+ it "prints the message when VERBOSE is true" do
+ -> { Warning.warn("foo") }.should complain("foo", verbose: true)
end
end