summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/ruby/.rubocop.yml2
-rw-r--r--spec/ruby/core/array/fixtures/classes.rb744
-rw-r--r--spec/ruby/core/array/pack/buffer_spec.rb10
-rw-r--r--spec/ruby/fixtures/io.rb (renamed from spec/ruby/library/io-wait/fixtures/classes.rb)10
-rw-r--r--spec/ruby/language/case_spec.rb2
-rw-r--r--spec/ruby/language/pattern_matching/3.1.rb75
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb1468
-rw-r--r--spec/ruby/library/io-wait/wait_readable_spec.rb19
-rw-r--r--spec/ruby/library/io-wait/wait_spec.rb39
-rw-r--r--spec/ruby/library/io-wait/wait_writable_spec.rb21
-rw-r--r--spec/ruby/library/rbconfig/rbconfig_spec.rb53
-rw-r--r--spec/ruby/optional/capi/io_spec.rb63
12 files changed, 1238 insertions, 1268 deletions
diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml
index be32ce8900..5a902e0f01 100644
--- a/spec/ruby/.rubocop.yml
+++ b/spec/ruby/.rubocop.yml
@@ -1,7 +1,7 @@
inherit_from: .rubocop_todo.yml
AllCops:
- TargetRubyVersion: 3.0
+ TargetRubyVersion: 3.1
DisplayCopNames: true
Exclude:
- command_line/fixtures/bad_syntax.rb
diff --git a/spec/ruby/core/array/fixtures/classes.rb b/spec/ruby/core/array/fixtures/classes.rb
index 8596245fb8..05283c0f74 100644
--- a/spec/ruby/core/array/fixtures/classes.rb
+++ b/spec/ruby/core/array/fixtures/classes.rb
@@ -56,23 +56,20 @@ module ArraySpecs
101.621, 102.816, 104.010, 105.202, 106.393, 107.583, 108.771, 109.958, 111.144, 112.329,
113.512, 114.695, 115.876, 117.057, 118.236, 119.414, 120.591, 121.767, 122.942, 124.116,
125.289, 126.462, 127.633, 128.803, 129.973, 131.141, 132.309, 133.476, 134.642, 135.807,
- ]
+ ]
def self.measure_sample_fairness(size, samples, iters)
ary = Array.new(size) { |x| x }
+ expected = iters.fdiv size
(samples).times do |i|
chi_results = []
3.times do
- counts = Array.new(size) { 0 }
- expected = iters / size
+ counts = Array.new(size, 0)
iters.times do
x = ary.sample(samples)[i]
counts[x] += 1
end
- chi_squared = 0.0
- counts.each do |count|
- chi_squared += (((count - expected) ** 2) * 1.0 / expected)
- end
+ chi_squared = counts.sum {|count| (count - expected) ** 2} / expected
chi_results << chi_squared
break if chi_squared <= CHI_SQUARED_CRITICAL_VALUES[size]
end
@@ -83,17 +80,14 @@ module ArraySpecs
def self.measure_sample_fairness_large_sample_size(size, samples, iters)
ary = Array.new(size) { |x| x }
- counts = Array.new(size) { 0 }
- expected = iters * samples / size
+ counts = Array.new(size, 0)
+ expected = (iters * samples).fdiv size
iters.times do
ary.sample(samples).each do |sample|
counts[sample] += 1
end
end
- chi_squared = 0.0
- counts.each do |count|
- chi_squared += (((count - expected) ** 2) * 1.0 / expected)
- end
+ chi_squared = counts.sum {|count| (count - expected) ** 2} / expected
# Chi squared critical values for tests with 4 degrees of freedom
# Values obtained from NIST Engineering Statistic Handbook at
@@ -223,366 +217,370 @@ module ArraySpecs
obj
end
- LargeArray = ["test_create_table_with_force_true_does_not_drop_nonexisting_table",
- "test_add_table",
- "assert_difference",
- "assert_operator",
- "instance_variables",
- "class",
- "instance_variable_get",
- "__class__",
- "expects",
- "assert_no_difference",
- "name",
- "assert_blank",
- "assert_not_same",
- "is_a?",
- "test_add_table_with_decimals",
- "test_create_table_with_timestamps_should_create_datetime_columns",
- "assert_present",
- "assert_no_match",
- "__instance_of__",
- "assert_deprecated",
- "assert",
- "assert_throws",
- "kind_of?",
- "try",
- "__instance_variable_get__",
- "object_id",
- "timeout",
- "instance_variable_set",
- "assert_nothing_thrown",
- "__instance_variable_set__",
- "copy_object",
- "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
- "assert_not_deprecated",
- "assert_in_delta",
- "id",
- "copy_metaclass",
- "test_create_table_without_a_block",
- "dup",
- "assert_not_nil",
- "send",
- "__instance_variables__",
- "to_sql",
- "mock",
- "assert_send",
- "instance_variable_defined?",
- "clone",
- "require",
- "test_migrator",
- "__instance_variable_defined_eh__",
- "frozen?",
- "test_add_column_not_null_with_default",
- "freeze",
- "test_migrator_one_up",
- "test_migrator_one_down",
- "singleton_methods",
- "method_exists?",
- "create_fixtures",
- "test_migrator_one_up_one_down",
- "test_native_decimal_insert_manual_vs_automatic",
- "instance_exec",
- "__is_a__",
- "test_migrator_double_up",
- "stub",
- "private_methods",
- "stubs",
- "test_migrator_double_down",
- "fixture_path",
- "private_singleton_methods",
- "stub_everything",
- "test_migrator_one_up_with_exception_and_rollback",
- "sequence",
- "protected_methods",
- "enum_for",
- "test_finds_migrations",
- "run_before_mocha",
- "states",
- "protected_singleton_methods",
- "to_json",
- "instance_values",
- "==",
- "mocha_setup",
- "public_methods",
- "test_finds_pending_migrations",
- "mocha_verify",
- "assert_kind_of",
- "===",
- "=~",
- "test_relative_migrations",
- "mocha_teardown",
- "gem",
- "mocha",
- "test_only_loads_pending_migrations",
- "test_add_column_with_precision_and_scale",
- "require_or_load",
- "eql?",
- "require_dependency",
- "test_native_types",
- "test_target_version_zero_should_run_only_once",
- "extend",
- "to_matcher",
- "unloadable",
- "require_association",
- "hash",
- "__id__",
- "load_dependency",
- "equals",
- "test_migrator_db_has_no_schema_migrations_table",
- "test_migrator_verbosity",
- "kind_of",
- "to_yaml",
- "to_bool",
- "test_migrator_verbosity_off",
- "taint",
- "test_migrator_going_down_due_to_version_target",
- "tainted?",
- "mocha_inspect",
- "test_migrator_rollback",
- "vim",
- "untaint",
- "taguri=",
- "test_migrator_forward",
- "test_schema_migrations_table_name",
- "test_proper_table_name",
- "all_of",
- "test_add_drop_table_with_prefix_and_suffix",
- "_setup_callbacks",
- "setup",
- "Not",
- "test_create_table_with_binary_column",
- "assert_not_equal",
- "enable_warnings",
- "acts_like?",
- "Rational",
- "_removed_setup_callbacks",
- "Table",
- "bind",
- "any_of",
- "__method__",
- "test_migrator_with_duplicates",
- "_teardown_callbacks",
- "method",
- "test_migrator_with_duplicate_names",
- "_removed_teardown_callbacks",
- "any_parameters",
- "test_migrator_with_missing_version_numbers",
- "test_add_remove_single_field_using_string_arguments",
- "test_create_table_with_custom_sequence_name",
- "test_add_remove_single_field_using_symbol_arguments",
- "_one_time_conditions_valid_14?",
- "_one_time_conditions_valid_16?",
- "run_callbacks",
- "anything",
- "silence_warnings",
- "instance_variable_names",
- "_fixture_path",
- "copy_instance_variables_from",
- "fixture_path?",
- "has_entry",
- "__marshal__",
- "_fixture_table_names",
- "__kind_of__",
- "fixture_table_names?",
- "test_add_rename",
- "assert_equal",
- "_fixture_class_names",
- "fixture_class_names?",
- "has_entries",
- "_use_transactional_fixtures",
- "people",
- "test_rename_column_using_symbol_arguments",
- "use_transactional_fixtures?",
- "instance_eval",
- "blank?",
- "with_warnings",
- "__nil__",
- "load",
- "metaclass",
- "_use_instantiated_fixtures",
- "has_key",
- "class_eval",
- "present?",
- "test_rename_column",
- "teardown",
- "use_instantiated_fixtures?",
- "method_name",
- "silence_stderr",
- "presence",
- "test_rename_column_preserves_default_value_not_null",
- "silence_stream",
- "_pre_loaded_fixtures",
- "__metaclass__",
- "__fixnum__",
- "pre_loaded_fixtures?",
- "has_value",
- "suppress",
- "to_yaml_properties",
- "test_rename_nonexistent_column",
- "test_add_index",
- "includes",
- "find_correlate_in",
- "equality_predicate_sql",
- "assert_nothing_raised",
- "let",
- "not_predicate_sql",
- "test_rename_column_with_sql_reserved_word",
- "singleton_class",
- "test_rename_column_with_an_index",
- "display",
- "taguri",
- "to_yaml_style",
- "test_remove_column_with_index",
- "size",
- "current_adapter?",
- "test_remove_column_with_multi_column_index",
- "respond_to?",
- "test_change_type_of_not_null_column",
- "is_a",
- "to_a",
- "test_rename_table_for_sqlite_should_work_with_reserved_words",
- "require_library_or_gem",
- "setup_fixtures",
- "equal?",
- "teardown_fixtures",
- "nil?",
- "fixture_table_names",
- "fixture_class_names",
- "test_create_table_without_id",
- "use_transactional_fixtures",
- "test_add_column_with_primary_key_attribute",
- "repair_validations",
- "use_instantiated_fixtures",
- "instance_of?",
- "test_create_table_adds_id",
- "test_rename_table",
- "pre_loaded_fixtures",
- "to_enum",
- "test_create_table_with_not_null_column",
- "instance_of",
- "test_change_column_nullability",
- "optionally",
- "test_rename_table_with_an_index",
- "run",
- "test_change_column",
- "default_test",
- "assert_raise",
- "test_create_table_with_defaults",
- "assert_nil",
- "flunk",
- "regexp_matches",
- "duplicable?",
- "reset_mocha",
- "stubba_method",
- "filter_backtrace",
- "test_create_table_with_limits",
- "responds_with",
- "stubba_object",
- "test_change_column_with_nil_default",
- "assert_block",
- "__show__",
- "assert_date_from_db",
- "__respond_to_eh__",
- "run_in_transaction?",
- "inspect",
- "assert_sql",
- "test_change_column_with_new_default",
- "yaml_equivalent",
- "build_message",
- "to_s",
- "test_change_column_default",
- "assert_queries",
- "pending",
- "as_json",
- "assert_no_queries",
- "test_change_column_quotes_column_names",
- "assert_match",
- "test_keeping_default_and_notnull_constraint_on_change",
- "methods",
- "connection_allow_concurrency_setup",
- "connection_allow_concurrency_teardown",
- "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
- "__send__",
- "make_connection",
- "assert_raises",
- "tap",
- "with_kcode",
- "assert_instance_of",
- "test_create_table_with_primary_key_prefix_as_table_name",
- "assert_respond_to",
- "test_change_column_default_to_null",
- "assert_same",
- "__extend__"]
-
- LargeTestArraySorted = ["test_add_column_not_null_with_default",
- "test_add_column_with_precision_and_scale",
- "test_add_column_with_primary_key_attribute",
- "test_add_drop_table_with_prefix_and_suffix",
- "test_add_index",
- "test_add_remove_single_field_using_string_arguments",
- "test_add_remove_single_field_using_symbol_arguments",
- "test_add_rename",
- "test_add_table",
- "test_add_table_with_decimals",
- "test_change_column",
- "test_change_column_default",
- "test_change_column_default_to_null",
- "test_change_column_nullability",
- "test_change_column_quotes_column_names",
- "test_change_column_with_new_default",
- "test_change_column_with_nil_default",
- "test_change_type_of_not_null_column",
- "test_create_table_adds_id",
- "test_create_table_with_binary_column",
- "test_create_table_with_custom_sequence_name",
- "test_create_table_with_defaults",
- "test_create_table_with_force_true_does_not_drop_nonexisting_table",
- "test_create_table_with_limits",
- "test_create_table_with_not_null_column",
- "test_create_table_with_primary_key_prefix_as_table_name",
- "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
- "test_create_table_with_timestamps_should_create_datetime_columns",
- "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
- "test_create_table_without_a_block",
- "test_create_table_without_id",
- "test_finds_migrations",
- "test_finds_pending_migrations",
- "test_keeping_default_and_notnull_constraint_on_change",
- "test_migrator",
- "test_migrator_db_has_no_schema_migrations_table",
- "test_migrator_double_down",
- "test_migrator_double_up",
- "test_migrator_forward",
- "test_migrator_going_down_due_to_version_target",
- "test_migrator_one_down",
- "test_migrator_one_up",
- "test_migrator_one_up_one_down",
- "test_migrator_one_up_with_exception_and_rollback",
- "test_migrator_rollback",
- "test_migrator_verbosity",
- "test_migrator_verbosity_off",
- "test_migrator_with_duplicate_names",
- "test_migrator_with_duplicates",
- "test_migrator_with_missing_version_numbers",
- "test_native_decimal_insert_manual_vs_automatic",
- "test_native_types",
- "test_only_loads_pending_migrations",
- "test_proper_table_name",
- "test_relative_migrations",
- "test_remove_column_with_index",
- "test_remove_column_with_multi_column_index",
- "test_rename_column",
- "test_rename_column_preserves_default_value_not_null",
- "test_rename_column_using_symbol_arguments",
- "test_rename_column_with_an_index",
- "test_rename_column_with_sql_reserved_word",
- "test_rename_nonexistent_column",
- "test_rename_table",
- "test_rename_table_for_sqlite_should_work_with_reserved_words",
- "test_rename_table_with_an_index",
- "test_schema_migrations_table_name",
- "test_target_version_zero_should_run_only_once"]
+ LargeArray = [
+ "test_create_table_with_force_true_does_not_drop_nonexisting_table",
+ "test_add_table",
+ "assert_difference",
+ "assert_operator",
+ "instance_variables",
+ "class",
+ "instance_variable_get",
+ "__class__",
+ "expects",
+ "assert_no_difference",
+ "name",
+ "assert_blank",
+ "assert_not_same",
+ "is_a?",
+ "test_add_table_with_decimals",
+ "test_create_table_with_timestamps_should_create_datetime_columns",
+ "assert_present",
+ "assert_no_match",
+ "__instance_of__",
+ "assert_deprecated",
+ "assert",
+ "assert_throws",
+ "kind_of?",
+ "try",
+ "__instance_variable_get__",
+ "object_id",
+ "timeout",
+ "instance_variable_set",
+ "assert_nothing_thrown",
+ "__instance_variable_set__",
+ "copy_object",
+ "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
+ "assert_not_deprecated",
+ "assert_in_delta",
+ "id",
+ "copy_metaclass",
+ "test_create_table_without_a_block",
+ "dup",
+ "assert_not_nil",
+ "send",
+ "__instance_variables__",
+ "to_sql",
+ "mock",
+ "assert_send",
+ "instance_variable_defined?",
+ "clone",
+ "require",
+ "test_migrator",
+ "__instance_variable_defined_eh__",
+ "frozen?",
+ "test_add_column_not_null_with_default",
+ "freeze",
+ "test_migrator_one_up",
+ "test_migrator_one_down",
+ "singleton_methods",
+ "method_exists?",
+ "create_fixtures",
+ "test_migrator_one_up_one_down",
+ "test_native_decimal_insert_manual_vs_automatic",
+ "instance_exec",
+ "__is_a__",
+ "test_migrator_double_up",
+ "stub",
+ "private_methods",
+ "stubs",
+ "test_migrator_double_down",
+ "fixture_path",
+ "private_singleton_methods",
+ "stub_everything",
+ "test_migrator_one_up_with_exception_and_rollback",
+ "sequence",
+ "protected_methods",
+ "enum_for",
+ "test_finds_migrations",
+ "run_before_mocha",
+ "states",
+ "protected_singleton_methods",
+ "to_json",
+ "instance_values",
+ "==",
+ "mocha_setup",
+ "public_methods",
+ "test_finds_pending_migrations",
+ "mocha_verify",
+ "assert_kind_of",
+ "===",
+ "=~",
+ "test_relative_migrations",
+ "mocha_teardown",
+ "gem",
+ "mocha",
+ "test_only_loads_pending_migrations",
+ "test_add_column_with_precision_and_scale",
+ "require_or_load",
+ "eql?",
+ "require_dependency",
+ "test_native_types",
+ "test_target_version_zero_should_run_only_once",
+ "extend",
+ "to_matcher",
+ "unloadable",
+ "require_association",
+ "hash",
+ "__id__",
+ "load_dependency",
+ "equals",
+ "test_migrator_db_has_no_schema_migrations_table",
+ "test_migrator_verbosity",
+ "kind_of",
+ "to_yaml",
+ "to_bool",
+ "test_migrator_verbosity_off",
+ "taint",
+ "test_migrator_going_down_due_to_version_target",
+ "tainted?",
+ "mocha_inspect",
+ "test_migrator_rollback",
+ "vim",
+ "untaint",
+ "taguri=",
+ "test_migrator_forward",
+ "test_schema_migrations_table_name",
+ "test_proper_table_name",
+ "all_of",
+ "test_add_drop_table_with_prefix_and_suffix",
+ "_setup_callbacks",
+ "setup",
+ "Not",
+ "test_create_table_with_binary_column",
+ "assert_not_equal",
+ "enable_warnings",
+ "acts_like?",
+ "Rational",
+ "_removed_setup_callbacks",
+ "Table",
+ "bind",
+ "any_of",
+ "__method__",
+ "test_migrator_with_duplicates",
+ "_teardown_callbacks",
+ "method",
+ "test_migrator_with_duplicate_names",
+ "_removed_teardown_callbacks",
+ "any_parameters",
+ "test_migrator_with_missing_version_numbers",
+ "test_add_remove_single_field_using_string_arguments",
+ "test_create_table_with_custom_sequence_name",
+ "test_add_remove_single_field_using_symbol_arguments",
+ "_one_time_conditions_valid_14?",
+ "_one_time_conditions_valid_16?",
+ "run_callbacks",
+ "anything",
+ "silence_warnings",
+ "instance_variable_names",
+ "_fixture_path",
+ "copy_instance_variables_from",
+ "fixture_path?",
+ "has_entry",
+ "__marshal__",
+ "_fixture_table_names",
+ "__kind_of__",
+ "fixture_table_names?",
+ "test_add_rename",
+ "assert_equal",
+ "_fixture_class_names",
+ "fixture_class_names?",
+ "has_entries",
+ "_use_transactional_fixtures",
+ "people",
+ "test_rename_column_using_symbol_arguments",
+ "use_transactional_fixtures?",
+ "instance_eval",
+ "blank?",
+ "with_warnings",
+ "__nil__",
+ "load",
+ "metaclass",
+ "_use_instantiated_fixtures",
+ "has_key",
+ "class_eval",
+ "present?",
+ "test_rename_column",
+ "teardown",
+ "use_instantiated_fixtures?",
+ "method_name",
+ "silence_stderr",
+ "presence",
+ "test_rename_column_preserves_default_value_not_null",
+ "silence_stream",
+ "_pre_loaded_fixtures",
+ "__metaclass__",
+ "__fixnum__",
+ "pre_loaded_fixtures?",
+ "has_value",
+ "suppress",
+ "to_yaml_properties",
+ "test_rename_nonexistent_column",
+ "test_add_index",
+ "includes",
+ "find_correlate_in",
+ "equality_predicate_sql",
+ "assert_nothing_raised",
+ "let",
+ "not_predicate_sql",
+ "test_rename_column_with_sql_reserved_word",
+ "singleton_class",
+ "test_rename_column_with_an_index",
+ "display",
+ "taguri",
+ "to_yaml_style",
+ "test_remove_column_with_index",
+ "size",
+ "current_adapter?",
+ "test_remove_column_with_multi_column_index",
+ "respond_to?",
+ "test_change_type_of_not_null_column",
+ "is_a",
+ "to_a",
+ "test_rename_table_for_sqlite_should_work_with_reserved_words",
+ "require_library_or_gem",
+ "setup_fixtures",
+ "equal?",
+ "teardown_fixtures",
+ "nil?",
+ "fixture_table_names",
+ "fixture_class_names",
+ "test_create_table_without_id",
+ "use_transactional_fixtures",
+ "test_add_column_with_primary_key_attribute",
+ "repair_validations",
+ "use_instantiated_fixtures",
+ "instance_of?",
+ "test_create_table_adds_id",
+ "test_rename_table",
+ "pre_loaded_fixtures",
+ "to_enum",
+ "test_create_table_with_not_null_column",
+ "instance_of",
+ "test_change_column_nullability",
+ "optionally",
+ "test_rename_table_with_an_index",
+ "run",
+ "test_change_column",
+ "default_test",
+ "assert_raise",
+ "test_create_table_with_defaults",
+ "assert_nil",
+ "flunk",
+ "regexp_matches",
+ "duplicable?",
+ "reset_mocha",
+ "stubba_method",
+ "filter_backtrace",
+ "test_create_table_with_limits",
+ "responds_with",
+ "stubba_object",
+ "test_change_column_with_nil_default",
+ "assert_block",
+ "__show__",
+ "assert_date_from_db",
+ "__respond_to_eh__",
+ "run_in_transaction?",
+ "inspect",
+ "assert_sql",
+ "test_change_column_with_new_default",
+ "yaml_equivalent",
+ "build_message",
+ "to_s",
+ "test_change_column_default",
+ "assert_queries",
+ "pending",
+ "as_json",
+ "assert_no_queries",
+ "test_change_column_quotes_column_names",
+ "assert_match",
+ "test_keeping_default_and_notnull_constraint_on_change",
+ "methods",
+ "connection_allow_concurrency_setup",
+ "connection_allow_concurrency_teardown",
+ "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
+ "__send__",
+ "make_connection",
+ "assert_raises",
+ "tap",
+ "with_kcode",
+ "assert_instance_of",
+ "test_create_table_with_primary_key_prefix_as_table_name",
+ "assert_respond_to",
+ "test_change_column_default_to_null",
+ "assert_same",
+ "__extend__",
+ ]
+
+ LargeTestArraySorted = [
+ "test_add_column_not_null_with_default",
+ "test_add_column_with_precision_and_scale",
+ "test_add_column_with_primary_key_attribute",
+ "test_add_drop_table_with_prefix_and_suffix",
+ "test_add_index",
+ "test_add_remove_single_field_using_string_arguments",
+ "test_add_remove_single_field_using_symbol_arguments",
+ "test_add_rename",
+ "test_add_table",
+ "test_add_table_with_decimals",
+ "test_change_column",
+ "test_change_column_default",
+ "test_change_column_default_to_null",
+ "test_change_column_nullability",
+ "test_change_column_quotes_column_names",
+ "test_change_column_with_new_default",
+ "test_change_column_with_nil_default",
+ "test_change_type_of_not_null_column",
+ "test_create_table_adds_id",
+ "test_create_table_with_binary_column",
+ "test_create_table_with_custom_sequence_name",
+ "test_create_table_with_defaults",
+ "test_create_table_with_force_true_does_not_drop_nonexisting_table",
+ "test_create_table_with_limits",
+ "test_create_table_with_not_null_column",
+ "test_create_table_with_primary_key_prefix_as_table_name",
+ "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
+ "test_create_table_with_timestamps_should_create_datetime_columns",
+ "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
+ "test_create_table_without_a_block",
+ "test_create_table_without_id",
+ "test_finds_migrations",
+ "test_finds_pending_migrations",
+ "test_keeping_default_and_notnull_constraint_on_change",
+ "test_migrator",
+ "test_migrator_db_has_no_schema_migrations_table",
+ "test_migrator_double_down",
+ "test_migrator_double_up",
+ "test_migrator_forward",
+ "test_migrator_going_down_due_to_version_target",
+ "test_migrator_one_down",
+ "test_migrator_one_up",
+ "test_migrator_one_up_one_down",
+ "test_migrator_one_up_with_exception_and_rollback",
+ "test_migrator_rollback",
+ "test_migrator_verbosity",
+ "test_migrator_verbosity_off",
+ "test_migrator_with_duplicate_names",
+ "test_migrator_with_duplicates",
+ "test_migrator_with_missing_version_numbers",
+ "test_native_decimal_insert_manual_vs_automatic",
+ "test_native_types",
+ "test_only_loads_pending_migrations",
+ "test_proper_table_name",
+ "test_relative_migrations",
+ "test_remove_column_with_index",
+ "test_remove_column_with_multi_column_index",
+ "test_rename_column",
+ "test_rename_column_preserves_default_value_not_null",
+ "test_rename_column_using_symbol_arguments",
+ "test_rename_column_with_an_index",
+ "test_rename_column_with_sql_reserved_word",
+ "test_rename_nonexistent_column",
+ "test_rename_table",
+ "test_rename_table_for_sqlite_should_work_with_reserved_words",
+ "test_rename_table_with_an_index",
+ "test_schema_migrations_table_name",
+ "test_target_version_zero_should_run_only_once",
+ ]
class PrivateToAry
private
diff --git a/spec/ruby/core/array/pack/buffer_spec.rb b/spec/ruby/core/array/pack/buffer_spec.rb
index f1206efb3e..b77b2d1efa 100644
--- a/spec/ruby/core/array/pack/buffer_spec.rb
+++ b/spec/ruby/core/array/pack/buffer_spec.rb
@@ -28,6 +28,16 @@ describe "Array#pack with :buffer option" do
TypeError, "buffer must be String, not Array")
end
+ it "raise FrozenError if buffer is frozen" do
+ -> { [65].pack("c", buffer: "frozen-string".freeze) }.should raise_error(FrozenError)
+ end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ [65, 66, 67].pack("ccc", buffer: buffer)
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
+
context "offset (@) is specified" do
it 'keeps buffer content if it is longer than offset' do
n = [ 65, 66, 67 ]
diff --git a/spec/ruby/library/io-wait/fixtures/classes.rb b/spec/ruby/fixtures/io.rb
index 837c7edd06..87ebbbb2bd 100644
--- a/spec/ruby/library/io-wait/fixtures/classes.rb
+++ b/spec/ruby/fixtures/io.rb
@@ -1,12 +1,12 @@
-module IOWaitSpec
+module IOSpec
def self.exhaust_write_buffer(io)
written = 0
buf = " " * 4096
- begin
+ while true
written += io.write_nonblock(buf)
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK
- return written
- end while true
+ end
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK
+ written
end
end
diff --git a/spec/ruby/language/case_spec.rb b/spec/ruby/language/case_spec.rb
index d289eca037..464d06e46a 100644
--- a/spec/ruby/language/case_spec.rb
+++ b/spec/ruby/language/case_spec.rb
@@ -427,7 +427,7 @@ describe "The 'case'-construct" do
:bar
end
RUBY
- }.should complain(/warning: duplicated .when' clause with line \d+ is ignored/, verbose: true)
+ }.should complain(/warning: (duplicated .when' clause with line \d+ is ignored|'when' clause on line \d+ duplicates 'when' clause on line \d+ and is ignored)/, verbose: true)
end
end
diff --git a/spec/ruby/language/pattern_matching/3.1.rb b/spec/ruby/language/pattern_matching/3.1.rb
new file mode 100644
index 0000000000..7a09084e41
--- /dev/null
+++ b/spec/ruby/language/pattern_matching/3.1.rb
@@ -0,0 +1,75 @@
+describe "Pattern matching" do
+ before :each do
+ ScratchPad.record []
+ end
+
+ describe "Ruby 3.1 improvements" do
+ ruby_version_is "3.1" do
+ it "can omit parentheses in one line pattern matching" do
+ [1, 2] => a, b
+ [a, b].should == [1, 2]
+
+ {a: 1} => a:
+ a.should == 1
+ end
+
+ it "supports pinning instance variables" do
+ @a = /a/
+ case 'abc'
+ in ^@a
+ true
+ end.should == true
+ end
+
+ it "supports pinning class variables" do
+ result = nil
+ Module.new do
+ result = module_eval(<<~RUBY)
+ @@a = 0..10
+
+ case 2
+ in ^@@a
+ true
+ end
+ RUBY
+ end
+
+ result.should == true
+ end
+
+ it "supports pinning global variables" do
+ $a = /a/
+ case 'abc'
+ in ^$a
+ true
+ end.should == true
+ end
+
+ it "supports pinning expressions" do
+ case 'abc'
+ in ^(/a/)
+ true
+ end.should == true
+
+ case 0
+ in ^(0 + 0)
+ true
+ end.should == true
+ end
+
+ it "supports pinning expressions in array pattern" do
+ case [3]
+ in [^(1 + 2)]
+ true
+ end.should == true
+ end
+
+ it "supports pinning expressions in hash pattern" do
+ case {name: '2.6', released_at: Time.new(2018, 12, 25)}
+ in {released_at: ^(Time.new(2010)..Time.new(2020))}
+ true
+ end.should == true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/language/pattern_matching_spec.rb b/spec/ruby/language/pattern_matching_spec.rb
index a8ec078cd0..8c5df06a17 100644
--- a/spec/ruby/language/pattern_matching_spec.rb
+++ b/spec/ruby/language/pattern_matching_spec.rb
@@ -1,9 +1,6 @@
require_relative '../spec_helper'
describe "Pattern matching" do
- # TODO: Remove excessive eval calls when Ruby 3 is the minimum version.
- # It is best to keep the eval's longer if other Ruby impls cannot parse pattern matching yet.
-
before :each do
ScratchPad.record []
end
@@ -11,145 +8,119 @@ describe "Pattern matching" do
describe "can be standalone assoc operator that" do
it "deconstructs value" do
suppress_warning do
- eval(<<-RUBY).should == [0, 1]
- [0, 1] => [a, b]
- [a, b]
- RUBY
+ [0, 1] => [a, b]
+ [a, b].should == [0, 1]
end
end
it "deconstructs value and properly scopes variables" do
suppress_warning do
- eval(<<-RUBY).should == [0, nil]
- a = nil
- eval(<<-PATTERN)
- [0, 1] => [a, b]
- PATTERN
- [a, defined?(b)]
- RUBY
+ a = nil
+ 1.times {
+ [0, 1] => [a, b]
+ }
+ [a, defined?(b)].should == [0, nil]
end
end
end
describe "find pattern" do
it "captures preceding elements to the pattern" do
- eval(<<~RUBY).should == [0, 1]
- case [0, 1, 2, 3]
- in [*pre, 2, 3]
- pre
- else
- false
- end
- RUBY
+ case [0, 1, 2, 3]
+ in [*pre, 2, 3]
+ pre
+ else
+ false
+ end.should == [0, 1]
end
it "captures following elements to the pattern" do
- eval(<<~RUBY).should == [2, 3]
- case [0, 1, 2, 3]
- in [0, 1, *post]
- post
- else
- false
- end
- RUBY
+ case [0, 1, 2, 3]
+ in [0, 1, *post]
+ post
+ else
+ false
+ end.should == [2, 3]
end
it "captures both preceding and following elements to the pattern" do
- eval(<<~RUBY).should == [[0, 1], [3, 4]]
- case [0, 1, 2, 3, 4]
- in [*pre, 2, *post]
- [pre, post]
- else
- false
- end
- RUBY
+ case [0, 1, 2, 3, 4]
+ in [*pre, 2, *post]
+ [pre, post]
+ else
+ false
+ end.should == [[0, 1], [3, 4]]
end
it "can capture the entirety of the pattern" do
- eval(<<~RUBY).should == [0, 1, 2, 3, 4]
- case [0, 1, 2, 3, 4]
- in [*everything]
- everything
- else
- false
- end
- RUBY
+ case [0, 1, 2, 3, 4]
+ in [*everything]
+ everything
+ else
+ false
+ end.should == [0, 1, 2, 3, 4]
end
it "will match an empty Array-like structure" do
- eval(<<~RUBY).should == []
- case []
- in [*everything]
- everything
- else
- false
- end
- RUBY
+ case []
+ in [*everything]
+ everything
+ else
+ false
+ end.should == []
end
it "can be nested" do
- eval(<<~RUBY).should == [[0, [2, 4, 6]], [[4, 16, 64]], 27]
- case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
- in [*pre, [*, 9, a], *post]
- [pre, post, a]
- else
- false
- end
- RUBY
+ case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
+ in [*pre, [*, 9, a], *post]
+ [pre, post, a]
+ else
+ false
+ end.should == [[0, [2, 4, 6]], [[4, 16, 64]], 27]
end
it "can be nested with an array pattern" do
- eval(<<~RUBY).should == [[4, 16, 64]]
- case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
- in [_, _, [*, 9, *], *post]
- post
- else
- false
- end
- RUBY
+ case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
+ in [_, _, [*, 9, *], *post]
+ post
+ else
+ false
+ end.should == [[4, 16, 64]]
end
it "can be nested within a hash pattern" do
- eval(<<~RUBY).should == [27]
- case {a: [3, 9, 27]}
- in {a: [*, 9, *post]}
- post
- else
- false
- end
- RUBY
+ case {a: [3, 9, 27]}
+ in {a: [*, 9, *post]}
+ post
+ else
+ false
+ end.should == [27]
end
it "can nest hash and array patterns" do
- eval(<<~RUBY).should == [42, 2]
- case [0, {a: 42, b: [0, 1]}, {a: 42, b: [1, 2]}]
- in [*, {a:, b: [1, c]}, *]
- [a, c]
- else
- false
- end
- RUBY
+ case [0, {a: 42, b: [0, 1]}, {a: 42, b: [1, 2]}]
+ in [*, {a:, b: [1, c]}, *]
+ [a, c]
+ else
+ false
+ end.should == [42, 2]
end
end
it "extends case expression with case/in construction" do
- eval(<<~RUBY).should == :bar
- case [0, 1]
- in [0]
- :foo
- in [0, 1]
- :bar
- end
- RUBY
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ end.should == :bar
end
it "allows using then operator" do
- eval(<<~RUBY).should == :bar
- case [0, 1]
- in [0] then :foo
- in [0, 1] then :bar
- end
- RUBY
+ case [0, 1]
+ in [0] then :foo
+ in [0, 1] then :bar
+ end.should == :bar
end
describe "warning" do
@@ -191,12 +162,10 @@ describe "Pattern matching" do
end
it "binds variables" do
- eval(<<~RUBY).should == 1
- case [0, 1]
- in [0, a]
- a
- end
- RUBY
+ case [0, 1]
+ in [0, a]
+ a
+ end.should == 1
end
it "cannot mix in and when operators" do
@@ -220,47 +189,45 @@ describe "Pattern matching" do
end
it "checks patterns until the first matching" do
- eval(<<~RUBY).should == :bar
- case [0, 1]
- in [0]
- :foo
- in [0, 1]
- :bar
- in [0, 1]
- :baz
- end
- RUBY
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ in [0, 1]
+ :baz
+ end.should == :bar
end
it "executes else clause if no pattern matches" do
- eval(<<~RUBY).should == false
- case [0, 1]
- in [0]
- true
- else
- false
- end
- RUBY
+ case [0, 1]
+ in [0]
+ true
+ else
+ false
+ end.should == false
end
it "raises NoMatchingPatternError if no pattern matches and no else clause" do
-> {
- eval <<~RUBY
- case [0, 1]
- in [0]
- end
- RUBY
+ case [0, 1]
+ in [0]
+ end
}.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
+
+ -> {
+ case {a: 0, b: 1}
+ in a: 1, b: 1
+ end
+ }.should raise_error(NoMatchingPatternError, /\{:a=>0, :b=>1\}/)
end
it "raises NoMatchingPatternError if no pattern matches and evaluates the expression only once" do
evals = 0
-> {
- eval <<~RUBY
- case (evals += 1; [0, 1])
- in [0]
- end
- RUBY
+ case (evals += 1; [0, 1])
+ in [0]
+ end
}.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
evals.should == 1
end
@@ -273,230 +240,185 @@ describe "Pattern matching" do
true
end
RUBY
- }.should raise_error(SyntaxError, /unexpected|expected a delimiter after the predicates of a `when` clause/)
+ }.should raise_error(SyntaxError, /unexpected|expected a delimiter after the patterns of an `in` clause/)
end
it "evaluates the case expression once for multiple patterns, caching the result" do
- eval(<<~RUBY).should == true
- case (ScratchPad << :foo; 1)
- in 0
- false
- in 1
- true
- end
- RUBY
+ case (ScratchPad << :foo; 1)
+ in 0
+ false
+ in 1
+ true
+ end.should == true
ScratchPad.recorded.should == [:foo]
end
describe "guards" do
it "supports if guard" do
- eval(<<~RUBY).should == false
- case 0
- in 0 if false
- true
- else
- false
- end
- RUBY
+ case 0
+ in 0 if false
+ true
+ else
+ false
+ end.should == false
- eval(<<~RUBY).should == true
- case 0
- in 0 if true
- true
- else
- false
- end
- RUBY
+ case 0
+ in 0 if true
+ true
+ else
+ false
+ end.should == true
end
it "supports unless guard" do
- eval(<<~RUBY).should == false
- case 0
- in 0 unless true
- true
- else
- false
- end
- RUBY
+ case 0
+ in 0 unless true
+ true
+ else
+ false
+ end.should == false
- eval(<<~RUBY).should == true
- case 0
- in 0 unless false
- true
- else
- false
- end
- RUBY
+ case 0
+ in 0 unless false
+ true
+ else
+ false
+ end.should == true
end
it "makes bound variables visible in guard" do
- eval(<<~RUBY).should == true
- case [0, 1]
- in [a, 1] if a >= 0
- true
- end
- RUBY
+ case [0, 1]
+ in [a, 1] if a >= 0
+ true
+ end.should == true
end
it "does not evaluate guard if pattern does not match" do
- eval <<~RUBY
- case 0
- in 1 if (ScratchPad << :foo) || true
- else
- end
- RUBY
+ case 0
+ in 1 if (ScratchPad << :foo) || true
+ else
+ end
ScratchPad.recorded.should == []
end
it "takes guards into account when there are several matching patterns" do
- eval(<<~RUBY).should == :bar
- case 0
- in 0 if false
- :foo
- in 0 if true
- :bar
- end
- RUBY
+ case 0
+ in 0 if false
+ :foo
+ in 0 if true
+ :bar
+ end.should == :bar
end
it "executes else clause if no guarded pattern matches" do
- eval(<<~RUBY).should == false
- case 0
- in 0 if false
- true
- else
- false
- end
- RUBY
+ case 0
+ in 0 if false
+ true
+ else
+ false
+ end.should == false
end
it "raises NoMatchingPatternError if no guarded pattern matches and no else clause" do
-> {
- eval <<~RUBY
- case [0, 1]
- in [0, 1] if false
- end
- RUBY
+ case [0, 1]
+ in [0, 1] if false
+ end
}.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
end
end
describe "value pattern" do
it "matches an object such that pattern === object" do
- eval(<<~RUBY).should == true
- case 0
- in 0
- true
- end
- RUBY
+ case 0
+ in 0
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case 0
- in (-1..1)
- true
- end
- RUBY
+ case 0
+ in (
+ -1..1)
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case 0
- in Integer
- true
- end
- RUBY
+ case 0
+ in Integer
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case "0"
- in /0/
- true
- end
- RUBY
+ case "0"
+ in /0/
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case "0"
- in ->(s) { s == "0" }
- true
- end
- RUBY
+ case "0"
+ in -> s { s == "0" }
+ true
+ end.should == true
end
it "allows string literal with interpolation" do
x = "x"
- eval(<<~RUBY).should == true
- case "x"
- in "#{x + ""}"
- true
- end
- RUBY
+ case "x"
+ in "#{x + ""}"
+ true
+ end.should == true
end
end
describe "variable pattern" do
it "matches a value and binds variable name to this value" do
- eval(<<~RUBY).should == 0
- case 0
- in a
- a
- end
- RUBY
+ case 0
+ in a
+ a
+ end.should == 0
end
it "makes bounded variable visible outside a case statement scope" do
- eval(<<~RUBY).should == 0
- case 0
- in a
- end
+ case 0
+ in a
+ end
- a
- RUBY
+ a.should == 0
end
it "create local variables even if a pattern doesn't match" do
- eval(<<~RUBY).should == [0, nil, nil]
- case 0
- in a
- in b
- in c
- end
+ case 0
+ in a
+ in b
+ in c
+ end
- [a, b, c]
- RUBY
+ [a, b, c].should == [0, nil, nil]
end
it "allow using _ name to drop values" do
- eval(<<~RUBY).should == 0
- case [0, 1]
- in [a, _]
- a
- end
- RUBY
+ case [0, 1]
+ in [a, _]
+ a
+ end.should == 0
end
it "supports using _ in a pattern several times" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in [0, _, _]
- true
- end
- RUBY
+ case [0, 1, 2]
+ in [0, _, _]
+ true
+ end.should == true
end
it "supports using any name with _ at the beginning in a pattern several times" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in [0, _x, _x]
- true
- end
- RUBY
+ case [0, 1, 2]
+ in [0, _x, _x]
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case {a: 0, b: 1, c: 2}
- in {a: 0, b: _x, c: _x}
- true
- end
- RUBY
+ case {a: 0, b: 1, c: 2}
+ in {a: 0, b: _x, c: _x}
+ true
+ end.should == true
end
it "does not support using variable name (except _) several times" do
@@ -512,30 +434,24 @@ describe "Pattern matching" do
it "supports existing variables in a pattern specified with ^ operator" do
a = 0
- eval(<<~RUBY).should == true
- case 0
- in ^a
- true
- end
- RUBY
+ case 0
+ in ^a
+ true
+ end.should == true
end
it "allows applying ^ operator to bound variables" do
- eval(<<~RUBY).should == 1
- case [1, 1]
- in [n, ^n]
- n
- end
- RUBY
+ case [1, 1]
+ in [n, ^n]
+ n
+ end.should == 1
- eval(<<~RUBY).should == false
- case [1, 2]
- in [n, ^n]
- true
- else
- false
- end
- RUBY
+ case [1, 2]
+ in [n, ^n]
+ true
+ else
+ false
+ end.should == false
end
it "requires bound variable to be specified in a pattern before ^ operator when it relies on a bound variable" do
@@ -554,12 +470,10 @@ describe "Pattern matching" do
describe "alternative pattern" do
it "matches if any of patterns matches" do
- eval(<<~RUBY).should == true
- case 0
- in 0 | 1 | 2
- true
- end
- RUBY
+ case 0
+ in 0 | 1 | 2
+ true
+ end.should == true
end
it "does not support variable binding" do
@@ -573,120 +487,99 @@ describe "Pattern matching" do
end
it "support underscore prefixed variables in alternation" do
- eval(<<~RUBY).should == true
- case [0, 1]
- in [1, _]
- false
- in [0, 0] | [0, _a]
- true
- end
- RUBY
+ case [0, 1]
+ in [1, _]
+ false
+ in [0, 0] | [0, _a]
+ true
+ end.should == true
end
it "can be used as a nested pattern" do
- eval(<<~RUBY).should == true
- case [[1], ["2"]]
- in [[0] | nil, _]
- false
- in [[1], [1]]
- false
- in [[1], [2 | "2"]]
- true
- end
- RUBY
+ case [[1], ["2"]]
+ in [[0] | nil, _]
+ false
+ in [[1], [1]]
+ false
+ in [[1], [2 | "2"]]
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case [1, 2]
- in [0, _] | {a: 0}
- false
- in {a: 1, b: 2} | [1, 2]
- true
- end
- RUBY
+ case [1, 2]
+ in [0, _] | {a: 0}
+ false
+ in {a: 1, b: 2} | [1, 2]
+ true
+ end.should == true
end
end
describe "AS pattern" do
it "binds a variable to a value if pattern matches" do
- eval(<<~RUBY).should == 0
- case 0
- in Integer => n
- n
- end
- RUBY
+ case 0
+ in Integer => n
+ n
+ end.should == 0
end
it "can be used as a nested pattern" do
- eval(<<~RUBY).should == [2, 3]
- case [1, [2, 3]]
- in [1, Array => ary]
- ary
- end
- RUBY
+ case [1, [2, 3]]
+ in [1, Array => ary]
+ ary
+ end.should == [2, 3]
end
end
describe "Array pattern" do
it "supports form Constant(pat, pat, ...)" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in Array(0, 1, 2)
- true
- end
- RUBY
+ case [0, 1, 2]
+ in Array(0, 1, 2)
+ true
+ end.should == true
end
it "supports form Constant[pat, pat, ...]" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in Array[0, 1, 2]
- true
- end
- RUBY
+ case [0, 1, 2]
+ in Array[0, 1, 2]
+ true
+ end.should == true
end
it "supports form [pat, pat, ...]" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in [0, 1, 2]
- true
- end
- RUBY
+ case [0, 1, 2]
+ in [0, 1, 2]
+ true
+ end.should == true
end
it "supports form pat, pat, ..." do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in 0, 1, 2
- true
- end
- RUBY
+ case [0, 1, 2]
+ in 0, 1, 2
+ true
+ end.should == true
- eval(<<~RUBY).should == 1
- case [0, 1, 2]
- in 0, a, 2
- a
- end
- RUBY
+ case [0, 1, 2]
+ in 0, a, 2
+ a
+ end.should == 1
- eval(<<~RUBY).should == [1, 2]
- case [0, 1, 2]
- in 0, *rest
- rest
- end
- RUBY
+ case [0, 1, 2]
+ in 0, *rest
+ rest
+ end.should == [1, 2]
end
it "matches an object with #deconstruct method which returns an array and each element in array matches element in pattern" do
obj = Object.new
- def obj.deconstruct; [0, 1] end
- eval(<<~RUBY).should == true
- case obj
- in [Integer, Integer]
- true
- end
- RUBY
+ def obj.deconstruct
+ [0, 1]
+ end
+
+ case obj
+ in [Integer, Integer]
+ true
+ end.should == true
end
it "calls #deconstruct once for multiple patterns, caching the result" do
@@ -697,314 +590,267 @@ describe "Pattern matching" do
[0, 1]
end
- eval(<<~RUBY).should == true
- case obj
- in [1, 2]
- false
- in [0, 1]
- true
- end
- RUBY
+ case obj
+ in [1, 2]
+ false
+ in [0, 1]
+ true
+ end.should == true
ScratchPad.recorded.should == [:deconstruct]
end
it "calls #deconstruct even on objects that are already an array" do
obj = [1, 2]
+
def obj.deconstruct
ScratchPad << :deconstruct
[3, 4]
end
- eval(<<~RUBY).should == true
- case obj
- in [3, 4]
- true
- else
- false
- end
- RUBY
+ case obj
+ in [3, 4]
+ true
+ else
+ false
+ end.should == true
ScratchPad.recorded.should == [:deconstruct]
end
it "does not match object if Constant === object returns false" do
- eval(<<~RUBY).should == false
- case [0, 1, 2]
- in String[0, 1, 2]
- true
- else
- false
- end
- RUBY
+ case [0, 1, 2]
+ in String[0, 1, 2]
+ true
+ else
+ false
+ end.should == false
end
it "checks Constant === object before calling #deconstruct" do
c1 = Class.new
obj = c1.new
obj.should_not_receive(:deconstruct)
- eval(<<~RUBY).should == false
- case obj
- in String[1]
- true
- else
- false
- end
- RUBY
+
+ case obj
+ in String[1]
+ true
+ else
+ false
+ end.should == false
end
it "does not match object without #deconstruct method" do
obj = Object.new
obj.should_receive(:respond_to?).with(:deconstruct)
- eval(<<~RUBY).should == false
- case obj
- in Object[]
- true
- else
- false
- end
- RUBY
+ case obj
+ in Object[]
+ true
+ else
+ false
+ end.should == false
end
it "raises TypeError if #deconstruct method does not return array" do
obj = Object.new
- def obj.deconstruct; "" end
+
+ def obj.deconstruct
+ ""
+ end
-> {
- eval <<~RUBY
- case obj
- in Object[]
- else
- end
- RUBY
+ case obj
+ in Object[]
+ else
+ end
}.should raise_error(TypeError, /deconstruct must return Array/)
end
it "accepts a subclass of Array from #deconstruct" do
obj = Object.new
+
def obj.deconstruct
Class.new(Array).new([0, 1])
end
- eval(<<~RUBY).should == true
- case obj
- in [1, 2]
- false
- in [0, 1]
- true
- end
- RUBY
+ case obj
+ in [1, 2]
+ false
+ in [0, 1]
+ true
+ end.should == true
end
it "does not match object if elements of array returned by #deconstruct method does not match elements in pattern" do
obj = Object.new
- def obj.deconstruct; [1] end
- eval(<<~RUBY).should == false
- case obj
- in Object[0]
- true
- else
- false
- end
- RUBY
+ def obj.deconstruct
+ [1]
+ end
+
+ case obj
+ in Object[0]
+ true
+ else
+ false
+ end.should == false
end
it "binds variables" do
- eval(<<~RUBY).should == [0, 1, 2]
- case [0, 1, 2]
- in [a, b, c]
- [a, b, c]
- end
- RUBY
+ case [0, 1, 2]
+ in [a, b, c]
+ [a, b, c]
+ end.should == [0, 1, 2]
end
it "supports splat operator *rest" do
- eval(<<~RUBY).should == [1, 2]
- case [0, 1, 2]
- in [0, *rest]
- rest
- end
- RUBY
+ case [0, 1, 2]
+ in [0, *rest]
+ rest
+ end.should == [1, 2]
end
it "does not match partially by default" do
- eval(<<~RUBY).should == false
- case [0, 1, 2, 3]
- in [1, 2]
- true
- else
- false
- end
- RUBY
+ case [0, 1, 2, 3]
+ in [1, 2]
+ true
+ else
+ false
+ end.should == false
end
it "does match partially from the array beginning if list + , syntax used" do
- eval(<<~RUBY).should == true
- case [0, 1, 2, 3]
- in [0, 1,]
- true
- end
- RUBY
+ case [0, 1, 2, 3]
+ in [0, 1, ]
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case [0, 1, 2, 3]
- in 0, 1,;
- true
- end
- RUBY
+ case [0, 1, 2, 3]
+ in 0, 1,;
+ true
+ end.should == true
end
it "matches [] with []" do
- eval(<<~RUBY).should == true
- case []
- in []
- true
- end
- RUBY
+ case []
+ in []
+ true
+ end.should == true
end
it "matches anything with *" do
- eval(<<~RUBY).should == true
- case [0, 1]
- in *;
- true
- end
- RUBY
+ case [0, 1]
+ in *;
+ true
+ end.should == true
end
it "can be used as a nested pattern" do
- eval(<<~RUBY).should == true
- case [[1], ["2"]]
- in [[0] | nil, _]
- false
- in [[1], [1]]
- false
- in [[1], [2 | "2"]]
- true
- end
- RUBY
+ case [[1], ["2"]]
+ in [[0] | nil, _]
+ false
+ in [[1], [1]]
+ false
+ in [[1], [2 | "2"]]
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case [1, 2]
- in [0, _] | {a: 0}
- false
- in {a: 1, b: 2} | [1, 2]
- true
- end
- RUBY
+ case [1, 2]
+ in [0, _] | {a: 0}
+ false
+ in {a: 1, b: 2} | [1, 2]
+ true
+ end.should == true
end
end
describe "Hash pattern" do
it "supports form Constant(id: pat, id: pat, ...)" do
- eval(<<~RUBY).should == true
- case {a: 0, b: 1}
- in Hash(a: 0, b: 1)
- true
- end
- RUBY
+ case {a: 0, b: 1}
+ in Hash(a: 0, b: 1)
+ true
+ end.should == true
end
it "supports form Constant[id: pat, id: pat, ...]" do
- eval(<<~RUBY).should == true
- case {a: 0, b: 1}
- in Hash[a: 0, b: 1]
- true
- end
- RUBY
+ case {a: 0, b: 1}
+ in Hash[a: 0, b: 1]
+ true
+ end.should == true
end
it "supports form {id: pat, id: pat, ...}" do
- eval(<<~RUBY).should == true
- case {a: 0, b: 1}
- in {a: 0, b: 1}
- true
- end
- RUBY
+ case {a: 0, b: 1}
+ in {a: 0, b: 1}
+ true
+ end.should == true
end
it "supports form id: pat, id: pat, ..." do
- eval(<<~RUBY).should == true
- case {a: 0, b: 1}
- in a: 0, b: 1
- true
- end
- RUBY
+ case {a: 0, b: 1}
+ in a: 0, b: 1
+ true
+ end.should == true
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in a: a, b: b
- [a, b]
- end
- RUBY
+ case {a: 0, b: 1}
+ in a: a, b: b
+ [a, b]
+ end.should == [0, 1]
- eval(<<~RUBY).should == { b: 1, c: 2 }
- case {a: 0, b: 1, c: 2}
- in a: 0, **rest
- rest
- end
- RUBY
+ case {a: 0, b: 1, c: 2}
+ in a: 0, **rest
+ rest
+ end.should == {b: 1, c: 2}
end
it "supports a: which means a: a" do
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in Hash(a:, b:)
- [a, b]
- end
- RUBY
+ case {a: 0, b: 1}
+ in Hash(a:, b:)
+ [a, b]
+ end.should == [0, 1]
a = b = nil
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in Hash[a:, b:]
- [a, b]
- end
- RUBY
+
+ case {a: 0, b: 1}
+ in Hash[a:, b:]
+ [a, b]
+ end.should == [0, 1]
a = b = nil
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in {a:, b:}
- [a, b]
- end
- RUBY
+
+ case {a: 0, b: 1}
+ in {a:, b:}
+ [a, b]
+ end.should == [0, 1]
a = nil
- eval(<<~RUBY).should == [0, {b: 1, c: 2}]
- case {a: 0, b: 1, c: 2}
- in {a:, **rest}
- [a, rest]
- end
- RUBY
+
+ case {a: 0, b: 1, c: 2}
+ in {a:, **rest}
+ [a, rest]
+ end.should == [0, {b: 1, c: 2}]
a = b = nil
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in a:, b:
- [a, b]
- end
- RUBY
+
+ case {a: 0, b: 1}
+ in a:, b:
+ [a, b]
+ end.should == [0, 1]
end
it "can mix key (a:) and key-value (a: b) declarations" do
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in Hash(a:, b: x)
- [a, x]
- end
- RUBY
+ case {a: 0, b: 1}
+ in Hash(a:, b: x)
+ [a, x]
+ end.should == [0, 1]
end
it "supports 'string': key literal" do
- eval(<<~RUBY).should == true
- case {a: 0}
- in {"a": 0}
- true
- end
- RUBY
+ case {a: 0}
+ in {"a": 0}
+ true
+ end.should == true
end
it "does not support non-symbol keys" do
@@ -1018,8 +864,6 @@ describe "Pattern matching" do
end
it "does not support string interpolation in keys" do
- x = "a"
-
-> {
eval <<~'RUBY'
case {a: 1}
@@ -1041,14 +885,15 @@ describe "Pattern matching" do
it "matches an object with #deconstruct_keys method which returns a Hash with equal keys and each value in Hash matches value in pattern" do
obj = Object.new
- def obj.deconstruct_keys(*); {a: 1} end
- eval(<<~RUBY).should == true
- case obj
- in {a: 1}
- true
- end
- RUBY
+ def obj.deconstruct_keys(*)
+ {a: 1}
+ end
+
+ case obj
+ in {a: 1}
+ true
+ end.should == true
end
it "calls #deconstruct_keys per pattern" do
@@ -1059,96 +904,92 @@ describe "Pattern matching" do
{a: 1}
end
- eval(<<~RUBY).should == true
- case obj
- in {b: 1}
- false
- in {a: 1}
- true
- end
- RUBY
+ case obj
+ in {b: 1}
+ false
+ in {a: 1}
+ true
+ end.should == true
ScratchPad.recorded.should == [:deconstruct_keys, :deconstruct_keys]
end
it "does not match object if Constant === object returns false" do
- eval(<<~RUBY).should == false
- case {a: 1}
- in String[a: 1]
- true
- else
- false
- end
- RUBY
+ case {a: 1}
+ in String[a: 1]
+ true
+ else
+ false
+ end.should == false
end
it "checks Constant === object before calling #deconstruct_keys" do
c1 = Class.new
obj = c1.new
obj.should_not_receive(:deconstruct_keys)
- eval(<<~RUBY).should == false
- case obj
- in String(a: 1)
- true
- else
- false
- end
- RUBY
+
+ case obj
+ in String(a: 1)
+ true
+ else
+ false
+ end.should == false
end
it "does not match object without #deconstruct_keys method" do
obj = Object.new
obj.should_receive(:respond_to?).with(:deconstruct_keys)
- eval(<<~RUBY).should == false
- case obj
- in Object[a: 1]
- true
- else
- false
- end
- RUBY
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
+ end.should == false
end
it "does not match object if #deconstruct_keys method does not return Hash" do
obj = Object.new
- def obj.deconstruct_keys(*); "" end
+
+ def obj.deconstruct_keys(*)
+ ""
+ end
-> {
- eval <<~RUBY
- case obj
- in Object[a: 1]
- end
- RUBY
+ case obj
+ in Object[a: 1]
+ end
}.should raise_error(TypeError, /deconstruct_keys must return Hash/)
end
it "does not match object if #deconstruct_keys method returns Hash with non-symbol keys" do
obj = Object.new
- def obj.deconstruct_keys(*); {"a" => 1} end
- eval(<<~RUBY).should == false
- case obj
- in Object[a: 1]
- true
- else
- false
- end
- RUBY
+ def obj.deconstruct_keys(*)
+ {"a" => 1}
+ end
+
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
+ end.should == false
end
it "does not match object if elements of Hash returned by #deconstruct_keys method does not match values in pattern" do
obj = Object.new
- def obj.deconstruct_keys(*); {a: 1} end
- eval(<<~RUBY).should == false
- case obj
- in Object[a: 2]
- true
- else
- false
- end
- RUBY
+ def obj.deconstruct_keys(*)
+ {a: 1}
+ end
+
+ case obj
+ in Object[a: 2]
+ true
+ else
+ false
+ end.should == false
end
it "passes keys specified in pattern as arguments to #deconstruct_keys method" do
@@ -1159,11 +1000,9 @@ describe "Pattern matching" do
{a: 1, b: 2, c: 3}
end
- eval <<~RUBY
- case obj
- in Object[a: 1, b: 2, c: 3]
- end
- RUBY
+ case obj
+ in Object[a: 1, b: 2, c: 3]
+ end
ScratchPad.recorded.sort.should == [[[:a, :b, :c]]]
end
@@ -1176,11 +1015,9 @@ describe "Pattern matching" do
{a: 1, b: 2, c: 3}
end
- eval <<~RUBY
- case obj
- in Object[a: 1, b: 2, **]
- end
- RUBY
+ case obj
+ in Object[a: 1, b: 2, **]
+ end
ScratchPad.recorded.sort.should == [[[:a, :b]]]
end
@@ -1193,131 +1030,105 @@ describe "Pattern matching" do
{a: 1, b: 2}
end
- eval <<~RUBY
- case obj
- in Object[a: 1, **rest]
- end
- RUBY
+ case obj
+ in Object[a: 1, **rest]
+ end
ScratchPad.recorded.should == [[nil]]
end
it "binds variables" do
- eval(<<~RUBY).should == [0, 1, 2]
- case {a: 0, b: 1, c: 2}
- in {a: x, b: y, c: z}
- [x, y, z]
- end
- RUBY
+ case {a: 0, b: 1, c: 2}
+ in {a: x, b: y, c: z}
+ [x, y, z]
+ end.should == [0, 1, 2]
end
it "supports double splat operator **rest" do
- eval(<<~RUBY).should == {b: 1, c: 2}
- case {a: 0, b: 1, c: 2}
- in {a: 0, **rest}
- rest
- end
- RUBY
+ case {a: 0, b: 1, c: 2}
+ in {a: 0, **rest}
+ rest
+ end.should == {b: 1, c: 2}
end
it "treats **nil like there should not be any other keys in a matched Hash" do
- eval(<<~RUBY).should == true
- case {a: 1, b: 2}
- in {a: 1, b: 2, **nil}
- true
- end
- RUBY
+ case {a: 1, b: 2}
+ in {a: 1, b: 2, **nil}
+ true
+ end.should == true
- eval(<<~RUBY).should == false
- case {a: 1, b: 2}
- in {a: 1, **nil}
- true
- else
- false
- end
- RUBY
+ case {a: 1, b: 2}
+ in {a: 1, **nil}
+ true
+ else
+ false
+ end.should == false
end
it "can match partially" do
- eval(<<~RUBY).should == true
- case {a: 1, b: 2}
- in {a: 1}
- true
- end
- RUBY
+ case {a: 1, b: 2}
+ in {a: 1}
+ true
+ end.should == true
end
it "matches {} with {}" do
- eval(<<~RUBY).should == true
- case {}
- in {}
- true
- end
- RUBY
+ case {}
+ in {}
+ true
+ end.should == true
end
it "in {} only matches empty hashes" do
- eval(<<~RUBY).should == false
- case {a: 1}
- in {}
- true
- else
- false
- end
- RUBY
+ case {a: 1}
+ in {}
+ true
+ else
+ false
+ end.should == false
end
it "in {**nil} only matches empty hashes" do
- eval(<<~RUBY).should == true
- case {}
- in {**nil}
- true
- else
- false
- end
- RUBY
+ case {}
+ in {**nil}
+ true
+ else
+ false
+ end.should == true
- eval(<<~RUBY).should == false
- case {a: 1}
- in {**nil}
- true
- else
- false
- end
- RUBY
+ case {a: 1}
+ in {**nil}
+ true
+ else
+ false
+ end.should == false
end
it "matches anything with **" do
- eval(<<~RUBY).should == true
- case {a: 1}
- in **;
- true
- end
- RUBY
+ case {a: 1}
+ in **;
+ true
+ end.should == true
end
it "can be used as a nested pattern" do
- eval(<<~RUBY).should == true
- case {a: {a: 1, b: 1}, b: {a: 1, b: 2}}
- in {a: {a: 0}}
- false
- in {a: {a: 1}, b: {b: 1}}
- false
- in {a: {a: 1}, b: {b: 2}}
- true
- end
- RUBY
+ case {a: {a: 1, b: 1}, b: {a: 1, b: 2}}
+ in {a: {a: 0}}
+ false
+ in {a: {a: 1}, b: {b: 1}}
+ false
+ in {a: {a: 1}, b: {b: 2} }
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case [{a: 1, b: [1]}, {a: 1, c: ["2"]}]
- in [{a:, c:},]
- false
- in [{a: 1, b:}, {a: 1, c: [Integer]}]
- false
- in [_, {a: 1, c: [String]}]
- true
- end
- RUBY
+ case [{a: 1, b: [1]}, {a: 1, c: ["2"]}]
+ in [{a:, c:}, ]
+ false
+ in [{a: 1, b:}, {a: 1, c: [Integer]}]
+ false
+ in [_, {a: 1, c: [String]}]
+ true
+ end.should == true
end
end
@@ -1335,12 +1146,11 @@ describe "Pattern matching" do
Module.new do
using refinery
- result = eval(<<~RUBY)
+ result =
case []
in [0]
true
end
- RUBY
end
result.should == true
@@ -1359,12 +1169,11 @@ describe "Pattern matching" do
Module.new do
using refinery
- result = eval(<<~RUBY)
+ result =
case {}
in a: 0
true
end
- RUBY
end
result.should == true
@@ -1383,127 +1192,18 @@ describe "Pattern matching" do
Module.new do
using refinery
- result = eval(<<~RUBY)
+ result =
case {}
in Array
true
end
- RUBY
end
result.should == true
end
end
+end
- describe "Ruby 3.1 improvements" do
- ruby_version_is "3.1" do
- it "can omit parentheses in one line pattern matching" do
- eval(<<~RUBY).should == [1, 2]
- [1, 2] => a, b
- [a, b]
- RUBY
-
- eval(<<~RUBY).should == 1
- {a: 1} => a:
- a
- RUBY
- end
-
- it "supports pinning instance variables" do
- eval(<<~RUBY).should == true
- @a = /a/
- case 'abc'
- in ^@a
- true
- end
- RUBY
- end
-
- it "supports pinning class variables" do
- result = nil
- Module.new do
- result = module_eval(<<~RUBY)
- @@a = 0..10
-
- case 2
- in ^@@a
- true
- end
- RUBY
- end
-
- result.should == true
- end
-
- it "supports pinning global variables" do
- eval(<<~RUBY).should == true
- $a = /a/
- case 'abc'
- in ^$a
- true
- end
- RUBY
- end
-
- it "supports pinning expressions" do
- eval(<<~RUBY).should == true
- case 'abc'
- in ^(/a/)
- true
- end
- RUBY
-
- eval(<<~RUBY).should == true
- case 0
- in ^(0+0)
- true
- end
- RUBY
- end
-
- it "supports pinning expressions in array pattern" do
- eval(<<~RUBY).should == true
- case [3]
- in [^(1+2)]
- true
- end
- RUBY
- end
-
- it "supports pinning expressions in hash pattern" do
- eval(<<~RUBY).should == true
- case {name: '2.6', released_at: Time.new(2018, 12, 25)}
- in {released_at: ^(Time.new(2010)..Time.new(2020))}
- true
- end
- RUBY
- end
- end
- end
-
- describe "value in pattern" do
- it "returns true if the pattern matches" do
- eval("1 in 1").should == true
-
- eval("1 in Integer").should == true
-
- e = nil
- eval("[1, 2] in [1, e]").should == true
- e.should == 2
-
- k = nil
- eval("{k: 1} in {k:}").should == true
- k.should == 1
- end
-
- it "returns false if the pattern does not match" do
- eval("1 in 2").should == false
-
- eval("1 in Float").should == false
-
- eval("[1, 2] in [2, e]").should == false
-
- eval("{k: 1} in {k: 2}").should == false
- end
- end
+ruby_version_is "3.1" do
+ require_relative 'pattern_matching/3.1'
end
diff --git a/spec/ruby/library/io-wait/wait_readable_spec.rb b/spec/ruby/library/io-wait/wait_readable_spec.rb
index 06ffbda5c8..df25fdb931 100644
--- a/spec/ruby/library/io-wait/wait_readable_spec.rb
+++ b/spec/ruby/library/io-wait/wait_readable_spec.rb
@@ -24,4 +24,23 @@ describe "IO#wait_readable" do
it "waits for the IO to become readable with the given large timeout" do
@io.wait_readable(365 * 24 * 60 * 60).should == @io
end
+
+ it "can be interrupted" do
+ rd, wr = IO.pipe
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ rd.wait_readable(10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ ensure
+ rd.close
+ wr.close
+ end
end
diff --git a/spec/ruby/library/io-wait/wait_spec.rb b/spec/ruby/library/io-wait/wait_spec.rb
index fc07c6a8d9..5952f127f7 100644
--- a/spec/ruby/library/io-wait/wait_spec.rb
+++ b/spec/ruby/library/io-wait/wait_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+require_relative '../../fixtures/io'
ruby_version_is ''...'3.2' do
require 'io/wait'
@@ -55,7 +55,7 @@ describe "IO#wait" do
end
it "waits for the WRITABLE event to be ready" do
- written_bytes = IOWaitSpec.exhaust_write_buffer(@w)
+ written_bytes = IOSpec.exhaust_write_buffer(@w)
@w.wait(IO::WRITABLE, 0).should == nil
@r.read(written_bytes)
@@ -67,7 +67,7 @@ describe "IO#wait" do
end
it "returns nil when the WRITABLE event is not ready during the timeout" do
- IOWaitSpec.exhaust_write_buffer(@w)
+ IOSpec.exhaust_write_buffer(@w)
@w.wait(IO::WRITABLE, 0).should == nil
end
@@ -92,7 +92,7 @@ describe "IO#wait" do
end
it "changes thread status to 'sleep' when waits for WRITABLE event" do
- written_bytes = IOWaitSpec.exhaust_write_buffer(@w)
+ IOSpec.exhaust_write_buffer(@w)
t = Thread.new { @w.wait(IO::WRITABLE, 10) }
sleep 1
@@ -100,6 +100,37 @@ describe "IO#wait" do
t.kill
t.join # Thread#kill doesn't wait for the thread to end
end
+
+ it "can be interrupted when waiting for READABLE event" do
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @r.wait(IO::READABLE, 10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join # Thread#kill doesn't wait for the thread to end
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ end
+
+ it "can be interrupted when waiting for WRITABLE event" do
+ IOSpec.exhaust_write_buffer(@w)
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @w.wait(IO::WRITABLE, 10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join # Thread#kill doesn't wait for the thread to end
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ end
end
context "[timeout, mode] passed" do
diff --git a/spec/ruby/library/io-wait/wait_writable_spec.rb b/spec/ruby/library/io-wait/wait_writable_spec.rb
index 8c44780d39..8639dd717b 100644
--- a/spec/ruby/library/io-wait/wait_writable_spec.rb
+++ b/spec/ruby/library/io-wait/wait_writable_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative '../../fixtures/io'
ruby_version_is ''...'3.2' do
require 'io/wait'
@@ -17,4 +18,24 @@ describe "IO#wait_writable" do
# Represents one year and is larger than a 32-bit int
STDOUT.wait_writable(365 * 24 * 60 * 60).should == STDOUT
end
+
+ it "can be interrupted" do
+ rd, wr = IO.pipe
+ IOSpec.exhaust_write_buffer(wr)
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ wr.wait_writable(10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ ensure
+ rd.close unless rd.closed?
+ wr.close unless wr.closed?
+ end
end
diff --git a/spec/ruby/library/rbconfig/rbconfig_spec.rb b/spec/ruby/library/rbconfig/rbconfig_spec.rb
index b90cc90970..8e38227c21 100644
--- a/spec/ruby/library/rbconfig/rbconfig_spec.rb
+++ b/spec/ruby/library/rbconfig/rbconfig_spec.rb
@@ -88,6 +88,30 @@ describe 'RbConfig::CONFIG' do
end
end
end
+
+ guard -> { %w[aarch64 arm64].include? RbConfig::CONFIG['host_cpu'] } do
+ it "['host_cpu'] returns CPU architecture properly for AArch64" do
+ platform_is :darwin do
+ RbConfig::CONFIG['host_cpu'].should == 'arm64'
+ end
+
+ platform_is_not :darwin do
+ RbConfig::CONFIG['host_cpu'].should == 'aarch64'
+ end
+ end
+ end
+
+ guard -> { platform_is(:linux) || platform_is(:darwin) } do
+ it "['host_os'] returns a proper OS name or platform" do
+ platform_is :darwin do
+ RbConfig::CONFIG['host_os'].should.match?(/darwin/)
+ end
+
+ platform_is :linux do
+ RbConfig::CONFIG['host_os'].should.match?(/linux/)
+ end
+ end
+ end
end
describe "RbConfig::TOPDIR" do
@@ -99,3 +123,32 @@ describe "RbConfig::TOPDIR" do
end
end
end
+
+describe "RUBY_PLATFORM" do
+ it "RUBY_PLATFORM contains a proper CPU architecture" do
+ RUBY_PLATFORM.should.include? RbConfig::CONFIG['host_cpu']
+ end
+
+ guard -> { platform_is(:linux) || platform_is(:darwin) } do
+ it "RUBY_PLATFORM contains OS name" do
+ # don't use RbConfig::CONFIG['host_os'] as far as it could be slightly different, e.g. linux-gnu
+ platform_is(:linux) do
+ RUBY_PLATFORM.should.include? 'linux'
+ end
+
+ platform_is(:darwin) do
+ RUBY_PLATFORM.should.include? 'darwin'
+ end
+ end
+ end
+end
+
+describe "RUBY_DESCRIPTION" do
+ it "contains version" do
+ RUBY_DESCRIPTION.should.include? RUBY_VERSION
+ end
+
+ it "contains RUBY_PLATFORM" do
+ RUBY_DESCRIPTION.should.include? RUBY_PLATFORM
+ end
+end
diff --git a/spec/ruby/optional/capi/io_spec.rb b/spec/ruby/optional/capi/io_spec.rb
index 870abef3ea..bdec46f5e1 100644
--- a/spec/ruby/optional/capi/io_spec.rb
+++ b/spec/ruby/optional/capi/io_spec.rb
@@ -1,4 +1,5 @@
require_relative 'spec_helper'
+require_relative '../../fixtures/io'
load_extension('io')
@@ -279,6 +280,22 @@ describe "C-API IO function" do
it "raises an IOError if the IO is not initialized" do
-> { @o.rb_io_maybe_wait_writable(0, IO.allocate, nil) }.should raise_error(IOError, "uninitialized stream")
end
+
+ it "can be interrupted" do
+ IOSpec.exhaust_write_buffer(@w_io)
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @o.rb_io_maybe_wait_writable(0, @w_io, 10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ end
end
end
@@ -355,6 +372,21 @@ describe "C-API IO function" do
thr.join
end
+ it "can be interrupted" do
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @o.rb_io_maybe_wait_readable(0, @r_io, 10, false)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ end
+
it "raises an IOError if the IO is closed" do
@r_io.close
-> { @o.rb_io_maybe_wait_readable(0, @r_io, nil, false) }.should raise_error(IOError, "closed stream")
@@ -438,6 +470,37 @@ describe "C-API IO function" do
it "raises an IOError if the IO is not initialized" do
-> { @o.rb_io_maybe_wait(0, IO.allocate, IO::WRITABLE, nil) }.should raise_error(IOError, "uninitialized stream")
end
+
+ it "can be interrupted when waiting for READABLE event" do
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @o.rb_io_maybe_wait(0, @r_io, IO::READABLE, 10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ end
+
+ it "can be interrupted when waiting for WRITABLE event" do
+ IOSpec.exhaust_write_buffer(@w_io)
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @o.rb_io_maybe_wait(0, @w_io, IO::WRITABLE, 10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ end
end
end