summaryrefslogtreecommitdiff
path: root/spec/ruby/library
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/library')
-rw-r--r--spec/ruby/library/English/English_spec.rb171
-rw-r--r--spec/ruby/library/abbrev/abbrev_spec.rb31
-rw-r--r--spec/ruby/library/base64/decode64_spec.rb9
-rw-r--r--spec/ruby/library/base64/encode64_spec.rb14
-rw-r--r--spec/ruby/library/base64/urlsafe_decode64_spec.rb27
-rw-r--r--spec/ruby/library/base64/urlsafe_encode64_spec.rb22
-rw-r--r--spec/ruby/library/bigdecimal/abs_spec.rb50
-rw-r--r--spec/ruby/library/bigdecimal/add_spec.rb179
-rw-r--r--spec/ruby/library/bigdecimal/case_compare_spec.rb7
-rw-r--r--spec/ruby/library/bigdecimal/ceil_spec.rb104
-rw-r--r--spec/ruby/library/bigdecimal/coerce_spec.rb26
-rw-r--r--spec/ruby/library/bigdecimal/comparison_spec.rb81
-rw-r--r--spec/ruby/library/bigdecimal/div_spec.rb102
-rw-r--r--spec/ruby/library/bigdecimal/divide_spec.rb7
-rw-r--r--spec/ruby/library/bigdecimal/divmod_spec.rb180
-rw-r--r--spec/ruby/library/bigdecimal/double_fig_spec.rb9
-rw-r--r--spec/ruby/library/bigdecimal/eql_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/equal_value_spec.rb7
-rw-r--r--spec/ruby/library/bigdecimal/exponent_spec.rb38
-rw-r--r--spec/ruby/library/bigdecimal/finite_spec.rb35
-rw-r--r--spec/ruby/library/bigdecimal/fix_spec.rb57
-rw-r--r--spec/ruby/library/bigdecimal/fixtures/classes.rb17
-rw-r--r--spec/ruby/library/bigdecimal/floor_spec.rb100
-rw-r--r--spec/ruby/library/bigdecimal/frac_spec.rb48
-rw-r--r--spec/ruby/library/bigdecimal/gt_spec.rb98
-rw-r--r--spec/ruby/library/bigdecimal/gte_spec.rb102
-rw-r--r--spec/ruby/library/bigdecimal/infinite_spec.rb32
-rw-r--r--spec/ruby/library/bigdecimal/inspect_spec.rb47
-rw-r--r--spec/ruby/library/bigdecimal/limit_spec.rb30
-rw-r--r--spec/ruby/library/bigdecimal/lt_spec.rb96
-rw-r--r--spec/ruby/library/bigdecimal/lte_spec.rb102
-rw-r--r--spec/ruby/library/bigdecimal/minus_spec.rb58
-rw-r--r--spec/ruby/library/bigdecimal/mode_spec.rb36
-rw-r--r--spec/ruby/library/bigdecimal/modulo_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/mult_spec.rb24
-rw-r--r--spec/ruby/library/bigdecimal/multiply_spec.rb26
-rw-r--r--spec/ruby/library/bigdecimal/nan_spec.rb23
-rw-r--r--spec/ruby/library/bigdecimal/new_spec.rb109
-rw-r--r--spec/ruby/library/bigdecimal/nonzero_spec.rb29
-rw-r--r--spec/ruby/library/bigdecimal/plus_spec.rb47
-rw-r--r--spec/ruby/library/bigdecimal/power_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/precs_spec.rb49
-rw-r--r--spec/ruby/library/bigdecimal/quo_spec.rb13
-rw-r--r--spec/ruby/library/bigdecimal/remainder_spec.rb84
-rw-r--r--spec/ruby/library/bigdecimal/round_spec.rb202
-rw-r--r--spec/ruby/library/bigdecimal/shared/eql.rb61
-rw-r--r--spec/ruby/library/bigdecimal/shared/modulo.rb116
-rw-r--r--spec/ruby/library/bigdecimal/shared/mult.rb97
-rw-r--r--spec/ruby/library/bigdecimal/shared/power.rb72
-rw-r--r--spec/ruby/library/bigdecimal/shared/quo.rb59
-rw-r--r--spec/ruby/library/bigdecimal/shared/to_int.rb16
-rw-r--r--spec/ruby/library/bigdecimal/sign_spec.rb47
-rw-r--r--spec/ruby/library/bigdecimal/split_spec.rb88
-rw-r--r--spec/ruby/library/bigdecimal/sqrt_spec.rb112
-rw-r--r--spec/ruby/library/bigdecimal/sub_spec.rb53
-rw-r--r--spec/ruby/library/bigdecimal/to_f_spec.rb55
-rw-r--r--spec/ruby/library/bigdecimal/to_i_spec.rb7
-rw-r--r--spec/ruby/library/bigdecimal/to_int_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/to_r_spec.rb16
-rw-r--r--spec/ruby/library/bigdecimal/to_s_spec.rb73
-rw-r--r--spec/ruby/library/bigdecimal/truncate_spec.rb81
-rw-r--r--spec/ruby/library/bigdecimal/uminus_spec.rb58
-rw-r--r--spec/ruby/library/bigdecimal/uplus_spec.rb20
-rw-r--r--spec/ruby/library/bigdecimal/ver_spec.rb11
-rw-r--r--spec/ruby/library/bigdecimal/zero_spec.rb28
-rw-r--r--spec/ruby/library/bigmath/log_spec.rb10
-rw-r--r--spec/ruby/library/cgi/cookie/domain_spec.rb23
-rw-r--r--spec/ruby/library/cgi/cookie/expires_spec.rb23
-rw-r--r--spec/ruby/library/cgi/cookie/initialize_spec.rb147
-rw-r--r--spec/ruby/library/cgi/cookie/name_spec.rb23
-rw-r--r--spec/ruby/library/cgi/cookie/parse_spec.rb18
-rw-r--r--spec/ruby/library/cgi/cookie/path_spec.rb23
-rw-r--r--spec/ruby/library/cgi/cookie/secure_spec.rb70
-rw-r--r--spec/ruby/library/cgi/cookie/to_s_spec.rb42
-rw-r--r--spec/ruby/library/cgi/cookie/value_spec.rb76
-rw-r--r--spec/ruby/library/cgi/escapeElement_spec.rb20
-rw-r--r--spec/ruby/library/cgi/escapeHTML_spec.rb13
-rw-r--r--spec/ruby/library/cgi/escape_spec.rb26
-rw-r--r--spec/ruby/library/cgi/htmlextension/a_spec.rb49
-rw-r--r--spec/ruby/library/cgi/htmlextension/base_spec.rb33
-rw-r--r--spec/ruby/library/cgi/htmlextension/blockquote_spec.rb33
-rw-r--r--spec/ruby/library/cgi/htmlextension/br_spec.rb22
-rw-r--r--spec/ruby/library/cgi/htmlextension/caption_spec.rb33
-rw-r--r--spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb76
-rw-r--r--spec/ruby/library/cgi/htmlextension/checkbox_spec.rb77
-rw-r--r--spec/ruby/library/cgi/htmlextension/doctype_spec.rb27
-rw-r--r--spec/ruby/library/cgi/htmlextension/file_field_spec.rb72
-rw-r--r--spec/ruby/library/cgi/htmlextension/fixtures/common.rb15
-rw-r--r--spec/ruby/library/cgi/htmlextension/form_spec.rb58
-rw-r--r--spec/ruby/library/cgi/htmlextension/frame_spec.rb14
-rw-r--r--spec/ruby/library/cgi/htmlextension/frameset_spec.rb14
-rw-r--r--spec/ruby/library/cgi/htmlextension/hidden_spec.rb59
-rw-r--r--spec/ruby/library/cgi/htmlextension/html_spec.rb66
-rw-r--r--spec/ruby/library/cgi/htmlextension/image_button_spec.rb69
-rw-r--r--spec/ruby/library/cgi/htmlextension/img_spec.rb83
-rw-r--r--spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb64
-rw-r--r--spec/ruby/library/cgi/htmlextension/password_field_spec.rb84
-rw-r--r--spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb8
-rw-r--r--spec/ruby/library/cgi/htmlextension/radio_button_spec.rb77
-rw-r--r--spec/ruby/library/cgi/htmlextension/radio_group_spec.rb77
-rw-r--r--spec/ruby/library/cgi/htmlextension/reset_spec.rb57
-rw-r--r--spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb8
-rw-r--r--spec/ruby/library/cgi/htmlextension/shared/popup_menu.rb94
-rw-r--r--spec/ruby/library/cgi/htmlextension/submit_spec.rb57
-rw-r--r--spec/ruby/library/cgi/htmlextension/text_field_spec.rb84
-rw-r--r--spec/ruby/library/cgi/htmlextension/textarea_spec.rb73
-rw-r--r--spec/ruby/library/cgi/http_header_spec.rb8
-rw-r--r--spec/ruby/library/cgi/initialize_spec.rb133
-rw-r--r--spec/ruby/library/cgi/out_spec.rb51
-rw-r--r--spec/ruby/library/cgi/parse_spec.rb24
-rw-r--r--spec/ruby/library/cgi/pretty_spec.rb24
-rw-r--r--spec/ruby/library/cgi/print_spec.rb26
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_charset_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_language_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/auth_type_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/cache_control_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/content_length_spec.rb26
-rw-r--r--spec/ruby/library/cgi/queryextension/content_type_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/cookies_spec.rb10
-rw-r--r--spec/ruby/library/cgi/queryextension/element_reference_spec.rb27
-rw-r--r--spec/ruby/library/cgi/queryextension/from_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/has_key_spec.rb7
-rw-r--r--spec/ruby/library/cgi/queryextension/host_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/include_spec.rb7
-rw-r--r--spec/ruby/library/cgi/queryextension/key_spec.rb7
-rw-r--r--spec/ruby/library/cgi/queryextension/keys_spec.rb20
-rw-r--r--spec/ruby/library/cgi/queryextension/multipart_spec.rb40
-rw-r--r--spec/ruby/library/cgi/queryextension/negotiate_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/params_spec.rb37
-rw-r--r--spec/ruby/library/cgi/queryextension/path_info_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/path_translated_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/pragma_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/query_string_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/referer_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_addr_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_host_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_ident_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_user_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/request_method_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/script_name_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/server_name_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/server_port_spec.rb26
-rw-r--r--spec/ruby/library/cgi/queryextension/server_protocol_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/server_software_spec.rb22
-rw-r--r--spec/ruby/library/cgi/queryextension/shared/has_key.rb19
-rw-r--r--spec/ruby/library/cgi/queryextension/user_agent_spec.rb22
-rw-r--r--spec/ruby/library/cgi/rfc1123_date_spec.rb10
-rw-r--r--spec/ruby/library/cgi/shared/http_header.rb112
-rw-r--r--spec/ruby/library/cgi/unescapeElement_spec.rb20
-rw-r--r--spec/ruby/library/cgi/unescapeHTML_spec.rb39
-rw-r--r--spec/ruby/library/cgi/unescape_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/acos_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/acosh_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/asin_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/asinh_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/atan2_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/atan_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/atanh_spec.rb17
-rw-r--r--spec/ruby/library/complex/math/cos_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/cosh_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/exp_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/fixtures/classes.rb4
-rw-r--r--spec/ruby/library/complex/math/log10_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/log_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/shared/acos.rb41
-rw-r--r--spec/ruby/library/complex/math/shared/acosh.rb37
-rw-r--r--spec/ruby/library/complex/math/shared/asin.rb47
-rw-r--r--spec/ruby/library/complex/math/shared/asinh.rb32
-rw-r--r--spec/ruby/library/complex/math/shared/atan.rb32
-rw-r--r--spec/ruby/library/complex/math/shared/atan2.rb34
-rw-r--r--spec/ruby/library/complex/math/shared/atanh.rb30
-rw-r--r--spec/ruby/library/complex/math/shared/cos.rb30
-rw-r--r--spec/ruby/library/complex/math/shared/cosh.rb28
-rw-r--r--spec/ruby/library/complex/math/shared/exp.rb28
-rw-r--r--spec/ruby/library/complex/math/shared/log.rb39
-rw-r--r--spec/ruby/library/complex/math/shared/log10.rb41
-rw-r--r--spec/ruby/library/complex/math/shared/sin.rb30
-rw-r--r--spec/ruby/library/complex/math/shared/sinh.rb28
-rw-r--r--spec/ruby/library/complex/math/shared/sqrt.rb34
-rw-r--r--spec/ruby/library/complex/math/shared/tan.rb28
-rw-r--r--spec/ruby/library/complex/math/shared/tanh.rb32
-rw-r--r--spec/ruby/library/complex/math/sin_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/sinh_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/sqrt_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/tan_spec.rb15
-rw-r--r--spec/ruby/library/complex/math/tanh_spec.rb15
-rw-r--r--spec/ruby/library/complex/numeric/im_spec.rb3
-rw-r--r--spec/ruby/library/conditionvariable/broadcast_spec.rb67
-rw-r--r--spec/ruby/library/conditionvariable/signal_spec.rb69
-rw-r--r--spec/ruby/library/conditionvariable/wait_spec.rb25
-rw-r--r--spec/ruby/library/coverage/fixtures/second_class.rb5
-rw-r--r--spec/ruby/library/coverage/fixtures/some_class.rb16
-rw-r--r--spec/ruby/library/coverage/fixtures/spec_helper.rb11
-rw-r--r--spec/ruby/library/coverage/fixtures/start_coverage.rb3
-rw-r--r--spec/ruby/library/coverage/peek_result_spec.rb67
-rw-r--r--spec/ruby/library/coverage/result_spec.rb78
-rw-r--r--spec/ruby/library/coverage/start_spec.rb6
-rw-r--r--spec/ruby/library/csv/basicwriter/close_on_terminate_spec.rb6
-rw-r--r--spec/ruby/library/csv/basicwriter/initialize_spec.rb6
-rw-r--r--spec/ruby/library/csv/basicwriter/terminate_spec.rb6
-rw-r--r--spec/ruby/library/csv/cell/data_spec.rb6
-rw-r--r--spec/ruby/library/csv/cell/initialize_spec.rb6
-rw-r--r--spec/ruby/library/csv/fixtures/one_line.csv1
-rw-r--r--spec/ruby/library/csv/foreach_spec.rb6
-rw-r--r--spec/ruby/library/csv/generate_line_spec.rb30
-rw-r--r--spec/ruby/library/csv/generate_row_spec.rb6
-rw-r--r--spec/ruby/library/csv/generate_spec.rb32
-rw-r--r--spec/ruby/library/csv/iobuf/close_spec.rb6
-rw-r--r--spec/ruby/library/csv/iobuf/initialize_spec.rb6
-rw-r--r--spec/ruby/library/csv/iobuf/read_spec.rb6
-rw-r--r--spec/ruby/library/csv/iobuf/terminate_spec.rb6
-rw-r--r--spec/ruby/library/csv/ioreader/close_on_terminate_spec.rb6
-rw-r--r--spec/ruby/library/csv/ioreader/get_row_spec.rb6
-rw-r--r--spec/ruby/library/csv/ioreader/initialize_spec.rb6
-rw-r--r--spec/ruby/library/csv/ioreader/terminate_spec.rb6
-rw-r--r--spec/ruby/library/csv/open_spec.rb6
-rw-r--r--spec/ruby/library/csv/parse_spec.rb81
-rw-r--r--spec/ruby/library/csv/read_spec.rb6
-rw-r--r--spec/ruby/library/csv/readlines_spec.rb23
-rw-r--r--spec/ruby/library/csv/streambuf/add_buf_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/buf_size_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/drop_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/element_reference_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/get_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/idx_is_eos_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/initialize_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/is_eos_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/read_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/rel_buf_spec.rb6
-rw-r--r--spec/ruby/library/csv/streambuf/terminate_spec.rb6
-rw-r--r--spec/ruby/library/csv/stringreader/get_row_spec.rb6
-rw-r--r--spec/ruby/library/csv/stringreader/initialize_spec.rb6
-rw-r--r--spec/ruby/library/csv/writer/add_row_spec.rb6
-rw-r--r--spec/ruby/library/csv/writer/append_spec.rb6
-rw-r--r--spec/ruby/library/csv/writer/close_spec.rb6
-rw-r--r--spec/ruby/library/csv/writer/create_spec.rb6
-rw-r--r--spec/ruby/library/csv/writer/generate_spec.rb6
-rw-r--r--spec/ruby/library/csv/writer/initialize_spec.rb6
-rw-r--r--spec/ruby/library/csv/writer/terminate_spec.rb6
-rw-r--r--spec/ruby/library/date/accessor_spec.rb91
-rw-r--r--spec/ruby/library/date/add_month_spec.rb38
-rw-r--r--spec/ruby/library/date/add_spec.rb30
-rw-r--r--spec/ruby/library/date/ajd_spec.rb6
-rw-r--r--spec/ruby/library/date/ajd_to_amjd_spec.rb6
-rw-r--r--spec/ruby/library/date/ajd_to_jd_spec.rb6
-rw-r--r--spec/ruby/library/date/amjd_spec.rb6
-rw-r--r--spec/ruby/library/date/amjd_to_ajd_spec.rb6
-rw-r--r--spec/ruby/library/date/append_spec.rb6
-rw-r--r--spec/ruby/library/date/asctime_spec.rb6
-rw-r--r--spec/ruby/library/date/boat_spec.rb24
-rw-r--r--spec/ruby/library/date/case_compare_spec.rb6
-rw-r--r--spec/ruby/library/date/civil_spec.rb12
-rw-r--r--spec/ruby/library/date/commercial_spec.rb18
-rw-r--r--spec/ruby/library/date/commercial_to_jd_spec.rb6
-rw-r--r--spec/ruby/library/date/comparison_spec.rb6
-rw-r--r--spec/ruby/library/date/constants_spec.rb44
-rw-r--r--spec/ruby/library/date/conversions_spec.rb43
-rw-r--r--spec/ruby/library/date/ctime_spec.rb6
-rw-r--r--spec/ruby/library/date/cwday_spec.rb6
-rw-r--r--spec/ruby/library/date/cweek_spec.rb6
-rw-r--r--spec/ruby/library/date/cwyear_spec.rb6
-rw-r--r--spec/ruby/library/date/day_fraction_spec.rb6
-rw-r--r--spec/ruby/library/date/day_fraction_to_time_spec.rb6
-rw-r--r--spec/ruby/library/date/day_spec.rb6
-rw-r--r--spec/ruby/library/date/downto_spec.rb18
-rw-r--r--spec/ruby/library/date/england_spec.rb6
-rw-r--r--spec/ruby/library/date/eql_spec.rb12
-rw-r--r--spec/ruby/library/date/format/bag/method_missing_spec.rb6
-rw-r--r--spec/ruby/library/date/format/bag/to_hash_spec.rb6
-rw-r--r--spec/ruby/library/date/gregorian_leap_spec.rb16
-rw-r--r--spec/ruby/library/date/gregorian_spec.rb16
-rw-r--r--spec/ruby/library/date/hash_spec.rb8
-rw-r--r--spec/ruby/library/date/infinity/abs_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity/coerce_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity/comparison_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity/d_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity/finite_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity/infinite_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity/nan_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity/uminus_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity/uplus_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity/zero_spec.rb6
-rw-r--r--spec/ruby/library/date/infinity_spec.rb67
-rw-r--r--spec/ruby/library/date/inspect_spec.rb6
-rw-r--r--spec/ruby/library/date/italy_spec.rb6
-rw-r--r--spec/ruby/library/date/jd_spec.rb15
-rw-r--r--spec/ruby/library/date/jd_to_ajd_spec.rb6
-rw-r--r--spec/ruby/library/date/jd_to_civil_spec.rb6
-rw-r--r--spec/ruby/library/date/jd_to_commercial_spec.rb6
-rw-r--r--spec/ruby/library/date/jd_to_ld_spec.rb6
-rw-r--r--spec/ruby/library/date/jd_to_mjd_spec.rb6
-rw-r--r--spec/ruby/library/date/jd_to_ordinal_spec.rb6
-rw-r--r--spec/ruby/library/date/jd_to_wday_spec.rb6
-rw-r--r--spec/ruby/library/date/julian_leap_spec.rb15
-rw-r--r--spec/ruby/library/date/julian_spec.rb16
-rw-r--r--spec/ruby/library/date/ld_spec.rb6
-rw-r--r--spec/ruby/library/date/ld_to_jd_spec.rb6
-rw-r--r--spec/ruby/library/date/leap_spec.rb10
-rw-r--r--spec/ruby/library/date/mday_spec.rb6
-rw-r--r--spec/ruby/library/date/minus_month_spec.rb34
-rw-r--r--spec/ruby/library/date/minus_spec.rb30
-rw-r--r--spec/ruby/library/date/mjd_spec.rb6
-rw-r--r--spec/ruby/library/date/mjd_to_jd_spec.rb6
-rw-r--r--spec/ruby/library/date/mon_spec.rb6
-rw-r--r--spec/ruby/library/date/month_spec.rb6
-rw-r--r--spec/ruby/library/date/new_spec.rb8
-rw-r--r--spec/ruby/library/date/new_start_spec.rb6
-rw-r--r--spec/ruby/library/date/next_day_spec.rb10
-rw-r--r--spec/ruby/library/date/next_spec.rb6
-rw-r--r--spec/ruby/library/date/next_year_spec.rb12
-rw-r--r--spec/ruby/library/date/ordinal_spec.rb8
-rw-r--r--spec/ruby/library/date/ordinal_to_jd_spec.rb6
-rw-r--r--spec/ruby/library/date/parse_spec.rb137
-rw-r--r--spec/ruby/library/date/plus_spec.rb20
-rw-r--r--spec/ruby/library/date/prev_year_spec.rb12
-rw-r--r--spec/ruby/library/date/relationship_spec.rb20
-rw-r--r--spec/ruby/library/date/right_shift_spec.rb6
-rw-r--r--spec/ruby/library/date/shared/civil.rb57
-rw-r--r--spec/ruby/library/date/shared/commercial.rb39
-rw-r--r--spec/ruby/library/date/shared/jd.rb14
-rw-r--r--spec/ruby/library/date/shared/new_bang.rb14
-rw-r--r--spec/ruby/library/date/shared/ordinal.rb22
-rw-r--r--spec/ruby/library/date/shared/parse.rb54
-rw-r--r--spec/ruby/library/date/shared/parse_eu.rb37
-rw-r--r--spec/ruby/library/date/shared/parse_us.rb36
-rw-r--r--spec/ruby/library/date/shared/valid_civil.rb36
-rw-r--r--spec/ruby/library/date/shared/valid_commercial.rb34
-rw-r--r--spec/ruby/library/date/shared/valid_jd.rb15
-rw-r--r--spec/ruby/library/date/shared/valid_ordinal.rb26
-rw-r--r--spec/ruby/library/date/start_spec.rb6
-rw-r--r--spec/ruby/library/date/step_spec.rb56
-rw-r--r--spec/ruby/library/date/strftime_spec.rb40
-rw-r--r--spec/ruby/library/date/strptime_spec.rb149
-rw-r--r--spec/ruby/library/date/succ_spec.rb6
-rw-r--r--spec/ruby/library/date/time_to_day_fraction_spec.rb6
-rw-r--r--spec/ruby/library/date/to_s_spec.rb6
-rw-r--r--spec/ruby/library/date/today_spec.rb6
-rw-r--r--spec/ruby/library/date/upto_spec.rb16
-rw-r--r--spec/ruby/library/date/valid_civil_spec.rb10
-rw-r--r--spec/ruby/library/date/valid_commercial_spec.rb10
-rw-r--r--spec/ruby/library/date/valid_date_spec.rb7
-rw-r--r--spec/ruby/library/date/valid_jd_spec.rb10
-rw-r--r--spec/ruby/library/date/valid_ordinal_spec.rb10
-rw-r--r--spec/ruby/library/date/valid_time_spec.rb6
-rw-r--r--spec/ruby/library/date/wday_spec.rb6
-rw-r--r--spec/ruby/library/date/yday_spec.rb6
-rw-r--r--spec/ruby/library/date/year_spec.rb6
-rw-r--r--spec/ruby/library/date/zone_to_diff_spec.rb6
-rw-r--r--spec/ruby/library/datetime/_strptime_spec.rb6
-rw-r--r--spec/ruby/library/datetime/civil_spec.rb6
-rw-r--r--spec/ruby/library/datetime/commercial_spec.rb6
-rw-r--r--spec/ruby/library/datetime/hour_spec.rb47
-rw-r--r--spec/ruby/library/datetime/httpdate_spec.rb6
-rw-r--r--spec/ruby/library/datetime/iso8601_spec.rb10
-rw-r--r--spec/ruby/library/datetime/jd_spec.rb6
-rw-r--r--spec/ruby/library/datetime/jisx0301_spec.rb10
-rw-r--r--spec/ruby/library/datetime/min_spec.rb6
-rw-r--r--spec/ruby/library/datetime/minute_spec.rb6
-rw-r--r--spec/ruby/library/datetime/new_offset_spec.rb6
-rw-r--r--spec/ruby/library/datetime/new_spec.rb52
-rw-r--r--spec/ruby/library/datetime/now_spec.rb8
-rw-r--r--spec/ruby/library/datetime/offset_spec.rb6
-rw-r--r--spec/ruby/library/datetime/ordinal_spec.rb6
-rw-r--r--spec/ruby/library/datetime/parse_spec.rb127
-rw-r--r--spec/ruby/library/datetime/rfc2822_spec.rb6
-rw-r--r--spec/ruby/library/datetime/rfc3339_spec.rb10
-rw-r--r--spec/ruby/library/datetime/rfc822_spec.rb6
-rw-r--r--spec/ruby/library/datetime/sec_fraction_spec.rb6
-rw-r--r--spec/ruby/library/datetime/sec_spec.rb6
-rw-r--r--spec/ruby/library/datetime/second_fraction_spec.rb6
-rw-r--r--spec/ruby/library/datetime/second_spec.rb6
-rw-r--r--spec/ruby/library/datetime/shared/min.rb40
-rw-r--r--spec/ruby/library/datetime/shared/sec.rb45
-rw-r--r--spec/ruby/library/datetime/strftime_spec.rb51
-rw-r--r--spec/ruby/library/datetime/strptime_spec.rb6
-rw-r--r--spec/ruby/library/datetime/to_date_spec.rb6
-rw-r--r--spec/ruby/library/datetime/to_datetime_spec.rb6
-rw-r--r--spec/ruby/library/datetime/to_s_spec.rb6
-rw-r--r--spec/ruby/library/datetime/to_time_spec.rb6
-rw-r--r--spec/ruby/library/datetime/xmlschema_spec.rb10
-rw-r--r--spec/ruby/library/datetime/zone_spec.rb6
-rw-r--r--spec/ruby/library/delegate/delegate_class/instance_method_spec.rb52
-rw-r--r--spec/ruby/library/delegate/delegate_class/instance_methods_spec.rb26
-rw-r--r--spec/ruby/library/delegate/delegate_class/private_instance_methods_spec.rb23
-rw-r--r--spec/ruby/library/delegate/delegate_class/protected_instance_methods_spec.rb29
-rw-r--r--spec/ruby/library/delegate/delegate_class/public_instance_methods_spec.rb25
-rw-r--r--spec/ruby/library/delegate/delegate_class/respond_to_missing_spec.rb23
-rw-r--r--spec/ruby/library/delegate/delegator/case_compare_spec.rb11
-rw-r--r--spec/ruby/library/delegate/delegator/compare_spec.rb11
-rw-r--r--spec/ruby/library/delegate/delegator/complement_spec.rb11
-rw-r--r--spec/ruby/library/delegate/delegator/eql_spec.rb46
-rw-r--r--spec/ruby/library/delegate/delegator/equal_spec.rb13
-rw-r--r--spec/ruby/library/delegate/delegator/equal_value_spec.rb24
-rw-r--r--spec/ruby/library/delegate/delegator/frozen_spec.rb39
-rw-r--r--spec/ruby/library/delegate/delegator/hash_spec.rb11
-rw-r--r--spec/ruby/library/delegate/delegator/marshal_spec.rb21
-rw-r--r--spec/ruby/library/delegate/delegator/method_spec.rb69
-rw-r--r--spec/ruby/library/delegate/delegator/methods_spec.rb37
-rw-r--r--spec/ruby/library/delegate/delegator/not_equal_spec.rb24
-rw-r--r--spec/ruby/library/delegate/delegator/not_spec.rb11
-rw-r--r--spec/ruby/library/delegate/delegator/private_methods_spec.rb20
-rw-r--r--spec/ruby/library/delegate/delegator/protected_methods_spec.rb18
-rw-r--r--spec/ruby/library/delegate/delegator/public_methods_spec.rb18
-rw-r--r--spec/ruby/library/delegate/delegator/send_spec.rb26
-rw-r--r--spec/ruby/library/delegate/delegator/taint_spec.rb23
-rw-r--r--spec/ruby/library/delegate/delegator/tap_spec.rb16
-rw-r--r--spec/ruby/library/delegate/delegator/trust_spec.rb22
-rw-r--r--spec/ruby/library/delegate/delegator/untaint_spec.rb24
-rw-r--r--spec/ruby/library/delegate/delegator/untrust_spec.rb23
-rw-r--r--spec/ruby/library/delegate/fixtures/classes.rb60
-rw-r--r--spec/ruby/library/digest/bubblebabble_spec.rb29
-rw-r--r--spec/ruby/library/digest/hexencode_spec.rb31
-rw-r--r--spec/ruby/library/digest/md5/append_spec.rb7
-rw-r--r--spec/ruby/library/digest/md5/block_length_spec.rb12
-rw-r--r--spec/ruby/library/digest/md5/digest_bang_spec.rb13
-rw-r--r--spec/ruby/library/digest/md5/digest_length_spec.rb12
-rw-r--r--spec/ruby/library/digest/md5/digest_spec.rb32
-rw-r--r--spec/ruby/library/digest/md5/equal_spec.rb38
-rw-r--r--spec/ruby/library/digest/md5/file_spec.rb43
-rw-r--r--spec/ruby/library/digest/md5/hexdigest_bang_spec.rb14
-rw-r--r--spec/ruby/library/digest/md5/hexdigest_spec.rb32
-rw-r--r--spec/ruby/library/digest/md5/inspect_spec.rb12
-rw-r--r--spec/ruby/library/digest/md5/length_spec.rb8
-rw-r--r--spec/ruby/library/digest/md5/reset_spec.rb15
-rw-r--r--spec/ruby/library/digest/md5/shared/constants.rb16
-rw-r--r--spec/ruby/library/digest/md5/shared/length.rb8
-rw-r--r--spec/ruby/library/digest/md5/shared/sample.rb17
-rw-r--r--spec/ruby/library/digest/md5/shared/update.rb7
-rw-r--r--spec/ruby/library/digest/md5/size_spec.rb8
-rw-r--r--spec/ruby/library/digest/md5/to_s_spec.rb24
-rw-r--r--spec/ruby/library/digest/md5/update_spec.rb7
-rw-r--r--spec/ruby/library/digest/sha1/digest_spec.rb20
-rw-r--r--spec/ruby/library/digest/sha1/file_spec.rb43
-rw-r--r--spec/ruby/library/digest/sha1/shared/constants.rb17
-rw-r--r--spec/ruby/library/digest/sha256/append_spec.rb7
-rw-r--r--spec/ruby/library/digest/sha256/block_length_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha256/digest_bang_spec.rb13
-rw-r--r--spec/ruby/library/digest/sha256/digest_length_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha256/digest_spec.rb32
-rw-r--r--spec/ruby/library/digest/sha256/equal_spec.rb37
-rw-r--r--spec/ruby/library/digest/sha256/file_spec.rb43
-rw-r--r--spec/ruby/library/digest/sha256/hexdigest_bang_spec.rb14
-rw-r--r--spec/ruby/library/digest/sha256/hexdigest_spec.rb32
-rw-r--r--spec/ruby/library/digest/sha256/inspect_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha256/length_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha256/reset_spec.rb15
-rw-r--r--spec/ruby/library/digest/sha256/shared/constants.rb17
-rw-r--r--spec/ruby/library/digest/sha256/shared/length.rb8
-rw-r--r--spec/ruby/library/digest/sha256/shared/update.rb7
-rw-r--r--spec/ruby/library/digest/sha256/size_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha256/to_s_spec.rb21
-rw-r--r--spec/ruby/library/digest/sha256/update_spec.rb7
-rw-r--r--spec/ruby/library/digest/sha384/append_spec.rb7
-rw-r--r--spec/ruby/library/digest/sha384/block_length_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha384/digest_bang_spec.rb13
-rw-r--r--spec/ruby/library/digest/sha384/digest_length_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha384/digest_spec.rb32
-rw-r--r--spec/ruby/library/digest/sha384/equal_spec.rb37
-rw-r--r--spec/ruby/library/digest/sha384/file_spec.rb43
-rw-r--r--spec/ruby/library/digest/sha384/hexdigest_bang_spec.rb14
-rw-r--r--spec/ruby/library/digest/sha384/hexdigest_spec.rb32
-rw-r--r--spec/ruby/library/digest/sha384/inspect_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha384/length_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha384/reset_spec.rb15
-rw-r--r--spec/ruby/library/digest/sha384/shared/constants.rb18
-rw-r--r--spec/ruby/library/digest/sha384/shared/length.rb8
-rw-r--r--spec/ruby/library/digest/sha384/shared/update.rb7
-rw-r--r--spec/ruby/library/digest/sha384/size_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha384/to_s_spec.rb21
-rw-r--r--spec/ruby/library/digest/sha384/update_spec.rb7
-rw-r--r--spec/ruby/library/digest/sha512/append_spec.rb7
-rw-r--r--spec/ruby/library/digest/sha512/block_length_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha512/digest_bang_spec.rb13
-rw-r--r--spec/ruby/library/digest/sha512/digest_length_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha512/digest_spec.rb32
-rw-r--r--spec/ruby/library/digest/sha512/equal_spec.rb37
-rw-r--r--spec/ruby/library/digest/sha512/file_spec.rb43
-rw-r--r--spec/ruby/library/digest/sha512/hexdigest_bang_spec.rb14
-rw-r--r--spec/ruby/library/digest/sha512/hexdigest_spec.rb32
-rw-r--r--spec/ruby/library/digest/sha512/inspect_spec.rb12
-rw-r--r--spec/ruby/library/digest/sha512/length_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha512/reset_spec.rb15
-rw-r--r--spec/ruby/library/digest/sha512/shared/constants.rb17
-rw-r--r--spec/ruby/library/digest/sha512/shared/length.rb8
-rw-r--r--spec/ruby/library/digest/sha512/shared/update.rb7
-rw-r--r--spec/ruby/library/digest/sha512/size_spec.rb8
-rw-r--r--spec/ruby/library/digest/sha512/to_s_spec.rb21
-rw-r--r--spec/ruby/library/digest/sha512/update_spec.rb7
-rw-r--r--spec/ruby/library/drb/fixtures/test_server.rb8
-rw-r--r--spec/ruby/library/drb/start_service_spec.rb28
-rw-r--r--spec/ruby/library/erb/def_class_spec.rb29
-rw-r--r--spec/ruby/library/erb/def_method_spec.rb26
-rw-r--r--spec/ruby/library/erb/def_module_spec.rb27
-rw-r--r--spec/ruby/library/erb/defmethod/def_erb_method_spec.rb63
-rw-r--r--spec/ruby/library/erb/filename_spec.rb40
-rw-r--r--spec/ruby/library/erb/new_spec.rb132
-rw-r--r--spec/ruby/library/erb/result_spec.rb86
-rw-r--r--spec/ruby/library/erb/run_spec.rb97
-rw-r--r--spec/ruby/library/erb/src_spec.rb33
-rw-r--r--spec/ruby/library/erb/util/h_spec.rb7
-rw-r--r--spec/ruby/library/erb/util/html_escape_spec.rb8
-rw-r--r--spec/ruby/library/erb/util/shared/html_escape.rb42
-rw-r--r--spec/ruby/library/erb/util/shared/url_encode.rb50
-rw-r--r--spec/ruby/library/erb/util/u_spec.rb8
-rw-r--r--spec/ruby/library/erb/util/url_encode_spec.rb7
-rw-r--r--spec/ruby/library/etc/endgrent_spec.rb7
-rw-r--r--spec/ruby/library/etc/endpwent_spec.rb7
-rw-r--r--spec/ruby/library/etc/getgrent_spec.rb7
-rw-r--r--spec/ruby/library/etc/getgrgid_spec.rb70
-rw-r--r--spec/ruby/library/etc/getgrnam_spec.rb30
-rw-r--r--spec/ruby/library/etc/getlogin_spec.rb32
-rw-r--r--spec/ruby/library/etc/getpwent_spec.rb7
-rw-r--r--spec/ruby/library/etc/getpwnam_spec.rb28
-rw-r--r--spec/ruby/library/etc/getpwuid_spec.rb36
-rw-r--r--spec/ruby/library/etc/group_spec.rb18
-rw-r--r--spec/ruby/library/etc/nprocessors_spec.rb11
-rw-r--r--spec/ruby/library/etc/shared/windows.rb7
-rw-r--r--spec/ruby/library/etc/struct_group_spec.rb31
-rw-r--r--spec/ruby/library/etc/struct_passwd_spec.rb43
-rw-r--r--spec/ruby/library/expect/expect_spec.rb62
-rw-r--r--spec/ruby/library/fiber/alive_spec.rb48
-rw-r--r--spec/ruby/library/fiber/current_spec.rb61
-rw-r--r--spec/ruby/library/fiber/resume_spec.rb14
-rw-r--r--spec/ruby/library/fiber/transfer_spec.rb51
-rw-r--r--spec/ruby/library/find/find_spec.rb30
-rw-r--r--spec/ruby/library/find/fixtures/common.rb174
-rw-r--r--spec/ruby/library/find/prune_spec.rb12
-rw-r--r--spec/ruby/library/getoptlong/each_option_spec.rb7
-rw-r--r--spec/ruby/library/getoptlong/each_spec.rb7
-rw-r--r--spec/ruby/library/getoptlong/error_message_spec.rb23
-rw-r--r--spec/ruby/library/getoptlong/get_option_spec.rb7
-rw-r--r--spec/ruby/library/getoptlong/get_spec.rb7
-rw-r--r--spec/ruby/library/getoptlong/initialize_spec.rb28
-rw-r--r--spec/ruby/library/getoptlong/ordering_spec.rb38
-rw-r--r--spec/ruby/library/getoptlong/set_options_spec.rb98
-rw-r--r--spec/ruby/library/getoptlong/shared/each.rb18
-rw-r--r--spec/ruby/library/getoptlong/shared/get.rb64
-rw-r--r--spec/ruby/library/getoptlong/terminate_spec.rb30
-rw-r--r--spec/ruby/library/getoptlong/terminated_spec.rb17
-rw-r--r--spec/ruby/library/ipaddr/hton_spec.rb30
-rw-r--r--spec/ruby/library/ipaddr/ipv4_conversion_spec.rb46
-rw-r--r--spec/ruby/library/ipaddr/new_spec.rb93
-rw-r--r--spec/ruby/library/ipaddr/operator_spec.rb80
-rw-r--r--spec/ruby/library/ipaddr/reverse_spec.rb27
-rw-r--r--spec/ruby/library/ipaddr/to_s_spec.rb20
-rw-r--r--spec/ruby/library/logger/device/close_spec.rb22
-rw-r--r--spec/ruby/library/logger/device/new_spec.rb47
-rw-r--r--spec/ruby/library/logger/device/write_spec.rb42
-rw-r--r--spec/ruby/library/logger/fixtures/common.rb9
-rw-r--r--spec/ruby/library/logger/logger/add_spec.rb81
-rw-r--r--spec/ruby/library/logger/logger/close_spec.rb20
-rw-r--r--spec/ruby/library/logger/logger/datetime_format_spec.rb60
-rw-r--r--spec/ruby/library/logger/logger/debug_spec.rb52
-rw-r--r--spec/ruby/library/logger/logger/error_spec.rb53
-rw-r--r--spec/ruby/library/logger/logger/fatal_spec.rb53
-rw-r--r--spec/ruby/library/logger/logger/info_spec.rb53
-rw-r--r--spec/ruby/library/logger/logger/new_spec.rb63
-rw-r--r--spec/ruby/library/logger/logger/unknown_spec.rb36
-rw-r--r--spec/ruby/library/logger/logger/warn_spec.rb53
-rw-r--r--spec/ruby/library/logger/severity_spec.rb13
-rw-r--r--spec/ruby/library/mathn/bignum/exponent_spec.rb21
-rw-r--r--spec/ruby/library/mathn/complex/Complex_spec.rb14
-rw-r--r--spec/ruby/library/mathn/fixnum/exponent_spec.rb17
-rw-r--r--spec/ruby/library/mathn/float/exponent_spec.rb17
-rw-r--r--spec/ruby/library/mathn/integer/from_prime_division_spec.rb11
-rw-r--r--spec/ruby/library/mathn/integer/prime_division_spec.rb21
-rw-r--r--spec/ruby/library/mathn/math/fixtures/classes.rb3
-rw-r--r--spec/ruby/library/mathn/math/rsqrt_spec.rb17
-rw-r--r--spec/ruby/library/mathn/math/shared/rsqrt.rb21
-rw-r--r--spec/ruby/library/mathn/math/shared/sqrt.rb25
-rw-r--r--spec/ruby/library/mathn/math/sqrt_spec.rb17
-rw-r--r--spec/ruby/library/mathn/rational/Rational_spec.rb14
-rw-r--r--spec/ruby/library/mathn/rational/inspect_spec.rb15
-rw-r--r--spec/ruby/library/matrix/I_spec.rb6
-rw-r--r--spec/ruby/library/matrix/build_spec.rb73
-rw-r--r--spec/ruby/library/matrix/clone_spec.rb25
-rw-r--r--spec/ruby/library/matrix/coerce_spec.rb10
-rw-r--r--spec/ruby/library/matrix/collect_spec.rb6
-rw-r--r--spec/ruby/library/matrix/column_size_spec.rb13
-rw-r--r--spec/ruby/library/matrix/column_spec.rb35
-rw-r--r--spec/ruby/library/matrix/column_vector_spec.rb25
-rw-r--r--spec/ruby/library/matrix/column_vectors_spec.rb26
-rw-r--r--spec/ruby/library/matrix/columns_spec.rb42
-rw-r--r--spec/ruby/library/matrix/conj_spec.rb6
-rw-r--r--spec/ruby/library/matrix/conjugate_spec.rb6
-rw-r--r--spec/ruby/library/matrix/constructor_spec.rb65
-rw-r--r--spec/ruby/library/matrix/det_spec.rb7
-rw-r--r--spec/ruby/library/matrix/determinant_spec.rb7
-rw-r--r--spec/ruby/library/matrix/diagonal_spec.rb72
-rw-r--r--spec/ruby/library/matrix/divide_spec.rb55
-rw-r--r--spec/ruby/library/matrix/each_spec.rb74
-rw-r--r--spec/ruby/library/matrix/each_with_index_spec.rb81
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb9
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb22
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb20
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb22
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb24
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb18
-rw-r--r--spec/ruby/library/matrix/element_reference_spec.rb23
-rw-r--r--spec/ruby/library/matrix/empty_spec.rb68
-rw-r--r--spec/ruby/library/matrix/eql_spec.rb11
-rw-r--r--spec/ruby/library/matrix/equal_value_spec.rb11
-rw-r--r--spec/ruby/library/matrix/exponent_spec.rb51
-rw-r--r--spec/ruby/library/matrix/find_index_spec.rb146
-rw-r--r--spec/ruby/library/matrix/fixtures/classes.rb7
-rw-r--r--spec/ruby/library/matrix/hash_spec.rb15
-rw-r--r--spec/ruby/library/matrix/hermitian_spec.rb34
-rw-r--r--spec/ruby/library/matrix/identity_spec.rb6
-rw-r--r--spec/ruby/library/matrix/imag_spec.rb6
-rw-r--r--spec/ruby/library/matrix/imaginary_spec.rb6
-rw-r--r--spec/ruby/library/matrix/inspect_spec.rb27
-rw-r--r--spec/ruby/library/matrix/inv_spec.rb7
-rw-r--r--spec/ruby/library/matrix/inverse_from_spec.rb6
-rw-r--r--spec/ruby/library/matrix/inverse_spec.rb7
-rw-r--r--spec/ruby/library/matrix/lower_triangular_spec.rb24
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb21
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb13
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/l_spec.rb18
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/p_spec.rb18
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/solve_spec.rb53
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb33
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/u_spec.rb18
-rw-r--r--spec/ruby/library/matrix/map_spec.rb6
-rw-r--r--spec/ruby/library/matrix/minor_spec.rb85
-rw-r--r--spec/ruby/library/matrix/minus_spec.rb42
-rw-r--r--spec/ruby/library/matrix/multiply_spec.rb68
-rw-r--r--spec/ruby/library/matrix/new_spec.rb8
-rw-r--r--spec/ruby/library/matrix/normal_spec.rb26
-rw-r--r--spec/ruby/library/matrix/orthogonal_spec.rb26
-rw-r--r--spec/ruby/library/matrix/permutation_spec.rb32
-rw-r--r--spec/ruby/library/matrix/plus_spec.rb42
-rw-r--r--spec/ruby/library/matrix/rank_spec.rb19
-rw-r--r--spec/ruby/library/matrix/real_spec.rb42
-rw-r--r--spec/ruby/library/matrix/rect_spec.rb6
-rw-r--r--spec/ruby/library/matrix/rectangular_spec.rb6
-rw-r--r--spec/ruby/library/matrix/regular_spec.rb31
-rw-r--r--spec/ruby/library/matrix/round_spec.rb21
-rw-r--r--spec/ruby/library/matrix/row_size_spec.rb13
-rw-r--r--spec/ruby/library/matrix/row_spec.rb36
-rw-r--r--spec/ruby/library/matrix/row_vector_spec.rb24
-rw-r--r--spec/ruby/library/matrix/row_vectors_spec.rb26
-rw-r--r--spec/ruby/library/matrix/rows_spec.rb41
-rw-r--r--spec/ruby/library/matrix/scalar/Fail_spec.rb6
-rw-r--r--spec/ruby/library/matrix/scalar/Raise_spec.rb6
-rw-r--r--spec/ruby/library/matrix/scalar/divide_spec.rb6
-rw-r--r--spec/ruby/library/matrix/scalar/exponent_spec.rb6
-rw-r--r--spec/ruby/library/matrix/scalar/included_spec.rb6
-rw-r--r--spec/ruby/library/matrix/scalar/initialize_spec.rb6
-rw-r--r--spec/ruby/library/matrix/scalar/minus_spec.rb6
-rw-r--r--spec/ruby/library/matrix/scalar/multiply_spec.rb6
-rw-r--r--spec/ruby/library/matrix/scalar/plus_spec.rb6
-rw-r--r--spec/ruby/library/matrix/scalar_spec.rb67
-rw-r--r--spec/ruby/library/matrix/shared/collect.rb26
-rw-r--r--spec/ruby/library/matrix/shared/conjugate.rb20
-rw-r--r--spec/ruby/library/matrix/shared/determinant.rb38
-rw-r--r--spec/ruby/library/matrix/shared/equal_value.rb33
-rw-r--r--spec/ruby/library/matrix/shared/identity.rb19
-rw-r--r--spec/ruby/library/matrix/shared/imaginary.rb20
-rw-r--r--spec/ruby/library/matrix/shared/inverse.rb38
-rw-r--r--spec/ruby/library/matrix/shared/rectangular.rb18
-rw-r--r--spec/ruby/library/matrix/shared/trace.rb12
-rw-r--r--spec/ruby/library/matrix/shared/transpose.rb19
-rw-r--r--spec/ruby/library/matrix/singular_spec.rb31
-rw-r--r--spec/ruby/library/matrix/spec_helper.rb35
-rw-r--r--spec/ruby/library/matrix/square_spec.rb28
-rw-r--r--spec/ruby/library/matrix/symmetric_spec.rb29
-rw-r--r--spec/ruby/library/matrix/t_spec.rb6
-rw-r--r--spec/ruby/library/matrix/to_a_spec.rb11
-rw-r--r--spec/ruby/library/matrix/to_s_spec.rb6
-rw-r--r--spec/ruby/library/matrix/tr_spec.rb7
-rw-r--r--spec/ruby/library/matrix/trace_spec.rb7
-rw-r--r--spec/ruby/library/matrix/transpose_spec.rb6
-rw-r--r--spec/ruby/library/matrix/unit_spec.rb6
-rw-r--r--spec/ruby/library/matrix/unitary_spec.rb28
-rw-r--r--spec/ruby/library/matrix/upper_triangular_spec.rb24
-rw-r--r--spec/ruby/library/matrix/vector/cross_product_spec.rb14
-rw-r--r--spec/ruby/library/matrix/vector/each2_spec.rb49
-rw-r--r--spec/ruby/library/matrix/vector/eql_spec.rb16
-rw-r--r--spec/ruby/library/matrix/vector/inner_product_spec.rb22
-rw-r--r--spec/ruby/library/matrix/vector/normalize_spec.rb18
-rw-r--r--spec/ruby/library/matrix/zero_spec.rb52
-rw-r--r--spec/ruby/library/net/FTPError_spec.rb8
-rw-r--r--spec/ruby/library/net/FTPPermError_spec.rb12
-rw-r--r--spec/ruby/library/net/FTPProtoError_spec.rb12
-rw-r--r--spec/ruby/library/net/FTPReplyError_spec.rb12
-rw-r--r--spec/ruby/library/net/FTPTempError_spec.rb12
-rw-r--r--spec/ruby/library/net/ftp/abort_spec.rb62
-rw-r--r--spec/ruby/library/net/ftp/acct_spec.rb58
-rw-r--r--spec/ruby/library/net/ftp/binary_spec.rb24
-rw-r--r--spec/ruby/library/net/ftp/chdir_spec.rb99
-rw-r--r--spec/ruby/library/net/ftp/close_spec.rb30
-rw-r--r--spec/ruby/library/net/ftp/closed_spec.rb21
-rw-r--r--spec/ruby/library/net/ftp/connect_spec.rb49
-rw-r--r--spec/ruby/library/net/ftp/debug_mode_spec.rb23
-rw-r--r--spec/ruby/library/net/ftp/default_passive_spec.rb10
-rw-r--r--spec/ruby/library/net/ftp/delete_spec.rb59
-rw-r--r--spec/ruby/library/net/ftp/dir_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/fixtures/default_passive.rb3
-rw-r--r--spec/ruby/library/net/ftp/fixtures/passive.rb2
-rw-r--r--spec/ruby/library/net/ftp/fixtures/putbinaryfile3
-rw-r--r--spec/ruby/library/net/ftp/fixtures/puttextfile3
-rw-r--r--spec/ruby/library/net/ftp/fixtures/server.rb273
-rw-r--r--spec/ruby/library/net/ftp/get_spec.rb21
-rw-r--r--spec/ruby/library/net/ftp/getbinaryfile_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/getdir_spec.rb7
-rw-r--r--spec/ruby/library/net/ftp/gettextfile_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/help_spec.rb66
-rw-r--r--spec/ruby/library/net/ftp/initialize_spec.rb87
-rw-r--r--spec/ruby/library/net/ftp/last_response_code_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/last_response_spec.rb25
-rw-r--r--spec/ruby/library/net/ftp/lastresp_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/list_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/login_spec.rb195
-rw-r--r--spec/ruby/library/net/ftp/ls_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/mdtm_spec.rb38
-rw-r--r--spec/ruby/library/net/ftp/mkdir_spec.rb61
-rw-r--r--spec/ruby/library/net/ftp/mtime_spec.rb50
-rw-r--r--spec/ruby/library/net/ftp/nlst_spec.rb92
-rw-r--r--spec/ruby/library/net/ftp/noop_spec.rb38
-rw-r--r--spec/ruby/library/net/ftp/open_spec.rb55
-rw-r--r--spec/ruby/library/net/ftp/passive_spec.rb36
-rw-r--r--spec/ruby/library/net/ftp/put_spec.rb21
-rw-r--r--spec/ruby/library/net/ftp/putbinaryfile_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/puttextfile_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/pwd_spec.rb53
-rw-r--r--spec/ruby/library/net/ftp/quit_spec.rb33
-rw-r--r--spec/ruby/library/net/ftp/rename_spec.rb94
-rw-r--r--spec/ruby/library/net/ftp/resume_spec.rb23
-rw-r--r--spec/ruby/library/net/ftp/retrbinary_spec.rb30
-rw-r--r--spec/ruby/library/net/ftp/retrlines_spec.rb34
-rw-r--r--spec/ruby/library/net/ftp/return_code_spec.rb24
-rw-r--r--spec/ruby/library/net/ftp/rmdir_spec.rb58
-rw-r--r--spec/ruby/library/net/ftp/sendcmd_spec.rb54
-rw-r--r--spec/ruby/library/net/ftp/set_socket_spec.rb8
-rw-r--r--spec/ruby/library/net/ftp/shared/getbinaryfile.rb150
-rw-r--r--spec/ruby/library/net/ftp/shared/gettextfile.rb100
-rw-r--r--spec/ruby/library/net/ftp/shared/last_response_code.rb25
-rw-r--r--spec/ruby/library/net/ftp/shared/list.rb104
-rw-r--r--spec/ruby/library/net/ftp/shared/putbinaryfile.rb167
-rw-r--r--spec/ruby/library/net/ftp/shared/puttextfile.rb120
-rw-r--r--spec/ruby/library/net/ftp/shared/pwd.rb3
-rw-r--r--spec/ruby/library/net/ftp/site_spec.rb53
-rw-r--r--spec/ruby/library/net/ftp/size_spec.rb48
-rw-r--r--spec/ruby/library/net/ftp/spec_helper.rb5
-rw-r--r--spec/ruby/library/net/ftp/status_spec.rb63
-rw-r--r--spec/ruby/library/net/ftp/storbinary_spec.rb48
-rw-r--r--spec/ruby/library/net/ftp/storlines_spec.rb43
-rw-r--r--spec/ruby/library/net/ftp/system_spec.rb48
-rw-r--r--spec/ruby/library/net/ftp/voidcmd_spec.rb54
-rw-r--r--spec/ruby/library/net/ftp/welcome_spec.rb25
-rw-r--r--spec/ruby/library/net/http/HTTPBadResponse_spec.rb8
-rw-r--r--spec/ruby/library/net/http/HTTPError_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPFatalError_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPHeaderSyntaxError_spec.rb8
-rw-r--r--spec/ruby/library/net/http/HTTPRetriableError_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPServerException_spec.rb12
-rw-r--r--spec/ruby/library/net/http/http/Proxy_spec.rb35
-rw-r--r--spec/ruby/library/net/http/http/active_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/address_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/close_on_empty_response_spec.rb10
-rw-r--r--spec/ruby/library/net/http/http/copy_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/delete_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/finish_spec.rb29
-rw-r--r--spec/ruby/library/net/http/http/fixtures/http_server.rb93
-rw-r--r--spec/ruby/library/net/http/http/get2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/get_print_spec.rb30
-rw-r--r--spec/ruby/library/net/http/http/get_response_spec.rb30
-rw-r--r--spec/ruby/library/net/http/http/get_spec.rb26
-rw-r--r--spec/ruby/library/net/http/http/head2_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/head_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/http_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/https_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/initialize_spec.rb46
-rw-r--r--spec/ruby/library/net/http/http/inspect_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/is_version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/is_version_1_2_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/lock_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/mkcol_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/move_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/new_spec.rb86
-rw-r--r--spec/ruby/library/net/http/http/newobj_spec.rb48
-rw-r--r--spec/ruby/library/net/http/http/open_timeout_spec.rb35
-rw-r--r--spec/ruby/library/net/http/http/options_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/port_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/post2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/post_form_spec.rb22
-rw-r--r--spec/ruby/library/net/http/http/post_spec.rb38
-rw-r--r--spec/ruby/library/net/http/http/propfind_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/proppatch_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/proxy_address_spec.rb31
-rw-r--r--spec/ruby/library/net/http/http/proxy_class_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/proxy_pass_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/proxy_port_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/proxy_user_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/put2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/put_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/read_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/request_get_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_head_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_post_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_put_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_spec.rb109
-rw-r--r--spec/ruby/library/net/http/http/request_types_spec.rb254
-rw-r--r--spec/ruby/library/net/http/http/send_request_spec.rb61
-rw-r--r--spec/ruby/library/net/http/http/set_debug_output_spec.rb33
-rw-r--r--spec/ruby/library/net/http/http/shared/request_get.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/request_head.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/request_post.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/request_put.rb41
-rw-r--r--spec/ruby/library/net/http/http/shared/started.rb26
-rw-r--r--spec/ruby/library/net/http/http/shared/version_1_1.rb6
-rw-r--r--spec/ruby/library/net/http/http/shared/version_1_2.rb6
-rw-r--r--spec/ruby/library/net/http/http/socket_type_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/start_spec.rb111
-rw-r--r--spec/ruby/library/net/http/http/started_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/trace_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/unlock_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/use_ssl_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/version_1_2_spec.rb20
-rw-r--r--spec/ruby/library/net/http/httpexceptions/fixtures/classes.rb5
-rw-r--r--spec/ruby/library/net/http/httpexceptions/initialize_spec.rb17
-rw-r--r--spec/ruby/library/net/http/httpexceptions/response_spec.rb10
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/body_exist_spec.rb22
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/body_spec.rb30
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/body_stream_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/exec_spec.rb131
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/inspect_spec.rb25
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/method_spec.rb15
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/path_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/request_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/response_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/set_body_internal_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpheader/add_field_spec.rb31
-rw-r--r--spec/ruby/library/net/http/httpheader/basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net/http/httpheader/canonical_each_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/chunked_spec.rb22
-rw-r--r--spec/ruby/library/net/http/httpheader/content_length_spec.rb54
-rw-r--r--spec/ruby/library/net/http/httpheader/content_range_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpheader/content_type_spec.rb26
-rw-r--r--spec/ruby/library/net/http/httpheader/delete_spec.rb30
-rw-r--r--spec/ruby/library/net/http/httpheader/each_capitalized_name_spec.rb35
-rw-r--r--spec/ruby/library/net/http/httpheader/each_capitalized_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpheader/each_header_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_key_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_name_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_value_spec.rb35
-rw-r--r--spec/ruby/library/net/http/httpheader/element_reference_spec.rb39
-rw-r--r--spec/ruby/library/net/http/httpheader/element_set_spec.rb41
-rw-r--r--spec/ruby/library/net/http/httpheader/fetch_spec.rb68
-rw-r--r--spec/ruby/library/net/http/httpheader/fixtures/classes.rb11
-rw-r--r--spec/ruby/library/net/http/httpheader/form_data_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/get_fields_spec.rb39
-rw-r--r--spec/ruby/library/net/http/httpheader/initialize_http_header_spec.rb22
-rw-r--r--spec/ruby/library/net/http/httpheader/key_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpheader/length_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/main_type_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpheader/proxy_basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net/http/httpheader/range_length_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpheader/range_spec.rb48
-rw-r--r--spec/ruby/library/net/http/httpheader/set_content_type_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/set_form_data_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/set_range_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/each_capitalized.rb31
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/each_header.rb31
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/each_name.rb31
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/set_content_type.rb18
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/set_form_data.rb27
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/set_range.rb89
-rw-r--r--spec/ruby/library/net/http/httpheader/shared/size.rb18
-rw-r--r--spec/ruby/library/net/http/httpheader/size_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/sub_type_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpheader/to_hash_spec.rb25
-rw-r--r--spec/ruby/library/net/http/httpheader/type_params_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httprequest/initialize_spec.rb45
-rw-r--r--spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb13
-rw-r--r--spec/ruby/library/net/http/httpresponse/body_spec.rb7
-rw-r--r--spec/ruby/library/net/http/httpresponse/code_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/code_type_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/entity_spec.rb7
-rw-r--r--spec/ruby/library/net/http/httpresponse/error_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/error_type_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/exception_type_spec.rb13
-rw-r--r--spec/ruby/library/net/http/httpresponse/header_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/http_version_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpresponse/initialize_spec.rb11
-rw-r--r--spec/ruby/library/net/http/httpresponse/inspect_spec.rb15
-rw-r--r--spec/ruby/library/net/http/httpresponse/message_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/msg_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/read_body_spec.rb86
-rw-r--r--spec/ruby/library/net/http/httpresponse/read_header_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/read_new_spec.rb22
-rw-r--r--spec/ruby/library/net/http/httpresponse/reading_body_spec.rb58
-rw-r--r--spec/ruby/library/net/http/httpresponse/response_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/shared/body.rb18
-rw-r--r--spec/ruby/library/net/http/httpresponse/value_spec.rb24
-rw-r--r--spec/ruby/library/observer/add_observer_spec.rb23
-rw-r--r--spec/ruby/library/observer/count_observers_spec.rb23
-rw-r--r--spec/ruby/library/observer/delete_observer_spec.rb19
-rw-r--r--spec/ruby/library/observer/delete_observers_spec.rb19
-rw-r--r--spec/ruby/library/observer/fixtures/classes.rb17
-rw-r--r--spec/ruby/library/observer/notify_observers_spec.rb31
-rw-r--r--spec/ruby/library/open3/capture2_spec.rb6
-rw-r--r--spec/ruby/library/open3/capture2e_spec.rb6
-rw-r--r--spec/ruby/library/open3/capture3_spec.rb6
-rw-r--r--spec/ruby/library/open3/pipeline_r_spec.rb6
-rw-r--r--spec/ruby/library/open3/pipeline_rw_spec.rb6
-rw-r--r--spec/ruby/library/open3/pipeline_spec.rb6
-rw-r--r--spec/ruby/library/open3/pipeline_start_spec.rb6
-rw-r--r--spec/ruby/library/open3/pipeline_w_spec.rb6
-rw-r--r--spec/ruby/library/open3/popen2_spec.rb6
-rw-r--r--spec/ruby/library/open3/popen2e_spec.rb6
-rw-r--r--spec/ruby/library/open3/popen3_spec.rb43
-rw-r--r--spec/ruby/library/openssl/cipher_spec.rb9
-rw-r--r--spec/ruby/library/openssl/config/freeze_spec.rb16
-rw-r--r--spec/ruby/library/openssl/hmac/digest_spec.rb16
-rw-r--r--spec/ruby/library/openssl/hmac/hexdigest_spec.rb16
-rw-r--r--spec/ruby/library/openssl/random/pseudo_bytes_spec.rb8
-rw-r--r--spec/ruby/library/openssl/random/random_bytes_spec.rb6
-rw-r--r--spec/ruby/library/openssl/random/shared/random_bytes.rb29
-rw-r--r--spec/ruby/library/openssl/shared/constants.rb11
-rw-r--r--spec/ruby/library/openssl/x509/name/parse_spec.rb48
-rw-r--r--spec/ruby/library/openstruct/delete_field_spec.rb19
-rw-r--r--spec/ruby/library/openstruct/element_reference_spec.rb13
-rw-r--r--spec/ruby/library/openstruct/element_set_spec.rb13
-rw-r--r--spec/ruby/library/openstruct/equal_value_spec.rb28
-rw-r--r--spec/ruby/library/openstruct/fixtures/classes.rb4
-rw-r--r--spec/ruby/library/openstruct/frozen_spec.rb38
-rw-r--r--spec/ruby/library/openstruct/initialize_spec.rb8
-rw-r--r--spec/ruby/library/openstruct/inspect_spec.rb8
-rw-r--r--spec/ruby/library/openstruct/marshal_dump_spec.rb9
-rw-r--r--spec/ruby/library/openstruct/marshal_load_spec.rb12
-rw-r--r--spec/ruby/library/openstruct/method_missing_spec.rb47
-rw-r--r--spec/ruby/library/openstruct/new_spec.rb20
-rw-r--r--spec/ruby/library/openstruct/shared/inspect.rb20
-rw-r--r--spec/ruby/library/openstruct/to_h_spec.rb29
-rw-r--r--spec/ruby/library/openstruct/to_s_spec.rb8
-rw-r--r--spec/ruby/library/pathname/absolute_spec.rb23
-rw-r--r--spec/ruby/library/pathname/equal_value_spec.rb15
-rw-r--r--spec/ruby/library/pathname/hash_spec.rb15
-rw-r--r--spec/ruby/library/pathname/join_spec.rb40
-rw-r--r--spec/ruby/library/pathname/new_spec.rb28
-rw-r--r--spec/ruby/library/pathname/parent_spec.rb19
-rw-r--r--spec/ruby/library/pathname/realdirpath_spec.rb10
-rw-r--r--spec/ruby/library/pathname/realpath_spec.rb10
-rw-r--r--spec/ruby/library/pathname/relative_path_from_spec.rb51
-rw-r--r--spec/ruby/library/pathname/relative_spec.rb23
-rw-r--r--spec/ruby/library/pathname/root_spec.rb27
-rw-r--r--spec/ruby/library/pathname/sub_spec.rb16
-rw-r--r--spec/ruby/library/pp/pp_spec.rb25
-rw-r--r--spec/ruby/library/prime/each_spec.rb167
-rw-r--r--spec/ruby/library/prime/instance_spec.rb21
-rw-r--r--spec/ruby/library/prime/int_from_prime_division_spec.rb13
-rw-r--r--spec/ruby/library/prime/integer/each_prime_spec.rb13
-rw-r--r--spec/ruby/library/prime/integer/from_prime_division_spec.rb13
-rw-r--r--spec/ruby/library/prime/integer/prime_division_spec.rb19
-rw-r--r--spec/ruby/library/prime/integer/prime_spec.rb17
-rw-r--r--spec/ruby/library/prime/next_spec.rb7
-rw-r--r--spec/ruby/library/prime/prime_division_spec.rb25
-rw-r--r--spec/ruby/library/prime/prime_spec.rb17
-rw-r--r--spec/ruby/library/prime/shared/next.rb8
-rw-r--r--spec/ruby/library/prime/succ_spec.rb7
-rw-r--r--spec/ruby/library/readline/basic_quote_characters_spec.rb18
-rw-r--r--spec/ruby/library/readline/basic_word_break_characters_spec.rb16
-rw-r--r--spec/ruby/library/readline/completer_quote_characters_spec.rb16
-rw-r--r--spec/ruby/library/readline/completer_word_break_characters_spec.rb16
-rw-r--r--spec/ruby/library/readline/completion_append_character_spec.rb16
-rw-r--r--spec/ruby/library/readline/completion_case_fold_spec.rb18
-rw-r--r--spec/ruby/library/readline/completion_proc_spec.rb22
-rw-r--r--spec/ruby/library/readline/constants_spec.rb18
-rw-r--r--spec/ruby/library/readline/emacs_editing_mode_spec.rb11
-rw-r--r--spec/ruby/library/readline/filename_quote_characters_spec.rb18
-rw-r--r--spec/ruby/library/readline/history/append_spec.rb28
-rw-r--r--spec/ruby/library/readline/history/delete_at_spec.rb45
-rw-r--r--spec/ruby/library/readline/history/each_spec.rb29
-rw-r--r--spec/ruby/library/readline/history/element_reference_spec.rb40
-rw-r--r--spec/ruby/library/readline/history/element_set_spec.rb35
-rw-r--r--spec/ruby/library/readline/history/empty_spec.rb13
-rw-r--r--spec/ruby/library/readline/history/history_spec.rb9
-rw-r--r--spec/ruby/library/readline/history/length_spec.rb9
-rw-r--r--spec/ruby/library/readline/history/pop_spec.rb30
-rw-r--r--spec/ruby/library/readline/history/push_spec.rb26
-rw-r--r--spec/ruby/library/readline/history/shared/size.rb14
-rw-r--r--spec/ruby/library/readline/history/shift_spec.rb30
-rw-r--r--spec/ruby/library/readline/history/size_spec.rb9
-rw-r--r--spec/ruby/library/readline/history/to_s_spec.rb9
-rw-r--r--spec/ruby/library/readline/readline_spec.rb31
-rw-r--r--spec/ruby/library/readline/spec_helper.rb11
-rw-r--r--spec/ruby/library/readline/vi_editing_mode_spec.rb11
-rw-r--r--spec/ruby/library/resolv/get_address_spec.rb21
-rw-r--r--spec/ruby/library/resolv/get_addresses_spec.rb14
-rw-r--r--spec/ruby/library/resolv/get_name_spec.rb19
-rw-r--r--spec/ruby/library/resolv/get_names_spec.rb14
-rw-r--r--spec/ruby/library/rexml/attribute/clone_spec.rb11
-rw-r--r--spec/ruby/library/rexml/attribute/element_spec.rb23
-rw-r--r--spec/ruby/library/rexml/attribute/equal_value_spec.rb18
-rw-r--r--spec/ruby/library/rexml/attribute/hash_spec.rb13
-rw-r--r--spec/ruby/library/rexml/attribute/initialize_spec.rb29
-rw-r--r--spec/ruby/library/rexml/attribute/inspect_spec.rb20
-rw-r--r--spec/ruby/library/rexml/attribute/namespace_spec.rb24
-rw-r--r--spec/ruby/library/rexml/attribute/node_type_spec.rb10
-rw-r--r--spec/ruby/library/rexml/attribute/prefix_spec.rb18
-rw-r--r--spec/ruby/library/rexml/attribute/remove_spec.rb20
-rw-r--r--spec/ruby/library/rexml/attribute/to_s_spec.rb14
-rw-r--r--spec/ruby/library/rexml/attribute/to_string_spec.rb15
-rw-r--r--spec/ruby/library/rexml/attribute/value_spec.rb15
-rw-r--r--spec/ruby/library/rexml/attribute/write_spec.rb23
-rw-r--r--spec/ruby/library/rexml/attribute/xpath_spec.rb20
-rw-r--r--spec/ruby/library/rexml/attributes/add_spec.rb7
-rw-r--r--spec/ruby/library/rexml/attributes/append_spec.rb7
-rw-r--r--spec/ruby/library/rexml/attributes/delete_all_spec.rb31
-rw-r--r--spec/ruby/library/rexml/attributes/delete_spec.rb27
-rw-r--r--spec/ruby/library/rexml/attributes/each_attribute_spec.rb25
-rw-r--r--spec/ruby/library/rexml/attributes/each_spec.rb25
-rw-r--r--spec/ruby/library/rexml/attributes/element_reference_spec.rb19
-rw-r--r--spec/ruby/library/rexml/attributes/element_set_spec.rb26
-rw-r--r--spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb14
-rw-r--r--spec/ruby/library/rexml/attributes/get_attribute_spec.rb29
-rw-r--r--spec/ruby/library/rexml/attributes/initialize_spec.rb18
-rw-r--r--spec/ruby/library/rexml/attributes/length_spec.rb7
-rw-r--r--spec/ruby/library/rexml/attributes/namespaces_spec.rb6
-rw-r--r--spec/ruby/library/rexml/attributes/prefixes_spec.rb24
-rw-r--r--spec/ruby/library/rexml/attributes/shared/add.rb17
-rw-r--r--spec/ruby/library/rexml/attributes/shared/length.rb13
-rw-r--r--spec/ruby/library/rexml/attributes/size_spec.rb7
-rw-r--r--spec/ruby/library/rexml/attributes/to_a_spec.rb20
-rw-r--r--spec/ruby/library/rexml/cdata/clone_spec.rb10
-rw-r--r--spec/ruby/library/rexml/cdata/initialize_spec.rb24
-rw-r--r--spec/ruby/library/rexml/cdata/shared/to_s.rb11
-rw-r--r--spec/ruby/library/rexml/cdata/to_s_spec.rb7
-rw-r--r--spec/ruby/library/rexml/cdata/value_spec.rb7
-rw-r--r--spec/ruby/library/rexml/document/add_element_spec.rb31
-rw-r--r--spec/ruby/library/rexml/document/add_spec.rb57
-rw-r--r--spec/ruby/library/rexml/document/clone_spec.rb20
-rw-r--r--spec/ruby/library/rexml/document/doctype_spec.rb15
-rw-r--r--spec/ruby/library/rexml/document/encoding_spec.rb22
-rw-r--r--spec/ruby/library/rexml/document/expanded_name_spec.rb16
-rw-r--r--spec/ruby/library/rexml/document/new_spec.rb36
-rw-r--r--spec/ruby/library/rexml/document/node_type_spec.rb8
-rw-r--r--spec/ruby/library/rexml/document/root_spec.rb12
-rw-r--r--spec/ruby/library/rexml/document/stand_alone_spec.rb19
-rw-r--r--spec/ruby/library/rexml/document/version_spec.rb14
-rw-r--r--spec/ruby/library/rexml/document/write_spec.rb35
-rw-r--r--spec/ruby/library/rexml/document/xml_decl_spec.rb15
-rw-r--r--spec/ruby/library/rexml/element/add_attribute_spec.rb41
-rw-r--r--spec/ruby/library/rexml/element/add_attributes_spec.rb22
-rw-r--r--spec/ruby/library/rexml/element/add_element_spec.rb39
-rw-r--r--spec/ruby/library/rexml/element/add_namespace_spec.rb24
-rw-r--r--spec/ruby/library/rexml/element/add_text_spec.rb24
-rw-r--r--spec/ruby/library/rexml/element/attribute_spec.rb17
-rw-r--r--spec/ruby/library/rexml/element/attributes_spec.rb19
-rw-r--r--spec/ruby/library/rexml/element/cdatas_spec.rb24
-rw-r--r--spec/ruby/library/rexml/element/clone_spec.rb29
-rw-r--r--spec/ruby/library/rexml/element/comments_spec.rb20
-rw-r--r--spec/ruby/library/rexml/element/delete_attribute_spec.rb39
-rw-r--r--spec/ruby/library/rexml/element/delete_element_spec.rb49
-rw-r--r--spec/ruby/library/rexml/element/delete_namespace_spec.rb25
-rw-r--r--spec/ruby/library/rexml/element/document_spec.rb18
-rw-r--r--spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb35
-rw-r--r--spec/ruby/library/rexml/element/each_element_with_text_spec.rb31
-rw-r--r--spec/ruby/library/rexml/element/get_text_spec.rb18
-rw-r--r--spec/ruby/library/rexml/element/has_attributes_spec.rb17
-rw-r--r--spec/ruby/library/rexml/element/has_elements_spec.rb18
-rw-r--r--spec/ruby/library/rexml/element/has_text_spec.rb16
-rw-r--r--spec/ruby/library/rexml/element/inspect_spec.rb27
-rw-r--r--spec/ruby/library/rexml/element/instructions_spec.rb21
-rw-r--r--spec/ruby/library/rexml/element/namespace_spec.rb27
-rw-r--r--spec/ruby/library/rexml/element/namespaces_spec.rb32
-rw-r--r--spec/ruby/library/rexml/element/new_spec.rb35
-rw-r--r--spec/ruby/library/rexml/element/next_element_spec.rb19
-rw-r--r--spec/ruby/library/rexml/element/node_type_spec.rb8
-rw-r--r--spec/ruby/library/rexml/element/prefixes_spec.rb23
-rw-r--r--spec/ruby/library/rexml/element/previous_element_spec.rb20
-rw-r--r--spec/ruby/library/rexml/element/raw_spec.rb24
-rw-r--r--spec/ruby/library/rexml/element/root_spec.rb28
-rw-r--r--spec/ruby/library/rexml/element/text_spec.rb46
-rw-r--r--spec/ruby/library/rexml/element/texts_spec.rb16
-rw-r--r--spec/ruby/library/rexml/element/whitespace_spec.rb23
-rw-r--r--spec/ruby/library/rexml/node/each_recursive_spec.rb21
-rw-r--r--spec/ruby/library/rexml/node/find_first_recursive_spec.rb25
-rw-r--r--spec/ruby/library/rexml/node/index_in_parent_spec.rb15
-rw-r--r--spec/ruby/library/rexml/node/next_sibling_node_spec.rb21
-rw-r--r--spec/ruby/library/rexml/node/parent_spec.rb21
-rw-r--r--spec/ruby/library/rexml/node/previous_sibling_node_spec.rb21
-rw-r--r--spec/ruby/library/rexml/shared/each_element.rb36
-rw-r--r--spec/ruby/library/rexml/shared/elements_to_a.rb34
-rw-r--r--spec/ruby/library/rexml/text/append_spec.rb10
-rw-r--r--spec/ruby/library/rexml/text/clone_spec.rb10
-rw-r--r--spec/ruby/library/rexml/text/comparison_spec.rb25
-rw-r--r--spec/ruby/library/rexml/text/empty_spec.rb12
-rw-r--r--spec/ruby/library/rexml/text/indent_text_spec.rb24
-rw-r--r--spec/ruby/library/rexml/text/inspect_spec.rb8
-rw-r--r--spec/ruby/library/rexml/text/new_spec.rb49
-rw-r--r--spec/ruby/library/rexml/text/node_type_spec.rb8
-rw-r--r--spec/ruby/library/rexml/text/normalize_spec.rb8
-rw-r--r--spec/ruby/library/rexml/text/read_with_substitution_spec.rb13
-rw-r--r--spec/ruby/library/rexml/text/to_s_spec.rb18
-rw-r--r--spec/ruby/library/rexml/text/unnormalize_spec.rb8
-rw-r--r--spec/ruby/library/rexml/text/value_spec.rb37
-rw-r--r--spec/ruby/library/rexml/text/wrap_spec.rb21
-rw-r--r--spec/ruby/library/rexml/text/write_with_substitution_spec.rb33
-rw-r--r--spec/ruby/library/scanf/io/block_scanf_spec.rb7
-rw-r--r--spec/ruby/library/scanf/io/fixtures/date.txt4
-rw-r--r--spec/ruby/library/scanf/io/fixtures/helloworld.txt1
-rw-r--r--spec/ruby/library/scanf/io/scanf_spec.rb35
-rw-r--r--spec/ruby/library/scanf/io/shared/block_scanf.rb28
-rw-r--r--spec/ruby/library/scanf/string/block_scanf_spec.rb7
-rw-r--r--spec/ruby/library/scanf/string/scanf_spec.rb53
-rw-r--r--spec/ruby/library/scanf/string/shared/block_scanf.rb25
-rw-r--r--spec/ruby/library/securerandom/base64_spec.rb55
-rw-r--r--spec/ruby/library/securerandom/hex_spec.rb54
-rw-r--r--spec/ruby/library/securerandom/random_bytes_spec.rb50
-rw-r--r--spec/ruby/library/securerandom/random_number_spec.rb95
-rw-r--r--spec/ruby/library/set/add_spec.rb27
-rw-r--r--spec/ruby/library/set/append_spec.rb7
-rw-r--r--spec/ruby/library/set/case_equality_spec.rb9
-rw-r--r--spec/ruby/library/set/classify_spec.rb27
-rw-r--r--spec/ruby/library/set/clear_spec.rb17
-rw-r--r--spec/ruby/library/set/collect_spec.rb7
-rw-r--r--spec/ruby/library/set/constructor_spec.rb15
-rw-r--r--spec/ruby/library/set/delete_if_spec.rb38
-rw-r--r--spec/ruby/library/set/delete_spec.rb37
-rw-r--r--spec/ruby/library/set/difference_spec.rb7
-rw-r--r--spec/ruby/library/set/divide_spec.rb34
-rw-r--r--spec/ruby/library/set/each_spec.rb26
-rw-r--r--spec/ruby/library/set/empty_spec.rb10
-rw-r--r--spec/ruby/library/set/enumerable/to_set_spec.rb19
-rw-r--r--spec/ruby/library/set/eql_spec.rb15
-rw-r--r--spec/ruby/library/set/equal_value_spec.rb26
-rw-r--r--spec/ruby/library/set/exclusion_spec.rb18
-rw-r--r--spec/ruby/library/set/flatten_merge_spec.rb23
-rw-r--r--spec/ruby/library/set/flatten_spec.rb40
-rw-r--r--spec/ruby/library/set/hash_spec.rb13
-rw-r--r--spec/ruby/library/set/include_spec.rb7
-rw-r--r--spec/ruby/library/set/initialize_spec.rb24
-rw-r--r--spec/ruby/library/set/inspect_spec.rb18
-rw-r--r--spec/ruby/library/set/intersection_spec.rb11
-rw-r--r--spec/ruby/library/set/keep_if_spec.rb38
-rw-r--r--spec/ruby/library/set/length_spec.rb7
-rw-r--r--spec/ruby/library/set/map_spec.rb7
-rw-r--r--spec/ruby/library/set/member_spec.rb7
-rw-r--r--spec/ruby/library/set/merge_spec.rb19
-rw-r--r--spec/ruby/library/set/minus_spec.rb7
-rw-r--r--spec/ruby/library/set/plus_spec.rb7
-rw-r--r--spec/ruby/library/set/pretty_print_cycle_spec.rb10
-rw-r--r--spec/ruby/library/set/pretty_print_spec.rb17
-rw-r--r--spec/ruby/library/set/proper_subset_spec.rb34
-rw-r--r--spec/ruby/library/set/proper_superset_spec.rb34
-rw-r--r--spec/ruby/library/set/reject_spec.rb42
-rw-r--r--spec/ruby/library/set/replace_spec.rb17
-rw-r--r--spec/ruby/library/set/select_spec.rb42
-rw-r--r--spec/ruby/library/set/shared/add.rb14
-rw-r--r--spec/ruby/library/set/shared/collect.rb20
-rw-r--r--spec/ruby/library/set/shared/difference.rb15
-rw-r--r--spec/ruby/library/set/shared/include.rb7
-rw-r--r--spec/ruby/library/set/shared/intersection.rb15
-rw-r--r--spec/ruby/library/set/shared/length.rb6
-rw-r--r--spec/ruby/library/set/shared/union.rb15
-rw-r--r--spec/ruby/library/set/size_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/add_spec.rb33
-rw-r--r--spec/ruby/library/set/sortedset/append_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/case_equality_spec.rb9
-rw-r--r--spec/ruby/library/set/sortedset/classify_spec.rb27
-rw-r--r--spec/ruby/library/set/sortedset/clear_spec.rb17
-rw-r--r--spec/ruby/library/set/sortedset/collect_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/constructor_spec.rb15
-rw-r--r--spec/ruby/library/set/sortedset/delete_if_spec.rb38
-rw-r--r--spec/ruby/library/set/sortedset/delete_spec.rb37
-rw-r--r--spec/ruby/library/set/sortedset/difference_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/divide_spec.rb34
-rw-r--r--spec/ruby/library/set/sortedset/each_spec.rb26
-rw-r--r--spec/ruby/library/set/sortedset/empty_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/eql_spec.rb16
-rw-r--r--spec/ruby/library/set/sortedset/equal_value_spec.rb13
-rw-r--r--spec/ruby/library/set/sortedset/exclusion_spec.rb18
-rw-r--r--spec/ruby/library/set/sortedset/flatten_merge_spec.rb8
-rw-r--r--spec/ruby/library/set/sortedset/flatten_spec.rb44
-rw-r--r--spec/ruby/library/set/sortedset/hash_spec.rb13
-rw-r--r--spec/ruby/library/set/sortedset/include_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/initialize_spec.rb24
-rw-r--r--spec/ruby/library/set/sortedset/inspect_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/intersection_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/keep_if_spec.rb31
-rw-r--r--spec/ruby/library/set/sortedset/length_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/map_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/member_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/merge_spec.rb19
-rw-r--r--spec/ruby/library/set/sortedset/minus_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/plus_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/pretty_print_spec.rb17
-rw-r--r--spec/ruby/library/set/sortedset/proper_subset_spec.rb33
-rw-r--r--spec/ruby/library/set/sortedset/proper_superset_spec.rb33
-rw-r--r--spec/ruby/library/set/sortedset/reject_spec.rb42
-rw-r--r--spec/ruby/library/set/sortedset/replace_spec.rb17
-rw-r--r--spec/ruby/library/set/sortedset/select_spec.rb35
-rw-r--r--spec/ruby/library/set/sortedset/shared/add.rb14
-rw-r--r--spec/ruby/library/set/sortedset/shared/collect.rb20
-rw-r--r--spec/ruby/library/set/sortedset/shared/difference.rb15
-rw-r--r--spec/ruby/library/set/sortedset/shared/include.rb7
-rw-r--r--spec/ruby/library/set/sortedset/shared/intersection.rb15
-rw-r--r--spec/ruby/library/set/sortedset/shared/length.rb6
-rw-r--r--spec/ruby/library/set/sortedset/shared/union.rb15
-rw-r--r--spec/ruby/library/set/sortedset/size_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/subset_spec.rb33
-rw-r--r--spec/ruby/library/set/sortedset/subtract_spec.rb17
-rw-r--r--spec/ruby/library/set/sortedset/superset_spec.rb33
-rw-r--r--spec/ruby/library/set/sortedset/to_a_spec.rb8
-rw-r--r--spec/ruby/library/set/sortedset/union_spec.rb11
-rw-r--r--spec/ruby/library/set/subset_spec.rb34
-rw-r--r--spec/ruby/library/set/subtract_spec.rb17
-rw-r--r--spec/ruby/library/set/superset_spec.rb34
-rw-r--r--spec/ruby/library/set/to_a_spec.rb8
-rw-r--r--spec/ruby/library/set/union_spec.rb11
-rw-r--r--spec/ruby/library/shellwords/shellwords_spec.rb29
-rw-r--r--spec/ruby/library/singleton/allocate_spec.rb8
-rw-r--r--spec/ruby/library/singleton/clone_spec.rb8
-rw-r--r--spec/ruby/library/singleton/dump_spec.rb14
-rw-r--r--spec/ruby/library/singleton/dup_spec.rb8
-rw-r--r--spec/ruby/library/singleton/fixtures/classes.rb18
-rw-r--r--spec/ruby/library/singleton/instance_spec.rb30
-rw-r--r--spec/ruby/library/singleton/load_spec.rb21
-rw-r--r--spec/ruby/library/singleton/new_spec.rb8
-rw-r--r--spec/ruby/library/socket/addrinfo/afamily_spec.rb38
-rw-r--r--spec/ruby/library/socket/addrinfo/bind_spec.rb29
-rw-r--r--spec/ruby/library/socket/addrinfo/canonname_spec.rb19
-rw-r--r--spec/ruby/library/socket/addrinfo/initialize_spec.rb253
-rw-r--r--spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb25
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_address_spec.rb36
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_port_spec.rb36
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_spec.rb36
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb36
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb46
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb46
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb41
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_spec.rb36
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb46
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb46
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_spec.rb36
-rw-r--r--spec/ruby/library/socket/addrinfo/pfamily_spec.rb38
-rw-r--r--spec/ruby/library/socket/addrinfo/protocol_spec.rb38
-rw-r--r--spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb35
-rw-r--r--spec/ruby/library/socket/addrinfo/socktype_spec.rb38
-rw-r--r--spec/ruby/library/socket/addrinfo/tcp_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/to_s_spec.rb7
-rw-r--r--spec/ruby/library/socket/addrinfo/to_sockaddr_spec.rb7
-rw-r--r--spec/ruby/library/socket/addrinfo/udp_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/unix_path_spec.rb40
-rw-r--r--spec/ruby/library/socket/addrinfo/unix_spec.rb54
-rw-r--r--spec/ruby/library/socket/basicsocket/close_read_spec.rb43
-rw-r--r--spec/ruby/library/socket/basicsocket/close_write_spec.rb48
-rw-r--r--spec/ruby/library/socket/basicsocket/do_not_reverse_lookup_spec.rb39
-rw-r--r--spec/ruby/library/socket/basicsocket/for_fd_spec.rb21
-rw-r--r--spec/ruby/library/socket/basicsocket/getpeername_spec.rb26
-rw-r--r--spec/ruby/library/socket/basicsocket/getsockname_spec.rb28
-rw-r--r--spec/ruby/library/socket/basicsocket/getsockopt_spec.rb46
-rw-r--r--spec/ruby/library/socket/basicsocket/ioctl_spec.rb43
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb7
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_spec.rb96
-rw-r--r--spec/ruby/library/socket/basicsocket/send_spec.rb85
-rw-r--r--spec/ruby/library/socket/basicsocket/setsockopt_spec.rb213
-rw-r--r--spec/ruby/library/socket/basicsocket/shutdown_spec.rb6
-rw-r--r--spec/ruby/library/socket/constants/constants_spec.rb90
-rw-r--r--spec/ruby/library/socket/fixtures/classes.rb93
-rw-r--r--spec/ruby/library/socket/fixtures/send_io.txt1
-rw-r--r--spec/ruby/library/socket/ipsocket/addr_spec.rb42
-rw-r--r--spec/ruby/library/socket/ipsocket/getaddress_spec.rb27
-rw-r--r--spec/ruby/library/socket/ipsocket/peeraddr_spec.rb49
-rw-r--r--spec/ruby/library/socket/ipsocket/recvfrom_spec.rb72
-rw-r--r--spec/ruby/library/socket/option/bool_spec.rb25
-rw-r--r--spec/ruby/library/socket/option/inspect_spec.rb20
-rw-r--r--spec/ruby/library/socket/option/int_spec.rb28
-rw-r--r--spec/ruby/library/socket/option/linger_spec.rb62
-rw-r--r--spec/ruby/library/socket/option/new_spec.rb35
-rw-r--r--spec/ruby/library/socket/shared/pack_sockaddr.rb50
-rw-r--r--spec/ruby/library/socket/shared/partially_closable_sockets.rb13
-rw-r--r--spec/ruby/library/socket/shared/recv_nonblock.rb54
-rw-r--r--spec/ruby/library/socket/shared/socketpair.rb23
-rw-r--r--spec/ruby/library/socket/socket/accept_nonblock_spec.rb37
-rw-r--r--spec/ruby/library/socket/socket/accept_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/bind_spec.rb81
-rw-r--r--spec/ruby/library/socket/socket/connect_nonblock_spec.rb73
-rw-r--r--spec/ruby/library/socket/socket/connect_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/for_fd_spec.rb31
-rw-r--r--spec/ruby/library/socket/socket/getaddrinfo_spec.rb112
-rw-r--r--spec/ruby/library/socket/socket/gethostbyaddr_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/gethostbyname_spec.rb17
-rw-r--r--spec/ruby/library/socket/socket/gethostname_spec.rb8
-rw-r--r--spec/ruby/library/socket/socket/getnameinfo_spec.rb66
-rw-r--r--spec/ruby/library/socket/socket/getservbyname_spec.rb24
-rw-r--r--spec/ruby/library/socket/socket/listen_spec.rb22
-rw-r--r--spec/ruby/library/socket/socket/new_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/pack_sockaddr_in_spec.rb7
-rw-r--r--spec/ruby/library/socket/socket/pack_sockaddr_un_spec.rb7
-rw-r--r--spec/ruby/library/socket/socket/pair_spec.rb7
-rw-r--r--spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/recvfrom_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/sockaddr_in_spec.rb7
-rw-r--r--spec/ruby/library/socket/socket/sockaddr_un_spec.rb7
-rw-r--r--spec/ruby/library/socket/socket/socket_spec.rb38
-rw-r--r--spec/ruby/library/socket/socket/socketpair_spec.rb7
-rw-r--r--spec/ruby/library/socket/socket/sysaccept_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb29
-rw-r--r--spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb26
-rw-r--r--spec/ruby/library/socket/tcpserver/accept_nonblock_spec.rb50
-rw-r--r--spec/ruby/library/socket/tcpserver/accept_spec.rb65
-rw-r--r--spec/ruby/library/socket/tcpserver/gets_spec.rb16
-rw-r--r--spec/ruby/library/socket/tcpserver/listen_spec.rb18
-rw-r--r--spec/ruby/library/socket/tcpserver/new_spec.rb96
-rw-r--r--spec/ruby/library/socket/tcpserver/sysaccept_spec.rb32
-rw-r--r--spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb51
-rw-r--r--spec/ruby/library/socket/tcpsocket/new_spec.rb5
-rw-r--r--spec/ruby/library/socket/tcpsocket/open_spec.rb5
-rw-r--r--spec/ruby/library/socket/tcpsocket/partially_closable_spec.rb21
-rw-r--r--spec/ruby/library/socket/tcpsocket/recv_nonblock_spec.rb36
-rw-r--r--spec/ruby/library/socket/tcpsocket/setsockopt_spec.rb45
-rw-r--r--spec/ruby/library/socket/tcpsocket/shared/new.rb79
-rw-r--r--spec/ruby/library/socket/udpsocket/bind_spec.rb42
-rw-r--r--spec/ruby/library/socket/udpsocket/new_spec.rb32
-rw-r--r--spec/ruby/library/socket/udpsocket/open_spec.rb13
-rw-r--r--spec/ruby/library/socket/udpsocket/send_spec.rb78
-rw-r--r--spec/ruby/library/socket/udpsocket/write_spec.rb21
-rw-r--r--spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb38
-rw-r--r--spec/ruby/library/socket/unixserver/accept_spec.rb61
-rw-r--r--spec/ruby/library/socket/unixserver/for_fd_spec.rb23
-rw-r--r--spec/ruby/library/socket/unixserver/new_spec.rb6
-rw-r--r--spec/ruby/library/socket/unixserver/open_spec.rb25
-rw-r--r--spec/ruby/library/socket/unixserver/shared/new.rb23
-rw-r--r--spec/ruby/library/socket/unixsocket/addr_spec.rb36
-rw-r--r--spec/ruby/library/socket/unixsocket/inspect_spec.rb17
-rw-r--r--spec/ruby/library/socket/unixsocket/new_spec.rb6
-rw-r--r--spec/ruby/library/socket/unixsocket/open_spec.rb27
-rw-r--r--spec/ruby/library/socket/unixsocket/pair_spec.rb39
-rw-r--r--spec/ruby/library/socket/unixsocket/partially_closable_spec.rb25
-rw-r--r--spec/ruby/library/socket/unixsocket/path_spec.rb28
-rw-r--r--spec/ruby/library/socket/unixsocket/peeraddr_spec.rb28
-rw-r--r--spec/ruby/library/socket/unixsocket/recv_io_spec.rb44
-rw-r--r--spec/ruby/library/socket/unixsocket/recvfrom_spec.rb47
-rw-r--r--spec/ruby/library/socket/unixsocket/send_io_spec.rb35
-rw-r--r--spec/ruby/library/socket/unixsocket/shared/new.rb24
-rw-r--r--spec/ruby/library/stringio/append_spec.rb84
-rw-r--r--spec/ruby/library/stringio/binmode_spec.rb9
-rw-r--r--spec/ruby/library/stringio/bytes_spec.rb11
-rw-r--r--spec/ruby/library/stringio/chars_spec.rb11
-rw-r--r--spec/ruby/library/stringio/close_read_spec.rb36
-rw-r--r--spec/ruby/library/stringio/close_spec.rb32
-rw-r--r--spec/ruby/library/stringio/close_write_spec.rb36
-rw-r--r--spec/ruby/library/stringio/closed_read_spec.rb12
-rw-r--r--spec/ruby/library/stringio/closed_spec.rb16
-rw-r--r--spec/ruby/library/stringio/closed_write_spec.rb12
-rw-r--r--spec/ruby/library/stringio/codepoints_spec.rb9
-rw-r--r--spec/ruby/library/stringio/each_byte_spec.rb11
-rw-r--r--spec/ruby/library/stringio/each_char_spec.rb11
-rw-r--r--spec/ruby/library/stringio/each_codepoint_spec.rb10
-rw-r--r--spec/ruby/library/stringio/each_line_spec.rb15
-rw-r--r--spec/ruby/library/stringio/each_spec.rb15
-rw-r--r--spec/ruby/library/stringio/eof_spec.rb11
-rw-r--r--spec/ruby/library/stringio/external_encoding_spec.rb21
-rw-r--r--spec/ruby/library/stringio/fcntl_spec.rb8
-rw-r--r--spec/ruby/library/stringio/fileno_spec.rb9
-rw-r--r--spec/ruby/library/stringio/fixtures/classes.rb15
-rw-r--r--spec/ruby/library/stringio/flush_spec.rb9
-rw-r--r--spec/ruby/library/stringio/fsync_spec.rb9
-rw-r--r--spec/ruby/library/stringio/getbyte_spec.rb19
-rw-r--r--spec/ruby/library/stringio/getc_spec.rb19
-rw-r--r--spec/ruby/library/stringio/getch_spec.rb46
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb238
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb185
-rw-r--r--spec/ruby/library/stringio/internal_encoding_spec.rb10
-rw-r--r--spec/ruby/library/stringio/isatty_spec.rb7
-rw-r--r--spec/ruby/library/stringio/length_spec.rb7
-rw-r--r--spec/ruby/library/stringio/lineno_spec.rb30
-rw-r--r--spec/ruby/library/stringio/lines_spec.rb15
-rw-r--r--spec/ruby/library/stringio/open_spec.rb208
-rw-r--r--spec/ruby/library/stringio/path_spec.rb8
-rw-r--r--spec/ruby/library/stringio/pid_spec.rb8
-rw-r--r--spec/ruby/library/stringio/pos_spec.rb28
-rw-r--r--spec/ruby/library/stringio/print_spec.rb100
-rw-r--r--spec/ruby/library/stringio/printf_spec.rb61
-rw-r--r--spec/ruby/library/stringio/putc_spec.rb88
-rw-r--r--spec/ruby/library/stringio/puts_spec.rb159
-rw-r--r--spec/ruby/library/stringio/read_nonblock_spec.rb20
-rw-r--r--spec/ruby/library/stringio/read_spec.rb62
-rw-r--r--spec/ruby/library/stringio/readbyte_spec.rb20
-rw-r--r--spec/ruby/library/stringio/readchar_spec.rb20
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb122
-rw-r--r--spec/ruby/library/stringio/readlines_spec.rb92
-rw-r--r--spec/ruby/library/stringio/readpartial_spec.rb80
-rw-r--r--spec/ruby/library/stringio/reopen_spec.rb288
-rw-r--r--spec/ruby/library/stringio/rewind_spec.rb24
-rw-r--r--spec/ruby/library/stringio/seek_spec.rb67
-rw-r--r--spec/ruby/library/stringio/set_encoding_spec.rb10
-rw-r--r--spec/ruby/library/stringio/shared/codepoints.rb45
-rw-r--r--spec/ruby/library/stringio/shared/each.rb105
-rw-r--r--spec/ruby/library/stringio/shared/each_byte.rb48
-rw-r--r--spec/ruby/library/stringio/shared/each_char.rb36
-rw-r--r--spec/ruby/library/stringio/shared/eof.rb24
-rw-r--r--spec/ruby/library/stringio/shared/getc.rb43
-rw-r--r--spec/ruby/library/stringio/shared/isatty.rb5
-rw-r--r--spec/ruby/library/stringio/shared/length.rb5
-rw-r--r--spec/ruby/library/stringio/shared/read.rb121
-rw-r--r--spec/ruby/library/stringio/shared/readchar.rb29
-rw-r--r--spec/ruby/library/stringio/shared/sysread.rb15
-rw-r--r--spec/ruby/library/stringio/shared/tell.rb12
-rw-r--r--spec/ruby/library/stringio/shared/write.rb87
-rw-r--r--spec/ruby/library/stringio/size_spec.rb7
-rw-r--r--spec/ruby/library/stringio/string_spec.rb50
-rw-r--r--spec/ruby/library/stringio/stringio_spec.rb9
-rw-r--r--spec/ruby/library/stringio/sync_spec.rb19
-rw-r--r--spec/ruby/library/stringio/sysread_spec.rb48
-rw-r--r--spec/ruby/library/stringio/syswrite_spec.rb19
-rw-r--r--spec/ruby/library/stringio/tell_spec.rb7
-rw-r--r--spec/ruby/library/stringio/truncate_spec.rb70
-rw-r--r--spec/ruby/library/stringio/tty_spec.rb7
-rw-r--r--spec/ruby/library/stringio/ungetbyte_spec.rb6
-rw-r--r--spec/ruby/library/stringio/ungetc_spec.rb72
-rw-r--r--spec/ruby/library/stringio/write_nonblock_spec.rb19
-rw-r--r--spec/ruby/library/stringio/write_spec.rb19
-rw-r--r--spec/ruby/library/stringscanner/append_spec.rb11
-rw-r--r--spec/ruby/library/stringscanner/beginning_of_line_spec.rb7
-rw-r--r--spec/ruby/library/stringscanner/bol_spec.rb7
-rw-r--r--spec/ruby/library/stringscanner/check_spec.rb16
-rw-r--r--spec/ruby/library/stringscanner/check_until_spec.rb15
-rw-r--r--spec/ruby/library/stringscanner/clear_spec.rb20
-rw-r--r--spec/ruby/library/stringscanner/concat_spec.rb11
-rw-r--r--spec/ruby/library/stringscanner/dup_spec.rb39
-rw-r--r--spec/ruby/library/stringscanner/element_reference_spec.rb61
-rw-r--r--spec/ruby/library/stringscanner/empty_spec.rb20
-rw-r--r--spec/ruby/library/stringscanner/eos_spec.rb7
-rw-r--r--spec/ruby/library/stringscanner/exist_spec.rb24
-rw-r--r--spec/ruby/library/stringscanner/get_byte_spec.rb7
-rw-r--r--spec/ruby/library/stringscanner/getbyte_spec.rb23
-rw-r--r--spec/ruby/library/stringscanner/getch_spec.rb35
-rw-r--r--spec/ruby/library/stringscanner/initialize_spec.rb28
-rw-r--r--spec/ruby/library/stringscanner/inspect_spec.rb20
-rw-r--r--spec/ruby/library/stringscanner/match_spec.rb28
-rw-r--r--spec/ruby/library/stringscanner/matched_size_spec.rb7
-rw-r--r--spec/ruby/library/stringscanner/matched_spec.rb41
-rw-r--r--spec/ruby/library/stringscanner/must_C_version_spec.rb8
-rw-r--r--spec/ruby/library/stringscanner/peek_spec.rb8
-rw-r--r--spec/ruby/library/stringscanner/peep_spec.rb20
-rw-r--r--spec/ruby/library/stringscanner/pointer_spec.rb11
-rw-r--r--spec/ruby/library/stringscanner/pos_spec.rb11
-rw-r--r--spec/ruby/library/stringscanner/post_match_spec.rb28
-rw-r--r--spec/ruby/library/stringscanner/pre_match_spec.rb41
-rw-r--r--spec/ruby/library/stringscanner/reset_spec.rb15
-rw-r--r--spec/ruby/library/stringscanner/rest_size_spec.rb7
-rw-r--r--spec/ruby/library/stringscanner/rest_spec.rb48
-rw-r--r--spec/ruby/library/stringscanner/restsize_spec.rb20
-rw-r--r--spec/ruby/library/stringscanner/scan_full_spec.rb30
-rw-r--r--spec/ruby/library/stringscanner/scan_spec.rb43
-rw-r--r--spec/ruby/library/stringscanner/scan_until_spec.rb23
-rw-r--r--spec/ruby/library/stringscanner/search_full_spec.rb30
-rw-r--r--spec/ruby/library/stringscanner/shared/bol.rb25
-rw-r--r--spec/ruby/library/stringscanner/shared/concat.rb30
-rw-r--r--spec/ruby/library/stringscanner/shared/eos.rb17
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range.rb22
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range_matched.rb22
-rw-r--r--spec/ruby/library/stringscanner/shared/get_byte.rb29
-rw-r--r--spec/ruby/library/stringscanner/shared/matched_size.rb21
-rw-r--r--spec/ruby/library/stringscanner/shared/peek.rb47
-rw-r--r--spec/ruby/library/stringscanner/shared/pos.rb52
-rw-r--r--spec/ruby/library/stringscanner/shared/rest_size.rb18
-rw-r--r--spec/ruby/library/stringscanner/shared/terminate.rb8
-rw-r--r--spec/ruby/library/stringscanner/skip_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/skip_until_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/string_spec.rb40
-rw-r--r--spec/ruby/library/stringscanner/terminate_spec.rb7
-rw-r--r--spec/ruby/library/stringscanner/unscan_spec.rb28
-rw-r--r--spec/ruby/library/syslog/alert_spec.rb9
-rw-r--r--spec/ruby/library/syslog/close_spec.rb57
-rw-r--r--spec/ruby/library/syslog/constants_spec.rb40
-rw-r--r--spec/ruby/library/syslog/crit_spec.rb9
-rw-r--r--spec/ruby/library/syslog/debug_spec.rb9
-rw-r--r--spec/ruby/library/syslog/emerg_spec.rb15
-rw-r--r--spec/ruby/library/syslog/err_spec.rb9
-rw-r--r--spec/ruby/library/syslog/facility_spec.rb47
-rw-r--r--spec/ruby/library/syslog/ident_spec.rb34
-rw-r--r--spec/ruby/library/syslog/info_spec.rb9
-rw-r--r--spec/ruby/library/syslog/inspect_spec.rb38
-rw-r--r--spec/ruby/library/syslog/instance_spec.rb12
-rw-r--r--spec/ruby/library/syslog/log_spec.rb55
-rw-r--r--spec/ruby/library/syslog/mask_spec.rb112
-rw-r--r--spec/ruby/library/syslog/notice_spec.rb9
-rw-r--r--spec/ruby/library/syslog/open_spec.rb86
-rw-r--r--spec/ruby/library/syslog/opened_spec.rb38
-rw-r--r--spec/ruby/library/syslog/options_spec.rb47
-rw-r--r--spec/ruby/library/syslog/reopen_spec.rb9
-rw-r--r--spec/ruby/library/syslog/shared/log.rb40
-rw-r--r--spec/ruby/library/syslog/shared/reopen.rb40
-rw-r--r--spec/ruby/library/syslog/warning_spec.rb9
-rw-r--r--spec/ruby/library/tempfile/_close_spec.rb21
-rw-r--r--spec/ruby/library/tempfile/callback_spec.rb6
-rw-r--r--spec/ruby/library/tempfile/close_spec.rb57
-rw-r--r--spec/ruby/library/tempfile/delete_spec.rb7
-rw-r--r--spec/ruby/library/tempfile/initialize_spec.rb41
-rw-r--r--spec/ruby/library/tempfile/length_spec.rb7
-rw-r--r--spec/ruby/library/tempfile/open_spec.rb82
-rw-r--r--spec/ruby/library/tempfile/path_spec.rb26
-rw-r--r--spec/ruby/library/tempfile/shared/length.rb21
-rw-r--r--spec/ruby/library/tempfile/shared/unlink.rb12
-rw-r--r--spec/ruby/library/tempfile/size_spec.rb7
-rw-r--r--spec/ruby/library/tempfile/unlink_spec.rb7
-rw-r--r--spec/ruby/library/thread/exclusive_spec.rb12
-rw-r--r--spec/ruby/library/thread/queue/append_spec.rb7
-rw-r--r--spec/ruby/library/thread/queue/clear_spec.rb9
-rw-r--r--spec/ruby/library/thread/queue/close_spec.rb9
-rw-r--r--spec/ruby/library/thread/queue/closed_spec.rb9
-rw-r--r--spec/ruby/library/thread/queue/deq_spec.rb7
-rw-r--r--spec/ruby/library/thread/queue/empty_spec.rb7
-rw-r--r--spec/ruby/library/thread/queue/enq_spec.rb7
-rw-r--r--spec/ruby/library/thread/queue/length_spec.rb7
-rw-r--r--spec/ruby/library/thread/queue/num_waiting_spec.rb7
-rw-r--r--spec/ruby/library/thread/queue/pop_spec.rb7
-rw-r--r--spec/ruby/library/thread/queue/push_spec.rb7
-rw-r--r--spec/ruby/library/thread/queue/shift_spec.rb7
-rw-r--r--spec/ruby/library/thread/queue/size_spec.rb7
-rw-r--r--spec/ruby/library/thread/shared/queue/clear.rb10
-rw-r--r--spec/ruby/library/thread/shared/queue/close.rb26
-rw-r--r--spec/ruby/library/thread/shared/queue/closed.rb12
-rw-r--r--spec/ruby/library/thread/shared/queue/deque.rb37
-rw-r--r--spec/ruby/library/thread/shared/queue/empty.rb12
-rw-r--r--spec/ruby/library/thread/shared/queue/enque.rb10
-rw-r--r--spec/ruby/library/thread/shared/queue/length.rb9
-rw-r--r--spec/ruby/library/thread/shared/queue/num_waiting.rb16
-rw-r--r--spec/ruby/library/thread/sizedqueue/append_spec.rb12
-rw-r--r--spec/ruby/library/thread/sizedqueue/clear_spec.rb9
-rw-r--r--spec/ruby/library/thread/sizedqueue/close_spec.rb9
-rw-r--r--spec/ruby/library/thread/sizedqueue/closed_spec.rb9
-rw-r--r--spec/ruby/library/thread/sizedqueue/deq_spec.rb7
-rw-r--r--spec/ruby/library/thread/sizedqueue/empty_spec.rb7
-rw-r--r--spec/ruby/library/thread/sizedqueue/enq_spec.rb12
-rw-r--r--spec/ruby/library/thread/sizedqueue/length_spec.rb7
-rw-r--r--spec/ruby/library/thread/sizedqueue/max_spec.rb52
-rw-r--r--spec/ruby/library/thread/sizedqueue/new_spec.rb25
-rw-r--r--spec/ruby/library/thread/sizedqueue/num_waiting_spec.rb18
-rw-r--r--spec/ruby/library/thread/sizedqueue/pop_spec.rb7
-rw-r--r--spec/ruby/library/thread/sizedqueue/push_spec.rb12
-rw-r--r--spec/ruby/library/thread/sizedqueue/shared/enque.rb34
-rw-r--r--spec/ruby/library/thread/sizedqueue/shift_spec.rb7
-rw-r--r--spec/ruby/library/thread/sizedqueue/size_spec.rb7
-rw-r--r--spec/ruby/library/time/httpdate_spec.rb21
-rw-r--r--spec/ruby/library/time/iso8601_spec.rb7
-rw-r--r--spec/ruby/library/time/rfc2822_spec.rb7
-rw-r--r--spec/ruby/library/time/rfc822_spec.rb7
-rw-r--r--spec/ruby/library/time/shared/rfc2822.rb65
-rw-r--r--spec/ruby/library/time/shared/xmlschema.rb53
-rw-r--r--spec/ruby/library/time/to_date_spec.rb42
-rw-r--r--spec/ruby/library/time/xmlschema_spec.rb7
-rw-r--r--spec/ruby/library/timeout/error_spec.rb8
-rw-r--r--spec/ruby/library/timeout/timeout_spec.rb37
-rw-r--r--spec/ruby/library/tmpdir/dir/mktmpdir_spec.rb117
-rw-r--r--spec/ruby/library/tmpdir/dir/tmpdir_spec.rb10
-rw-r--r--spec/ruby/library/uri/decode_www_form_component_spec.rb6
-rw-r--r--spec/ruby/library/uri/decode_www_form_spec.rb6
-rw-r--r--spec/ruby/library/uri/encode_www_form_component_spec.rb6
-rw-r--r--spec/ruby/library/uri/encode_www_form_spec.rb6
-rw-r--r--spec/ruby/library/uri/eql_spec.rb10
-rw-r--r--spec/ruby/library/uri/equality_spec.rb46
-rw-r--r--spec/ruby/library/uri/escape/decode_spec.rb6
-rw-r--r--spec/ruby/library/uri/escape/encode_spec.rb6
-rw-r--r--spec/ruby/library/uri/escape/escape_spec.rb6
-rw-r--r--spec/ruby/library/uri/escape/unescape_spec.rb6
-rw-r--r--spec/ruby/library/uri/extract_spec.rb86
-rw-r--r--spec/ruby/library/uri/fixtures/classes.rb11
-rw-r--r--spec/ruby/library/uri/fixtures/normalization.rb54
-rw-r--r--spec/ruby/library/uri/ftp/build_spec.rb6
-rw-r--r--spec/ruby/library/uri/ftp/merge_spec.rb6
-rw-r--r--spec/ruby/library/uri/ftp/new2_spec.rb6
-rw-r--r--spec/ruby/library/uri/ftp/path_spec.rb26
-rw-r--r--spec/ruby/library/uri/ftp/set_typecode_spec.rb6
-rw-r--r--spec/ruby/library/uri/ftp/to_s_spec.rb15
-rw-r--r--spec/ruby/library/uri/ftp/typecode_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/absolute_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/build2_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/build_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/coerce_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/component_ary_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/component_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/default_port_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/eql_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/equal_value_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/fragment_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/hash_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/hierarchical_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/host_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/inspect_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/merge_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/minus_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/normalize_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/opaque_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/password_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/path_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/plus_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/port_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/query_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/registry_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/relative_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/route_from_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/route_to_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/scheme_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/select_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_fragment_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_host_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_opaque_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_password_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_path_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_port_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_query_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_registry_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_scheme_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_user_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/set_userinfo_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/to_s_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/use_registry_spec.rb6
-rw-r--r--spec/ruby/library/uri/generic/user_spec.rb10
-rw-r--r--spec/ruby/library/uri/generic/userinfo_spec.rb10
-rw-r--r--spec/ruby/library/uri/http/build_spec.rb6
-rw-r--r--spec/ruby/library/uri/http/request_uri_spec.rb16
-rw-r--r--spec/ruby/library/uri/join_spec.rb57
-rw-r--r--spec/ruby/library/uri/ldap/attributes_spec.rb10
-rw-r--r--spec/ruby/library/uri/ldap/build_spec.rb6
-rw-r--r--spec/ruby/library/uri/ldap/dn_spec.rb10
-rw-r--r--spec/ruby/library/uri/ldap/extensions_spec.rb10
-rw-r--r--spec/ruby/library/uri/ldap/filter_spec.rb10
-rw-r--r--spec/ruby/library/uri/ldap/hierarchical_spec.rb6
-rw-r--r--spec/ruby/library/uri/ldap/scope_spec.rb10
-rw-r--r--spec/ruby/library/uri/ldap/set_attributes_spec.rb6
-rw-r--r--spec/ruby/library/uri/ldap/set_dn_spec.rb6
-rw-r--r--spec/ruby/library/uri/ldap/set_extensions_spec.rb6
-rw-r--r--spec/ruby/library/uri/ldap/set_filter_spec.rb6
-rw-r--r--spec/ruby/library/uri/ldap/set_scope_spec.rb6
-rw-r--r--spec/ruby/library/uri/mailto/build_spec.rb98
-rw-r--r--spec/ruby/library/uri/mailto/headers_spec.rb10
-rw-r--r--spec/ruby/library/uri/mailto/set_headers_spec.rb6
-rw-r--r--spec/ruby/library/uri/mailto/set_to_spec.rb6
-rw-r--r--spec/ruby/library/uri/mailto/to_mailtext_spec.rb6
-rw-r--r--spec/ruby/library/uri/mailto/to_rfc822text_spec.rb6
-rw-r--r--spec/ruby/library/uri/mailto/to_s_spec.rb6
-rw-r--r--spec/ruby/library/uri/mailto/to_spec.rb10
-rw-r--r--spec/ruby/library/uri/merge_spec.rb20
-rw-r--r--spec/ruby/library/uri/normalize_spec.rb35
-rw-r--r--spec/ruby/library/uri/parse_spec.rb203
-rw-r--r--spec/ruby/library/uri/parser/escape_spec.rb6
-rw-r--r--spec/ruby/library/uri/parser/extract_spec.rb7
-rw-r--r--spec/ruby/library/uri/parser/inspect_spec.rb6
-rw-r--r--spec/ruby/library/uri/parser/join_spec.rb7
-rw-r--r--spec/ruby/library/uri/parser/make_regexp_spec.rb6
-rw-r--r--spec/ruby/library/uri/parser/parse_spec.rb7
-rw-r--r--spec/ruby/library/uri/parser/split_spec.rb6
-rw-r--r--spec/ruby/library/uri/parser/unescape_spec.rb6
-rw-r--r--spec/ruby/library/uri/plus_spec.rb459
-rw-r--r--spec/ruby/library/uri/regexp_spec.rb18
-rw-r--r--spec/ruby/library/uri/route_from_spec.rb23
-rw-r--r--spec/ruby/library/uri/route_to_spec.rb26
-rw-r--r--spec/ruby/library/uri/select_spec.rb31
-rw-r--r--spec/ruby/library/uri/set_component_spec.rb47
-rw-r--r--spec/ruby/library/uri/shared/eql.rb17
-rw-r--r--spec/ruby/library/uri/shared/extract.rb83
-rw-r--r--spec/ruby/library/uri/shared/join.rb54
-rw-r--r--spec/ruby/library/uri/shared/parse.rb199
-rw-r--r--spec/ruby/library/uri/split_spec.rb6
-rw-r--r--spec/ruby/library/uri/uri_spec.rb29
-rw-r--r--spec/ruby/library/uri/util/make_components_hash_spec.rb6
-rw-r--r--spec/ruby/library/weakref/__getobj___spec.rb17
-rw-r--r--spec/ruby/library/weakref/fixtures/classes.rb24
-rw-r--r--spec/ruby/library/weakref/send_spec.rb37
-rw-r--r--spec/ruby/library/weakref/weakref_alive_spec.rb15
-rw-r--r--spec/ruby/library/win32ole/fixtures/classes.rb14
-rw-r--r--spec/ruby/library/win32ole/win32ole/_getproperty_spec.rb19
-rw-r--r--spec/ruby/library/win32ole/win32ole/_invoke_spec.rb23
-rw-r--r--spec/ruby/library/win32ole/win32ole/codepage_spec.rb15
-rw-r--r--spec/ruby/library/win32ole/win32ole/connect_spec.rb17
-rw-r--r--spec/ruby/library/win32ole/win32ole/const_load_spec.rb34
-rw-r--r--spec/ruby/library/win32ole/win32ole/constants_spec.rb44
-rw-r--r--spec/ruby/library/win32ole/win32ole/create_guid_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole/invoke_spec.rb19
-rw-r--r--spec/ruby/library/win32ole/win32ole/locale_spec.rb31
-rw-r--r--spec/ruby/library/win32ole/win32ole/new_spec.rb27
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb27
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_method_help_spec.rb12
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_method_spec.rb12
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb27
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb23
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb27
-rw-r--r--spec/ruby/library/win32ole/win32ole/setproperty_spec.rb12
-rw-r--r--spec/ruby/library/win32ole/win32ole/shared/ole_method.rb25
-rw-r--r--spec/ruby/library/win32ole/win32ole/shared/setproperty.rb25
-rw-r--r--spec/ruby/library/win32ole/win32ole_event/new_spec.rb33
-rw-r--r--spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb62
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb26
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/event_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb26
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/name_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/new_spec.rb33
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/params_spec.rb28
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/shared/name.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/visible_spec.rb20
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/default_spec.rb31
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/input_spec.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/name_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/optional_spec.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/retval_spec.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/shared/name.rb21
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/guid_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/name_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/new_spec.rb37
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/progid_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/progids_spec.rb14
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/shared/name.rb19
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb22
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/variables_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/visible_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/name_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb19
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/shared/name.rb18
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/to_s_spec.rb11
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/value_spec.rb19
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb19
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb19
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb18
-rw-r--r--spec/ruby/library/yaml/add_builtin_type_spec.rb2
-rw-r--r--spec/ruby/library/yaml/add_domain_type_spec.rb2
-rw-r--r--spec/ruby/library/yaml/add_private_type_spec.rb2
-rw-r--r--spec/ruby/library/yaml/add_ruby_type_spec.rb2
-rw-r--r--spec/ruby/library/yaml/detect_implicit_spec.rb2
-rw-r--r--spec/ruby/library/yaml/dump_spec.rb51
-rw-r--r--spec/ruby/library/yaml/dump_stream_spec.rb8
-rw-r--r--spec/ruby/library/yaml/each_node_spec.rb2
-rw-r--r--spec/ruby/library/yaml/emitter_spec.rb2
-rw-r--r--spec/ruby/library/yaml/fixtures/common.rb10
-rw-r--r--spec/ruby/library/yaml/fixtures/example_class.rb5
-rw-r--r--spec/ruby/library/yaml/fixtures/strings.rb36
-rw-r--r--spec/ruby/library/yaml/fixtures/test_yaml.yml2
-rw-r--r--spec/ruby/library/yaml/generic_parser_spec.rb2
-rw-r--r--spec/ruby/library/yaml/load_documents_spec.rb10
-rw-r--r--spec/ruby/library/yaml/load_file_spec.rb13
-rw-r--r--spec/ruby/library/yaml/load_spec.rb116
-rw-r--r--spec/ruby/library/yaml/load_stream_spec.rb8
-rw-r--r--spec/ruby/library/yaml/object_maker_spec.rb2
-rw-r--r--spec/ruby/library/yaml/parse_documents_spec.rb2
-rw-r--r--spec/ruby/library/yaml/parse_file_spec.rb10
-rw-r--r--spec/ruby/library/yaml/parse_spec.rb22
-rw-r--r--spec/ruby/library/yaml/parser_spec.rb2
-rw-r--r--spec/ruby/library/yaml/quick_emit_spec.rb2
-rw-r--r--spec/ruby/library/yaml/read_type_class_spec.rb2
-rw-r--r--spec/ruby/library/yaml/shared/each_document.rb18
-rw-r--r--spec/ruby/library/yaml/tagurize_spec.rb11
-rw-r--r--spec/ruby/library/yaml/to_yaml_spec.rb99
-rw-r--r--spec/ruby/library/yaml/transfer_spec.rb2
-rw-r--r--spec/ruby/library/yaml/try_implicit_spec.rb2
-rw-r--r--spec/ruby/library/zlib/adler32_spec.rb46
-rw-r--r--spec/ruby/library/zlib/crc32_spec.rb52
-rw-r--r--spec/ruby/library/zlib/crc_table_spec.rb75
-rw-r--r--spec/ruby/library/zlib/deflate/append_spec.rb1
-rw-r--r--spec/ruby/library/zlib/deflate/deflate_spec.rb128
-rw-r--r--spec/ruby/library/zlib/deflate/flush_spec.rb1
-rw-r--r--spec/ruby/library/zlib/deflate/new_spec.rb1
-rw-r--r--spec/ruby/library/zlib/deflate/params_spec.rb17
-rw-r--r--spec/ruby/library/zlib/deflate/set_dictionary_spec.rb15
-rw-r--r--spec/ruby/library/zlib/gzipfile/close_spec.rb22
-rw-r--r--spec/ruby/library/zlib/gzipfile/closed_spec.rb17
-rw-r--r--spec/ruby/library/zlib/gzipfile/comment_spec.rb27
-rw-r--r--spec/ruby/library/zlib/gzipfile/crc_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipfile/finish_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipfile/level_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipfile/mtime_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipfile/orig_name_spec.rb27
-rw-r--r--spec/ruby/library/zlib/gzipfile/os_code_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipfile/sync_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipfile/to_io_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipfile/wrap_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_byte_spec.rb51
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_line_spec.rb5
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_spec.rb5
-rw-r--r--spec/ruby/library/zlib/gzipreader/eof_spec.rb56
-rw-r--r--spec/ruby/library/zlib/gzipreader/getc_spec.rb41
-rw-r--r--spec/ruby/library/zlib/gzipreader/gets_spec.rb22
-rw-r--r--spec/ruby/library/zlib/gzipreader/lineno_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/new_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/open_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/pos_spec.rb27
-rw-r--r--spec/ruby/library/zlib/gzipreader/read_spec.rb68
-rw-r--r--spec/ruby/library/zlib/gzipreader/readchar_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/readline_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/readlines_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/readpartial_spec.rb17
-rw-r--r--spec/ruby/library/zlib/gzipreader/rewind_spec.rb48
-rw-r--r--spec/ruby/library/zlib/gzipreader/shared/each.rb51
-rw-r--r--spec/ruby/library/zlib/gzipreader/tell_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipreader/ungetbyte_spec.rb122
-rw-r--r--spec/ruby/library/zlib/gzipreader/ungetc_spec.rb292
-rw-r--r--spec/ruby/library/zlib/gzipreader/unused_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/append_spec.rb17
-rw-r--r--spec/ruby/library/zlib/gzipwriter/comment_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/flush_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/mtime_spec.rb38
-rw-r--r--spec/ruby/library/zlib/gzipwriter/new_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/open_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/orig_name_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/pos_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/print_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/printf_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/putc_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/puts_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/tell_spec.rb1
-rw-r--r--spec/ruby/library/zlib/gzipwriter/write_spec.rb36
-rw-r--r--spec/ruby/library/zlib/inflate/append_spec.rb60
-rw-r--r--spec/ruby/library/zlib/inflate/finish_spec.rb28
-rw-r--r--spec/ruby/library/zlib/inflate/inflate_spec.rb152
-rw-r--r--spec/ruby/library/zlib/inflate/new_spec.rb1
-rw-r--r--spec/ruby/library/zlib/inflate/set_dictionary_spec.rb21
-rw-r--r--spec/ruby/library/zlib/inflate/sync_point_spec.rb1
-rw-r--r--spec/ruby/library/zlib/inflate/sync_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zlib_version_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/adler_spec.rb11
-rw-r--r--spec/ruby/library/zlib/zstream/avail_in_spec.rb9
-rw-r--r--spec/ruby/library/zlib/zstream/avail_out_spec.rb9
-rw-r--r--spec/ruby/library/zlib/zstream/close_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/closed_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/data_type_spec.rb9
-rw-r--r--spec/ruby/library/zlib/zstream/end_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/ended_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/finish_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/finished_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/flush_next_in_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/flush_next_out_spec.rb16
-rw-r--r--spec/ruby/library/zlib/zstream/reset_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/stream_end_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/total_in_spec.rb1
-rw-r--r--spec/ruby/library/zlib/zstream/total_out_spec.rb1
1866 files changed, 49358 insertions, 0 deletions
diff --git a/spec/ruby/library/English/English_spec.rb b/spec/ruby/library/English/English_spec.rb
new file mode 100644
index 0000000000..75a336eba2
--- /dev/null
+++ b/spec/ruby/library/English/English_spec.rb
@@ -0,0 +1,171 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+require 'English'
+
+describe "English" do
+ it "aliases $ERROR_INFO to $!" do
+ begin
+ raise "error"
+ rescue
+ $ERROR_INFO.should_not be_nil
+ $ERROR_INFO.should == $!
+ end
+ $ERROR_INFO.should be_nil
+ end
+
+ it "aliases $ERROR_POSITION to $@" do
+ begin
+ raise "error"
+ rescue
+ $ERROR_POSITION.should_not be_nil
+ $ERROR_POSITION.should == $@
+ end
+ $ERROR_POSITION.should be_nil
+ end
+
+ it "aliases $FS to $;" do
+ original = $;
+ $; = ","
+ $FS.should_not be_nil
+ $FS.should == $;
+ $; = original
+ end
+
+ it "aliases $FIELD_SEPARATOR to $;" do
+ original = $;
+ $; = ","
+ $FIELD_SEPARATOR.should_not be_nil
+ $FIELD_SEPARATOR.should == $;
+ $; = original
+ end
+
+ it "aliases $OFS to $," do
+ original = $,
+ $, = "|"
+ $OFS.should_not be_nil
+ $OFS.should == $,
+ $, = original
+ end
+
+ it "aliases $OUTPUT_FIELD_SEPARATOR to $," do
+ original = $,
+ $, = "|"
+ $OUTPUT_FIELD_SEPARATOR.should_not be_nil
+ $OUTPUT_FIELD_SEPARATOR.should == $,
+ $, = original
+ end
+
+ it "aliases $RS to $/" do
+ $RS.should_not be_nil
+ $RS.should == $/
+ end
+
+ it "aliases $INPUT_RECORD_SEPARATOR to $/" do
+ $INPUT_RECORD_SEPARATOR.should_not be_nil
+ $INPUT_RECORD_SEPARATOR.should == $/
+ end
+
+ it "aliases $ORS to $\\" do
+ original = $\
+ $\ = "\t"
+ $ORS.should_not be_nil
+ $ORS.should == $\
+ $\ = original
+ end
+
+ it "aliases $OUTPUT_RECORD_SEPARATOR to $\\" do
+ original = $\
+ $\ = "\t"
+ $OUTPUT_RECORD_SEPARATOR.should_not be_nil
+ $OUTPUT_RECORD_SEPARATOR.should == $\
+ $\ = original
+ end
+
+ it "aliases $INPUT_LINE_NUMBER to $." do
+ $INPUT_LINE_NUMBER.should_not be_nil
+ $INPUT_LINE_NUMBER.should == $.
+ end
+
+ it "aliases $NR to $." do
+ $NR.should_not be_nil
+ $NR.should == $.
+ end
+
+ it "aliases $LAST_READ_LINE to $_ needs to be reviewed for spec completeness"
+
+ it "aliases $DEFAULT_OUTPUT to $>" do
+ $DEFAULT_OUTPUT.should_not be_nil
+ $DEFAULT_OUTPUT.should == $>
+ end
+
+ it "aliases $DEFAULT_INPUT to $<" do
+ $DEFAULT_INPUT.should_not be_nil
+ $DEFAULT_INPUT.should == $<
+ end
+
+ it "aliases $PID to $$" do
+ $PID.should_not be_nil
+ $PID.should == $$
+ end
+
+ it "aliases $PID to $$" do
+ $PID.should_not be_nil
+ $PID.should == $$
+ end
+
+ it "aliases $PROCESS_ID to $$" do
+ $PROCESS_ID.should_not be_nil
+ $PROCESS_ID.should == $$
+ end
+
+ it "aliases $CHILD_STATUS to $?" do
+ ruby_exe('exit 0')
+ $CHILD_STATUS.should_not be_nil
+ $CHILD_STATUS.should == $?
+ end
+
+ it "aliases $LAST_MATCH_INFO to $~" do
+ /c(a)t/ =~ "cat"
+ $LAST_MATCH_INFO.should_not be_nil
+ $LAST_MATCH_INFO.should == $~
+ end
+
+ it "aliases $IGNORECASE to $=" do
+ $VERBOSE, verbose = nil, $VERBOSE
+ begin
+ $IGNORECASE.should_not be_nil
+ $IGNORECASE.should == $=
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+
+ it "aliases $ARGV to $*" do
+ $ARGV.should_not be_nil
+ $ARGV.should == $*
+ end
+
+ it "aliases $MATCH to $&" do
+ /c(a)t/ =~ "cat"
+ $MATCH.should_not be_nil
+ $MATCH.should == $&
+ end
+
+ it "aliases $PREMATCH to $`" do
+ /c(a)t/ =~ "cat"
+ $PREMATCH.should_not be_nil
+ $PREMATCH.should == $`
+ end
+
+ it "aliases $POSTMATCH to $'" do
+ /c(a)t/ =~ "cat"
+ $POSTMATCH.should_not be_nil
+ $POSTMATCH.should == $'
+ end
+
+ it "aliases $LAST_PAREN_MATCH to $+" do
+ /c(a)t/ =~ "cat"
+ $LAST_PAREN_MATCH.should_not be_nil
+ $LAST_PAREN_MATCH.should == $+
+ end
+end
diff --git a/spec/ruby/library/abbrev/abbrev_spec.rb b/spec/ruby/library/abbrev/abbrev_spec.rb
new file mode 100644
index 0000000000..b2321cc679
--- /dev/null
+++ b/spec/ruby/library/abbrev/abbrev_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'abbrev'
+
+#test both Abbrev.abbrev and Array#abbrev in
+#the same manner, as they're more or less aliases
+#of one another
+
+[["Abbrev.abbrev", lambda {|a| Abbrev.abbrev(a)}],
+ ["Array#abbrev", lambda {|a| a.abbrev}]
+].each do |(name, func)|
+
+ describe name do
+ it "returns a hash of all unambiguous abbreviations of the array of strings passed in" do
+ func.call(['ruby', 'rules']).should == {"rub" => "ruby",
+ "ruby" => "ruby",
+ "rul" => "rules",
+ "rule" => "rules",
+ "rules" => "rules"}
+
+ func.call(["car", "cone"]).should == {"ca" => "car",
+ "car" => "car",
+ "co" => "cone",
+ "con" => "cone",
+ "cone" => "cone"}
+ end
+
+ it "returns an empty hash when called on an empty array" do
+ func.call([]).should == {}
+ end
+ end
+end
diff --git a/spec/ruby/library/base64/decode64_spec.rb b/spec/ruby/library/base64/decode64_spec.rb
new file mode 100644
index 0000000000..34d5ed6989
--- /dev/null
+++ b/spec/ruby/library/base64/decode64_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+require 'base64'
+
+describe "Base64#decode64" do
+ it "returns the Base64-decoded version of the given string" do
+ Base64.decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n").should == "Send reinforcements"
+ end
+end
diff --git a/spec/ruby/library/base64/encode64_spec.rb b/spec/ruby/library/base64/encode64_spec.rb
new file mode 100644
index 0000000000..08df694e54
--- /dev/null
+++ b/spec/ruby/library/base64/encode64_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+require 'base64'
+
+describe "Base64#encode64" do
+ it "returns the Base64-encoded version of the given string" do
+ Base64.encode64("Now is the time for all good coders\nto learn Ruby").should ==
+ "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nUnVieQ==\n"
+ end
+
+ it "returns the Base64-encoded version of the given string" do
+ Base64.encode64('Send reinforcements').should == "U2VuZCByZWluZm9yY2VtZW50cw==\n"
+ end
+end
diff --git a/spec/ruby/library/base64/urlsafe_decode64_spec.rb b/spec/ruby/library/base64/urlsafe_decode64_spec.rb
new file mode 100644
index 0000000000..bea9a7cefb
--- /dev/null
+++ b/spec/ruby/library/base64/urlsafe_decode64_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+require 'base64'
+
+describe "Base64#urlsafe_decode64" do
+ it "uses '_' instead of '/'" do
+ decoded = Base64.urlsafe_decode64("V2hlcmUgYW0gST8gV2hvIGFtIEk_IEFtIEk_IEk_")
+ decoded.should == 'Where am I? Who am I? Am I? I?'
+ end
+
+ it "uses '-' instead of '+'" do
+ decoded = Base64.urlsafe_decode64('IkJlaW5nIGRpc2ludGVncmF0ZWQgbWFrZXMgbWUgdmUtcnkgYW4tZ3J5ISIgPGh1ZmYsIGh1ZmY-')
+ decoded.should == '"Being disintegrated makes me ve-ry an-gry!" <huff, huff>'
+ end
+
+ ruby_version_is ""..."2.3" do
+ it "requires padding" do
+ lambda { Base64.urlsafe_decode64("MQ") }.should raise_error(ArgumentError)
+ end
+ end
+
+ ruby_version_is "2.3" do
+ it "does not require padding" do
+ Base64.urlsafe_decode64("MQ").should == "1"
+ end
+ end
+end
diff --git a/spec/ruby/library/base64/urlsafe_encode64_spec.rb b/spec/ruby/library/base64/urlsafe_encode64_spec.rb
new file mode 100644
index 0000000000..32fce72603
--- /dev/null
+++ b/spec/ruby/library/base64/urlsafe_encode64_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+require 'base64'
+
+describe "Base64#urlsafe_encode64" do
+ it "uses '_' instead of '/'" do
+ encoded = Base64.urlsafe_encode64('Where am I? Who am I? Am I? I?')
+ encoded.should == "V2hlcmUgYW0gST8gV2hvIGFtIEk_IEFtIEk_IEk_"
+ end
+
+ it "uses '-' instead of '+'" do
+ encoded = Base64.urlsafe_encode64('"Being disintegrated makes me ve-ry an-gry!" <huff, huff>')
+ encoded.should == 'IkJlaW5nIGRpc2ludGVncmF0ZWQgbWFrZXMgbWUgdmUtcnkgYW4tZ3J5ISIgPGh1ZmYsIGh1ZmY-'
+ end
+
+ ruby_version_is "2.3" do
+ it "makes padding optional" do
+ Base64.urlsafe_encode64("1", padding: false).should == "MQ"
+ Base64.urlsafe_encode64("1").should == "MQ=="
+ end
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/abs_spec.rb b/spec/ruby/library/bigdecimal/abs_spec.rb
new file mode 100644
index 0000000000..9027abfb47
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/abs_spec.rb
@@ -0,0 +1,50 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#abs" do
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @two = BigDecimal("2")
+ @three = BigDecimal("3")
+ @mixed = BigDecimal("1.23456789")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ end
+
+ it "returns the absolute value" do
+ pos_int = BigDecimal("2E5555")
+ neg_int = BigDecimal("-2E5555")
+ pos_frac = BigDecimal("2E-9999")
+ neg_frac = BigDecimal("-2E-9999")
+
+ pos_int.abs.should == pos_int
+ neg_int.abs.should == pos_int
+ pos_frac.abs.should == pos_frac
+ neg_frac.abs.should == pos_frac
+ @one.abs.should == 1
+ @two.abs.should == 2
+ @three.abs.should == 3
+ @mixed.abs.should == @mixed
+ @one_minus.abs.should == @one
+ end
+
+ it "properly handles special values" do
+ @infinity.abs.should == @infinity
+ @infinity_minus.abs.should == @infinity
+ @nan.abs.nan?.should == true # have to do it this way, since == doesn't work on NaN
+ @zero.abs.should == 0
+ @zero.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ @zero_pos.abs.should == 0
+ @zero_pos.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ @zero_neg.abs.should == 0
+ @zero_neg.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/add_spec.rb b/spec/ruby/library/bigdecimal/add_spec.rb
new file mode 100644
index 0000000000..6136c9dccb
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/add_spec.rb
@@ -0,0 +1,179 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+require 'bigdecimal'
+
+describe "BigDecimal#add" do
+
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @two = BigDecimal("2")
+ @three = BigDecimal("3")
+ @ten = BigDecimal("10")
+ @eleven = BigDecimal("11")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ @frac_3 = BigDecimal("12345E10")
+ @frac_4 = BigDecimal("98765E10")
+ @dot_ones = BigDecimal("0.1111111111")
+ end
+
+ it "returns a + b with given precision" do
+ # documentation states, that precision ist optional, but it ain't,
+ @two.add(@one, 1).should == @three
+ @one .add(@two, 1).should == @three
+ @one.add(@one_minus, 1).should == @zero
+ @ten.add(@one, 2).should == @eleven
+ @zero.add(@one, 1).should == @one
+ @frac_2.add(@frac_1, 10000).should == BigDecimal("1.9E-99999")
+ @frac_1.add(@frac_1, 10000).should == BigDecimal("2E-99999")
+ @frac_3.add(@frac_4, 0).should == BigDecimal("0.11111E16")
+ @frac_3.add(@frac_4, 1).should == BigDecimal("0.1E16")
+ @frac_3.add(@frac_4, 2).should == BigDecimal("0.11E16")
+ @frac_3.add(@frac_4, 3).should == BigDecimal("0.111E16")
+ @frac_3.add(@frac_4, 4).should == BigDecimal("0.1111E16")
+ @frac_3.add(@frac_4, 5).should == BigDecimal("0.11111E16")
+ @frac_3.add(@frac_4, 6).should == BigDecimal("0.11111E16")
+ end
+
+ it "returns a + [Fixnum value] with given precision" do
+ (1..10).each {|precision|
+ @dot_ones.add(0, precision).should == BigDecimal("0." + "1" * precision)
+ }
+ BigDecimal("0.88").add(0, 1).should == BigDecimal("0.9")
+ end
+
+ it "returns a + [Bignum value] with given precision" do
+ bignum = 10000000000000000000
+ (1..20).each {|precision|
+ @dot_ones.add(bignum, precision).should == BigDecimal("0.1E20")
+ }
+ (21..30).each {|precision|
+ @dot_ones.add(bignum, precision).should == BigDecimal(
+ "0.10000000000000000000" + "1" * (precision - 20) + "E20")
+ }
+ end
+
+# TODO:
+# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/17374
+#
+# This doesn't work on MRI and looks like a bug to me:
+# one can use BigDecimal + Float, but not Bigdecimal.add(Float)
+#
+# it "returns a + [Float value] with given precision" do
+# (1..10).each {|precision|
+# @dot_ones.add(0.0, precision).should == BigDecimal("0." + "1" * precision)
+# }
+#
+# BigDecimal("0.88").add(0.0, 1).should == BigDecimal("0.9")
+# end
+
+ it "favors the precision specified in the second argument over the global limit" do
+ BigDecimalSpecs.with_limit(1) do
+ BigDecimal('0.888').add(@zero, 3).should == BigDecimal('0.888')
+ end
+
+ BigDecimalSpecs.with_limit(2) do
+ BigDecimal('0.888').add(@zero, 1).should == BigDecimal('0.9')
+ end
+ end
+
+ it "uses the current rounding mode if rounding is needed" do
+ BigDecimalSpecs.with_rounding(BigDecimal::ROUND_UP) do
+ BigDecimal('0.111').add(@zero, 1).should == BigDecimal('0.2')
+ BigDecimal('-0.111').add(@zero, 1).should == BigDecimal('-0.2')
+ end
+ BigDecimalSpecs.with_rounding(BigDecimal::ROUND_DOWN) do
+ BigDecimal('0.999').add(@zero, 1).should == BigDecimal('0.9')
+ BigDecimal('-0.999').add(@zero, 1).should == BigDecimal('-0.9')
+ end
+ BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_UP) do
+ BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9')
+ BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9')
+ end
+ BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_DOWN) do
+ BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8')
+ BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8')
+ end
+ BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_EVEN) do
+ BigDecimal('0.75').add(@zero, 1).should == BigDecimal('0.8')
+ BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8')
+ BigDecimal('-0.75').add(@zero, 1).should == BigDecimal('-0.8')
+ BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8')
+ end
+ BigDecimalSpecs.with_rounding(BigDecimal::ROUND_CEILING) do
+ BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9')
+ BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8')
+ end
+ BigDecimalSpecs.with_rounding(BigDecimal::ROUND_FLOOR) do
+ BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8')
+ BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9')
+ end
+ end
+
+ it "uses the default ROUND_HALF_UP rounding if it wasn't explicitly changed" do
+ BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9')
+ BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9')
+ end
+
+ it "returns NaN if NaN is involved" do
+ @one.add(@nan, 10000).nan?.should == true
+ @nan.add(@one, 1).nan?.should == true
+ end
+
+ it "returns Infinity or -Infinity if these are involved" do
+ @zero.add(@infinity, 1).should == @infinity
+ @frac_2.add(@infinity, 1).should == @infinity
+ @one_minus.add(@infinity, 1).should == @infinity
+ @two.add(@infinity, 1).should == @infinity
+
+ @zero.add(@infinity_minus, 1).should == @infinity_minus
+ @frac_2.add(@infinity_minus, 1).should == @infinity_minus
+ @one_minus.add(@infinity_minus, 1).should == @infinity_minus
+ @two.add(@infinity_minus, 1).should == @infinity_minus
+
+ @infinity.add(@zero, 1).should == @infinity
+ @infinity.add(@frac_2, 1).should == @infinity
+ @infinity.add(@one_minus, 1).should == @infinity
+ @infinity.add(@two, 1).should == @infinity
+
+ @infinity_minus.add(@zero, 1).should == @infinity_minus
+ @infinity_minus.add(@frac_2, 1).should == @infinity_minus
+ @infinity_minus.add(@one_minus, 1).should == @infinity_minus
+ @infinity_minus.add(@two, 1).should == @infinity_minus
+
+ @infinity.add(@infinity, 10000).should == @infinity
+ @infinity_minus.add(@infinity_minus, 10000).should == @infinity_minus
+ end
+
+ it "returns NaN if Infinity + (- Infinity)" do
+ @infinity.add(@infinity_minus, 10000).nan?.should == true
+ @infinity_minus.add(@infinity, 10000).nan?.should == true
+ end
+
+ it "raises TypeError when adds nil" do
+ lambda {
+ @one.add(nil, 10)
+ }.should raise_error(TypeError)
+ lambda {
+ @one.add(nil, 0)
+ }.should raise_error(TypeError)
+ end
+
+ it "raises TypeError when precision parameter is nil" do
+ lambda {
+ @one.add(@one, nil)
+ }.should raise_error(TypeError)
+ end
+
+ it "raises ArgumentError when precision parameter is negative" do
+ lambda {
+ @one.add(@one, -10)
+ }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/case_compare_spec.rb b/spec/ruby/library/bigdecimal/case_compare_spec.rb
new file mode 100644
index 0000000000..dcbde80e85
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/case_compare_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/eql.rb', __FILE__)
+
+
+describe "BigDecimal#===" do
+ it_behaves_like(:bigdecimal_eql, :===)
+end
diff --git a/spec/ruby/library/bigdecimal/ceil_spec.rb b/spec/ruby/library/bigdecimal/ceil_spec.rb
new file mode 100644
index 0000000000..d8829411b9
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/ceil_spec.rb
@@ -0,0 +1,104 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#ceil" do
+ before :each do
+ @zero = BigDecimal("0")
+ @one = BigDecimal("1")
+ @three = BigDecimal("3")
+ @four = BigDecimal("4")
+ @mixed = BigDecimal("1.23456789")
+ @mixed_big = BigDecimal("1.23456789E100")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+ @nan = BigDecimal("NaN")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ end
+
+ it "returns an Integer, if n is unspecified" do
+ @mixed.ceil.kind_of?(Integer).should == true
+ end
+
+ it "returns a BigDecimal, if n is specified" do
+ @pos_int.ceil(2).kind_of?(BigDecimal).should == true
+ end
+
+ it "returns the smallest integer greater or equal to self, if n is unspecified" do
+ @pos_int.ceil.should == @pos_int
+ @neg_int.ceil.should == @neg_int
+ @pos_frac.ceil.should == BigDecimal("1")
+ @neg_frac.ceil.should == @zero
+ @zero.ceil.should == 0
+ @zero_pos.ceil.should == @zero_pos
+ @zero_neg.ceil.should == @zero_neg
+
+
+ BigDecimal('2.3').ceil.should == 3
+ BigDecimal('2.5').ceil.should == 3
+ BigDecimal('2.9999').ceil.should == 3
+ BigDecimal('-2.3').ceil.should == -2
+ BigDecimal('-2.5').ceil.should == -2
+ BigDecimal('-2.9999').ceil.should == -2
+ end
+
+ it "raise exception, if self is special value" do
+ lambda { @infinity.ceil }.should raise_error(FloatDomainError)
+ lambda { @infinity_neg.ceil }.should raise_error(FloatDomainError)
+ lambda { @nan.ceil }.should raise_error(FloatDomainError)
+ end
+
+ it "returns n digits right of the decimal point if given n > 0" do
+ @mixed.ceil(1).should == BigDecimal("1.3")
+ @mixed.ceil(5).should == BigDecimal("1.23457")
+
+ BigDecimal("-0.03").ceil(1).should == BigDecimal("0")
+ BigDecimal("0.03").ceil(1).should == BigDecimal("0.1")
+
+ BigDecimal("23.45").ceil(0).should == BigDecimal('24')
+ BigDecimal("23.45").ceil(1).should == BigDecimal('23.5')
+ BigDecimal("23.45").ceil(2).should == BigDecimal('23.45')
+
+ BigDecimal("-23.45").ceil(0).should == BigDecimal('-23')
+ BigDecimal("-23.45").ceil(1).should == BigDecimal('-23.4')
+ BigDecimal("-23.45").ceil(2).should == BigDecimal('-23.45')
+
+ BigDecimal("2E-10").ceil(0).should == @one
+ BigDecimal("2E-10").ceil(9).should == BigDecimal('1E-9')
+ BigDecimal("2E-10").ceil(10).should == BigDecimal('2E-10')
+ BigDecimal("2E-10").ceil(11).should == BigDecimal('2E-10')
+
+ (1..10).each do |n|
+ # 0.4, 0.34, 0.334, etc.
+ (@one.div(@three,20)).ceil(n).should == BigDecimal("0.#{'3'*(n-1)}4")
+ # 1.4, 1.34, 1.334, etc.
+ (@four.div(@three,20)).ceil(n).should == BigDecimal("1.#{'3'*(n-1)}4")
+ (BigDecimal('31').div(@three,20)).ceil(n).should == BigDecimal("10.#{'3'*(n-1)}4")
+ end
+ (1..10).each do |n|
+ # -0.4, -0.34, -0.334, etc.
+ (-@one.div(@three,20)).ceil(n).should == BigDecimal("-0.#{'3'* n}")
+ end
+ (1..10).each do |n|
+ (@three.div(@one,20)).ceil(n).should == @three
+ end
+ (1..10).each do |n|
+ (-@three.div(@one,20)).ceil(n).should == -@three
+ end
+ end
+
+ it "sets n digits left of the decimal point to 0, if given n < 0" do
+ BigDecimal("13345.234").ceil(-2).should == BigDecimal("13400.0")
+ @mixed_big.ceil(-99).should == BigDecimal("0.13E101")
+ @mixed_big.ceil(-100).should == BigDecimal("0.2E101")
+ @mixed_big.ceil(-95).should == BigDecimal("0.123457E101")
+ BigDecimal("1E10").ceil(-30).should == BigDecimal('1E30')
+ BigDecimal("-1E10").ceil(-30).should == @zero
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/coerce_spec.rb b/spec/ruby/library/bigdecimal/coerce_spec.rb
new file mode 100644
index 0000000000..1c63ddf2bc
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/coerce_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#coerce" do
+
+ it "returns [other, self] both as BigDecimal" do
+ one = BigDecimal("1.0")
+ five_point_28 = BigDecimal("5.28")
+ zero_minus = BigDecimal("-0.0")
+ some_value = 32434234234234234234
+
+ BigDecimal("1.2").coerce(1).should == [one, BigDecimal("1.2")]
+ five_point_28.coerce(1.0).should == [one, BigDecimal("5.28")]
+ one.coerce(one).should == [one, one]
+ one.coerce(2.5).should == [2.5, one]
+ BigDecimal("1").coerce(3.14).should == [3.14, one]
+ a, b = zero_minus.coerce(some_value)
+ a.should == BigDecimal(some_value.to_s)
+ b.should == zero_minus
+ a, b = one.coerce(some_value)
+ a.should == BigDecimal(some_value.to_s)
+ b.to_f.should be_close(1.0, TOLERANCE) # can we take out the to_f once BigDecimal#- is implemented?
+ b.should == one
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/comparison_spec.rb b/spec/ruby/library/bigdecimal/comparison_spec.rb
new file mode 100644
index 0000000000..c4de8348b2
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/comparison_spec.rb
@@ -0,0 +1,81 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#<=>" do
+ before :each do
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @mixed = BigDecimal("1.23456789")
+ @mixed_big = BigDecimal("1.23456789E100")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @int_mock = mock('123')
+ class << @int_mock
+ def coerce(other)
+ return [other, BigDecimal('123')]
+ end
+ def >= (other)
+ BigDecimal('123') >= other
+ end
+ end
+
+ @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac,
+ -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1,
+ @zero , 1, 2, 10, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg]
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+ @nan = BigDecimal("NaN")
+ end
+
+
+ it "returns 0 if a == b" do
+ (@pos_int <=> @pos_int).should == 0
+ (@neg_int <=> @neg_int).should == 0
+ (@pos_frac <=> @pos_frac).should == 0
+ (@neg_frac <=> @neg_frac).should == 0
+ (@zero <=> @zero).should == 0
+ (@infinity <=> @infinity).should == 0
+ (@infinity_neg <=> @infinity_neg).should == 0
+ end
+
+ it "returns 1 if a > b" do
+ (@pos_int <=> @neg_int).should == 1
+ (@pos_frac <=> @neg_frac).should == 1
+ (@pos_frac <=> @zero).should == 1
+ @values.each { |val|
+ (@infinity <=> val).should == 1
+ }
+ end
+
+ it "returns -1 if a < b" do
+ (@zero <=> @pos_frac).should == -1
+ (@neg_int <=> @pos_frac).should == -1
+ (@pos_frac <=> @pos_int).should == -1
+ @values.each { |val|
+ (@infinity_neg <=> val).should == -1
+ }
+ end
+
+ it "returns nil if NaN is involved" do
+ @values += [@infinity, @infinity_neg, @nan]
+ @values << nil
+ @values << Object.new
+ @values.each { |val|
+ (@nan <=> val).should == nil
+ }
+ end
+
+ it "returns nil if the argument is nil" do
+ (@zero <=> nil).should == nil
+ (@infinity <=> nil).should == nil
+ (@infinity_neg <=> nil).should == nil
+ (@mixed <=> nil).should == nil
+ (@pos_int <=> nil).should == nil
+ (@neg_frac <=> nil).should == nil
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/div_spec.rb b/spec/ruby/library/bigdecimal/div_spec.rb
new file mode 100644
index 0000000000..f8f8ac4e5e
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/div_spec.rb
@@ -0,0 +1,102 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/quo', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#div with precision set to 0" do
+ # TODO: figure out if there is a better way to do these
+ # shared specs rather than sending [0]. See other specs
+ # that share :bigdecimal_quo.
+ it_behaves_like :bigdecimal_quo, :div, [0]
+end
+
+describe "BigDecimal#div" do
+
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @zero_plus = BigDecimal("+0")
+ @zero_minus = BigDecimal("-0")
+ @two = BigDecimal("2")
+ @three = BigDecimal("3")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ end
+
+ it "returns a / b with optional precision" do
+ @two.div(@one).should == @two
+ @one.div(@two).should == @zero
+ # ^^ is this really intended for a class with arbitrary precision?
+ @one.div(@two, 1).should == BigDecimal("0.5")
+ @one.div(@one_minus).should == @one_minus
+ @one_minus.div(@one_minus).should == @one
+ @frac_2.div(@frac_1, 1).should == BigDecimal("0.9")
+ @frac_1.div(@frac_1).should == @one
+
+ res = "0." + "3" * 1000
+ (1..100).each { |idx|
+ @one.div(@three, idx).to_s("F").should == "0." + res[2, idx]
+ }
+ end
+
+ it "raises FloatDomainError if NaN is involved" do
+ lambda { @one.div(@nan) }.should raise_error(FloatDomainError)
+ lambda { @nan.div(@one) }.should raise_error(FloatDomainError)
+ lambda { @nan.div(@nan) }.should raise_error(FloatDomainError)
+ end
+
+ it "returns 0 if divided by Infinity and no precision given" do
+ @zero.div(@infinity).should == 0
+ @frac_2.div(@infinity).should == 0
+ end
+
+ it "returns 0 if divided by Infinity with given precision" do
+ @zero.div(@infinity, 0).should == 0
+ @frac_2.div(@infinity, 1).should == 0
+ @zero.div(@infinity, 100000).should == 0
+ @frac_2.div(@infinity, 100000).should == 0
+ end
+
+ it "raises ZeroDivisionError if divided by zero and no precision given" do
+ lambda { @one.div(@zero) }.should raise_error(ZeroDivisionError)
+ lambda { @one.div(@zero_plus) }.should raise_error(ZeroDivisionError)
+ lambda { @one.div(@zero_minus) }.should raise_error(ZeroDivisionError)
+
+ lambda { @zero.div(@zero) }.should raise_error(ZeroDivisionError)
+ lambda { @zero_minus.div(@zero_plus) }.should raise_error(ZeroDivisionError)
+ lambda { @zero_minus.div(@zero_minus) }.should raise_error(ZeroDivisionError)
+ lambda { @zero_plus.div(@zero_minus) }.should raise_error(ZeroDivisionError)
+ end
+
+ it "returns NaN if zero is divided by zero" do
+ @zero.div(@zero, 0).nan?.should == true
+ @zero_minus.div(@zero_plus, 0).nan?.should == true
+ @zero_plus.div(@zero_minus, 0).nan?.should == true
+
+ @zero.div(@zero, 10).nan?.should == true
+ @zero_minus.div(@zero_plus, 10).nan?.should == true
+ @zero_plus.div(@zero_minus, 10).nan?.should == true
+ end
+
+ it "raises FloatDomainError if (+|-) Infinity divided by 1 and no precision given" do
+ lambda { @infinity_minus.div(@one) }.should raise_error(FloatDomainError)
+ lambda { @infinity.div(@one) }.should raise_error(FloatDomainError)
+ lambda { @infinity_minus.div(@one_minus) }.should raise_error(FloatDomainError)
+ end
+
+ it "returns (+|-)Infinity if (+|-)Infinity by 1 and precision given" do
+ @infinity_minus.div(@one, 0).should == @infinity_minus
+ @infinity.div(@one, 0).should == @infinity
+ @infinity_minus.div(@one_minus, 0).should == @infinity
+ end
+
+ it "returns NaN if Infinity / ((+|-) Infinity)" do
+ @infinity.div(@infinity_minus, 100000).nan?.should == true
+ @infinity_minus.div(@infinity, 1).nan?.should == true
+ end
+
+
+end
diff --git a/spec/ruby/library/bigdecimal/divide_spec.rb b/spec/ruby/library/bigdecimal/divide_spec.rb
new file mode 100644
index 0000000000..4dfe2702bb
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/divide_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/quo', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#/" do
+ it_behaves_like :bigdecimal_quo, :/, []
+end
diff --git a/spec/ruby/library/bigdecimal/divmod_spec.rb b/spec/ruby/library/bigdecimal/divmod_spec.rb
new file mode 100644
index 0000000000..839a289ab6
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/divmod_spec.rb
@@ -0,0 +1,180 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/modulo', __FILE__)
+require 'bigdecimal'
+
+module DivmodSpecs
+ def self.check_both_nan(array)
+ array.length.should == 2
+ array[0].nan?.should == true
+ array[1].nan?.should == true
+ end
+ def self.check_both_bigdecimal(array)
+ array.length.should == 2
+ array[0].kind_of?(BigDecimal).should == true
+ array[1].kind_of?(BigDecimal).should == true
+ end
+end
+
+# TODO: figure out a way to do the shared specs with helpers instead
+# of spec'ing a method that does not really exist
+describe "BigDecimal#mod_part_of_divmod" do
+ # BigDecimal#divmod[1] behaves exactly like #modulo
+ before :all do
+ class BigDecimal
+ def mod_part_of_divmod(arg)
+ divmod(arg)[1]
+ end
+ end
+ end
+
+ after :all do
+ class BigDecimal
+ undef mod_part_of_divmod
+ end
+ end
+
+ it_behaves_like :bigdecimal_modulo, :mod_part_of_divmod
+
+ it "raises ZeroDivisionError if other is zero" do
+ bd5667 = BigDecimal.new("5667.19")
+
+ lambda { bd5667.send(@method, 0) }.should raise_error(ZeroDivisionError)
+ lambda { bd5667.send(@method, BigDecimal("0")) }.should raise_error(ZeroDivisionError)
+ lambda { @zero.send(@method, @zero) }.should raise_error(ZeroDivisionError)
+ end
+end
+
+describe "BigDecimal#divmod" do
+
+ before :each do
+ @a = BigDecimal("42.00000000000000000001")
+
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+
+ @one = BigDecimal("1")
+ @mixed = BigDecimal("1.23456789")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+
+ @special_vals = [@infinity, @infinity_minus, @nan]
+ @regular_vals = [
+ @one, @mixed, @pos_int, @neg_int, @pos_frac,
+ @neg_frac, @one_minus, @frac_1, @frac_2]
+ @zeroes = [@zero, @zero_pos, @zero_neg]
+ end
+
+ it "divides value, returns an array" do
+ res = @a.divmod(5)
+ res.kind_of?(Array).should == true
+ end
+
+ it "array contains quotient and modulus as BigDecimal" do
+ res = @a.divmod(5)
+ DivmodSpecs.check_both_bigdecimal(res)
+ res[0].should == BigDecimal('0.8E1')
+ res[1].should == BigDecimal('2.00000000000000000001')
+
+ BigDecimal('1').divmod(BigDecimal('2')).should == [0, 1]
+ BigDecimal('2').divmod(BigDecimal('1')).should == [2, 0]
+
+ BigDecimal('1').divmod(BigDecimal('-2')).should == [-1, -1]
+ BigDecimal('2').divmod(BigDecimal('-1')).should == [-2, 0]
+
+ BigDecimal('-1').divmod(BigDecimal('2')).should == [-1, 1]
+ BigDecimal('-2').divmod(BigDecimal('1')).should == [-2, 0]
+ end
+
+ it "can be reversed with * and +" do
+ # Example taken from BigDecimal documentation
+ a = BigDecimal.new("42")
+ b = BigDecimal.new("9")
+ q, m = a.divmod(b)
+ c = q * b + m
+ a.should == c
+
+ values = [@one, @one_minus, BigDecimal('2'), BigDecimal('-2'),
+ BigDecimal('5'), BigDecimal('-5'), BigDecimal('10'), BigDecimal('-10'),
+ BigDecimal('20'), BigDecimal('-20'), BigDecimal('100'), BigDecimal('-100'),
+ BigDecimal('1.23456789E10'), BigDecimal('-1.23456789E10')
+ ]
+
+ # TODO: file MRI bug:
+ # BigDecimal('1').divmod(BigDecimal('3E-9'))[0] #=> 0.3E9,
+ # but really should be 0.333333333E9
+ values << BigDecimal('1E-10')
+ values << BigDecimal('-1E-10')
+ values << BigDecimal('2E55')
+ values << BigDecimal('-2E55')
+ values << BigDecimal('2E-5555')
+ values << BigDecimal('-2E-5555')
+
+
+ values_and_zeroes = values + @zeroes
+ values_and_zeroes.each do |val1|
+ values.each do |val2|
+ res = val1.divmod(val2)
+ DivmodSpecs.check_both_bigdecimal(res)
+ res[0].should == ((val1/val2).floor)
+ res[1].should == (val1 - res[0] * val2)
+ end
+ end
+ end
+
+ it "returns an array of two NaNs if NaN is involved" do
+ (@special_vals + @regular_vals + @zeroes).each do |val|
+ DivmodSpecs.check_both_nan(val.divmod(@nan))
+ DivmodSpecs.check_both_nan(@nan.divmod(val))
+ end
+ end
+
+ it "raises ZeroDivisionError if the divisor is zero" do
+ (@special_vals + @regular_vals + @zeroes - [@nan]).each do |val|
+ @zeroes.each do |zero|
+ lambda { val.divmod(zero) }.should raise_error(ZeroDivisionError)
+ end
+ end
+ end
+
+ it "returns an array of Infinity and NaN if the dividend is Infinity" do
+ @regular_vals.each do |val|
+ array = @infinity.divmod(val)
+ array.length.should == 2
+ array[0].infinite?.should == (val > 0 ? 1 : -1)
+ array[1].nan?.should == true
+ end
+ end
+
+ it "returns an array of zero and the dividend if the divisor is Infinity" do
+ @regular_vals.each do |val|
+ array = val.divmod(@infinity)
+ array.length.should == 2
+ array[0].should == @zero
+ array[1].should == val
+ end
+ end
+
+ it "returns an array of two zero if the diviend is zero" do
+ @zeroes.each do |zero|
+ @regular_vals.each do |val|
+ zero.divmod(val).should == [@zero, @zero]
+ end
+ end
+ end
+
+ it "raises TypeError if the argument cannot be coerced to BigDecimal" do
+ lambda {
+ @one.divmod('1')
+ }.should raise_error(TypeError)
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/double_fig_spec.rb b/spec/ruby/library/bigdecimal/double_fig_spec.rb
new file mode 100644
index 0000000000..3ab5c2f207
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/double_fig_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal.double_fig" do
+ # The result depends on the CPU and OS
+ it "returns the number of digits a Float number is allowed to have" do
+ BigDecimal.double_fig.should_not == nil
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/eql_spec.rb b/spec/ruby/library/bigdecimal/eql_spec.rb
new file mode 100644
index 0000000000..f3f525a7ba
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/eql_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/eql.rb', __FILE__)
+
+describe "BigDecimal#eql?" do
+ it_behaves_like(:bigdecimal_eql, :eql?)
+end
diff --git a/spec/ruby/library/bigdecimal/equal_value_spec.rb b/spec/ruby/library/bigdecimal/equal_value_spec.rb
new file mode 100644
index 0000000000..bd07217b98
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/equal_value_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/eql.rb', __FILE__)
+
+
+describe "BigDecimal#==" do
+ it_behaves_like(:bigdecimal_eql, :==)
+end
diff --git a/spec/ruby/library/bigdecimal/exponent_spec.rb b/spec/ruby/library/bigdecimal/exponent_spec.rb
new file mode 100644
index 0000000000..6bb678d4ed
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/exponent_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/power', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#**" do
+ it_behaves_like(:bigdecimal_power, :**)
+end
+
+describe "BigDecimal#exponent" do
+
+ it "returns an Integer" do
+ BigDecimal("2E100000000").exponent.kind_of?(Integer).should == true
+ BigDecimal("2E-999").exponent.kind_of?(Integer).should == true
+ end
+
+ it "is n if number can be represented as 0.xxx*10**n" do
+ BigDecimal("2E1000").exponent.should == 1001
+ BigDecimal("1234567E10").exponent.should == 17
+ end
+
+# commenting this spec out after discussion with Defiler, since it seems to be an MRI bug, not a real feature
+=begin
+ platform_is wordsize: 32 do
+ # TODO: write specs for both 32 and 64 bit
+ it "returns 0 if exponent can't be represented as Fixnum" do
+ BigDecimal("2E1000000000000000").exponent.should == 0
+ BigDecimal("-5E-999999999999999").exponent.should == 0
+ end
+ end
+=end
+
+ it "returns 0 if self is 0" do
+ BigDecimal("0").exponent.should == 0
+ BigDecimal("+0").exponent.should == 0
+ BigDecimal("-0").exponent.should == 0
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/finite_spec.rb b/spec/ruby/library/bigdecimal/finite_spec.rb
new file mode 100644
index 0000000000..6d6d8398fa
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/finite_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#finite?" do
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @two = BigDecimal("2")
+ @three = BigDecimal("3")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ @big = BigDecimal("2E40001")
+ @finite_vals = [@one, @zero, @zero_pos, @zero_neg, @two,
+ @three, @frac_1, @frac_2, @big, @one_minus]
+ end
+
+ it "is false if Infinity or NaN" do
+ @infinity.finite?.should == false
+ @infinity_minus.finite?.should == false
+ @nan.finite?.should == false
+ end
+
+ it "returns true for finite values" do
+ @finite_vals.each do |val|
+ val.finite?.should == true
+ end
+ end
+end
+
diff --git a/spec/ruby/library/bigdecimal/fix_spec.rb b/spec/ruby/library/bigdecimal/fix_spec.rb
new file mode 100644
index 0000000000..0a4a98c241
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/fix_spec.rb
@@ -0,0 +1,57 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#fix" do
+ before :each do
+ @zero = BigDecimal("0")
+ @mixed = BigDecimal("1.23456789")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+ @nan = BigDecimal("NaN")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ end
+
+ it "returns a BigDecimal" do
+ BigDecimal("2E100000000").fix.kind_of?(BigDecimal).should == true
+ BigDecimal("2E-999").kind_of?(BigDecimal).should == true
+ end
+
+ it "returns the integer part of the absolute value" do
+ a = BigDecimal("2E1000")
+ a.fix.should == a
+ b = BigDecimal("-2E1000")
+ b.fix.should == b
+ BigDecimal("0.123456789E5").fix.should == BigDecimal("0.12345E5")
+ BigDecimal("-0.123456789E5").fix.should == BigDecimal("-0.12345E5")
+ end
+
+ it "correctly handles special values" do
+ @infinity.fix.should == @infinity
+ @infinity_neg.fix.should == @infinity_neg
+ @nan.fix.nan?.should == true
+ end
+
+ it "returns 0 if the absolute value is < 1" do
+ BigDecimal("0.99999").fix.should == 0
+ BigDecimal("-0.99999").fix.should == 0
+ BigDecimal("0.000000001").fix.should == 0
+ BigDecimal("-0.00000001").fix.should == 0
+ BigDecimal("-1000000").fix.should_not == 0
+ @zero.fix.should == 0
+ @zero_pos.fix.should == @zero_pos
+ @zero_neg.fix.should == @zero_neg
+ end
+
+ it "does not allow any arguments" do
+ lambda {
+ @mixed.fix(10)
+ }.should raise_error(ArgumentError)
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/fixtures/classes.rb b/spec/ruby/library/bigdecimal/fixtures/classes.rb
new file mode 100644
index 0000000000..06e4474cf0
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/fixtures/classes.rb
@@ -0,0 +1,17 @@
+module BigDecimalSpecs
+ # helper method to sure that the global limit is reset back
+ def self.with_limit(l)
+ old = BigDecimal.limit(l)
+ yield
+ ensure
+ BigDecimal.limit(old)
+ end
+
+ def self.with_rounding(r)
+ old = BigDecimal.mode(BigDecimal::ROUND_MODE)
+ BigDecimal.mode(BigDecimal::ROUND_MODE, r)
+ yield
+ ensure
+ BigDecimal.mode(BigDecimal::ROUND_MODE, old)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/floor_spec.rb b/spec/ruby/library/bigdecimal/floor_spec.rb
new file mode 100644
index 0000000000..0bae6e4ab0
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/floor_spec.rb
@@ -0,0 +1,100 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#floor" do
+ before :each do
+ @one = BigDecimal("1")
+ @three = BigDecimal("3")
+ @four = BigDecimal("4")
+ @zero = BigDecimal("0")
+ @mixed = BigDecimal("1.23456789")
+ @mixed_big = BigDecimal("1.23456789E100")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+ @nan = BigDecimal("NaN")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ end
+
+ it "returns the greatest integer smaller or equal to self" do
+ @pos_int.floor.should == @pos_int
+ @neg_int.floor.should == @neg_int
+ @pos_frac.floor.should == @zero
+ @neg_frac.floor.should == BigDecimal("-1")
+ @zero.floor.should == 0
+ @zero_pos.floor.should == @zero_pos
+ @zero_neg.floor.should == @zero_neg
+
+ BigDecimal('2.3').floor.should == 2
+ BigDecimal('2.5').floor.should == 2
+ BigDecimal('2.9999').floor.should == 2
+ BigDecimal('-2.3').floor.should == -3
+ BigDecimal('-2.5').floor.should == -3
+ BigDecimal('-2.9999').floor.should == -3
+ BigDecimal('0.8').floor.should == 0
+ BigDecimal('-0.8').floor.should == -1
+ end
+
+ it "raise exception, if self is special value" do
+ lambda { @infinity.floor }.should raise_error(FloatDomainError)
+ lambda { @infinity_neg.floor }.should raise_error(FloatDomainError)
+ lambda { @nan.floor }.should raise_error(FloatDomainError)
+ end
+
+ it "returns n digits right of the decimal point if given n > 0" do
+ @mixed.floor(1).should == BigDecimal("1.2")
+ @mixed.floor(5).should == BigDecimal("1.23456")
+
+ BigDecimal("-0.03").floor(1).should == BigDecimal("-0.1")
+ BigDecimal("0.03").floor(1).should == BigDecimal("0")
+
+ BigDecimal("23.45").floor(0).should == BigDecimal('23')
+ BigDecimal("23.45").floor(1).should == BigDecimal('23.4')
+ BigDecimal("23.45").floor(2).should == BigDecimal('23.45')
+
+ BigDecimal("-23.45").floor(0).should == BigDecimal('-24')
+ BigDecimal("-23.45").floor(1).should == BigDecimal('-23.5')
+ BigDecimal("-23.45").floor(2).should == BigDecimal('-23.45')
+
+ BigDecimal("2E-10").floor(0).should == @zero
+ BigDecimal("2E-10").floor(9).should == @zero
+ BigDecimal("2E-10").floor(10).should == BigDecimal('2E-10')
+ BigDecimal("2E-10").floor(11).should == BigDecimal('2E-10')
+
+ (1..10).each do |n|
+ # 0.3, 0.33, 0.333, etc.
+ (@one.div(@three,20)).floor(n).should == BigDecimal("0.#{'3'*n}")
+ # 1.3, 1.33, 1.333, etc.
+ (@four.div(@three,20)).floor(n).should == BigDecimal("1.#{'3'*n}")
+ (BigDecimal('31').div(@three,20)).floor(n).should == BigDecimal("10.#{'3'*n}")
+ end
+ (1..10).each do |n|
+ # -0.4, -0.34, -0.334, etc.
+ (-@one.div(@three,20)).floor(n).should == BigDecimal("-0.#{'3'*(n-1)}4")
+ end
+ (1..10).each do |n|
+ (@three.div(@one,20)).floor(n).should == @three
+ end
+ (1..10).each do |n|
+ (-@three.div(@one,20)).floor(n).should == -@three
+ end
+ end
+
+ it "sets n digits left of the decimal point to 0, if given n < 0" do
+ BigDecimal("13345.234").floor(-2).should == BigDecimal("13300.0")
+ @mixed_big.floor(-99).should == BigDecimal("0.12E101")
+ @mixed_big.floor(-100).should == BigDecimal("0.1E101")
+ @mixed_big.floor(-95).should == BigDecimal("0.123456E101")
+ (1..10).each do |n|
+ BigDecimal('1.8').floor(-n).should == @zero
+ end
+ BigDecimal("1E10").floor(-30).should == @zero
+ BigDecimal("-1E10").floor(-30).should == BigDecimal('-1E30')
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/frac_spec.rb b/spec/ruby/library/bigdecimal/frac_spec.rb
new file mode 100644
index 0000000000..9a727a70dd
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/frac_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#frac" do
+ before :each do
+ @zero = BigDecimal("0")
+ @mixed = BigDecimal("1.23456789")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+ @nan = BigDecimal("NaN")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ end
+
+ it "returns a BigDecimal" do
+ @pos_int.frac.kind_of?(BigDecimal).should == true
+ @neg_int.frac.kind_of?(BigDecimal).should == true
+ @pos_frac.kind_of?(BigDecimal).should == true
+ @neg_frac.kind_of?(BigDecimal).should == true
+ end
+
+ it "returns the fractional part of the absolute value" do
+ @mixed.frac.should == BigDecimal("0.23456789")
+ @pos_frac.frac.should == @pos_frac
+ @neg_frac.frac.should == @neg_frac
+ end
+
+ it "returns 0 if the value is 0" do
+ @zero.frac.should == @zero
+ end
+
+ it "returns 0 if the value is an integer" do
+ @pos_int.frac.should == @zero
+ @neg_int.frac.should == @zero
+ end
+
+ it "correctly handles special values" do
+ @infinity.frac.should == @infinity
+ @infinity_neg.frac.should == @infinity_neg
+ @nan.frac.nan?.should == true
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/gt_spec.rb b/spec/ruby/library/bigdecimal/gt_spec.rb
new file mode 100644
index 0000000000..2f9ea4fd68
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/gt_spec.rb
@@ -0,0 +1,98 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#>" do
+ before :each do
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @mixed = BigDecimal("1.23456789")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @int_mock = mock('123')
+ class << @int_mock
+ def coerce(other)
+ return [other, BigDecimal('123')]
+ end
+ def > (other)
+ BigDecimal('123') > other
+ end
+ end
+
+ @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac,
+ -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1,
+ @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg]
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+
+ @float_infinity = Float::INFINITY
+ @float_infinity_neg = -Float::INFINITY
+
+ @nan = BigDecimal("NaN")
+ end
+
+ it "returns true if a > b" do
+ one = BigDecimal("1")
+ two = BigDecimal("2")
+
+ frac_1 = BigDecimal("1E-99999")
+ frac_2 = BigDecimal("0.9E-99999")
+ (@zero > one).should == false
+ (two > @zero).should == true
+ (frac_2 > frac_1).should == false
+
+ (@neg_int > @pos_int).should == false
+ (@pos_int > @neg_int).should == true
+ (@neg_int > @pos_frac).should == false
+ (@pos_frac > @neg_int).should == true
+ (@zero > @zero_pos).should == false
+ (@zero > @zero_neg).should == false
+ (@zero_neg > @zero_pos).should == false
+ (@zero_pos > @zero_neg).should == false
+ end
+
+ it "properly handles infinity values" do
+ @values.each { |val|
+ (val > @infinity).should == false
+ (@infinity > val).should == true
+ (val > @infinity_neg).should == true
+ (@infinity_neg > val).should == false
+ }
+ (@infinity > @infinity).should == false
+ (@infinity_neg > @infinity_neg).should == false
+ (@infinity > @infinity_neg).should == true
+ (@infinity_neg > @infinity).should == false
+ end
+
+ ruby_bug "#13674", ""..."2.4" do
+ it "properly handles Float infinity values" do
+ @values.each { |val|
+ (val > @float_infinity).should == false
+ (@float_infinity > val).should == true
+ (val > @float_infinity_neg).should == true
+ (@float_infinity_neg > val).should == false
+ }
+ end
+ end
+
+ it "properly handles NaN values" do
+ @values += [@infinity, @infinity_neg, @nan]
+ @values.each { |val|
+ (@nan > val).should == false
+ (val > @nan).should == false
+ }
+ end
+
+ it "raises an ArgumentError if the argument can't be coerced into a BigDecimal" do
+ lambda {@zero > nil }.should raise_error(ArgumentError)
+ lambda {@infinity > nil }.should raise_error(ArgumentError)
+ lambda {@infinity_neg > nil }.should raise_error(ArgumentError)
+ lambda {@mixed > nil }.should raise_error(ArgumentError)
+ lambda {@pos_int > nil }.should raise_error(ArgumentError)
+ lambda {@neg_frac > nil }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/gte_spec.rb b/spec/ruby/library/bigdecimal/gte_spec.rb
new file mode 100644
index 0000000000..aab5338ad6
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/gte_spec.rb
@@ -0,0 +1,102 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#>=" do
+ before :each do
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @mixed = BigDecimal("1.23456789")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @int_mock = mock('123')
+ class << @int_mock
+ def coerce(other)
+ return [other, BigDecimal('123')]
+ end
+ def >= (other)
+ BigDecimal('123') >= other
+ end
+ end
+
+ @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac,
+ -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1,
+ @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg]
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+
+ @float_infinity = Float::INFINITY
+ @float_infinity_neg = -Float::INFINITY
+
+ @nan = BigDecimal("NaN")
+ end
+
+ it "returns true if a >= b" do
+ one = BigDecimal("1")
+ two = BigDecimal("2")
+
+ frac_1 = BigDecimal("1E-99999")
+ frac_2 = BigDecimal("0.9E-99999")
+
+ (@zero >= one).should == false
+ (two >= @zero).should == true
+
+ (frac_2 >= frac_1).should == false
+ (two >= two).should == true
+ (frac_1 >= frac_1).should == true
+
+ (@neg_int >= @pos_int).should == false
+ (@pos_int >= @neg_int).should == true
+ (@neg_int >= @pos_frac).should == false
+ (@pos_frac >= @neg_int).should == true
+ (@zero >= @zero_pos).should == true
+ (@zero >= @zero_neg).should == true
+ (@zero_neg >= @zero_pos).should == true
+ (@zero_pos >= @zero_neg).should == true
+ end
+
+ it "properly handles infinity values" do
+ @values.each { |val|
+ (val >= @infinity).should == false
+ (@infinity >= val).should == true
+ (val >= @infinity_neg).should == true
+ (@infinity_neg >= val).should == false
+ }
+ (@infinity >= @infinity).should == true
+ (@infinity_neg >= @infinity_neg).should == true
+ (@infinity >= @infinity_neg).should == true
+ (@infinity_neg >= @infinity).should == false
+ end
+
+ ruby_bug "#13674", ""..."2.4" do
+ it "properly handles Float infinity values" do
+ @values.each { |val|
+ (val >= @float_infinity).should == false
+ (@float_infinity >= val).should == true
+ (val >= @float_infinity_neg).should == true
+ (@float_infinity_neg >= val).should == false
+ }
+ end
+ end
+
+ it "properly handles NaN values" do
+ @values += [@infinity, @infinity_neg, @nan]
+ @values.each { |val|
+ (@nan >= val).should == false
+ (val >= @nan).should == false
+ }
+ end
+
+ it "returns nil if the argument is nil" do
+ lambda {@zero >= nil }.should raise_error(ArgumentError)
+ lambda {@infinity >= nil }.should raise_error(ArgumentError)
+ lambda {@infinity_neg >= nil }.should raise_error(ArgumentError)
+ lambda {@mixed >= nil }.should raise_error(ArgumentError)
+ lambda {@pos_int >= nil }.should raise_error(ArgumentError)
+ lambda {@neg_frac >= nil }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/infinite_spec.rb b/spec/ruby/library/bigdecimal/infinite_spec.rb
new file mode 100644
index 0000000000..b218ee371c
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/infinite_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#infinite?" do
+
+ it "returns 1 if self is Infinity" do
+ BigDecimal("Infinity").infinite?.should == 1
+ end
+
+ it "returns -1 if self is -Infinity" do
+ BigDecimal("-Infinity").infinite?.should == -1
+ end
+
+ it "returns not true otherwise" do
+ e2_plus = BigDecimal("2E40001")
+ e3_minus = BigDecimal("3E-20001")
+ really_small_zero = BigDecimal("0E-200000000")
+ really_big_zero = BigDecimal("0E200000000000")
+ e3_minus.infinite?.should == nil
+ e2_plus.infinite?.should == nil
+ really_small_zero.infinite?.should == nil
+ really_big_zero.infinite?.should == nil
+ BigDecimal("0.000000000000000000000000").infinite?.should == nil
+ end
+
+ it "returns not true if self is NaN" do
+ # NaN is a special value which is neither finite nor infinite.
+ nan = BigDecimal("NaN")
+ nan.infinite?.should == nil
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/inspect_spec.rb b/spec/ruby/library/bigdecimal/inspect_spec.rb
new file mode 100644
index 0000000000..9831b2be8e
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/inspect_spec.rb
@@ -0,0 +1,47 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#inspect" do
+
+ before :each do
+ @bigdec = BigDecimal.new("1234.5678")
+ end
+
+ it "returns String" do
+ @bigdec.inspect.kind_of?(String).should == true
+ end
+
+ ruby_version_is ""..."2.4" do
+ it "returns String starting with #" do
+ @bigdec.inspect[0].should == ?#
+ end
+
+ it "encloses information in angle brackets" do
+ @bigdec.inspect.should =~ /^.<.*>$/
+ end
+
+ it "is comma separated list of three items" do
+ @bigdec.inspect.should =~ /...*,.*,.*/
+ end
+
+ it "value after first comma is value as string" do
+ @bigdec.inspect.split(",")[1].should == "\'0.12345678E4\'"
+ end
+
+ it "last part is number of significant digits" do
+ signific_string = "#{@bigdec.precs[0]}(#{@bigdec.precs[1]})"
+ @bigdec.inspect.split(",")[2].should == signific_string + ">"
+ end
+
+ it "looks like this" do
+ regex = /^\#\<BigDecimal\:.*,'0\.12345678E4',[0-9]+\([0-9]+\)>$/
+ @bigdec.inspect.should =~ regex
+ end
+ end
+
+ ruby_version_is "2.4" do
+ it "looks like this" do
+ @bigdec.inspect.should == "0.12345678e4"
+ end
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/limit_spec.rb b/spec/ruby/library/bigdecimal/limit_spec.rb
new file mode 100644
index 0000000000..41308abcd8
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/limit_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal.limit" do
+ it "returns the value before set if the passed argument is nil or is not specified" do
+ old = BigDecimal.limit
+ BigDecimal.limit.should == 0
+ BigDecimal.limit(10).should == 0
+ BigDecimal.limit.should == 10
+ BigDecimal.limit(old)
+ end
+
+ it "use the global limit if no precision is specified" do
+ BigDecimalSpecs.with_limit(0) do
+ (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.888')
+ (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.664')
+ end
+
+ BigDecimalSpecs.with_limit(1) do
+ (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.9')
+ (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('3')
+ end
+
+ BigDecimalSpecs.with_limit(2) do
+ (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.89')
+ (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.7')
+ end
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/lt_spec.rb b/spec/ruby/library/bigdecimal/lt_spec.rb
new file mode 100644
index 0000000000..089e7aef73
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/lt_spec.rb
@@ -0,0 +1,96 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#<" do
+ before :each do
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @mixed = BigDecimal("1.23456789")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @int_mock = mock('123')
+ class << @int_mock
+ def coerce(other)
+ return [other, BigDecimal('123')]
+ end
+ def < (other)
+ BigDecimal('123') < other
+ end
+ end
+
+ @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac,
+ -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1,
+ @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg]
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+
+ @float_infinity = Float::INFINITY
+ @float_infinity_neg = -Float::INFINITY
+
+ @nan = BigDecimal("NaN")
+ end
+
+ it "returns true if a < b" do
+ one = BigDecimal("1")
+ two = BigDecimal("2")
+ frac_1 = BigDecimal("1E-99999")
+ frac_2 = BigDecimal("0.9E-99999")
+ (@zero < one).should == true
+ (two < @zero).should == false
+ (frac_2 < frac_1).should == true
+ (@neg_int < @pos_int).should == true
+ (@pos_int < @neg_int).should == false
+ (@neg_int < @pos_frac).should == true
+ (@pos_frac < @neg_int).should == false
+ (@zero < @zero_pos).should == false
+ (@zero < @zero_neg).should == false
+ (@zero_neg < @zero_pos).should == false
+ (@zero_pos < @zero_neg).should == false
+ end
+
+ it "properly handles infinity values" do
+ @values.each { |val|
+ (val < @infinity).should == true
+ (@infinity < val).should == false
+ (val < @infinity_neg).should == false
+ (@infinity_neg < val).should == true
+ }
+ (@infinity < @infinity).should == false
+ (@infinity_neg < @infinity_neg).should == false
+ (@infinity < @infinity_neg).should == false
+ (@infinity_neg < @infinity).should == true
+ end
+
+ ruby_bug "#13674", ""..."2.4" do
+ it "properly handles Float infinity values" do
+ @values.each { |val|
+ (val < @float_infinity).should == true
+ (@float_infinity < val).should == false
+ (val < @float_infinity_neg).should == false
+ (@float_infinity_neg < val).should == true
+ }
+ end
+ end
+
+ it "properly handles NaN values" do
+ @values += [@infinity, @infinity_neg, @nan]
+ @values.each { |val|
+ (@nan < val).should == false
+ (val < @nan).should == false
+ }
+ end
+
+ it "raises an ArgumentError if the argument can't be coerced into a BigDecimal" do
+ lambda {@zero < nil }.should raise_error(ArgumentError)
+ lambda {@infinity < nil }.should raise_error(ArgumentError)
+ lambda {@infinity_neg < nil }.should raise_error(ArgumentError)
+ lambda {@mixed < nil }.should raise_error(ArgumentError)
+ lambda {@pos_int < nil }.should raise_error(ArgumentError)
+ lambda {@neg_frac < nil }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/lte_spec.rb b/spec/ruby/library/bigdecimal/lte_spec.rb
new file mode 100644
index 0000000000..5cda9842bd
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/lte_spec.rb
@@ -0,0 +1,102 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#<=" do
+ before :each do
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @mixed = BigDecimal("1.23456789")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @int_mock = mock('123')
+ class << @int_mock
+ def coerce(other)
+ return [other, BigDecimal('123')]
+ end
+ def <= (other)
+ BigDecimal('123') <= other
+ end
+ end
+
+ @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac,
+ -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1,
+ @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg]
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+
+ @float_infinity = Float::INFINITY
+ @float_infinity_neg = -Float::INFINITY
+
+ @nan = BigDecimal("NaN")
+ end
+
+ it "returns true if a <= b" do
+ one = BigDecimal("1")
+ two = BigDecimal("2")
+
+ frac_1 = BigDecimal("1E-99999")
+ frac_2 = BigDecimal("0.9E-99999")
+
+ (@zero <= one).should == true
+ (two <= @zero).should == false
+
+ (frac_2 <= frac_1).should == true
+ (two <= two).should == true
+ (frac_1 <= frac_1).should == true
+
+ (@neg_int <= @pos_int).should == true
+ (@pos_int <= @neg_int).should == false
+ (@neg_int <= @pos_frac).should == true
+ (@pos_frac <= @neg_int).should == false
+ (@zero <= @zero_pos).should == true
+ (@zero <= @zero_neg).should == true
+ (@zero_neg <= @zero_pos).should == true
+ (@zero_pos <= @zero_neg).should == true
+ end
+
+ it "properly handles infinity values" do
+ @values.each { |val|
+ (val <= @infinity).should == true
+ (@infinity <= val).should == false
+ (val <= @infinity_neg).should == false
+ (@infinity_neg <= val).should == true
+ }
+ (@infinity <= @infinity).should == true
+ (@infinity_neg <= @infinity_neg).should == true
+ (@infinity <= @infinity_neg).should == false
+ (@infinity_neg <= @infinity).should == true
+ end
+
+ ruby_bug "#13674", ""..."2.4" do
+ it "properly handles Float infinity values" do
+ @values.each { |val|
+ (val <= @float_infinity).should == true
+ (@float_infinity <= val).should == false
+ (val <= @float_infinity_neg).should == false
+ (@float_infinity_neg <= val).should == true
+ }
+ end
+ end
+
+ it "properly handles NaN values" do
+ @values += [@infinity, @infinity_neg, @nan]
+ @values.each { |val|
+ (@nan <= val).should == false
+ (val <= @nan).should == false
+ }
+ end
+
+ it "raises an ArgumentError if the argument can't be coerced into a BigDecimal" do
+ lambda {@zero <= nil }.should raise_error(ArgumentError)
+ lambda {@infinity <= nil }.should raise_error(ArgumentError)
+ lambda {@infinity_neg <= nil }.should raise_error(ArgumentError)
+ lambda {@mixed <= nil }.should raise_error(ArgumentError)
+ lambda {@pos_int <= nil }.should raise_error(ArgumentError)
+ lambda {@neg_frac <= nil }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/minus_spec.rb b/spec/ruby/library/bigdecimal/minus_spec.rb
new file mode 100644
index 0000000000..bdd8478465
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/minus_spec.rb
@@ -0,0 +1,58 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#-" do
+
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @two = BigDecimal("2")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ end
+
+ it "returns a - b" do
+ (@two - @one).should == @one
+ (@one - @two).should == @one_minus
+ (@one - @one_minus).should == @two
+ (@frac_2 - @frac_1).should == BigDecimal("-0.1E-99999")
+ (@two - @two).should == @zero
+ (@frac_1 - @frac_1).should == @zero
+ (BigDecimal('1.23456789') - BigDecimal('1.2')).should == BigDecimal("0.03456789")
+ end
+
+ it "returns NaN if NaN is involved" do
+ (@one - @nan).nan?.should == true
+ (@nan - @one).nan?.should == true
+ (@nan - @nan).nan?.should == true
+ (@nan - @infinity).nan?.should == true
+ (@nan - @infinity_minus).nan?.should == true
+ (@infinity - @nan).nan?.should == true
+ (@infinity_minus - @nan).nan?.should == true
+ end
+
+ it "returns NaN both operands are infinite with the same sign" do
+ (@infinity - @infinity).nan?.should == true
+ (@infinity_minus - @infinity_minus).nan?.should == true
+ end
+
+ it "returns Infinity or -Infinity if these are involved" do
+ (@infinity - @infinity_minus).should == @infinity
+ (@infinity_minus - @infinity).should == @infinity_minus
+
+ (@infinity - @zero).should == @infinity
+ (@infinity - @frac_2).should == @infinity
+ (@infinity - @two).should == @infinity
+ (@infinity - @one_minus).should == @infinity
+
+ (@zero - @infinity).should == @infinity_minus
+ (@frac_2 - @infinity).should == @infinity_minus
+ (@two - @infinity).should == @infinity_minus
+ (@one_minus - @infinity).should == @infinity_minus
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/mode_spec.rb b/spec/ruby/library/bigdecimal/mode_spec.rb
new file mode 100644
index 0000000000..d88ac61aaf
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/mode_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal.mode" do
+ #the default value of BigDecimal exception constants is false
+ after :each do
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false)
+ end
+
+ it "returns the appropriate value and continue the computation if the flag is false" do
+ BigDecimal("NaN").add(BigDecimal("1"),0).nan?.should == true
+ BigDecimal("0").add(BigDecimal("Infinity"),0).should == BigDecimal("Infinity")
+ BigDecimal("1").quo(BigDecimal("0")).should == BigDecimal("Infinity")
+ end
+
+ it "returns Infinity when too big" do
+ BigDecimal("1E11111111111111111111").should == BigDecimal("Infinity")
+ (BigDecimal("1E1000000000000000000")**10).should == BigDecimal("Infinity")
+ end
+
+ it "raise an exception if the flag is true" do
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true)
+ lambda { BigDecimal("NaN").add(BigDecimal("1"),0) }.should raise_error(FloatDomainError)
+ BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true)
+ lambda { BigDecimal("0").add(BigDecimal("Infinity"),0) }.should raise_error(FloatDomainError)
+ BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true)
+ lambda { BigDecimal("1").quo(BigDecimal("0")) }.should raise_error(FloatDomainError)
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true)
+ lambda { BigDecimal("1E11111111111111111111") }.should raise_error(FloatDomainError)
+ lambda { (BigDecimal("1E1000000000000000000")**10) }.should raise_error(FloatDomainError)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/modulo_spec.rb b/spec/ruby/library/bigdecimal/modulo_spec.rb
new file mode 100644
index 0000000000..6feeb685eb
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/modulo_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/modulo', __FILE__)
+
+describe "BigDecimal#%" do
+ it_behaves_like(:bigdecimal_modulo, :%)
+ it_behaves_like(:bigdecimal_modulo_zerodivisionerror, :%)
+end
+
+describe "BigDecimal#modulo" do
+ it_behaves_like(:bigdecimal_modulo, :modulo)
+ it_behaves_like(:bigdecimal_modulo_zerodivisionerror, :modulo)
+end
diff --git a/spec/ruby/library/bigdecimal/mult_spec.rb b/spec/ruby/library/bigdecimal/mult_spec.rb
new file mode 100644
index 0000000000..a140cf899a
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/mult_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/mult', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#mult" do
+ it_behaves_like :bigdecimal_mult, :mult, [10]
+end
+
+describe "BigDecimal#mult" do
+ before :each do
+ @one = BigDecimal "1"
+ @e3_minus = BigDecimal "3E-20001"
+ @e = BigDecimal "1.00000000000000000000123456789"
+ @tolerance = @e.sub @one, 1000
+ @tolerance2 = BigDecimal "30001E-20005"
+
+ end
+
+ it "multiply self with other with (optional) precision" do
+ @e.mult(@one, 1).should be_close(@one, @tolerance)
+ @e3_minus.mult(@one, 1).should be_close(0, @tolerance2)
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/multiply_spec.rb b/spec/ruby/library/bigdecimal/multiply_spec.rb
new file mode 100644
index 0000000000..842e22eaa2
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/multiply_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/mult', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#*" do
+ it_behaves_like :bigdecimal_mult, :*, []
+end
+
+describe "BigDecimal#*" do
+ before :each do
+ @e3_minus = BigDecimal("3E-20001")
+ @e3_plus = BigDecimal("3E20001")
+ @e = BigDecimal("1.00000000000000000000123456789")
+ @one = BigDecimal("1")
+ end
+
+ it "multiply self with other" do
+ (@one * @one).should == @one
+ (@e3_minus * @e3_plus).should == BigDecimal("9")
+ # Can't do this till we implement **
+ # (@e3_minus * @e3_minus).should == @e3_minus ** 2
+ # So let's rewrite it as:
+ (@e3_minus * @e3_minus).should == BigDecimal("9E-40002")
+ (@e * @one).should == @e
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/nan_spec.rb b/spec/ruby/library/bigdecimal/nan_spec.rb
new file mode 100644
index 0000000000..5c291629b3
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/nan_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#nan?" do
+
+ it "returns true if self is not a number" do
+ BigDecimal("NaN").nan?.should == true
+ end
+
+ it "returns false if self is not a NaN" do
+ BigDecimal("Infinity").nan?.should == false
+ BigDecimal("-Infinity").nan?.should == false
+ BigDecimal("0").nan?.should == false
+ BigDecimal("+0").nan?.should == false
+ BigDecimal("-0").nan?.should == false
+ BigDecimal("2E40001").nan?.should == false
+ BigDecimal("3E-20001").nan?.should == false
+ BigDecimal("0E-200000000").nan?.should == false
+ BigDecimal("0E200000000000").nan?.should == false
+ BigDecimal("0.000000000000000000000000").nan?.should == false
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/new_spec.rb b/spec/ruby/library/bigdecimal/new_spec.rb
new file mode 100644
index 0000000000..de3aa195ca
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/new_spec.rb
@@ -0,0 +1,109 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal.new" do
+
+ it "creates a new object of class BigDecimal" do
+ BigDecimal.new("3.14159").should be_kind_of(BigDecimal)
+ (0..9).each {|i|
+ BigDecimal.new("1#{i}").should == 10 + i
+ BigDecimal.new("-1#{i}").should == -10 - i
+ BigDecimal.new("1E#{i}").should == 10**i
+ BigDecimal.new("1000000E-#{i}").should == 10**(6-i).to_f
+ # ^ to_f to avoid Rational type
+ }
+ (1..9).each {|i|
+ BigDecimal.new("100.#{i}").to_s.should =~ /\A0\.100#{i}E3\z/i
+ BigDecimal.new("-100.#{i}").to_s.should =~ /\A-0\.100#{i}E3\z/i
+ }
+ end
+
+ it "accepts significant digits >= given precision" do
+ BigDecimal.new("3.1415923", 10).precs[1].should >= 10
+ end
+
+ it "determines precision from initial value" do
+ pi_string = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043"
+ BigDecimal.new(pi_string).precs[1].should >= pi_string.size-1
+ end
+
+ it "ignores leading whitespace" do
+ BigDecimal.new(" \t\n \r1234").should == BigDecimal.new("1234")
+ BigDecimal.new(" \t\n \rNaN \n").nan?.should == true
+ BigDecimal.new(" \t\n \rInfinity \n").infinite?.should == 1
+ BigDecimal.new(" \t\n \r-Infinity \n").infinite?.should == -1
+ end
+
+ it "ignores trailing garbage" do
+ BigDecimal.new("123E45ruby").should == BigDecimal.new("123E45")
+ BigDecimal.new("123x45").should == BigDecimal.new("123")
+ BigDecimal.new("123.4%E5").should == BigDecimal.new("123.4")
+ BigDecimal.new("1E2E3E4E5E").should == BigDecimal.new("100")
+ end
+
+ ruby_version_is ""..."2.4" do
+ it "treats invalid strings as 0.0" do
+ BigDecimal.new("ruby").should == BigDecimal.new("0.0")
+ BigDecimal.new(" \t\n \r-\t\t\tInfinity \n").should == BigDecimal.new("0.0")
+ end
+ end
+
+ ruby_version_is "2.4" do
+ it "raises ArgumentError for invalid strings" do
+ lambda { BigDecimal.new("ruby") }.should raise_error(ArgumentError)
+ lambda { BigDecimal.new(" \t\n \r-\t\t\tInfinity \n") }.should raise_error(ArgumentError)
+ end
+ end
+
+ it "allows omitting the integer part" do
+ BigDecimal.new(".123").should == BigDecimal.new("0.123")
+ end
+
+ it "allows for underscores in all parts" do
+ reference = BigDecimal.new("12345.67E89")
+
+ BigDecimal.new("12_345.67E89").should == reference
+ BigDecimal.new("1_2_3_4_5_._6____7_E89").should == reference
+ BigDecimal.new("12345_.67E_8__9_").should == reference
+ end
+
+ it "accepts NaN and [+-]Infinity" do
+ BigDecimal.new("NaN").nan?.should == true
+
+ pos_inf = BigDecimal.new("Infinity")
+ pos_inf.finite?.should == false
+ pos_inf.should > 0
+ pos_inf.should == BigDecimal.new("+Infinity")
+
+ neg_inf = BigDecimal.new("-Infinity")
+ neg_inf.finite?.should == false
+ neg_inf.should < 0
+ end
+
+ it "allows for [eEdD] as exponent separator" do
+ reference = BigDecimal.new("12345.67E89")
+
+ BigDecimal.new("12345.67e89").should == reference
+ BigDecimal.new("12345.67E89").should == reference
+ BigDecimal.new("12345.67d89").should == reference
+ BigDecimal.new("12345.67D89").should == reference
+ end
+
+ it "allows for varying signs" do
+ reference = BigDecimal.new("123.456E1")
+
+ BigDecimal.new("+123.456E1").should == reference
+ BigDecimal.new("-123.456E1").should == -reference
+ BigDecimal.new("123.456E+1").should == reference
+ BigDecimal.new("12345.6E-1").should == reference
+ BigDecimal.new("+123.456E+1").should == reference
+ BigDecimal.new("+12345.6E-1").should == reference
+ BigDecimal.new("-123.456E+1").should == -reference
+ BigDecimal.new("-12345.6E-1").should == -reference
+ end
+
+ it 'raises ArgumentError when Float is used without precision' do
+ lambda { BigDecimal(1.0) }.should raise_error(ArgumentError)
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/nonzero_spec.rb b/spec/ruby/library/bigdecimal/nonzero_spec.rb
new file mode 100644
index 0000000000..336c72a6b2
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/nonzero_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#nonzero?" do
+
+ it "returns self if self doesn't equal zero" do
+ # documentation says, it returns true. (04/10/08)
+ e2_plus = BigDecimal("2E40001")
+ e3_minus = BigDecimal("3E-20001")
+ infinity = BigDecimal("Infinity")
+ infinity_minus = BigDecimal("-Infinity")
+ nan = BigDecimal("NaN")
+ infinity.nonzero?.should equal(infinity)
+ infinity_minus.nonzero?.should equal(infinity_minus)
+ nan.nonzero?.should equal(nan)
+ e3_minus.nonzero?.should equal(e3_minus)
+ e2_plus.nonzero?.should equal(e2_plus)
+ end
+
+ it "returns nil otherwise" do
+ # documentation states, it should return false. (04/10/08)
+ really_small_zero = BigDecimal("0E-200000000")
+ really_big_zero = BigDecimal("0E200000000000")
+ really_small_zero.nonzero?.should == nil
+ really_big_zero.nonzero?.should == nil
+ BigDecimal("0.000000000000000000000000").nonzero?.should == nil
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/plus_spec.rb b/spec/ruby/library/bigdecimal/plus_spec.rb
new file mode 100644
index 0000000000..72ec282075
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/plus_spec.rb
@@ -0,0 +1,47 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#+" do
+
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @two = BigDecimal("2")
+ @three = BigDecimal("3")
+ @ten = BigDecimal("10")
+ @eleven = BigDecimal("11")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ end
+
+ it "returns a + b" do
+ (@two + @one).should == @three
+ (@one + @two).should == @three
+ (@one + @one_minus).should == @zero
+ (@zero + @one).should == @one
+ (@ten + @one).should == @eleven
+ (@frac_1 + @frac_2).should == BigDecimal("1.9E-99999")
+ (@frac_2 + @frac_1).should == BigDecimal("1.9E-99999")
+ (@frac_1 + @frac_1).should == BigDecimal("2E-99999")
+ end
+
+ it "returns NaN if NaN is involved" do
+ (@one + @nan).nan?.should == true
+ (@nan + @one).nan?.should == true
+ end
+
+ it "returns Infinity or -Infinity if these are involved" do
+ (@zero + @infinity).should == @infinity
+ (@frac_2 + @infinity).should == @infinity
+ (@two + @infinity_minus).should == @infinity_minus
+ end
+
+ it "returns NaN if Infinity + (- Infinity)" do
+ (@infinity + @infinity_minus).nan?.should == true
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/power_spec.rb b/spec/ruby/library/bigdecimal/power_spec.rb
new file mode 100644
index 0000000000..f2b1a9b5c8
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/power_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/power', __FILE__)
+
+describe "BigDecimal#power" do
+ it_behaves_like(:bigdecimal_power, :power)
+end
diff --git a/spec/ruby/library/bigdecimal/precs_spec.rb b/spec/ruby/library/bigdecimal/precs_spec.rb
new file mode 100644
index 0000000000..c7700a3819
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/precs_spec.rb
@@ -0,0 +1,49 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#precs" do
+
+ before :each do
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+ @nan = BigDecimal("NaN")
+ @zero = BigDecimal("0")
+ @zero_neg = BigDecimal("-0")
+
+ @arr = [BigDecimal("2E40001"), BigDecimal("3E-20001"),\
+ @infinity, @infinity_neg, @nan, @zero, @zero_neg]
+ @precision = BigDecimal::BASE.to_s.length - 1
+ end
+
+ it "returns array of two values" do
+ @arr.each do |x|
+ x.precs.kind_of?(Array).should == true
+ x.precs.size.should == 2
+ end
+ end
+
+ it "returns Integers as array values" do
+ @arr.each do |x|
+ x.precs[0].kind_of?(Integer).should == true
+ x.precs[1].kind_of?(Integer).should == true
+ end
+ end
+
+ it "returns the current value of significant digits as the first value" do
+ BigDecimal("3.14159").precs[0].should >= 6
+ BigDecimal('1').precs[0].should == BigDecimal('1' + '0' * 100).precs[0]
+ [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value|
+ value.precs[0].should <= @precision
+ end
+ end
+
+ it "returns the maximum number of significant digits as the second value" do
+ BigDecimal("3.14159").precs[1].should >= 6
+ BigDecimal('1').precs[1].should >= 1
+ BigDecimal('1' + '0' * 100).precs[1] >= 101
+ [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value|
+ value.precs[1].should >= 1
+ end
+ end
+end
+
diff --git a/spec/ruby/library/bigdecimal/quo_spec.rb b/spec/ruby/library/bigdecimal/quo_spec.rb
new file mode 100644
index 0000000000..bc27fd0f5e
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/quo_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/quo', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#quo" do
+ it_behaves_like :bigdecimal_quo, :quo, []
+
+ it "returns NaN if NaN is involved" do
+ BigDecimal("1").quo(BigDecimal("NaN")).nan?.should == true
+ BigDecimal("NaN").quo(BigDecimal("1")).nan?.should == true
+ end
+end
+
diff --git a/spec/ruby/library/bigdecimal/remainder_spec.rb b/spec/ruby/library/bigdecimal/remainder_spec.rb
new file mode 100644
index 0000000000..796522c5c8
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/remainder_spec.rb
@@ -0,0 +1,84 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#remainder" do
+
+ before :each do
+ @zero = BigDecimal("0")
+ @one = BigDecimal("0")
+ @mixed = BigDecimal("1.23456789")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ end
+
+ it "it equals modulo, if both values are of same sign" do
+ BigDecimal('1234567890123456789012345679').remainder(BigDecimal('1')).should == @zero
+ BigDecimal('123456789').remainder(BigDecimal('333333333333333333333333333E-50')).should == BigDecimal('0.12233333333333333333345679E-24')
+
+ @mixed.remainder(@pos_frac).should == @mixed % @pos_frac
+ @pos_int.remainder(@pos_frac).should == @pos_int % @pos_frac
+ @neg_frac.remainder(@neg_int).should == @neg_frac % @neg_int
+ @neg_int.remainder(@neg_frac).should == @neg_int % @neg_frac
+ end
+
+ it "means self-arg*(self/arg).truncate" do
+ @mixed.remainder(@neg_frac).should == @mixed - @neg_frac * (@mixed / @neg_frac).truncate
+ @pos_int.remainder(@neg_frac).should == @pos_int - @neg_frac * (@pos_int / @neg_frac).truncate
+ @neg_frac.remainder(@pos_int).should == @neg_frac - @pos_int * (@neg_frac / @pos_int).truncate
+ @neg_int.remainder(@pos_frac).should == @neg_int - @pos_frac * (@neg_int / @pos_frac).truncate
+ end
+
+ it "returns NaN used with zero" do
+ @mixed.remainder(@zero).nan?.should == true
+ @zero.remainder(@zero).nan?.should == true
+ end
+
+ it "returns zero if used on zero" do
+ @zero.remainder(@mixed).should == @zero
+ end
+
+ it "returns NaN if NaN is involved" do
+ @nan.remainder(@nan).nan?.should == true
+ @nan.remainder(@one).nan?.should == true
+ @one.remainder(@nan).nan?.should == true
+ @infinity.remainder(@nan).nan?.should == true
+ @nan.remainder(@infinity).nan?.should == true
+ end
+
+ it "returns NaN if Infinity is involved" do
+ @infinity.remainder(@infinity).nan?.should == true
+ @infinity.remainder(@one).nan?.should == true
+ @infinity.remainder(@mixed).nan?.should == true
+ @infinity.remainder(@one_minus).nan?.should == true
+ @infinity.remainder(@frac_1).nan?.should == true
+ @one.remainder(@infinity).nan?.should == true
+
+ @infinity_minus.remainder(@infinity_minus).nan?.should == true
+ @infinity_minus.remainder(@one).nan?.should == true
+ @one.remainder(@infinity_minus).nan?.should == true
+ @frac_2.remainder(@infinity_minus).nan?.should == true
+
+ @infinity.remainder(@infinity_minus).nan?.should == true
+ @infinity_minus.remainder(@infinity).nan?.should == true
+ end
+
+ it "coerces arguments to BigDecimal if possible" do
+ @one.remainder(2).should == @one
+ end
+
+
+ it "raises TypeError if the argument cannot be coerced to BigDecimal" do
+ lambda {
+ @one.remainder('2')
+ }.should raise_error(TypeError)
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/round_spec.rb b/spec/ruby/library/bigdecimal/round_spec.rb
new file mode 100644
index 0000000000..6c1987c5d8
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/round_spec.rb
@@ -0,0 +1,202 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#round" do
+ before :each do
+ @one = BigDecimal("1")
+ @two = BigDecimal("2")
+ @three = BigDecimal("3")
+
+ @neg_one = BigDecimal("-1")
+ @neg_two = BigDecimal("-2")
+ @neg_three = BigDecimal("-3")
+
+ @p1_50 = BigDecimal("1.50")
+ @p1_51 = BigDecimal("1.51")
+ @p1_49 = BigDecimal("1.49")
+ @n1_50 = BigDecimal("-1.50")
+ @n1_51 = BigDecimal("-1.51")
+ @n1_49 = BigDecimal("-1.49")
+
+ @p2_50 = BigDecimal("2.50")
+ @p2_51 = BigDecimal("2.51")
+ @p2_49 = BigDecimal("2.49")
+ @n2_50 = BigDecimal("-2.50")
+ @n2_51 = BigDecimal("-2.51")
+ @n2_49 = BigDecimal("-2.49")
+ end
+
+ after :each do
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP)
+ end
+
+ it "uses default rounding method unless given" do
+ @p1_50.round(0).should == @two
+ @p1_51.round(0).should == @two
+ @p1_49.round(0).should == @one
+ @n1_50.round(0).should == @neg_two
+ @n1_51.round(0).should == @neg_two
+ @n1_49.round(0).should == @neg_one
+
+ @p2_50.round(0).should == @three
+ @p2_51.round(0).should == @three
+ @p2_49.round(0).should == @two
+ @n2_50.round(0).should == @neg_three
+ @n2_51.round(0).should == @neg_three
+ @n2_49.round(0).should == @neg_two
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN)
+
+ @p1_50.round(0).should == @one
+ @p1_51.round(0).should == @one
+ @p1_49.round(0).should == @one
+ @n1_50.round(0).should == @neg_one
+ @n1_51.round(0).should == @neg_one
+ @n1_49.round(0).should == @neg_one
+
+ @p2_50.round(0).should == @two
+ @p2_51.round(0).should == @two
+ @p2_49.round(0).should == @two
+ @n2_50.round(0).should == @neg_two
+ @n2_51.round(0).should == @neg_two
+ @n2_49.round(0).should == @neg_two
+ end
+
+ describe "BigDecimal::ROUND_UP" do
+ it "rounds values away from zero" do
+ @p1_50.round(0, BigDecimal::ROUND_UP).should == @two
+ @p1_51.round(0, BigDecimal::ROUND_UP).should == @two
+ @p1_49.round(0, BigDecimal::ROUND_UP).should == @two
+ @n1_50.round(0, BigDecimal::ROUND_UP).should == @neg_two
+ @n1_51.round(0, BigDecimal::ROUND_UP).should == @neg_two
+ @n1_49.round(0, BigDecimal::ROUND_UP).should == @neg_two
+
+ @p2_50.round(0, BigDecimal::ROUND_UP).should == @three
+ @p2_51.round(0, BigDecimal::ROUND_UP).should == @three
+ @p2_49.round(0, BigDecimal::ROUND_UP).should == @three
+ @n2_50.round(0, BigDecimal::ROUND_UP).should == @neg_three
+ @n2_51.round(0, BigDecimal::ROUND_UP).should == @neg_three
+ @n2_49.round(0, BigDecimal::ROUND_UP).should == @neg_three
+ end
+ end
+
+ describe "BigDecimal::ROUND_DOWN" do
+ it "rounds values towards zero" do
+ @p1_50.round(0, BigDecimal::ROUND_DOWN).should == @one
+ @p1_51.round(0, BigDecimal::ROUND_DOWN).should == @one
+ @p1_49.round(0, BigDecimal::ROUND_DOWN).should == @one
+ @n1_50.round(0, BigDecimal::ROUND_DOWN).should == @neg_one
+ @n1_51.round(0, BigDecimal::ROUND_DOWN).should == @neg_one
+ @n1_49.round(0, BigDecimal::ROUND_DOWN).should == @neg_one
+
+ @p2_50.round(0, BigDecimal::ROUND_DOWN).should == @two
+ @p2_51.round(0, BigDecimal::ROUND_DOWN).should == @two
+ @p2_49.round(0, BigDecimal::ROUND_DOWN).should == @two
+ @n2_50.round(0, BigDecimal::ROUND_DOWN).should == @neg_two
+ @n2_51.round(0, BigDecimal::ROUND_DOWN).should == @neg_two
+ @n2_49.round(0, BigDecimal::ROUND_DOWN).should == @neg_two
+ end
+ end
+
+ describe "BigDecimal::ROUND_HALF_UP" do
+ it "rounds values >= 5 up, otherwise down" do
+ @p1_50.round(0, BigDecimal::ROUND_HALF_UP).should == @two
+ @p1_51.round(0, BigDecimal::ROUND_HALF_UP).should == @two
+ @p1_49.round(0, BigDecimal::ROUND_HALF_UP).should == @one
+ @n1_50.round(0, BigDecimal::ROUND_HALF_UP).should == @neg_two
+ @n1_51.round(0, BigDecimal::ROUND_HALF_UP).should == @neg_two
+ @n1_49.round(0, BigDecimal::ROUND_HALF_UP).should == @neg_one
+
+ @p2_50.round(0, BigDecimal::ROUND_HALF_UP).should == @three
+ @p2_51.round(0, BigDecimal::ROUND_HALF_UP).should == @three
+ @p2_49.round(0, BigDecimal::ROUND_HALF_UP).should == @two
+ @n2_50.round(0, BigDecimal::ROUND_HALF_UP).should == @neg_three
+ @n2_51.round(0, BigDecimal::ROUND_HALF_UP).should == @neg_three
+ @n2_49.round(0, BigDecimal::ROUND_HALF_UP).should == @neg_two
+ end
+ end
+
+ describe "BigDecimal::ROUND_HALF_DOWN" do
+ it "rounds values > 5 up, otherwise down" do
+ @p1_50.round(0, BigDecimal::ROUND_HALF_DOWN).should == @one
+ @p1_51.round(0, BigDecimal::ROUND_HALF_DOWN).should == @two
+ @p1_49.round(0, BigDecimal::ROUND_HALF_DOWN).should == @one
+ @n1_50.round(0, BigDecimal::ROUND_HALF_DOWN).should == @neg_one
+ @n1_51.round(0, BigDecimal::ROUND_HALF_DOWN).should == @neg_two
+ @n1_49.round(0, BigDecimal::ROUND_HALF_DOWN).should == @neg_one
+
+ @p2_50.round(0, BigDecimal::ROUND_HALF_DOWN).should == @two
+ @p2_51.round(0, BigDecimal::ROUND_HALF_DOWN).should == @three
+ @p2_49.round(0, BigDecimal::ROUND_HALF_DOWN).should == @two
+ @n2_50.round(0, BigDecimal::ROUND_HALF_DOWN).should == @neg_two
+ @n2_51.round(0, BigDecimal::ROUND_HALF_DOWN).should == @neg_three
+ @n2_49.round(0, BigDecimal::ROUND_HALF_DOWN).should == @neg_two
+ end
+ end
+
+ describe "BigDecimal::ROUND_CEILING" do
+ it "rounds values towards +infinity" do
+ @p1_50.round(0, BigDecimal::ROUND_CEILING).should == @two
+ @p1_51.round(0, BigDecimal::ROUND_CEILING).should == @two
+ @p1_49.round(0, BigDecimal::ROUND_CEILING).should == @two
+ @n1_50.round(0, BigDecimal::ROUND_CEILING).should == @neg_one
+ @n1_51.round(0, BigDecimal::ROUND_CEILING).should == @neg_one
+ @n1_49.round(0, BigDecimal::ROUND_CEILING).should == @neg_one
+
+ @p2_50.round(0, BigDecimal::ROUND_CEILING).should == @three
+ @p2_51.round(0, BigDecimal::ROUND_CEILING).should == @three
+ @p2_49.round(0, BigDecimal::ROUND_CEILING).should == @three
+ @n2_50.round(0, BigDecimal::ROUND_CEILING).should == @neg_two
+ @n2_51.round(0, BigDecimal::ROUND_CEILING).should == @neg_two
+ @n2_49.round(0, BigDecimal::ROUND_CEILING).should == @neg_two
+ end
+ end
+
+ describe "BigDecimal::ROUND_FLOOR" do
+ it "rounds values towards -infinity" do
+ @p1_50.round(0, BigDecimal::ROUND_FLOOR).should == @one
+ @p1_51.round(0, BigDecimal::ROUND_FLOOR).should == @one
+ @p1_49.round(0, BigDecimal::ROUND_FLOOR).should == @one
+ @n1_50.round(0, BigDecimal::ROUND_FLOOR).should == @neg_two
+ @n1_51.round(0, BigDecimal::ROUND_FLOOR).should == @neg_two
+ @n1_49.round(0, BigDecimal::ROUND_FLOOR).should == @neg_two
+
+ @p2_50.round(0, BigDecimal::ROUND_FLOOR).should == @two
+ @p2_51.round(0, BigDecimal::ROUND_FLOOR).should == @two
+ @p2_49.round(0, BigDecimal::ROUND_FLOOR).should == @two
+ @n2_50.round(0, BigDecimal::ROUND_FLOOR).should == @neg_three
+ @n2_51.round(0, BigDecimal::ROUND_FLOOR).should == @neg_three
+ @n2_49.round(0, BigDecimal::ROUND_FLOOR).should == @neg_three
+ end
+ end
+
+ describe "BigDecimal::ROUND_HALF_EVEN" do
+ it "rounds values > 5 up, < 5 down and == 5 towards even neighbor" do
+ @p1_50.round(0, BigDecimal::ROUND_HALF_EVEN).should == @two
+ @p1_51.round(0, BigDecimal::ROUND_HALF_EVEN).should == @two
+ @p1_49.round(0, BigDecimal::ROUND_HALF_EVEN).should == @one
+ @n1_50.round(0, BigDecimal::ROUND_HALF_EVEN).should == @neg_two
+ @n1_51.round(0, BigDecimal::ROUND_HALF_EVEN).should == @neg_two
+ @n1_49.round(0, BigDecimal::ROUND_HALF_EVEN).should == @neg_one
+
+ @p2_50.round(0, BigDecimal::ROUND_HALF_EVEN).should == @two
+ @p2_51.round(0, BigDecimal::ROUND_HALF_EVEN).should == @three
+ @p2_49.round(0, BigDecimal::ROUND_HALF_EVEN).should == @two
+ @n2_50.round(0, BigDecimal::ROUND_HALF_EVEN).should == @neg_two
+ @n2_51.round(0, BigDecimal::ROUND_HALF_EVEN).should == @neg_three
+ @n2_49.round(0, BigDecimal::ROUND_HALF_EVEN).should == @neg_two
+ end
+ end
+
+ it 'raise exception, if self is special value' do
+ lambda { BigDecimal('NaN').round }.should raise_error(FloatDomainError)
+ lambda { BigDecimal('Infinity').round }.should raise_error(FloatDomainError)
+ lambda { BigDecimal('-Infinity').round }.should raise_error(FloatDomainError)
+ end
+
+ it 'do not raise exception, if self is special value and precision is given' do
+ lambda { BigDecimal('NaN').round(2) }.should_not raise_error(FloatDomainError)
+ lambda { BigDecimal('Infinity').round(2) }.should_not raise_error(FloatDomainError)
+ lambda { BigDecimal('-Infinity').round(2) }.should_not raise_error(FloatDomainError)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/shared/eql.rb b/spec/ruby/library/bigdecimal/shared/eql.rb
new file mode 100644
index 0000000000..eaad272e9a
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/shared/eql.rb
@@ -0,0 +1,61 @@
+require 'bigdecimal'
+
+describe :bigdecimal_eql, shared: true do
+ before :each do
+ @bg6543_21 = BigDecimal.new("6543.21")
+ @bg5667_19 = BigDecimal.new("5667.19")
+ @a = BigDecimal("1.0000000000000000000000000000000000000000005")
+ @b = BigDecimal("1.00000000000000000000000000000000000000000005")
+ @bigint = BigDecimal("1000.0")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ end
+
+ it "tests for equality" do
+ @bg6543_21.send(@method, @bg6543_21).should == true
+ @a.send(@method, @a).should == true
+ @a.send(@method, @b).should == false
+ @bg6543_21.send(@method, @a).should == false
+ @bigint.send(@method, 1000).should == true
+ end
+
+ it "returns false for NaN as it is never equal to any number" do
+ @nan.send(@method, @nan).should == false
+ @a.send(@method, @nan).should == false
+ @nan.send(@method, @a).should == false
+ @nan.send(@method, @infinity).should == false
+ @nan.send(@method, @infinity_minus).should == false
+ @infinity.send(@method, @nan).should == false
+ @infinity_minus.send(@method, @nan).should == false
+ end
+
+ it "returns true for infinity values with the same sign" do
+ @infinity.send(@method, @infinity).should == true
+ @infinity.send(@method, BigDecimal("Infinity")).should == true
+ BigDecimal("Infinity").send(@method, @infinity).should == true
+
+ @infinity_minus.send(@method, @infinity_minus).should == true
+ @infinity_minus.send(@method, BigDecimal("-Infinity")).should == true
+ BigDecimal("-Infinity").send(@method, @infinity_minus).should == true
+ end
+
+ it "returns false for infinity values with different signs" do
+ @infinity.send(@method, @infinity_minus).should == false
+ @infinity_minus.send(@method, @infinity).should == false
+ end
+
+ it "returns false when infinite value compared to finite one" do
+ @infinity.send(@method, @a).should == false
+ @infinity_minus.send(@method, @a).should == false
+
+ @a.send(@method, @infinity).should == false
+ @a.send(@method, @infinity_minus).should == false
+ end
+
+ it "returns false when compared objects that can not be coerced into BigDecimal" do
+ @infinity.send(@method, nil).should == false
+ @bigint.send(@method, nil).should == false
+ @nan.send(@method, nil).should == false
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/shared/modulo.rb b/spec/ruby/library/bigdecimal/shared/modulo.rb
new file mode 100644
index 0000000000..78ebe8360d
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/shared/modulo.rb
@@ -0,0 +1,116 @@
+require 'bigdecimal'
+
+describe :bigdecimal_modulo, shared: true do
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @two = BigDecimal("2")
+ @three = BigDecimal("3")
+ @mixed = BigDecimal("1.23456789")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-9999")
+ @frac_2 = BigDecimal("0.9E-9999")
+ end
+
+ it "returns self modulo other" do
+ bd6543 = BigDecimal.new("6543.21")
+ bd5667 = BigDecimal.new("5667.19")
+ a = BigDecimal("1.0000000000000000000000000000000000000000005")
+ b = BigDecimal("1.00000000000000000000000000000000000000000005")
+
+ bd6543.send(@method, 137).should == BigDecimal("104.21")
+ bd5667.send(@method, bignum_value).should == 5667.19
+ bd6543.send(@method, BigDecimal("137.24")).should == BigDecimal("92.93")
+ bd6543.send(@method, 137).should be_close(6543.21.%(137), TOLERANCE)
+ bd6543.send(@method, 137).should == bd6543 % 137
+ bd5667.send(@method, bignum_value).should be_close(5667.19.%(0xffffffff), TOLERANCE)
+ bd5667.send(@method, bignum_value).should == bd5667.%(0xffffffff)
+ bd6543.send(@method, 137.24).should be_close(6543.21.%(137.24), TOLERANCE)
+ a.send(@method, b).should == BigDecimal("0.45E-42")
+ @zero.send(@method, @one).should == @zero
+ @zero.send(@method, @one_minus).should == @zero
+ @two.send(@method, @one).should == @zero
+ @one.send(@method, @two).should == @one
+ @frac_1.send(@method, @one).should == @frac_1
+ @frac_2.send(@method, @one).should == @frac_2
+ @one_minus.send(@method, @one_minus).should == @zero
+ @one_minus.send(@method, @one).should == @zero
+ @one_minus.send(@method, @two).should == @one
+ @one.send(@method, -@two).should == -@one
+
+ @one_minus.modulo(BigDecimal('0.9')).should == BigDecimal('0.8')
+ @one.modulo(BigDecimal('-0.9')).should == BigDecimal('-0.8')
+
+ @one_minus.modulo(BigDecimal('0.8')).should == BigDecimal('0.6')
+ @one.modulo(BigDecimal('-0.8')).should == BigDecimal('-0.6')
+
+ @one_minus.modulo(BigDecimal('0.6')).should == BigDecimal('0.2')
+ @one.modulo(BigDecimal('-0.6')).should == BigDecimal('-0.2')
+
+ @one_minus.modulo(BigDecimal('0.5')).should == @zero
+ @one.modulo(BigDecimal('-0.5')).should == @zero
+ @one_minus.modulo(BigDecimal('-0.5')).should == @zero
+
+ @one_minus.modulo(BigDecimal('0.4')).should == BigDecimal('0.2')
+ @one.modulo(BigDecimal('-0.4')).should == BigDecimal('-0.2')
+
+ @one_minus.modulo(BigDecimal('0.3')).should == BigDecimal('0.2')
+ @one_minus.modulo(BigDecimal('0.2')).should == @zero
+ end
+
+ it "returns a [Float value] when the argument is Float" do
+ @two.send(@method, 2.0).should == 0.0
+ @one.send(@method, 2.0).should == 1.0
+ res = @two.send(@method, 5.0)
+ res.kind_of?(BigDecimal).should == true
+ end
+
+ it "returns NaN if NaN is involved" do
+ @nan.send(@method, @nan).nan?.should == true
+ @nan.send(@method, @one).nan?.should == true
+ @one.send(@method, @nan).nan?.should == true
+ @infinity.send(@method, @nan).nan?.should == true
+ @nan.send(@method, @infinity).nan?.should == true
+ end
+
+ it "returns NaN if the dividend is Infinity" do
+ @infinity.send(@method, @infinity).nan?.should == true
+ @infinity.send(@method, @one).nan?.should == true
+ @infinity.send(@method, @mixed).nan?.should == true
+ @infinity.send(@method, @one_minus).nan?.should == true
+ @infinity.send(@method, @frac_1).nan?.should == true
+
+ @infinity_minus.send(@method, @infinity_minus).nan?.should == true
+ @infinity_minus.send(@method, @one).nan?.should == true
+
+ @infinity.send(@method, @infinity_minus).nan?.should == true
+ @infinity_minus.send(@method, @infinity).nan?.should == true
+ end
+
+ it "returns the dividend if the divisor is Infinity" do
+ @one.send(@method, @infinity).should == @one
+ @one.send(@method, @infinity_minus).should == @one
+ @frac_2.send(@method, @infinity_minus).should == @frac_2
+ end
+
+ it "raises TypeError if the argument cannot be coerced to BigDecimal" do
+ lambda {
+ @one.send(@method, '2')
+ }.should raise_error(TypeError)
+ end
+end
+
+describe :bigdecimal_modulo_zerodivisionerror, shared: true do
+ it "raises ZeroDivisionError if other is zero" do
+ bd5667 = BigDecimal.new("5667.19")
+
+ lambda { bd5667.send(@method, 0) }.should raise_error(ZeroDivisionError)
+ lambda { bd5667.send(@method, BigDecimal("0")) }.should raise_error(ZeroDivisionError)
+ lambda { @zero.send(@method, @zero) }.should raise_error(ZeroDivisionError)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/shared/mult.rb b/spec/ruby/library/bigdecimal/shared/mult.rb
new file mode 100644
index 0000000000..b94c9385de
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/shared/mult.rb
@@ -0,0 +1,97 @@
+require 'bigdecimal'
+
+describe :bigdecimal_mult, shared: true do
+ before :each do
+ @zero = BigDecimal "0"
+ @zero_pos = BigDecimal "+0"
+ @zero_neg = BigDecimal "-0"
+
+ @one = BigDecimal "1"
+ @mixed = BigDecimal "1.23456789"
+ @pos_int = BigDecimal "2E5555"
+ @neg_int = BigDecimal "-2E5555"
+ @pos_frac = BigDecimal "2E-9999"
+ @neg_frac = BigDecimal "-2E-9999"
+ @nan = BigDecimal "NaN"
+ @infinity = BigDecimal "Infinity"
+ @infinity_minus = BigDecimal "-Infinity"
+ @one_minus = BigDecimal "-1"
+ @frac_1 = BigDecimal "1E-99999"
+ @frac_2 = BigDecimal "0.9E-99999"
+
+ @e3_minus = BigDecimal "3E-20001"
+ @e = BigDecimal "1.00000000000000000000123456789"
+ @tolerance = @e.sub @one, 1000
+ @tolerance2 = BigDecimal "30001E-20005"
+
+ @special_vals = [@infinity, @infinity_minus, @nan]
+ @regular_vals = [ @one, @mixed, @pos_int, @neg_int,
+ @pos_frac, @neg_frac, @one_minus,
+ @frac_1, @frac_2
+ ]
+ @zeroes = [@zero, @zero_pos, @zero_neg]
+ end
+
+ it "returns zero of appropriate sign if self or argument is zero" do
+ @zero.send(@method, @zero, *@object).sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ @zero_neg.send(@method, @zero_neg, *@object).sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ @zero.send(@method, @zero_neg, *@object).sign.should == BigDecimal::SIGN_NEGATIVE_ZERO
+ @zero_neg.send(@method, @zero, *@object).sign.should == BigDecimal::SIGN_NEGATIVE_ZERO
+
+ @one.send(@method, @zero, *@object).sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ @one.send(@method, @zero_neg, *@object).sign.should == BigDecimal::SIGN_NEGATIVE_ZERO
+
+ @zero.send(@method, @one, *@object).sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ @zero.send(@method, @one_minus, *@object).sign.should == BigDecimal::SIGN_NEGATIVE_ZERO
+ @zero_neg.send(@method, @one_minus, *@object).sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ @zero_neg.send(@method, @one, *@object).sign.should == BigDecimal::SIGN_NEGATIVE_ZERO
+ end
+
+ it "returns NaN if NaN is involved" do
+ values = @regular_vals + @zeroes
+
+ values.each do |val|
+ @nan.send(@method, val, *@object).nan?.should == true
+ val.send(@method, @nan, *@object).nan?.should == true
+ end
+ end
+
+ it "returns zero if self or argument is zero" do
+ values = @regular_vals + @zeroes
+
+ values.each do |val|
+ @zeroes.each do |zero|
+ zero.send(@method, val, *@object).should == 0
+ zero.send(@method, val, *@object).zero?.should == true
+ val.send(@method, zero, *@object).should == 0
+ val.send(@method, zero, *@object).zero?.should == true
+ end
+ end
+ end
+
+ it "returns infinite value if self or argument is infinite" do
+ values = @regular_vals
+ infs = [@infinity, @infinity_minus]
+
+ values.each do |val|
+ infs.each do |inf|
+ inf.send(@method, val, *@object).finite?.should == false
+ val.send(@method, inf, *@object).finite?.should == false
+ end
+ end
+
+ @infinity.send(@method, @infinity, *@object).infinite?.should == 1
+ @infinity_minus.send(@method, @infinity_minus, *@object).infinite?.should == 1
+ @infinity.send(@method, @infinity_minus, *@object).infinite?.should == -1
+ @infinity_minus.send(@method, @infinity, *@object).infinite?.should == -1
+ @infinity.send(@method, @one, *@object).infinite?.should == 1
+ @infinity_minus.send(@method, @one, *@object).infinite?.should == -1
+ end
+
+ it "returns NaN if the result is undefined" do
+ @zero.send(@method, @infinity, *@object).nan?.should == true
+ @zero.send(@method, @infinity_minus, *@object).nan?.should == true
+ @infinity.send(@method, @zero, *@object).nan?.should == true
+ @infinity_minus.send(@method, @zero, *@object).nan?.should == true
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/shared/power.rb b/spec/ruby/library/bigdecimal/shared/power.rb
new file mode 100644
index 0000000000..a4848fb2e2
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/shared/power.rb
@@ -0,0 +1,72 @@
+require 'bigdecimal'
+
+describe :bigdecimal_power, shared: true do
+ it "powers of self" do
+ e3_minus = BigDecimal("3E-20001")
+ e3_minus_power_2 = BigDecimal("9E-40002")
+ e3_plus = BigDecimal("3E20001")
+ e2_plus = BigDecimal("2E40001")
+ e5_minus = BigDecimal("5E-40002")
+ e = BigDecimal("1.00000000000000000000123456789")
+ one = BigDecimal("1")
+ ten = BigDecimal("10")
+ # The tolerance is dependent upon the size of BASE_FIG
+ tolerance = BigDecimal("1E-70")
+ ten_powers = BigDecimal("1E10000")
+ pi = BigDecimal("3.14159265358979")
+ e3_minus.send(@method, 2).should == e3_minus_power_2
+ e3_plus.send(@method, 0).should == 1
+ e3_minus.send(@method, 1).should == e3_minus
+ e2_plus.send(@method, -1).should == e5_minus
+ e2_plus.send(@method, -1).should == e5_minus.power(1)
+ (e2_plus.send(@method, -1) * e5_minus.send(@method, -1)).should == 1
+ e.send(@method, 2).should == e * e
+ e.send(@method, -1).should be_close(one.div(e, 120), tolerance)
+ ten.send(@method, 10000).should == ten_powers
+ pi.send(@method, 10).should be_close(Math::PI ** 10, TOLERANCE)
+ end
+
+ it "powers of 1 equal 1" do
+ one = BigDecimal("1")
+ one.send(@method, 0).should == 1
+ one.send(@method, 1).should == 1
+ one.send(@method, 10).should == 1
+ one.send(@method, -10).should == 1
+ end
+
+ it "0 to power of 0 is 1" do
+ zero = BigDecimal("0")
+ zero.send(@method, 0).should == 1
+ end
+
+ it "0 to powers < 0 is Infinity" do
+ zero = BigDecimal("0")
+ infinity = BigDecimal("Infinity")
+ zero.send(@method, -10).should == infinity
+ zero.send(@method, -1).should == infinity
+ end
+
+ it "other powers of 0 are 0" do
+ zero = BigDecimal("0")
+ zero.send(@method, 1).should == 0
+ zero.send(@method, 10).should == 0
+ end
+
+ it "returns NaN if self is NaN" do
+ BigDecimal("NaN").send(@method, -5).nan?.should == true
+ BigDecimal("NaN").send(@method, 5).nan?.should == true
+ end
+
+ it "returns 0.0 if self is infinite and argument is negative" do
+ BigDecimal("Infinity").send(@method, -5).should == 0
+ BigDecimal("-Infinity").send(@method, -5).should == 0
+ end
+
+ it "returns infinite if self is infinite and argument is positive" do
+ infinity = BigDecimal("Infinity")
+ BigDecimal("Infinity").send(@method, 4).should == infinity
+ BigDecimal("-Infinity").send(@method, 4).should == infinity
+ BigDecimal("Infinity").send(@method, 5).should == infinity
+ BigDecimal("-Infinity").send(@method, 5).should == -infinity
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/shared/quo.rb b/spec/ruby/library/bigdecimal/shared/quo.rb
new file mode 100644
index 0000000000..cb51c10d71
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/shared/quo.rb
@@ -0,0 +1,59 @@
+require 'bigdecimal'
+
+describe :bigdecimal_quo, shared: true do
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @zero_plus = BigDecimal("+0")
+ @zero_minus = BigDecimal("-0")
+ @two = BigDecimal("2")
+ @three = BigDecimal("3")
+ @eleven = BigDecimal("11")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ end
+
+ it "returns a / b" do
+ @two.send(@method, @one, *@object).should == @two
+ @one.send(@method, @two, *@object).should == BigDecimal("0.5")
+ @eleven.send(@method, @three, *@object).should be_close(@three + (@two / @three), TOLERANCE)
+ @one.send(@method, @one_minus, *@object).should == @one_minus
+ @one_minus.send(@method, @one_minus, *@object).should == @one
+ @frac_2.send(@method, @frac_1, *@object).should == BigDecimal("0.9")
+ @frac_1.send(@method, @frac_1, *@object).should == @one
+ @one.send(@method, BigDecimal('-2E5555'), *@object).should == BigDecimal('-0.5E-5555')
+ @one.send(@method, BigDecimal('2E-5555'), *@object).should == BigDecimal('0.5E5555')
+ end
+
+ it "returns 0 if divided by Infinity" do
+ @zero.send(@method, @infinity, *@object).should == 0
+ @frac_2.send(@method, @infinity, *@object).should == 0
+ end
+
+ it "returns (+|-) Infinity if (+|-) Infinity divided by one" do
+ @infinity_minus.send(@method, @one, *@object).should == @infinity_minus
+ @infinity.send(@method, @one, *@object).should == @infinity
+ @infinity_minus.send(@method, @one_minus, *@object).should == @infinity
+ end
+
+ it "returns NaN if Infinity / ((+|-) Infinity)" do
+ @infinity.send(@method, @infinity_minus, *@object).nan?.should == true
+ @infinity_minus.send(@method, @infinity, *@object).nan?.should == true
+ end
+
+ it "returns (+|-) Infinity if divided by zero" do
+ @one.send(@method, @zero, *@object).should == @infinity
+ @one.send(@method, @zero_plus, *@object).should == @infinity
+ @one.send(@method, @zero_minus, *@object).should == @infinity_minus
+ end
+
+ it "returns NaN if zero is divided by zero" do
+ @zero.send(@method, @zero, *@object).nan?.should == true
+ @zero_minus.send(@method, @zero_plus, *@object).nan?.should == true
+ @zero_plus.send(@method, @zero_minus, *@object).nan?.should == true
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/shared/to_int.rb b/spec/ruby/library/bigdecimal/shared/to_int.rb
new file mode 100644
index 0000000000..729a25f511
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/shared/to_int.rb
@@ -0,0 +1,16 @@
+require 'bigdecimal'
+
+describe :bigdecimal_to_int , shared: true do
+ it "raises FloatDomainError if BigDecimal is infinity or NaN" do
+ lambda { BigDecimal("Infinity").send(@method) }.should raise_error(FloatDomainError)
+ lambda { BigDecimal("NaN").send(@method) }.should raise_error(FloatDomainError)
+ end
+
+ it "returns Integer or Bignum otherwise" do
+ BigDecimal("3E-20001").send(@method).should == 0
+ BigDecimal("2E4000").send(@method).should == 2 * 10 ** 4000
+ BigDecimal("2").send(@method).should == 2
+ BigDecimal("2E10").send(@method).should == 20000000000
+ BigDecimal("3.14159").send(@method).should == 3
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/sign_spec.rb b/spec/ruby/library/bigdecimal/sign_spec.rb
new file mode 100644
index 0000000000..0d722987b5
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/sign_spec.rb
@@ -0,0 +1,47 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#sign" do
+
+ it "defines several constants for signs" do
+ # are these really correct?
+ BigDecimal::SIGN_POSITIVE_INFINITE.should == 3
+ BigDecimal::SIGN_NEGATIVE_INFINITE.should == -3
+ BigDecimal::SIGN_POSITIVE_ZERO.should == 1
+ BigDecimal::SIGN_NEGATIVE_ZERO.should == -1
+ BigDecimal::SIGN_POSITIVE_FINITE.should == 2
+ BigDecimal::SIGN_NEGATIVE_FINITE.should == -2
+ end
+
+ it "returns positive value if BigDecimal greater than 0" do
+ BigDecimal("1").sign.should == BigDecimal::SIGN_POSITIVE_FINITE
+ BigDecimal("1E-20000000").sign.should == BigDecimal::SIGN_POSITIVE_FINITE
+ BigDecimal("1E200000000").sign.should == BigDecimal::SIGN_POSITIVE_FINITE
+ BigDecimal("Infinity").sign.should == BigDecimal::SIGN_POSITIVE_INFINITE
+ end
+
+ it "returns negative value if BigDecimal less than 0" do
+ BigDecimal("-1").sign.should == BigDecimal::SIGN_NEGATIVE_FINITE
+ BigDecimal("-1E-9990000").sign.should == BigDecimal::SIGN_NEGATIVE_FINITE
+ BigDecimal("-1E20000000").sign.should == BigDecimal::SIGN_NEGATIVE_FINITE
+ BigDecimal("-Infinity").sign.should == BigDecimal::SIGN_NEGATIVE_INFINITE
+ end
+
+ it "returns positive zero if BigDecimal equals positve zero" do
+ BigDecimal("0").sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ BigDecimal("0E-200000000").sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ BigDecimal("0E200000000").sign.should == BigDecimal::SIGN_POSITIVE_ZERO
+ end
+
+ it "returns negative zero if BigDecimal equals negative zero" do
+ BigDecimal("-0").sign.should == BigDecimal::SIGN_NEGATIVE_ZERO
+ BigDecimal("-0E-200000000").sign.should == BigDecimal::SIGN_NEGATIVE_ZERO
+ BigDecimal("-0E200000000").sign.should == BigDecimal::SIGN_NEGATIVE_ZERO
+ end
+
+ it "returns BigDecimal::SIGN_NaN if BigDecimal is NaN" do
+ BigDecimal("NaN").sign.should == BigDecimal::SIGN_NaN
+ end
+
+end
+
diff --git a/spec/ruby/library/bigdecimal/split_spec.rb b/spec/ruby/library/bigdecimal/split_spec.rb
new file mode 100644
index 0000000000..e2ba955a3b
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/split_spec.rb
@@ -0,0 +1,88 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#split" do
+
+ before :each do
+ @arr = BigDecimal("0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1").split
+ @arr_neg = BigDecimal("-0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1").split
+ @digits = "922337203685477580810101333333333333333333333333333"
+ @arr_big = BigDecimal("00#{@digits}000").split
+ @arr_big_neg = BigDecimal("-00#{@digits}000").split
+ @huge = BigDecimal('100000000000000000000000000000000000000000001E90000000').split
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+ @nan = BigDecimal("NaN")
+ @zero = BigDecimal("0")
+ @zero_neg = BigDecimal("-0")
+ end
+
+ it "splits BigDecimal in an array with four values" do
+ @arr.size.should == 4
+ end
+
+ it "first value: 1 for numbers > 0" do
+ @arr[0].should == 1
+ @arr_big[0].should == 1
+ @zero.split[0].should == 1
+ @huge[0].should == 1
+ BigDecimal("+0").split[0].should == 1
+ BigDecimal("1E400").split[0].should == 1
+ @infinity.split[0].should == 1
+ end
+
+ it "first value: -1 for numbers < 0" do
+ @arr_neg[0].should == -1
+ @arr_big_neg[0].should == -1
+ @zero_neg.split[0].should == -1
+ BigDecimal("-1E400").split[0].should == -1
+ @infinity_neg.split[0].should == -1
+ end
+
+ it "first value: 0 if BigDecimal is NaN" do
+ BigDecimal("NaN").split[0].should == 0
+ end
+
+ it "second value: a string with the significant digits" do
+ string = "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043"
+ @arr[1].should == string
+ @arr_big[1].should == @digits
+ @arr_big_neg[1].should == @digits
+ @huge[1].should == "100000000000000000000000000000000000000000001"
+ @infinity.split[1].should == @infinity.to_s
+ @nan.split[1].should == @nan.to_s
+ @infinity_neg.split[1].should == @infinity.to_s
+ @zero.split[1].should == "0"
+ BigDecimal("-0").split[1].should == "0"
+ end
+
+ it "third value: the base (currently always ten)" do
+ @arr[2].should == 10
+ @arr_neg[2].should == 10
+ @arr_big[2].should == 10
+ @arr_big_neg[2].should == 10
+ @huge[2].should == 10
+ @infinity.split[2].should == 10
+ @nan.split[2].should == 10
+ @infinity_neg.split[2].should == 10
+ @zero.split[2].should == 10
+ @zero_neg.split[2].should == 10
+ end
+
+ it "fourth value: the exponent" do
+ @arr[3].should == 1
+ @arr_neg[3].should == 1
+ @arr_big[3].should == 54
+ @arr_big_neg[3].should == 54
+ @huge[3].should == 90000045
+ @infinity.split[3].should == 0
+ @nan.split[3].should == 0
+ @infinity_neg.split[3].should == 0
+ @zero.split[3].should == 0
+ @zero_neg.split[3].should == 0
+ end
+
+end
+
+
diff --git a/spec/ruby/library/bigdecimal/sqrt_spec.rb b/spec/ruby/library/bigdecimal/sqrt_spec.rb
new file mode 100644
index 0000000000..f677192b33
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/sqrt_spec.rb
@@ -0,0 +1,112 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#sqrt" do
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @two = BigDecimal("2.0")
+ @three = BigDecimal("3.0")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ end
+
+ it "returns square root of 2 with desired precision" do
+ string = "1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157"
+ (1..99).each { |idx|
+ @two.sqrt(idx).should be_close(BigDecimal(string), BigDecimal("1E-#{idx-1}"))
+ }
+ end
+
+ it "returns square root of 3 with desired precision" do
+ sqrt_3 = "1.732050807568877293527446341505872366942805253810380628055806979451933016908800037081146186757248575"
+ (1..99).each { |idx|
+ @three.sqrt(idx).should be_close(BigDecimal(sqrt_3), BigDecimal("1E-#{idx-1}"))
+ }
+ end
+
+ it "returns square root of 121 with desired precision" do
+ BigDecimal('121').sqrt(5).should be_close(11, 0.00001)
+ end
+
+ it "returns square root of 0.9E-99999 with desired precision" do
+ @frac_2.sqrt(1).to_s.should =~ /\A0\.3E-49999\z/i
+ end
+
+ it "raises ArgumentError when no argument is given" do
+ lambda {
+ @one.sqrt
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if a negative number is given" do
+ lambda {
+ @one.sqrt(-1)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if 2 arguments are given" do
+ lambda {
+ @one.sqrt(1, 1)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises TypeError if nil is given" do
+ lambda {
+ @one.sqrt(nil)
+ }.should raise_error(TypeError)
+ end
+
+ it "raises TypeError if a string is given" do
+ lambda {
+ @one.sqrt("stuff")
+ }.should raise_error(TypeError)
+ end
+
+ it "raises TypeError if a plain Object is given" do
+ lambda {
+ @one.sqrt(Object.new)
+ }.should raise_error(TypeError)
+ end
+
+ it "returns 1 if precision is 0 or 1" do
+ @one.sqrt(1).should == 1
+ @one.sqrt(0).should == 1
+ end
+
+ it "raises FloatDomainError on negative values" do
+ lambda {
+ BigDecimal('-1').sqrt(10)
+ }.should raise_error(FloatDomainError)
+ end
+
+ it "returns positive infitinity for infinity" do
+ @infinity.sqrt(1).should == @infinity
+ end
+
+ it "raises FloatDomainError for negative infinity" do
+ lambda {
+ @infinity_minus.sqrt(1)
+ }.should raise_error(FloatDomainError)
+ end
+
+ it "raises FloatDomainError for NaN" do
+ lambda {
+ @nan.sqrt(1)
+ }.should raise_error(FloatDomainError)
+ end
+
+ it "returns 0 for 0, +0.0 and -0.0" do
+ @zero.sqrt(1).should == 0
+ @zero_pos.sqrt(1).should == 0
+ @zero_neg.sqrt(1).should == 0
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/sub_spec.rb b/spec/ruby/library/bigdecimal/sub_spec.rb
new file mode 100644
index 0000000000..06ad3b79d2
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/sub_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#sub" do
+
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @two = BigDecimal("2")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ end
+
+ it "returns a - b with given precision" do
+ # documentation states, that precision is optional
+ # but implementation raises ArgumentError if not given.
+
+ @two.sub(@one, 1).should == @one
+ @one.sub(@two, 1).should == @one_minus
+ @one.sub(@one_minus, 1).should == @two
+ @frac_2.sub(@frac_1, 1000000).should == BigDecimal("-0.1E-99999")
+ @frac_2.sub(@frac_1, 1).should == BigDecimal("-0.1E-99999")
+ # the above two examples puzzle me.
+ in_arow_one = BigDecimal("1.23456789")
+ in_arow_two = BigDecimal("1.2345678")
+ in_arow_one.sub(in_arow_two, 10).should == BigDecimal("0.9E-7")
+ @two.sub(@two,1).should == @zero
+ @frac_1.sub(@frac_1, 1000000).should == @zero
+ end
+
+ it "returns NaN if NaN is involved" do
+ @one.sub(@nan, 1).nan?.should == true
+ @nan.sub(@one, 1).nan?.should == true
+ end
+
+ it "returns NaN if both values are infinite with the same signs" do
+ @infinity.sub(@infinity, 1).nan?.should == true
+ @infinity_minus.sub(@infinity_minus, 1).nan?.should == true
+ end
+
+ it "returns Infinity or -Infinity if these are involved" do
+ @infinity.sub(@infinity_minus, 1).should == @infinity
+ @infinity_minus.sub(@infinity, 1).should == @infinity_minus
+ @zero.sub(@infinity, 1).should == @infinity_minus
+ @frac_2.sub( @infinity, 1).should == @infinity_minus
+ @two.sub(@infinity, 1).should == @infinity_minus
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/to_f_spec.rb b/spec/ruby/library/bigdecimal/to_f_spec.rb
new file mode 100644
index 0000000000..b490fce4d9
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/to_f_spec.rb
@@ -0,0 +1,55 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#to_f" do
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @two = BigDecimal("2")
+ @three = BigDecimal("3")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ @vals = [@one, @zero, @two, @three, @frac_1, @frac_2]
+ @spec_vals = [@zero_pos, @zero_neg, @nan, @infinity, @infinity_minus]
+ end
+
+ it "returns number of type float" do
+ BigDecimal("3.14159").to_f.should be_kind_of(Float)
+ @vals.each { |val| val.to_f.should be_kind_of(Float) }
+ @spec_vals.each { |val| val.to_f.should be_kind_of(Float) }
+ end
+
+ it "rounds correctly to Float precision" do
+ bigdec = BigDecimal("3.141592653589793238462643383279502884197169399375")
+ bigdec.to_f.should be_close(3.14159265358979, TOLERANCE)
+ @one.to_f.should == 1.0
+ @two.to_f.should == 2.0
+ @three.to_f.should be_close(3.0, TOLERANCE)
+ @one_minus.to_f.should == -1.0
+
+ # regression test for [ruby-talk:338957]
+ BigDecimal("10.03").to_f.should == 10.03
+ end
+
+ it "properly handles special values" do
+ @zero.to_f.should == 0
+ @zero.to_f.to_s.should == "0.0"
+
+ @nan.to_f.nan?.should == true
+
+ @infinity.to_f.infinite?.should == 1
+ @infinity_minus.to_f.infinite?.should == -1
+ end
+
+ it "remembers negative zero when converted to float" do
+ @zero_neg.to_f.should == 0
+ @zero_neg.to_f.to_s.should == "-0.0"
+ end
+end
+
diff --git a/spec/ruby/library/bigdecimal/to_i_spec.rb b/spec/ruby/library/bigdecimal/to_i_spec.rb
new file mode 100644
index 0000000000..8db69003c5
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/to_i_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/to_int', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#to_i" do
+ it_behaves_like(:bigdecimal_to_int, :to_i)
+end
diff --git a/spec/ruby/library/bigdecimal/to_int_spec.rb b/spec/ruby/library/bigdecimal/to_int_spec.rb
new file mode 100644
index 0000000000..56a60d4a03
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/to_int_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/to_int', __FILE__)
+require 'bigdecimal'
+
+
+describe "BigDecimal#to_int" do
+ it_behaves_like(:bigdecimal_to_int, :to_int)
+end
diff --git a/spec/ruby/library/bigdecimal/to_r_spec.rb b/spec/ruby/library/bigdecimal/to_r_spec.rb
new file mode 100644
index 0000000000..6f6e5a1bea
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/to_r_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#to_r" do
+
+ it "returns a Rational" do
+ BigDecimal("3.14159").to_r.should be_kind_of(Rational)
+ end
+
+ it "returns a Rational with bignum values" do
+ r = BigDecimal.new("3.141592653589793238462643").to_r
+ r.numerator.should eql(3141592653589793238462643)
+ r.denominator.should eql(1000000000000000000000000)
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/to_s_spec.rb b/spec/ruby/library/bigdecimal/to_s_spec.rb
new file mode 100644
index 0000000000..b97311c800
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/to_s_spec.rb
@@ -0,0 +1,73 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#to_s" do
+
+ before :each do
+ @bigdec_str = "3.14159265358979323846264338327950288419716939937"
+ @bigneg_str = "-3.1415926535897932384626433832795028841971693993"
+ @bigdec = BigDecimal(@bigdec_str)
+ @bigneg = BigDecimal(@bigneg_str)
+ end
+
+ it "return type is of class String" do
+ @bigdec.to_s.kind_of?(String).should == true
+ @bigneg.to_s.kind_of?(String).should == true
+ end
+
+ it "the default format looks like 0.xxxxEnn" do
+ @bigdec.to_s.should =~ /^0\.[0-9]*E[0-9]*$/i
+ end
+
+ it "takes an optional argument" do
+ lambda {@bigdec.to_s("F")}.should_not raise_error()
+ end
+
+ it "starts with + if + is supplied and value is positive" do
+ @bigdec.to_s("+").should =~ /^\+.*/
+ @bigneg.to_s("+").should_not =~ /^\+.*/
+ end
+
+ it "inserts a space every n chars, if integer n is supplied" do
+ re =\
+ /\A0\.314 159 265 358 979 323 846 264 338 327 950 288 419 716 939 937E1\z/i
+ @bigdec.to_s(3).should =~ re
+
+ str1 = '-123.45678 90123 45678 9'
+ BigDecimal.new("-123.45678901234567890").to_s('5F').should == str1
+ # trailing zeroes removed
+ BigDecimal.new("1.00000000000").to_s('1F').should == "1.0"
+ # 0 is treated as no spaces
+ BigDecimal.new("1.2345").to_s('0F').should == "1.2345"
+ end
+
+ it "can return a leading space for values > 0" do
+ @bigdec.to_s(" F").should =~ /\ .*/
+ @bigneg.to_s(" F").should_not =~ /\ .*/
+ end
+
+ it "removes trailing spaces in floating point notation" do
+ BigDecimal.new('-123.45678901234567890').to_s('F').should == "-123.4567890123456789"
+ BigDecimal.new('1.2500').to_s('F').should == "1.25"
+ BigDecimal.new('0000.00000').to_s('F').should == "0.0"
+ BigDecimal.new('-00.000010000').to_s('F').should == "-0.00001"
+ BigDecimal.new("5.00000E-2").to_s("F").should == "0.05"
+
+ BigDecimal.new("500000").to_s("F").should == "500000.0"
+ BigDecimal.new("5E2").to_s("F").should == "500.0"
+ BigDecimal.new("-5E100").to_s("F").should == "-5" + "0" * 100 + ".0"
+ end
+
+ it "can use engineering notation" do
+ @bigdec.to_s("E").should =~ /^0\.[0-9]*E[0-9]*$/i
+ end
+
+ it "can use conventional floating point notation" do
+ @bigdec.to_s("F").should == @bigdec_str
+ @bigneg.to_s("F").should == @bigneg_str
+ str2 = "+123.45678901 23456789"
+ BigDecimal.new('123.45678901234567890').to_s('+8F').should == str2
+ end
+
+end
+
diff --git a/spec/ruby/library/bigdecimal/truncate_spec.rb b/spec/ruby/library/bigdecimal/truncate_spec.rb
new file mode 100644
index 0000000000..41f0afc8fa
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/truncate_spec.rb
@@ -0,0 +1,81 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#truncate" do
+
+ before :each do
+ @arr = ['3.14159', '8.7', "0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1"]
+ @big = BigDecimal("123456.789")
+ @nan = BigDecimal('NaN')
+ @infinity = BigDecimal('Infinity')
+ @infinity_negative = BigDecimal('-Infinity')
+ end
+
+ it "returns value of type Integer." do
+ @arr.each do |x|
+ BigDecimal(x).truncate.kind_of?(Integer).should == true
+ end
+ end
+
+ it "returns the integer part as a BigDecimal if no precision given" do
+ BigDecimal(@arr[0]).truncate.should == 3
+ BigDecimal(@arr[1]).truncate.should == 8
+ BigDecimal(@arr[2]).truncate.should == 3
+ BigDecimal('0').truncate.should == 0
+ BigDecimal('0.1').truncate.should == 0
+ BigDecimal('-0.1').truncate.should == 0
+ BigDecimal('1.5').truncate.should == 1
+ BigDecimal('-1.5').truncate.should == -1
+ BigDecimal('1E10').truncate.should == BigDecimal('1E10')
+ BigDecimal('-1E10').truncate.should == BigDecimal('-1E10')
+ BigDecimal('1.8888E10').truncate.should == BigDecimal('1.8888E10')
+ BigDecimal('-1E-1').truncate.should == 0
+ end
+
+ it "returns value of given precision otherwise" do
+ BigDecimal('-1.55').truncate(1).should == BigDecimal('-1.5')
+ BigDecimal('1.55').truncate(1).should == BigDecimal('1.5')
+ BigDecimal(@arr[0]).truncate(2).should == BigDecimal("3.14")
+ BigDecimal('123.456').truncate(2).should == BigDecimal("123.45")
+ BigDecimal('123.456789').truncate(4).should == BigDecimal("123.4567")
+ BigDecimal('0.456789').truncate(10).should == BigDecimal("0.456789")
+ BigDecimal('-1E-1').truncate(1).should == BigDecimal('-0.1')
+ BigDecimal('-1E-1').truncate(2).should == BigDecimal('-0.1E0')
+ BigDecimal('-1E-1').truncate.should == BigDecimal('0')
+ BigDecimal('-1E-1').truncate(0).should == BigDecimal('0')
+ BigDecimal('-1E-1').truncate(-1).should == BigDecimal('0')
+ BigDecimal('-1E-1').truncate(-2).should == BigDecimal('0')
+
+ BigDecimal(@arr[1]).truncate(1).should == BigDecimal("8.7")
+ BigDecimal(@arr[2]).truncate(100).should == BigDecimal(\
+ "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679")
+ end
+
+ it "sets n digits left of the decimal point to 0, if given n < 0" do
+ @big.truncate(-1).should == BigDecimal("123450.0")
+ @big.truncate(-2).should == BigDecimal("123400.0")
+ BigDecimal(@arr[2]).truncate(-1).should == 0
+ end
+
+ it "returns NaN if self is NaN" do
+ @nan.truncate(-1).nan?.should == true
+ @nan.truncate(+1).nan?.should == true
+ @nan.truncate(0).nan?.should == true
+ end
+
+ it "returns Infinity if self is infinite" do
+ @infinity.truncate(-1).should == @infinity
+ @infinity.truncate(+1).should == @infinity
+ @infinity.truncate(0).should == @infinity
+
+ @infinity_negative.truncate(-1).should == @infinity_negative
+ @infinity_negative.truncate(+1).should == @infinity_negative
+ @infinity_negative.truncate(0).should == @infinity_negative
+ end
+
+ it "returns the same value if self is special value" do
+ lambda { @nan.truncate }.should raise_error(FloatDomainError)
+ lambda { @infinity.truncate }.should raise_error(FloatDomainError)
+ lambda { @infinity_negative.truncate }.should raise_error(FloatDomainError)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/uminus_spec.rb b/spec/ruby/library/bigdecimal/uminus_spec.rb
new file mode 100644
index 0000000000..901f9f59ce
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/uminus_spec.rb
@@ -0,0 +1,58 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#-@" do
+ before :each do
+ @one = BigDecimal("1")
+ @zero = BigDecimal("0")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ @nan = BigDecimal("NaN")
+ @infinity = BigDecimal("Infinity")
+ @infinity_minus = BigDecimal("-Infinity")
+ @one_minus = BigDecimal("-1")
+ @frac_1 = BigDecimal("1E-99999")
+ @frac_2 = BigDecimal("0.9E-99999")
+ @big = BigDecimal("333E99999")
+ @big_neg = BigDecimal("-333E99999")
+ @values = [@one, @zero, @zero_pos, @zero_neg, @infinity,
+ @infinity_minus, @one_minus, @frac_1, @frac_2, @big, @big_neg]
+ end
+
+ it "negates self" do
+ @one.send(:-@).should == @one_minus
+ @one_minus.send(:-@).should == @one
+ @frac_1.send(:-@).should == BigDecimal("-1E-99999")
+ @frac_2.send(:-@).should == BigDecimal("-0.9E-99999")
+ @big.send(:-@).should == @big_neg
+ @big_neg.send(:-@).should == @big
+ BigDecimal("2.221").send(:-@).should == BigDecimal("-2.221")
+ BigDecimal("2E10000").send(:-@).should == BigDecimal("-2E10000")
+ some_number = BigDecimal("2455999221.5512")
+ some_number_neg = BigDecimal("-2455999221.5512")
+ some_number.send(:-@).should == some_number_neg
+ (-BigDecimal("-5.5")).should == BigDecimal("5.5")
+ another_number = BigDecimal("-8.551551551551551551")
+ another_number_pos = BigDecimal("8.551551551551551551")
+ another_number.send(:-@).should == another_number_pos
+ @values.each do |val|
+ (val.send(:-@).send(:-@)).should == val
+ end
+ end
+
+ it "properly handles special values" do
+ @infinity.send(:-@).should == @infinity_minus
+ @infinity_minus.send(:-@).should == @infinity
+ @infinity.send(:-@).infinite?.should == -1
+ @infinity_minus.send(:-@).infinite?.should == 1
+
+ @zero.send(:-@).should == @zero
+ @zero.send(:-@).sign.should == -1
+ @zero_pos.send(:-@).should == @zero
+ @zero_pos.send(:-@).sign.should == -1
+ @zero_neg.send(:-@).should == @zero
+ @zero_neg.send(:-@).sign.should == 1
+
+ @nan.send(:-@).nan?.should == true
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/uplus_spec.rb b/spec/ruby/library/bigdecimal/uplus_spec.rb
new file mode 100644
index 0000000000..00aadc723c
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/uplus_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#+@" do
+ it "returns the same value with same sign (twos complement)" do
+ first = BigDecimal("34.56")
+ first.send(:+@).should == first
+ second = BigDecimal("-34.56")
+ second.send(:+@).should == second
+ third = BigDecimal("0.0")
+ third.send(:+@).should == third
+ fourth = BigDecimal("2E1000000")
+ fourth.send(:+@).should == fourth
+ fifth = BigDecimal("123456789E-1000000")
+ fifth.send(:+@).should == fifth
+ end
+end
+
+
+
diff --git a/spec/ruby/library/bigdecimal/ver_spec.rb b/spec/ruby/library/bigdecimal/ver_spec.rb
new file mode 100644
index 0000000000..61b073d8f1
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/ver_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal.ver" do
+
+ it "returns the Version number" do
+ lambda {BigDecimal.ver }.should_not raise_error()
+ BigDecimal.ver.should_not == nil
+ end
+
+end
diff --git a/spec/ruby/library/bigdecimal/zero_spec.rb b/spec/ruby/library/bigdecimal/zero_spec.rb
new file mode 100644
index 0000000000..7dbb0fa7f0
--- /dev/null
+++ b/spec/ruby/library/bigdecimal/zero_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#zero?" do
+
+ it "returns true if self does equal zero" do
+ really_small_zero = BigDecimal("0E-200000000")
+ really_big_zero = BigDecimal("0E200000000000")
+ really_small_zero.zero?.should == true
+ really_big_zero.zero?.should == true
+ BigDecimal("0.000000000000000000000000").zero?.should == true
+ BigDecimal("0").zero?.should == true
+ BigDecimal("0E0").zero?.should == true
+ BigDecimal("+0").zero?.should == true
+ BigDecimal("-0").zero?.should == true
+ end
+
+ it "returns false otherwise" do
+ BigDecimal("0000000001").zero?.should == false
+ BigDecimal("2E40001").zero?.should == false
+ BigDecimal("3E-20001").zero?.should == false
+ BigDecimal("Infinity").zero?.should == false
+ BigDecimal("-Infinity").zero?.should == false
+ BigDecimal("NaN").zero?.should == false
+ end
+
+end
+
diff --git a/spec/ruby/library/bigmath/log_spec.rb b/spec/ruby/library/bigmath/log_spec.rb
new file mode 100644
index 0000000000..126461f0e8
--- /dev/null
+++ b/spec/ruby/library/bigmath/log_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'bigdecimal'
+
+describe "BigDecimal#log" do
+ it "handles high-precision Rational arguments" do
+ result = BigDecimal('0.22314354220170971436137296411949880462556361100856391620766259404746040597133837784E0')
+ r = Rational(1_234_567_890, 987_654_321)
+ BigMath.log(r, 50).should == result
+ end
+end
diff --git a/spec/ruby/library/cgi/cookie/domain_spec.rb b/spec/ruby/library/cgi/cookie/domain_spec.rb
new file mode 100644
index 0000000000..05137dd4d1
--- /dev/null
+++ b/spec/ruby/library/cgi/cookie/domain_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::Cookie#domain" do
+ it "returns self's domain" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.domain.should be_nil
+
+ cookie = CGI::Cookie.new("name" => "test-cookie", "domain" => "example.com")
+ cookie.domain.should == "example.com"
+ end
+end
+
+describe "CGI::Cookie#domain=" do
+ it "sets self's domain" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.domain = "test.com"
+ cookie.domain.should == "test.com"
+
+ cookie.domain = "example.com"
+ cookie.domain.should == "example.com"
+ end
+end
diff --git a/spec/ruby/library/cgi/cookie/expires_spec.rb b/spec/ruby/library/cgi/cookie/expires_spec.rb
new file mode 100644
index 0000000000..89f18fe071
--- /dev/null
+++ b/spec/ruby/library/cgi/cookie/expires_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::Cookie#expires" do
+ it "returns self's expiration date" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.expires.should be_nil
+
+ cookie = CGI::Cookie.new("name" => "test-cookie", "expires" => Time.at(1196524602))
+ cookie.expires.should == Time.at(1196524602)
+ end
+end
+
+describe "CGI::Cookie#expires=" do
+ it "sets self's expiration date" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.expires = Time.at(1196524602)
+ cookie.expires.should == Time.at(1196524602)
+
+ cookie.expires = Time.at(1196525000)
+ cookie.expires.should == Time.at(1196525000)
+ end
+end
diff --git a/spec/ruby/library/cgi/cookie/initialize_spec.rb b/spec/ruby/library/cgi/cookie/initialize_spec.rb
new file mode 100644
index 0000000000..02f2a8ed2b
--- /dev/null
+++ b/spec/ruby/library/cgi/cookie/initialize_spec.rb
@@ -0,0 +1,147 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::Cookie#initialize when passed String" do
+ before :each do
+ @cookie = CGI::Cookie.allocate
+ end
+
+ it "sets the self's name to the passed String" do
+ @cookie.send(:initialize, "test-cookie")
+ @cookie.name.should == "test-cookie"
+ end
+
+ it "sets the self's value to an empty Array" do
+ @cookie.send(:initialize, "test-cookie")
+ @cookie.value.should == []
+ end
+
+ it "sets self to a non-secure cookie" do
+ @cookie.send(:initialize, "test")
+ @cookie.secure.should be_false
+ end
+
+ it "does set self's path to an empty String when ENV[\"SCRIPT_NAME\"] is not set" do
+ @cookie.send(:initialize, "test-cookie")
+ @cookie.path.should == ""
+ end
+
+ it "does set self's path based on ENV[\"SCRIPT_NAME\"] when ENV[\"SCRIPT_NAME\"] is set" do
+ old_script_name = ENV["SCRIPT_NAME"]
+
+ begin
+ ENV["SCRIPT_NAME"] = "some/path/script.rb"
+ @cookie.send(:initialize, "test-cookie")
+ @cookie.path.should == "some/path/"
+
+ ENV["SCRIPT_NAME"] = "script.rb"
+ @cookie.send(:initialize, "test-cookie")
+ @cookie.path.should == ""
+
+ ENV["SCRIPT_NAME"] = nil
+ @cookie.send(:initialize, "test-cookie")
+ @cookie.path.should == ""
+ ensure
+ ENV["SCRIPT_NAME"] = old_script_name
+ end
+ end
+
+ it "does not set self's expiration date" do
+ @cookie.expires.should be_nil
+ end
+
+ it "does not set self's domain" do
+ @cookie.domain.should be_nil
+ end
+end
+
+describe "CGI::Cookie#initialize when passed Hash" do
+ before :each do
+ @cookie = CGI::Cookie.allocate
+ end
+
+ it "sets self's contents based on the passed Hash" do
+ @cookie.send(:initialize,
+ 'name' => 'test-cookie',
+ 'value' => ["one", "two", "three"],
+ 'path' => 'some/path/',
+ 'domain' => 'example.com',
+ 'expires' => Time.at(1196524602),
+ 'secure' => true)
+
+ @cookie.name.should == "test-cookie"
+ @cookie.value.should == ["one", "two", "three"]
+ @cookie.path.should == "some/path/"
+ @cookie.domain.should == "example.com"
+ @cookie.expires.should == Time.at(1196524602)
+ @cookie.secure.should be_true
+ end
+
+ it "does set self's path based on ENV[\"SCRIPT_NAME\"] when the Hash has no 'path' entry" do
+ old_script_name = ENV["SCRIPT_NAME"]
+
+ begin
+ ENV["SCRIPT_NAME"] = "some/path/script.rb"
+ @cookie.send(:initialize, 'name' => 'test-cookie')
+ @cookie.path.should == "some/path/"
+
+ ENV["SCRIPT_NAME"] = "script.rb"
+ @cookie.send(:initialize, 'name' => 'test-cookie')
+ @cookie.path.should == ""
+
+ ENV["SCRIPT_NAME"] = nil
+ @cookie.send(:initialize, 'name' => 'test-cookie')
+ @cookie.path.should == ""
+ ensure
+ ENV["SCRIPT_NAME"] = old_script_name
+ end
+ end
+
+ it "tries to convert the Hash's 'value' to an Array using #Array" do
+ obj = mock("Converted To Array")
+ obj.should_receive(:to_ary).and_return(["1", "2", "3"])
+ @cookie.send(:initialize,
+ 'name' => 'test-cookie',
+ 'value' => obj)
+ @cookie.value.should == [ "1", "2", "3" ]
+
+ obj = mock("Converted To Array")
+ obj.should_receive(:to_a).and_return(["one", "two", "three"])
+ @cookie.send(:initialize,
+ 'name' => 'test-cookie',
+ 'value' => obj)
+ @cookie.value.should == [ "one", "two", "three" ]
+
+ obj = mock("Put into an Array")
+ @cookie.send(:initialize,
+ 'name' => 'test-cookie',
+ 'value' => obj)
+ @cookie.value.should == [ obj ]
+ end
+
+ it "raises a ArgumentError when the passed Hash has no 'name' entry" do
+ lambda { @cookie.send(:initialize, {}) }.should raise_error(ArgumentError)
+ lambda { @cookie.send(:initialize, "value" => "test") }.should raise_error(ArgumentError)
+ end
+end
+
+describe "CGI::Cookie#initialize when passed String, values ..." do
+ before :each do
+ @cookie = CGI::Cookie.allocate
+ end
+
+ it "sets the self's name to the passed String" do
+ @cookie.send(:initialize, "test-cookie", "one", "two", "three")
+ @cookie.name.should == "test-cookie"
+ end
+
+ it "sets the self's value to an Array containing all passed values" do
+ @cookie.send(:initialize, "test-cookie", "one", "two", "three")
+ @cookie.value.should == ["one", "two", "three"]
+ end
+
+ it "sets self to a non-secure cookie" do
+ @cookie.send(:initialize, "test", "one", "two", "three")
+ @cookie.secure.should be_false
+ end
+end
diff --git a/spec/ruby/library/cgi/cookie/name_spec.rb b/spec/ruby/library/cgi/cookie/name_spec.rb
new file mode 100644
index 0000000000..8a6be95944
--- /dev/null
+++ b/spec/ruby/library/cgi/cookie/name_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::Cookie#name" do
+ it "returns self's name" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.name.should == "test-cookie"
+
+ cookie = CGI::Cookie.new("name" => "another cookie")
+ cookie.name.should == "another cookie"
+ end
+end
+
+describe "CGI::Cookie#name=" do
+ it "sets self's expiration date" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.name = "another name"
+ cookie.name.should == "another name"
+
+ cookie.name = "and one more"
+ cookie.name.should == "and one more"
+ end
+end
diff --git a/spec/ruby/library/cgi/cookie/parse_spec.rb b/spec/ruby/library/cgi/cookie/parse_spec.rb
new file mode 100644
index 0000000000..dc8498dcb4
--- /dev/null
+++ b/spec/ruby/library/cgi/cookie/parse_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::Cookie.parse" do
+ it "parses a raw cookie string into a hash of Cookies" do
+ expected = { "test-cookie" => ["one", "two", "three"] }
+ CGI::Cookie.parse("test-cookie=one&two&three").should == expected
+
+ expected = { "second cookie" => ["three", "four"], "first cookie" => ["one", "two"] }
+ CGI::Cookie.parse("first cookie=one&two;second cookie=three&four").should == expected
+ end
+
+ it "unescapes the Cookie values" do
+ cookie = "test-cookie=+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E"
+ expected = { "test-cookie" => [ " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" ] }
+ CGI::Cookie.parse(cookie).should == expected
+ end
+end
diff --git a/spec/ruby/library/cgi/cookie/path_spec.rb b/spec/ruby/library/cgi/cookie/path_spec.rb
new file mode 100644
index 0000000000..2a21a55264
--- /dev/null
+++ b/spec/ruby/library/cgi/cookie/path_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::Cookie#path" do
+ it "returns self's path" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.path.should == ""
+
+ cookie = CGI::Cookie.new("name" => "test-cookie", "path" => "/some/path/")
+ cookie.path.should == "/some/path/"
+ end
+end
+
+describe "CGI::Cookie#path=" do
+ it "sets self's path" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.path = "/some/path/"
+ cookie.path.should == "/some/path/"
+
+ cookie.path = "/another/path/"
+ cookie.path.should == "/another/path/"
+ end
+end
diff --git a/spec/ruby/library/cgi/cookie/secure_spec.rb b/spec/ruby/library/cgi/cookie/secure_spec.rb
new file mode 100644
index 0000000000..37e9dbfda9
--- /dev/null
+++ b/spec/ruby/library/cgi/cookie/secure_spec.rb
@@ -0,0 +1,70 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::Cookie#secure" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
+
+ it "returns whether self is a secure cookie or not" do
+ @cookie.secure = true
+ @cookie.secure.should be_true
+
+ @cookie.secure = false
+ @cookie.secure.should be_false
+ end
+end
+
+describe "CGI::Cookie#secure= when passed true" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
+
+ it "returns true" do
+ (@cookie.secure = true).should be_true
+ end
+
+ it "sets self to a secure cookie" do
+ @cookie.secure = true
+ @cookie.secure.should be_true
+ end
+end
+
+describe "CGI::Cookie#secure= when passed false" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
+
+ it "returns false" do
+ (@cookie.secure = false).should be_false
+ end
+
+ it "sets self to a non-secure cookie" do
+ @cookie.secure = false
+ @cookie.secure.should be_false
+ end
+end
+
+describe "CGI::Cookie#secure= when passed Object" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
+
+ it "does not change self's secure value" do
+ @cookie.secure = false
+
+ @cookie.secure = Object.new
+ @cookie.secure.should be_false
+
+ @cookie.secure = "Test"
+ @cookie.secure.should be_false
+
+ @cookie.secure = true
+
+ @cookie.secure = Object.new
+ @cookie.secure.should be_true
+
+ @cookie.secure = "Test"
+ @cookie.secure.should be_true
+ end
+end
diff --git a/spec/ruby/library/cgi/cookie/to_s_spec.rb b/spec/ruby/library/cgi/cookie/to_s_spec.rb
new file mode 100644
index 0000000000..806071ba69
--- /dev/null
+++ b/spec/ruby/library/cgi/cookie/to_s_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::Cookie#to_s" do
+ it "returns a String representation of self" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.to_s.should == "test-cookie=; path="
+
+ cookie = CGI::Cookie.new("test-cookie", "value")
+ cookie.to_s.should == "test-cookie=value; path="
+
+ cookie = CGI::Cookie.new("test-cookie", "one", "two", "three")
+ cookie.to_s.should == "test-cookie=one&two&three; path="
+
+ cookie = CGI::Cookie.new(
+ 'name' => 'test-cookie',
+ 'value' => ["one", "two", "three"],
+ 'path' => 'some/path/',
+ 'domain' => 'example.com',
+ 'expires' => Time.at(1196524602),
+ 'secure' => true)
+ cookie.to_s.should == "test-cookie=one&two&three; domain=example.com; path=some/path/; expires=Sat, 01 Dec 2007 15:56:42 GMT; secure"
+ end
+
+ it "escapes the self's values" do
+ cookie = CGI::Cookie.new("test-cookie", " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}")
+ cookie.to_s.should == "test-cookie=+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D; path="
+ end
+
+ ruby_version_is ""..."2.5" do
+ it "escapes tilde" do
+ cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=%7E; path="
+ end
+ end
+
+ ruby_version_is "2.5" do
+ it "does not escape tilde" do
+ cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=~; path="
+ end
+ end
+
+end
diff --git a/spec/ruby/library/cgi/cookie/value_spec.rb b/spec/ruby/library/cgi/cookie/value_spec.rb
new file mode 100644
index 0000000000..81e3daf7de
--- /dev/null
+++ b/spec/ruby/library/cgi/cookie/value_spec.rb
@@ -0,0 +1,76 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::Cookie#value" do
+ it "returns self's value" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.value.should == []
+
+ cookie = CGI::Cookie.new("test-cookie", "one")
+ cookie.value.should == ["one"]
+
+ cookie = CGI::Cookie.new("test-cookie", "one", "two", "three")
+ cookie.value.should == ["one", "two", "three"]
+
+ cookie = CGI::Cookie.new("name" => "test-cookie", "value" => ["one", "two", "three"])
+ cookie.value.should == ["one", "two", "three"]
+ end
+
+ it "is in synch with self" do
+ fail = []
+ [
+ :pop,
+ :shift,
+ [:<<, "Hello"],
+ [:push, "Hello"],
+ [:unshift, "World"],
+ [:replace, ["A", "B"]],
+ [:[]=, 1, "Set"],
+ [:delete, "first"],
+ [:delete_at, 0],
+ ].each do |method, *args|
+ cookie1 = CGI::Cookie.new("test-cookie", "first", "second")
+ cookie2 = CGI::Cookie.new("test-cookie", "first", "second")
+ cookie1.send(method, *args)
+ cookie2.value.send(method, *args)
+ fail << method unless cookie1.value == cookie2.value
+ end
+ fail.should be_empty
+ end
+end
+
+describe "CGI::Cookie#value=" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
+
+ it "sets self's value" do
+ @cookie.value = ["one"]
+ @cookie.value.should == ["one"]
+
+ @cookie.value = ["one", "two", "three"]
+ @cookie.value.should == ["one", "two", "three"]
+ end
+
+ it "automatically converts the passed Object to an Array using #Array" do
+ @cookie.value = "test"
+ @cookie.value.should == ["test"]
+
+ obj = mock("to_a")
+ obj.should_receive(:to_a).and_return(["1", "2"])
+ @cookie.value = obj
+ @cookie.value.should == ["1", "2"]
+
+ obj = mock("to_ary")
+ obj.should_receive(:to_ary).and_return(["1", "2"])
+ @cookie.value = obj
+ @cookie.value.should == ["1", "2"]
+ end
+
+ it "does keep self and the values in sync" do
+ @cookie.value = ["one", "two", "three"]
+ @cookie[0].should == "one"
+ @cookie[1].should == "two"
+ @cookie[2].should == "three"
+ end
+end
diff --git a/spec/ruby/library/cgi/escapeElement_spec.rb b/spec/ruby/library/cgi/escapeElement_spec.rb
new file mode 100644
index 0000000000..18f804c7da
--- /dev/null
+++ b/spec/ruby/library/cgi/escapeElement_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI.escapeElement when passed String, elements, ..." do
+ it "escapes only the tags of the passed elements in the passed String" do
+ res = CGI.escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
+ res.should == "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;"
+
+ res = CGI.escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
+ res.should == "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;"
+ end
+
+ it "is case-insensitive" do
+ res = CGI.escapeElement('<BR><A HREF="url"></A>', "a", "img")
+ res.should == '<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;'
+
+ res = CGI.escapeElement('<br><a href="url"></a>', "A", "IMG")
+ res.should == '<br>&lt;a href=&quot;url&quot;&gt;&lt;/a&gt;'
+ end
+end
diff --git a/spec/ruby/library/cgi/escapeHTML_spec.rb b/spec/ruby/library/cgi/escapeHTML_spec.rb
new file mode 100644
index 0000000000..a3267db4a1
--- /dev/null
+++ b/spec/ruby/library/cgi/escapeHTML_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI.escapeHTML" do
+ it "escapes special HTML characters (&\"<>') in the passed argument" do
+ CGI.escapeHTML(%[& < > " ']).should == '&amp; &lt; &gt; &quot; &#39;'
+ end
+
+ it "does not escape any other characters" do
+ chars = " !\#$%()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
+ CGI.escapeHTML(chars).should == chars
+ end
+end
diff --git a/spec/ruby/library/cgi/escape_spec.rb b/spec/ruby/library/cgi/escape_spec.rb
new file mode 100644
index 0000000000..cf8861a39f
--- /dev/null
+++ b/spec/ruby/library/cgi/escape_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI.escape" do
+ it "url-encodes the passed argument" do
+ input = " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}"
+ expected = "+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D"
+ CGI.escape(input).should == expected
+
+ input = "http://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277"
+ expected = 'http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF'
+ CGI.escape(input).should == expected
+ end
+
+ ruby_version_is ""..."2.5" do
+ it "escapes tilde" do
+ CGI.escape("~").should == "%7E"
+ end
+ end
+
+ ruby_version_is "2.5" do
+ it "does not escape tilde" do
+ CGI.escape("~").should == "~"
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/a_spec.rb b/spec/ruby/library/cgi/htmlextension/a_spec.rb
new file mode 100644
index 0000000000..a4c0ee684c
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/a_spec.rb
@@ -0,0 +1,49 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#a" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed a String" do
+ it "returns an 'a'-element, using the passed String as the 'href'-attribute" do
+ output = @html.a("http://www.example.com")
+ output.should equal_element("A", "HREF" => "http://www.example.com")
+ end
+
+ it "includes the passed block's return value when passed a block" do
+ output = @html.a("http://www.example.com") { "Example" }
+ output.should equal_element("A", { "HREF" => "http://www.example.com" }, "Example")
+ end
+ end
+
+ describe "when passed a Hash" do
+ it "returns an 'a'-element, using the passed Hash for attributes" do
+ attributes = {"HREF" => "http://www.example.com", "TARGET" => "_top"}
+ @html.a(attributes).should equal_element("A", attributes)
+ end
+
+ it "includes the passed block's return value when passed a block" do
+ attributes = {"HREF" => "http://www.example.com", "TARGET" => "_top"}
+ @html.a(attributes) { "Example" }.should equal_element("A", attributes, "Example")
+ end
+ end
+
+ describe "when each HTML generation" do
+ it "returns the doctype declaration for HTML3" do
+ CGISpecs.cgi_new("html3").a.should == %(<A HREF=""></A>)
+ CGISpecs.cgi_new("html3").a { "link text" }.should == %(<A HREF="">link text</A>)
+ end
+
+ it "returns the doctype declaration for HTML4" do
+ CGISpecs.cgi_new("html4").a.should == %(<A HREF=""></A>)
+ CGISpecs.cgi_new("html4").a { "link text" }.should == %(<A HREF="">link text</A>)
+ end
+ it "returns the doctype declaration for the Transitional version of HTML4" do
+ CGISpecs.cgi_new("html4Tr").a.should == %(<A HREF=""></A>)
+ CGISpecs.cgi_new("html4Tr").a { "link text" }.should == %(<A HREF="">link text</A>)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/base_spec.rb b/spec/ruby/library/cgi/htmlextension/base_spec.rb
new file mode 100644
index 0000000000..36a8cc55c8
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/base_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#base" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when bassed a String" do
+ it "returns a 'base'-element, using the passed String as the 'href'-attribute" do
+ output = @html.base("http://www.example.com")
+ output.should equal_element("BASE", {"HREF" => "http://www.example.com"}, nil, not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.base("http://www.example.com") { "Example" }
+ output.should equal_element("BASE", {"HREF" => "http://www.example.com"}, nil, not_closed: true)
+ end
+ end
+
+ describe "when passed a Hash" do
+ it "returns a 'base'-element, using the passed Hash for attributes" do
+ output = @html.base("HREF" => "http://www.example.com", "ID" => "test")
+ output.should equal_element("BASE", {"HREF" => "http://www.example.com", "ID" => "test"}, nil, not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.base("HREF" => "http://www.example.com", "ID" => "test") { "Example" }
+ output.should equal_element("BASE", {"HREF" => "http://www.example.com", "ID" => "test"}, nil, not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/blockquote_spec.rb b/spec/ruby/library/cgi/htmlextension/blockquote_spec.rb
new file mode 100644
index 0000000000..f9848375e8
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/blockquote_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#blockquote" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed a String" do
+ it "returns a 'blockquote'-element, using the passed String for the 'cite'-attribute" do
+ output = @html.blockquote("http://www.example.com/quotes/foo.html")
+ output.should equal_element("BLOCKQUOTE", "CITE" => "http://www.example.com/quotes/foo.html")
+ end
+
+ it "includes the passed block's return value when passed a block" do
+ output = @html.blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
+ output.should equal_element("BLOCKQUOTE", { "CITE" => "http://www.example.com/quotes/foo.html" }, "Foo!")
+ end
+ end
+
+ describe "when passed a Hash" do
+ it "returns a 'blockquote'-element, using the passed Hash for attributes" do
+ output = @html.blockquote("CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test")
+ output.should equal_element("BLOCKQUOTE", "CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test")
+ end
+
+ it "includes the passed block's return value when passed a block" do
+ output = @html.blockquote("CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test") { "Foo!" }
+ output.should equal_element("BLOCKQUOTE", {"CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test"}, "Foo!")
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/br_spec.rb b/spec/ruby/library/cgi/htmlextension/br_spec.rb
new file mode 100644
index 0000000000..875d335fe5
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/br_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#br" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when each HTML generation" do
+ it "returns the doctype declaration for HTML3" do
+ CGISpecs.cgi_new("html3").br.should == "<BR>"
+ end
+
+ it "returns the doctype declaration for HTML4" do
+ CGISpecs.cgi_new("html4").br.should == "<BR>"
+ end
+ it "returns the doctype declaration for the Transitional version of HTML4" do
+ CGISpecs.cgi_new("html4Tr").br.should == "<BR>"
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/caption_spec.rb b/spec/ruby/library/cgi/htmlextension/caption_spec.rb
new file mode 100644
index 0000000000..a1b5f4d964
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/caption_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#caption" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed a String" do
+ it "returns a 'caption'-element, using the passed String for the 'align'-attribute" do
+ output = @html.caption("left")
+ output.should equal_element("CAPTION", "ALIGN" => "left")
+ end
+
+ it "includes the passed block's return value when passed a block" do
+ output = @html.caption("left") { "Capital Cities" }
+ output.should equal_element("CAPTION", {"ALIGN" => "left"}, "Capital Cities")
+ end
+ end
+
+ describe "when passed a Hash" do
+ it "returns a 'caption'-element, using the passed Hash for attributes" do
+ output = @html.caption("ALIGN" => "left", "ID" => "test")
+ output.should equal_element("CAPTION", "ALIGN" => "left", "ID" => "test")
+ end
+
+ it "includes the passed block's return value when passed a block" do
+ output = @html.caption("ALIGN" => "left", "ID" => "test") { "Capital Cities" }
+ output.should equal_element("CAPTION", {"ALIGN" => "left", "ID" => "test"}, "Capital Cities")
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb b/spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb
new file mode 100644
index 0000000000..f739d92a53
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb
@@ -0,0 +1,76 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#checkbox_group" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed name, values ..." do
+ it "returns a sequence of 'checkbox'-elements with the passed name and the passed values" do
+ output = CGISpecs.split(@html.checkbox_group("test", "foo", "bar", "baz"))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
+
+ it "allows passing a value inside an Array" do
+ output = CGISpecs.split(@html.checkbox_group("test", ["foo"], "bar", ["baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
+
+ it "allows passing a value as an Array containing the value and the checked state or a label" do
+ output = CGISpecs.split(@html.checkbox_group("test", ["foo"], ["bar", true], ["baz", "label for baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "label for baz", not_closed: true)
+ end
+
+ it "allows passing a value as an Array containing the value, a label and the checked state" do
+ output = CGISpecs.split(@html.checkbox_group("test", ["foo", "label for foo", true], ["bar", "label for bar", false], ["baz", "label for baz", true]))
+ output[0].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "label for foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "label for bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "label for baz", not_closed: true)
+ end
+
+ it "returns an empty String when passed no values" do
+ @html.checkbox_group("test").should == ""
+ end
+
+ it "ignores a passed block" do
+ output = CGISpecs.split(@html.checkbox_group("test", "foo", "bar", "baz") { "test" })
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "uses the passed Hash to generate the checkbox sequence" do
+ output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+
+ output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => [["foo"], ["bar", true], "baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+
+ output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "1"}, "Foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "checkbox", "VALUE" => "2"}, "Bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "Baz"}, "Baz", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]) { "test" })
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/checkbox_spec.rb b/spec/ruby/library/cgi/htmlextension/checkbox_spec.rb
new file mode 100644
index 0000000000..3abb3b4a31
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/checkbox_spec.rb
@@ -0,0 +1,77 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#checkbox" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns a checkbox-'input'-element without a name" do
+ output = @html.checkbox
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "checkbox"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.checkbox { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "checkbox"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name" do
+ it "returns a checkbox-'input'-element with the passed name" do
+ output = @html.checkbox("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.checkbox("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox"}, "", not_closed: true)
+ end
+ end
+
+ describe "CGI::HtmlExtension#checkbox when passed name, value" do
+ it "returns a checkbox-'input'-element with the passed name and value" do
+ output = @html.checkbox("test", "test-value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.checkbox("test", "test-value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, value, checked" do
+ it "returns a checked checkbox-'input'-element with the passed name and value when checked is true" do
+ output = @html.checkbox("test", "test-value", true)
+ output.should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+
+ output = @html.checkbox("test", "test-value", false)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+
+ output = @html.checkbox("test", "test-value", nil)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.checkbox("test", "test-value", nil) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns a checkbox-'input'-element using the passed Hash for attributes" do
+ attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
+ output = @html.checkbox(attributes)
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
+ output = @html.checkbox(attributes) { "test" }
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/doctype_spec.rb b/spec/ruby/library/cgi/htmlextension/doctype_spec.rb
new file mode 100644
index 0000000000..339ef20db9
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/doctype_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#doctype" do
+ describe "when each HTML generation" do
+ it "returns the doctype declaration for HTML3" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'
+ CGISpecs.cgi_new("html3").doctype.should == expect
+ end
+
+ it "returns the doctype declaration for HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
+ CGISpecs.cgi_new("html4").doctype.should == expect
+ end
+
+ it "returns the doctype declaration for the Frameset version of HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'
+ CGISpecs.cgi_new("html4Fr").doctype.should == expect
+ end
+
+ it "returns the doctype declaration for the Transitional version of HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
+ CGISpecs.cgi_new("html4Tr").doctype.should == expect
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/file_field_spec.rb b/spec/ruby/library/cgi/htmlextension/file_field_spec.rb
new file mode 100644
index 0000000000..57d91b5fd9
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/file_field_spec.rb
@@ -0,0 +1,72 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#file_field" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns a file-'input'-element without a name and a size of 20" do
+ output = @html.file_field
+ output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "", "TYPE" => "file"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.file_field { "test" }
+ output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "", "TYPE" => "file"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name" do
+ it "returns a checkbox-'input'-element with the passed name" do
+ output = @html.file_field("Example")
+ output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.file_field("Example") { "test" }
+ output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, size" do
+ it "returns a checkbox-'input'-element with the passed name and size" do
+ output = @html.file_field("Example", 40)
+ output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.file_field("Example", 40) { "test" }
+ output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, size, maxlength" do
+ it "returns a checkbox-'input'-element with the passed name, size and maxlength" do
+ output = @html.file_field("Example", 40, 100)
+ output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file", "MAXLENGTH" => 100}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.file_field("Example", 40, 100) { "test" }
+ output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file", "MAXLENGTH" => 100}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed a Hash" do
+ it "returns a file-'input'-element using the passed Hash for attributes" do
+ output = @html.file_field("NAME" => "test", "SIZE" => 40)
+ output.should equal_element("INPUT", {"NAME" => "test", "SIZE" => 40}, "", not_closed: true)
+
+ output = @html.file_field("NAME" => "test", "MAXLENGTH" => 100)
+ output.should equal_element("INPUT", {"NAME" => "test", "MAXLENGTH" => 100}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.file_field("NAME" => "test", "SIZE" => 40) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "SIZE" => 40}, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/fixtures/common.rb b/spec/ruby/library/cgi/htmlextension/fixtures/common.rb
new file mode 100644
index 0000000000..4f951f6389
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/fixtures/common.rb
@@ -0,0 +1,15 @@
+module CGISpecs
+ def self.cgi_new(html = "html4")
+ old_request_method = ENV['REQUEST_METHOD']
+ ENV['REQUEST_METHOD'] = "GET"
+ begin
+ CGI.new(tag_maker: html)
+ ensure
+ ENV['REQUEST_METHOD'] = old_request_method
+ end
+ end
+
+ def self.split(string)
+ string.split("<").reject { |x| x.empty? }.map { |x| "<#{x}" }
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/form_spec.rb b/spec/ruby/library/cgi/htmlextension/form_spec.rb
new file mode 100644
index 0000000000..0389910cd6
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/form_spec.rb
@@ -0,0 +1,58 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#form" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ @html.stub!(:script_name).and_return("/path/to/some/script")
+ end
+
+ describe "when passed no arguments" do
+ it "returns a 'form'-element" do
+ output = @html.form
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/path/to/some/script"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.form { "test" }
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/path/to/some/script"}, "test")
+ end
+ end
+
+ describe "when passed method" do
+ it "returns a 'form'-element with the passed method" do
+ output = @html.form("get")
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/path/to/some/script"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.form("get") { "test" }
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/path/to/some/script"}, "test")
+ end
+ end
+
+ describe "when passed method, action" do
+ it "returns a 'form'-element with the passed method and the passed action" do
+ output = @html.form("get", "/some/other/script")
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/some/other/script"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.form("get", "/some/other/script") { "test" }
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/some/other/script"}, "test")
+ end
+ end
+
+ describe "when passed method, action, enctype" do
+ it "returns a 'form'-element with the passed method, action and enctype" do
+ output = @html.form("get", "/some/other/script", "multipart/form-data")
+ output.should equal_element("FORM", {"ENCTYPE" => "multipart/form-data", "METHOD" => "get", "ACTION" => "/some/other/script"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.form("get", "/some/other/script", "multipart/form-data") { "test" }
+ output.should equal_element("FORM", {"ENCTYPE" => "multipart/form-data", "METHOD" => "get", "ACTION" => "/some/other/script"}, "test")
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/frame_spec.rb b/spec/ruby/library/cgi/htmlextension/frame_spec.rb
new file mode 100644
index 0000000000..d433d058e7
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/frame_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+require 'cgi'
+
+describe "CGI::HtmlExtension#frame" do
+ before :each do
+ @html = CGISpecs.cgi_new("html4Fr")
+ end
+
+ it "initializes the HTML Generation methods for the Frameset version of HTML4" do
+ @html.frameset.should == "<FRAMESET></FRAMESET>"
+ @html.frameset { "link text" }.should == "<FRAMESET>link text</FRAMESET>"
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/frameset_spec.rb b/spec/ruby/library/cgi/htmlextension/frameset_spec.rb
new file mode 100644
index 0000000000..81e92089e4
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/frameset_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+require 'cgi'
+
+describe "CGI::HtmlExtension#frameset" do
+ before :each do
+ @html = CGISpecs.cgi_new("html4Fr")
+ end
+
+ it "initializes the HTML Generation methods for the Frameset version of HTML4" do
+ @html.frameset.should == "<FRAMESET></FRAMESET>"
+ @html.frameset { "link text" }.should == "<FRAMESET>link text</FRAMESET>"
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/hidden_spec.rb b/spec/ruby/library/cgi/htmlextension/hidden_spec.rb
new file mode 100644
index 0000000000..dd06dfc354
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/hidden_spec.rb
@@ -0,0 +1,59 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#hidden" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns an hidden-'input'-element without a name" do
+ output = @html.hidden
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "hidden"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.hidden { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "hidden"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name" do
+ it "returns an hidden-'input'-element with the passed name" do
+ output = @html.hidden("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.hidden("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, value" do
+ it "returns an hidden-'input'-element with the passed name and value" do
+ output = @html.hidden("test", "some value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden", "VALUE" => "some value"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.hidden("test", "some value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden", "VALUE" => "some value"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns a checkbox-'input'-element using the passed Hash for attributes" do
+ attributes = { "NAME" => "test", "VALUE" => "some value" }
+ output = @html.hidden("test", "some value")
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ attributes = { "NAME" => "test", "VALUE" => "some value" }
+ output = @html.hidden("test", "some value") { "test" }
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/html_spec.rb b/spec/ruby/library/cgi/htmlextension/html_spec.rb
new file mode 100644
index 0000000000..0dfba297d2
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/html_spec.rb
@@ -0,0 +1,66 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#html" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ @html.stub!(:doctype).and_return("<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE>")
+ end
+
+ describe "when passed no arguments" do
+ it "returns a self's doctype and an 'html'-element" do
+ expected = '<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE><HTML>'
+ @html.html.should == expected
+ end
+
+ it "includes the passed block when passed a block" do
+ expected = '<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE><HTML>test</HTML>'
+ @html.html { "test" }.should == expected
+ end
+ end
+
+ describe "when passed 'PRETTY'" do
+ it "returns pretty output when the passed String is 'PRETTY" do
+ expected = "<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE>\n<HTML>\n"
+ @html.html("PRETTY").should == expected
+ end
+
+ it "includes the passed block when passed a block" do
+ expected = "<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE>\n<HTML>\n test\n</HTML>\n"
+ @html.html("PRETTY") { "test" }.should == expected
+ end
+ end
+
+ describe "when passed a Hash" do
+ it "returns an 'html'-element using the passed Hash for attributes" do
+ expected = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML BLA="TEST">'
+ @html.html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">', "BLA" => "TEST").should == expected
+ end
+
+ it "omits the doctype when the Hash contains a 'DOCTYPE' entry that's false or nil" do
+ @html.html("DOCTYPE" => false).should == "<HTML>"
+ @html.html("DOCTYPE" => nil).should == "<HTML>"
+ end
+ end
+
+ describe "when each HTML generation" do
+ it "returns the doctype declaration for HTML3" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'
+ CGISpecs.cgi_new("html3").html.should == expect + "<HTML>"
+ CGISpecs.cgi_new("html3").html { "html body" }.should == expect + "<HTML>html body</HTML>"
+ end
+
+ it "returns the doctype declaration for HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
+ CGISpecs.cgi_new("html4").html.should == expect + "<HTML>"
+ CGISpecs.cgi_new("html4").html { "html body" }.should == expect + "<HTML>html body</HTML>"
+ end
+
+ it "returns the doctype declaration for the Transitional version of HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
+ CGISpecs.cgi_new("html4Tr").html.should == expect + "<HTML>"
+ CGISpecs.cgi_new("html4Tr").html { "html body" }.should == expect + "<HTML>html body</HTML>"
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/image_button_spec.rb b/spec/ruby/library/cgi/htmlextension/image_button_spec.rb
new file mode 100644
index 0000000000..f4e39d8028
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/image_button_spec.rb
@@ -0,0 +1,69 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#image_button" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns an image-'input'-element without a source image" do
+ output = @html.image_button
+ output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.image_button { "test" }
+ output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed src" do
+ it "returns an image-'input'-element with the passed src" do
+ output = @html.image_button("/path/to/image.png")
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.image_button("/path/to/image.png") { "test" }
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed src, name" do
+ it "returns an image-'input'-element with the passed src and name" do
+ output = @html.image_button("/path/to/image.png", "test")
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.image_button("/path/to/image.png", "test") { "test" }
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed src, name, alt" do
+ it "returns an image-'input'-element with the passed src, name and alt" do
+ output = @html.image_button("/path/to/image.png", "test", "alternative")
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test", "ALT" => "alternative"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.image_button("/path/to/image.png", "test", "alternative") { "test" }
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test", "ALT" => "alternative"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns a image-'input'-element using the passed Hash for attributes" do
+ output = @html.image_button("NAME" => "test", "VALUE" => "test-value")
+ output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image", "NAME" => "test", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.image_button("NAME" => "test", "VALUE" => "test-value") { "test" }
+ output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image", "NAME" => "test", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/img_spec.rb b/spec/ruby/library/cgi/htmlextension/img_spec.rb
new file mode 100644
index 0000000000..8109bcd6c6
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/img_spec.rb
@@ -0,0 +1,83 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#img" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns an 'img'-element without an src-url or alt-text" do
+ output = @html.img
+ output.should equal_element("IMG", { "SRC" => "", "ALT" => "" }, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.img { "test" }
+ output.should equal_element("IMG", { "SRC" => "", "ALT" => "" }, "", not_closed: true)
+ end
+ end
+
+ describe "when passed src" do
+ it "returns an 'img'-element with the passed src-url" do
+ output = @html.img("/path/to/some/image.png")
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "" }, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.img("/path/to/some/image.png")
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "" }, "", not_closed: true)
+ end
+ end
+
+ describe "when passed src, alt" do
+ it "returns an 'img'-element with the passed src-url and the passed alt-text" do
+ output = @html.img("/path/to/some/image.png", "Alternative")
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative" }, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.img("/path/to/some/image.png", "Alternative") { "test" }
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative" }, "", not_closed: true)
+ end
+ end
+
+ describe "when passed src, alt, width" do
+ it "returns an 'img'-element with the passed src-url, the passed alt-text and the passed width" do
+ output = @html.img("/path/to/some/image.png", "Alternative", 40)
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative", "WIDTH" => "40" }, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.img("/path/to/some/image.png", "Alternative", 40) { "test" }
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative", "WIDTH" => "40" }, "", not_closed: true)
+ end
+ end
+
+ describe "when passed src, alt, width, height" do
+ it "returns an 'img'-element with the passed src-url, the passed alt-text, the passed width and the passed height" do
+ output = @html.img("/path/to/some/image.png", "Alternative", 40, 60)
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative", "WIDTH" => "40", "HEIGHT" => "60" }, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.img { "test" }
+ output.should equal_element("IMG", { "SRC" => "", "ALT" => "" }, "", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns an 'img'-element with the passed Hash as attributes" do
+ attributes = { "SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50 }
+ output = @html.img(attributes)
+ output.should equal_element("IMG", attributes, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ attributes = { "SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50 }
+ output = @html.img(attributes) { "test" }
+ output.should equal_element("IMG", attributes, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb b/spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb
new file mode 100644
index 0000000000..75d1b54666
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb
@@ -0,0 +1,64 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#multipart_form" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ @html.stub!(:script_name).and_return("/path/to/some/script.rb")
+ end
+
+ describe "when passed no arguments" do
+ it "returns a 'form'-element with it's enctype set to multipart" do
+ output = @html.multipart_form
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post" }, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.multipart_form { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post" }, "test")
+ end
+ end
+
+ describe "when passed action" do
+ it "returns a 'form'-element with the passed action" do
+ output = @html.multipart_form("/some/other/script.rb")
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.multipart_form("/some/other/script.rb") { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "test")
+ end
+ end
+
+ describe "when passed action, enctype" do
+ it "returns a 'form'-element with the passed action and enctype" do
+ output = @html.multipart_form("/some/other/script.rb", "application/x-www-form-urlencoded")
+ output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.multipart_form("/some/other/script.rb", "application/x-www-form-urlencoded") { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "test")
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns a 'form'-element with the passed Hash as attributes" do
+ output = @html.multipart_form("ID" => "test")
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ID" => "test" }, "")
+
+ output = @html.multipart_form("ID" => "test", "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get")
+ output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ID" => "test" }, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.multipart_form("ID" => "test") { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ID" => "test" }, "test")
+
+ output = @html.multipart_form("ID" => "test", "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get") { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ID" => "test" }, "test")
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/password_field_spec.rb b/spec/ruby/library/cgi/htmlextension/password_field_spec.rb
new file mode 100644
index 0000000000..bb1181de75
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/password_field_spec.rb
@@ -0,0 +1,84 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#password_field" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns an password-'input'-element without a name" do
+ output = @html.password_field
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.password_field { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name" do
+ it "returns an password-'input'-element with the passed name" do
+ output = @html.password_field("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.password_field("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, value" do
+ it "returns an password-'input'-element with the passed name and value" do
+ output = @html.password_field("test", "some value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.password_field("test", "some value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, value, size" do
+ it "returns an password-'input'-element with the passed name, value and size" do
+ output = @html.password_field("test", "some value", 60)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.password_field("test", "some value", 60) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, value, size, maxlength" do
+ it "returns an password-'input'-element with the passed name, value, size and maxlength" do
+ output = @html.password_field("test", "some value", 60, 12)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.password_field("test", "some value", 60, 12) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns a checkbox-'input'-element using the passed Hash for attributes" do
+ output = @html.password_field("NAME" => "test", "VALUE" => "some value")
+ output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "password" }, "", not_closed: true)
+
+ output = @html.password_field("TYPE" => "hidden")
+ output.should equal_element("INPUT", {"TYPE" => "password"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.password_field("NAME" => "test", "VALUE" => "some value") { "test" }
+ output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "password" }, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb b/spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb
new file mode 100644
index 0000000000..5e94ec1a3e
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+require File.expand_path('../shared/popup_menu', __FILE__)
+
+describe "CGI::HtmlExtension#popup_menu" do
+ it_behaves_like :cgi_htmlextension_popup_menu, :popup_menu
+end
diff --git a/spec/ruby/library/cgi/htmlextension/radio_button_spec.rb b/spec/ruby/library/cgi/htmlextension/radio_button_spec.rb
new file mode 100644
index 0000000000..0ce88f20d7
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/radio_button_spec.rb
@@ -0,0 +1,77 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#radio_button" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns a radio-'input'-element without a name" do
+ output = @html.radio_button
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "radio"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.radio_button { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "radio"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name" do
+ it "returns a radio-'input'-element with the passed name" do
+ output = @html.radio_button("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.radio_button("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio"}, "", not_closed: true)
+ end
+ end
+
+ describe "CGI::HtmlExtension#checkbox when passed name, value" do
+ it "returns a radio-'input'-element with the passed name and value" do
+ output = @html.radio_button("test", "test-value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.radio_button("test", "test-value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, value, checked" do
+ it "returns a checked radio-'input'-element with the passed name and value when checked is true" do
+ output = @html.radio_button("test", "test-value", true)
+ output.should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+
+ output = @html.radio_button("test", "test-value", false)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+
+ output = @html.radio_button("test", "test-value", nil)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.radio_button("test", "test-value", nil) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns a radio-'input'-element using the passed Hash for attributes" do
+ attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
+ output = @html.radio_button(attributes)
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
+ output = @html.radio_button(attributes) { "test" }
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/radio_group_spec.rb b/spec/ruby/library/cgi/htmlextension/radio_group_spec.rb
new file mode 100644
index 0000000000..69d3444072
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/radio_group_spec.rb
@@ -0,0 +1,77 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#radio_group" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed name, values ..." do
+ it "returns a sequence of 'radio'-elements with the passed name and the passed values" do
+ output = CGISpecs.split(@html.radio_group("test", "foo", "bar", "baz"))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
+
+ it "allows passing a value inside an Array" do
+ output = CGISpecs.split(@html.radio_group("test", ["foo"], "bar", ["baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
+
+ it "allows passing a value as an Array containing the value and the checked state or a label" do
+ output = CGISpecs.split(@html.radio_group("test", ["foo"], ["bar", true], ["baz", "label for baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "label for baz", not_closed: true)
+ end
+
+ # TODO: CGI does not like passing false instead of true.
+ it "allows passing a value as an Array containing the value, a label and the checked state" do
+ output = CGISpecs.split(@html.radio_group("test", ["foo", "label for foo", true], ["bar", "label for bar", false], ["baz", "label for baz", true]))
+ output[0].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "label for foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "label for bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "label for baz", not_closed: true)
+ end
+
+ it "returns an empty String when passed no values" do
+ @html.radio_group("test").should == ""
+ end
+
+ it "ignores a passed block" do
+ output = CGISpecs.split(@html.radio_group("test", "foo", "bar", "baz") { "test" })
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "uses the passed Hash to generate the radio sequence" do
+ output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+
+ output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => [["foo"], ["bar", true], "baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+
+ output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "1"}, "Foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "radio", "VALUE" => "2"}, "Bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "Baz"}, "Baz", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]) { "test" })
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/reset_spec.rb b/spec/ruby/library/cgi/htmlextension/reset_spec.rb
new file mode 100644
index 0000000000..09184347d0
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/reset_spec.rb
@@ -0,0 +1,57 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#reset" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns a reset-'input'-element" do
+ output = @html.reset
+ output.should equal_element("INPUT", {"TYPE" => "reset"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.reset { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "reset"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed value" do
+ it "returns a reset-'input'-element with the passed value" do
+ output = @html.reset("Example")
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.reset("Example") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed value, name" do
+ it "returns a reset-'input'-element with the passed value and the passed name" do
+ output = @html.reset("Example", "test-name")
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.reset("Example", "test-name") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns a reset-'input'-element with the passed value" do
+ output = @html.reset("Example")
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.reset("Example") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb b/spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb
new file mode 100644
index 0000000000..da295278b1
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+require 'cgi'
+require File.expand_path('../shared/popup_menu', __FILE__)
+
+describe "CGI::HtmlExtension#scrolling_list" do
+ it_behaves_like :cgi_htmlextension_popup_menu, :scrolling_list
+end
diff --git a/spec/ruby/library/cgi/htmlextension/shared/popup_menu.rb b/spec/ruby/library/cgi/htmlextension/shared/popup_menu.rb
new file mode 100644
index 0000000000..4787fd3f8e
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/shared/popup_menu.rb
@@ -0,0 +1,94 @@
+describe :cgi_htmlextension_popup_menu, shared: true do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns an empty 'select'-element without a name" do
+ output = @html.send(@method)
+ output.should equal_element("SELECT", {"NAME" => ""}, "")
+ end
+
+ it "ignores a passed block" do
+ output = @html.send(@method) { "test" }
+ output.should equal_element("SELECT", {"NAME" => ""}, "")
+ end
+ end
+
+ describe "when passed name, values ..." do
+ it "returns a 'select'-element with the passed name containing 'option'-elements based on the passed values" do
+ content = @html.option("VALUE" => "foo") { "foo" }
+ content << @html.option("VALUE" => "bar") { "bar" }
+ content << @html.option("VALUE" => "baz") { "baz" }
+
+ output = @html.send(@method, "test", "foo", "bar", "baz")
+ output.should equal_element("SELECT", {"NAME" => "test"}, content)
+ end
+
+ it "allows passing values inside of arrays" do
+ content = @html.option("VALUE" => "foo") { "foo" }
+ content << @html.option("VALUE" => "bar") { "bar" }
+ content << @html.option("VALUE" => "baz") { "baz" }
+
+ output = @html.send(@method, "test", ["foo"], ["bar"], ["baz"])
+ output.should equal_element("SELECT", {"NAME" => "test"}, content)
+ end
+
+ it "allows passing a value as an Array containing the value and the select state or a label" do
+ content = @html.option("VALUE" => "foo") { "foo" }
+ content << @html.option("VALUE" => "bar", "SELECTED" => true) { "bar" }
+ content << @html.option("VALUE" => "baz") { "baz" }
+
+ output = @html.send(@method, "test", ["foo"], ["bar", true], "baz")
+ output.should equal_element("SELECT", {"NAME" => "test"}, content)
+ end
+
+ it "allows passing a value as an Array containing the value, a label and the select state" do
+ content = @html.option("VALUE" => "1") { "Foo" }
+ content << @html.option("VALUE" => "2", "SELECTED" => true) { "Bar" }
+ content << @html.option("VALUE" => "Baz") { "Baz" }
+
+ output = @html.send(@method, "test", ["1", "Foo"], ["2", "Bar", true], "Baz")
+ output.should equal_element("SELECT", {"NAME" => "test"}, content)
+ end
+
+ it "ignores a passed block" do
+ content = @html.option("VALUE" => "foo") { "foo" }
+ content << @html.option("VALUE" => "bar") { "bar" }
+ content << @html.option("VALUE" => "baz") { "baz" }
+
+ output = @html.send(@method, "test", "foo", "bar", "baz") { "woot" }
+ output.should equal_element("SELECT", {"NAME" => "test"}, content)
+ end
+ end
+
+ describe "when passed a Hash" do
+ it "uses the passed Hash to generate the 'select'-element and the 'option'-elements" do
+ attributes = {
+ "NAME" => "test", "SIZE" => 2, "MULTIPLE" => true,
+ "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]
+ }
+
+ content = @html.option("VALUE" => "1") { "Foo" }
+ content << @html.option("VALUE" => "2", "SELECTED" => true) { "Bar" }
+ content << @html.option("VALUE" => "Baz") { "Baz" }
+
+ output = @html.send(@method, attributes)
+ output.should equal_element("SELECT", {"NAME" => "test", "SIZE" => 2, "MULTIPLE" => true}, content)
+ end
+
+ it "ignores a passed block" do
+ attributes = {
+ "NAME" => "test", "SIZE" => 2, "MULTIPLE" => true,
+ "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]
+ }
+
+ content = @html.option("VALUE" => "1") { "Foo" }
+ content << @html.option("VALUE" => "2", "SELECTED" => true) { "Bar" }
+ content << @html.option("VALUE" => "Baz") { "Baz" }
+
+ output = @html.send(@method, attributes) { "testing" }
+ output.should equal_element("SELECT", {"NAME" => "test", "SIZE" => 2, "MULTIPLE" => true}, content)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/submit_spec.rb b/spec/ruby/library/cgi/htmlextension/submit_spec.rb
new file mode 100644
index 0000000000..8b9d9b02d8
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/submit_spec.rb
@@ -0,0 +1,57 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#submit" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns a submit-'input'-element" do
+ output = @html.submit
+ output.should equal_element("INPUT", {"TYPE" => "submit"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.submit { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "submit"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed value" do
+ it "returns a submit-'input'-element with the passed value" do
+ output = @html.submit("Example")
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.submit("Example") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed value, name" do
+ it "returns a submit-'input'-element with the passed value and the passed name" do
+ output = @html.submit("Example", "test-name")
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.submit("Example", "test-name") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns a submit-'input'-element with the passed value" do
+ output = @html.submit("Example")
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.submit("Example") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/text_field_spec.rb b/spec/ruby/library/cgi/htmlextension/text_field_spec.rb
new file mode 100644
index 0000000000..b8031d6ff5
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/text_field_spec.rb
@@ -0,0 +1,84 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#text_field" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns an text-'input'-element without a name" do
+ output = @html.text_field
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.text_field { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name" do
+ it "returns an text-'input'-element with the passed name" do
+ output = @html.text_field("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.text_field("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, value" do
+ it "returns an text-'input'-element with the passed name and value" do
+ output = @html.text_field("test", "some value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.text_field("test", "some value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, value, size" do
+ it "returns an text-'input'-element with the passed name, value and size" do
+ output = @html.text_field("test", "some value", 60)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.text_field("test", "some value", 60) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed name, value, size, maxlength" do
+ it "returns an text-'input'-element with the passed name, value, size and maxlength" do
+ output = @html.text_field("test", "some value", 60, 12)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.text_field("test", "some value", 60, 12) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ end
+ end
+
+ describe "when passed Hash" do
+ it "returns a checkbox-'input'-element using the passed Hash for attributes" do
+ output = @html.text_field("NAME" => "test", "VALUE" => "some value")
+ output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "text" }, "", not_closed: true)
+
+ output = @html.text_field("TYPE" => "hidden")
+ output.should equal_element("INPUT", {"TYPE" => "text"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.text_field("NAME" => "test", "VALUE" => "some value") { "test" }
+ output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "text" }, "", not_closed: true)
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/htmlextension/textarea_spec.rb b/spec/ruby/library/cgi/htmlextension/textarea_spec.rb
new file mode 100644
index 0000000000..e47e6ed417
--- /dev/null
+++ b/spec/ruby/library/cgi/htmlextension/textarea_spec.rb
@@ -0,0 +1,73 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "CGI::HtmlExtension#textarea" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ end
+
+ describe "when passed no arguments" do
+ it "returns an 'textarea'-element without a name" do
+ output = @html.textarea
+ output.should equal_element("TEXTAREA", {"NAME" => "", "COLS" => "70", "ROWS" => "10"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.textarea { "Example" }
+ output.should equal_element("TEXTAREA", {"NAME" => "", "COLS" => "70", "ROWS" => "10"}, "Example")
+ end
+ end
+
+ describe "when passed name" do
+ it "returns an 'textarea'-element with the passed name" do
+ output = @html.textarea("test")
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "70", "ROWS" => "10"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.textarea("test") { "Example" }
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "70", "ROWS" => "10"}, "Example")
+ end
+ end
+
+ describe "when passed name, cols" do
+ it "returns an 'textarea'-element with the passed name and the passed amount of columns" do
+ output = @html.textarea("test", 40)
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "10"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.textarea("test", 40) { "Example" }
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "10"}, "Example")
+ end
+ end
+
+ describe "when passed name, cols, rows" do
+ it "returns an 'textarea'-element with the passed name, the passed amount of columns and the passed number of rows" do
+ output = @html.textarea("test", 40, 5)
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "5"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.textarea("test", 40, 5) { "Example" }
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "5"}, "Example")
+ end
+ end
+
+ describe "when passed Hash" do
+ it "uses the passed Hash as attributes" do
+ @html.textarea("ID" => "test").should == '<TEXTAREA ID="test"></TEXTAREA>'
+
+ attributes = {"ID" => "test-id", "NAME" => "test-name"}
+ output = @html.textarea(attributes)
+ output.should equal_element("TEXTAREA", attributes, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ attributes = {"ID" => "test-id", "NAME" => "test-name"}
+ output = @html.textarea(attributes) { "test" }
+ output.should equal_element("TEXTAREA", attributes, "test")
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/http_header_spec.rb b/spec/ruby/library/cgi/http_header_spec.rb
new file mode 100644
index 0000000000..1960d009e4
--- /dev/null
+++ b/spec/ruby/library/cgi/http_header_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+require File.expand_path('../shared/http_header', __FILE__)
+
+describe "CGI#http_header" do
+ it_behaves_like(:cgi_http_header, :http_header)
+end
diff --git a/spec/ruby/library/cgi/initialize_spec.rb b/spec/ruby/library/cgi/initialize_spec.rb
new file mode 100644
index 0000000000..6526aab5e8
--- /dev/null
+++ b/spec/ruby/library/cgi/initialize_spec.rb
@@ -0,0 +1,133 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI#initialize" do
+ it "is private" do
+ CGI.should have_private_instance_method(:initialize)
+ end
+end
+
+describe "CGI#initialize when passed no arguments" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.allocate
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "extends self with CGI::QueryExtension" do
+ @cgi.send(:initialize)
+ @cgi.should be_kind_of(CGI::QueryExtension)
+ end
+
+ it "does not extend self with CGI::HtmlExtension" do
+ @cgi.send(:initialize)
+ @cgi.should_not be_kind_of(CGI::HtmlExtension)
+ end
+
+ it "does not extend self with any of the other HTML modules" do
+ @cgi.send(:initialize)
+ @cgi.should_not be_kind_of(CGI::Html3)
+ @cgi.should_not be_kind_of(CGI::HtmlExtension)
+ @cgi.should_not be_kind_of(CGI::Html4)
+ @cgi.should_not be_kind_of(CGI::Html4Tr)
+ @cgi.should_not be_kind_of(CGI::Html4Fr)
+ end
+
+ it "sets #cookies based on ENV['HTTP_COOKIE']" do
+ begin
+ old_env, ENV["HTTP_COOKIE"] = ENV["HTTP_COOKIE"], "test=test yay"
+ @cgi.send(:initialize)
+ @cgi.cookies.should == { "test"=>[ "test yay" ] }
+ ensure
+ ENV["HTTP_COOKIE"] = old_env
+ end
+ end
+
+ it "sets #params based on ENV['QUERY_STRING'] when ENV['REQUEST_METHOD'] is GET" do
+ begin
+ old_env_query, ENV["QUERY_STRING"] = ENV["QUERY_STRING"], "?test=a&test2=b"
+ old_env_method, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], "GET"
+ @cgi.send(:initialize)
+ @cgi.params.should == { "test2" => ["b"], "?test" => ["a"] }
+ ensure
+ ENV["QUERY_STRING"] = old_env_query
+ ENV["REQUEST_METHOD"] = old_env_method
+ end
+ end
+
+ it "sets #params based on ENV['QUERY_STRING'] when ENV['REQUEST_METHOD'] is HEAD" do
+ begin
+ old_env_query, ENV["QUERY_STRING"] = ENV["QUERY_STRING"], "?test=a&test2=b"
+ old_env_method, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], "HEAD"
+ @cgi.send(:initialize)
+ @cgi.params.should == { "test2" => ["b"], "?test" => ["a"] }
+ ensure
+ ENV["QUERY_STRING"] = old_env_query
+ ENV["REQUEST_METHOD"] = old_env_method
+ end
+ end
+end
+
+describe "CGI#initialize when passed type" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.allocate
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+
+ it "extends self with CGI::QueryExtension" do
+ @cgi.send(:initialize, "test")
+ @cgi.should be_kind_of(CGI::QueryExtension)
+ end
+
+ it "extends self with CGI::QueryExtension, CGI::Html3 and CGI::HtmlExtension when the passed type is 'html3'" do
+ @cgi.send(:initialize, "html3")
+ @cgi.should be_kind_of(CGI::Html3)
+ @cgi.should be_kind_of(CGI::HtmlExtension)
+ @cgi.should be_kind_of(CGI::QueryExtension)
+
+ @cgi.should_not be_kind_of(CGI::Html4)
+ @cgi.should_not be_kind_of(CGI::Html4Tr)
+ @cgi.should_not be_kind_of(CGI::Html4Fr)
+ end
+
+ it "extends self with CGI::QueryExtension, CGI::Html4 and CGI::HtmlExtension when the passed type is 'html4'" do
+ @cgi.send(:initialize, "html4")
+ @cgi.should be_kind_of(CGI::Html4)
+ @cgi.should be_kind_of(CGI::HtmlExtension)
+ @cgi.should be_kind_of(CGI::QueryExtension)
+
+ @cgi.should_not be_kind_of(CGI::Html3)
+ @cgi.should_not be_kind_of(CGI::Html4Tr)
+ @cgi.should_not be_kind_of(CGI::Html4Fr)
+ end
+
+ it "extends self with CGI::QueryExtension, CGI::Html4Tr and CGI::HtmlExtension when the passed type is 'html4Tr'" do
+ @cgi.send(:initialize, "html4Tr")
+ @cgi.should be_kind_of(CGI::Html4Tr)
+ @cgi.should be_kind_of(CGI::HtmlExtension)
+ @cgi.should be_kind_of(CGI::QueryExtension)
+
+ @cgi.should_not be_kind_of(CGI::Html3)
+ @cgi.should_not be_kind_of(CGI::Html4)
+ @cgi.should_not be_kind_of(CGI::Html4Fr)
+ end
+
+ it "extends self with CGI::QueryExtension, CGI::Html4Tr, CGI::Html4Fr and CGI::HtmlExtension when the passed type is 'html4Fr'" do
+ @cgi.send(:initialize, "html4Fr")
+ @cgi.should be_kind_of(CGI::Html4Tr)
+ @cgi.should be_kind_of(CGI::Html4Fr)
+ @cgi.should be_kind_of(CGI::HtmlExtension)
+ @cgi.should be_kind_of(CGI::QueryExtension)
+
+ @cgi.should_not be_kind_of(CGI::Html3)
+ @cgi.should_not be_kind_of(CGI::Html4)
+ end
+end
diff --git a/spec/ruby/library/cgi/out_spec.rb b/spec/ruby/library/cgi/out_spec.rb
new file mode 100644
index 0000000000..05fe2662dc
--- /dev/null
+++ b/spec/ruby/library/cgi/out_spec.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI#out" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ $stdout, @old_stdout = IOStub.new, $stdout
+ end
+
+ after :each do
+ $stdout = @old_stdout
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "it writes a HTMl header based on the passed argument to $stdout" do
+ @cgi.out { "" }
+ $stdout.should == "Content-Type: text/html\r\nContent-Length: 0\r\n\r\n"
+ end
+
+ it "appends the block's return value to the HTML header" do
+ @cgi.out { "test!" }
+ $stdout.should == "Content-Type: text/html\r\nContent-Length: 5\r\n\r\ntest!"
+ end
+
+ it "automatically sets the Content-Length Header based on the block's return value" do
+ @cgi.out { "0123456789" }
+ $stdout.should == "Content-Type: text/html\r\nContent-Length: 10\r\n\r\n0123456789"
+ end
+
+ it "includes Cookies in the @output_cookies field" do
+ @cgi.instance_variable_set(:@output_cookies, ["multiple", "cookies"])
+ @cgi.out { "" }
+ $stdout.should == "Content-Type: text/html\r\nContent-Length: 0\r\nSet-Cookie: multiple\r\nSet-Cookie: cookies\r\n\r\n"
+ end
+end
+
+describe "CGI#out when passed no block" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "raises a LocalJumpError" do
+ lambda { @cgi.out }.should raise_error(LocalJumpError)
+ end
+end
diff --git a/spec/ruby/library/cgi/parse_spec.rb b/spec/ruby/library/cgi/parse_spec.rb
new file mode 100644
index 0000000000..8f05c91c7b
--- /dev/null
+++ b/spec/ruby/library/cgi/parse_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI.parse when passed String" do
+ it "parses a HTTP Query String into a Hash" do
+ CGI.parse("test=test&a=b").should == { "a" => ["b"], "test" => ["test"] }
+ CGI.parse("test=1,2,3").should == { "test" => ["1,2,3"] }
+ CGI.parse("test=a&a=&b=").should == { "test" => ["a"], "a" => [""], "b" => [""] }
+ end
+
+ it "parses query strings with semicolons in place of ampersands" do
+ CGI.parse("test=test;a=b").should == { "a" => ["b"], "test" => ["test"] }
+ CGI.parse("test=a;a=;b=").should == { "test" => ["a"], "a" => [""], "b" => [""] }
+ end
+
+ it "allows passing multiple values for one key" do
+ CGI.parse("test=1&test=2&test=3").should == { "test" => ["1", "2", "3"] }
+ CGI.parse("test[]=1&test[]=2&test[]=3").should == { "test[]" => [ "1", "2", "3" ] }
+ end
+
+ it "unescapes keys and values" do
+ CGI.parse("hello%3F=hello%21").should == { "hello?" => ["hello!"] }
+ end
+end
diff --git a/spec/ruby/library/cgi/pretty_spec.rb b/spec/ruby/library/cgi/pretty_spec.rb
new file mode 100644
index 0000000000..e09c327ef6
--- /dev/null
+++ b/spec/ruby/library/cgi/pretty_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI.pretty when passed html" do
+ it "indents the passed html String with two spaces" do
+ CGI.pretty("<HTML><BODY></BODY></HTML>").should == <<-EOS
+<HTML>
+ <BODY>
+ </BODY>
+</HTML>
+EOS
+ end
+end
+
+describe "CGI.pretty when passed html, indentation_unit" do
+ it "indents the passed html String with the passed indentation_unit" do
+ CGI.pretty("<HTML><BODY></BODY></HTML>", "\t").should == <<-EOS
+<HTML>
+\t<BODY>
+\t</BODY>
+</HTML>
+EOS
+ end
+end
diff --git a/spec/ruby/library/cgi/print_spec.rb b/spec/ruby/library/cgi/print_spec.rb
new file mode 100644
index 0000000000..0db5efa0dd
--- /dev/null
+++ b/spec/ruby/library/cgi/print_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI#print" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "passes all arguments to $stdout.print" do
+ $stdout.should_receive(:print).with("test")
+ @cgi.print("test")
+
+ $stdout.should_receive(:print).with("one", "two", "three", ["four", "five"])
+ @cgi.print("one", "two", "three", ["four", "five"])
+ end
+
+ it "returns the result of calling $stdout.print" do
+ $stdout.should_receive(:print).with("test").and_return(:expected)
+ @cgi.print("test").should == :expected
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/accept_charset_spec.rb b/spec/ruby/library/cgi/queryextension/accept_charset_spec.rb
new file mode 100644
index 0000000000..be340b26f0
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/accept_charset_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#accept_charset" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_ACCEPT_CHARSET']" do
+ old_value, ENV['HTTP_ACCEPT_CHARSET'] = ENV['HTTP_ACCEPT_CHARSET'], "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
+ begin
+ @cgi.accept_charset.should == "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
+ ensure
+ ENV['HTTP_ACCEPT_CHARSET'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb b/spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb
new file mode 100644
index 0000000000..a828ae7a42
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#accept_encoding" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_ACCEPT_ENCODING']" do
+ old_value, ENV['HTTP_ACCEPT_ENCODING'] = ENV['HTTP_ACCEPT_ENCODING'], "gzip,deflate"
+ begin
+ @cgi.accept_encoding.should == "gzip,deflate"
+ ensure
+ ENV['HTTP_ACCEPT_ENCODING'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/accept_language_spec.rb b/spec/ruby/library/cgi/queryextension/accept_language_spec.rb
new file mode 100644
index 0000000000..77b4740251
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/accept_language_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#accept_language" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_ACCEPT_LANGUAGE']" do
+ old_value, ENV['HTTP_ACCEPT_LANGUAGE'] = ENV['HTTP_ACCEPT_LANGUAGE'], "en-us,en;q=0.5"
+ begin
+ @cgi.accept_language.should == "en-us,en;q=0.5"
+ ensure
+ ENV['HTTP_ACCEPT_LANGUAGE'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/accept_spec.rb b/spec/ruby/library/cgi/queryextension/accept_spec.rb
new file mode 100644
index 0000000000..0c7aa2ab1f
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/accept_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#accept" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_ACCEPT']" do
+ old_value, ENV['HTTP_ACCEPT'] = ENV['HTTP_ACCEPT'], "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
+ begin
+ @cgi.accept.should == "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
+ ensure
+ ENV['HTTP_ACCEPT'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/auth_type_spec.rb b/spec/ruby/library/cgi/queryextension/auth_type_spec.rb
new file mode 100644
index 0000000000..0ec2835053
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/auth_type_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#auth_type" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['AUTH_TYPE']" do
+ old_value, ENV['AUTH_TYPE'] = ENV['AUTH_TYPE'], "Basic"
+ begin
+ @cgi.auth_type.should == "Basic"
+ ensure
+ ENV['AUTH_TYPE'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/cache_control_spec.rb b/spec/ruby/library/cgi/queryextension/cache_control_spec.rb
new file mode 100644
index 0000000000..f1718b0871
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/cache_control_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#cache_control" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_CACHE_CONTROL']" do
+ old_value, ENV['HTTP_CACHE_CONTROL'] = ENV['HTTP_CACHE_CONTROL'], "no-cache"
+ begin
+ @cgi.cache_control.should == "no-cache"
+ ensure
+ ENV['HTTP_CACHE_CONTROL'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/content_length_spec.rb b/spec/ruby/library/cgi/queryextension/content_length_spec.rb
new file mode 100644
index 0000000000..c9f0708f69
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/content_length_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#content_length" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['CONTENT_LENGTH'] as Integer" do
+ old_value = ENV['CONTENT_LENGTH']
+ begin
+ ENV['CONTENT_LENGTH'] = nil
+ @cgi.content_length.should be_nil
+
+ ENV['CONTENT_LENGTH'] = "100"
+ @cgi.content_length.should eql(100)
+ ensure
+ ENV['CONTENT_LENGTH'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/content_type_spec.rb b/spec/ruby/library/cgi/queryextension/content_type_spec.rb
new file mode 100644
index 0000000000..a65b0a6103
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/content_type_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#content_type" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['CONTENT_TYPE']" do
+ old_value, ENV['CONTENT_TYPE'] = ENV['CONTENT_TYPE'], "text/html"
+ begin
+ @cgi.content_type.should == "text/html"
+ ensure
+ ENV['CONTENT_TYPE'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/cookies_spec.rb b/spec/ruby/library/cgi/queryextension/cookies_spec.rb
new file mode 100644
index 0000000000..5df457f11c
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/cookies_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#cookies" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "CGI::QueryExtension#cookies=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/cgi/queryextension/element_reference_spec.rb b/spec/ruby/library/cgi/queryextension/element_reference_spec.rb
new file mode 100644
index 0000000000..4aabfaa277
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/element_reference_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#[]" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ ENV['QUERY_STRING'], @old_query_string = "one=a&two=b&two=c", ENV['QUERY_STRING']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ ENV['QUERY_STRING'] = @old_query_string
+ end
+
+ it "it returns the value for the parameter with the given key" do
+ @cgi["one"].should == "a"
+ end
+
+ it "only returns the first value for parameters with multiple values" do
+ @cgi["two"].should == "b"
+ end
+
+ it "returns a String" do
+ @cgi["one"].should be_kind_of(String)
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/from_spec.rb b/spec/ruby/library/cgi/queryextension/from_spec.rb
new file mode 100644
index 0000000000..aabd9b9bb3
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/from_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#from" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_FROM']" do
+ old_value, ENV['HTTP_FROM'] = ENV['HTTP_FROM'], "googlebot(at)googlebot.com"
+ begin
+ @cgi.from.should == "googlebot(at)googlebot.com"
+ ensure
+ ENV['HTTP_FROM'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb b/spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb
new file mode 100644
index 0000000000..8b006063d8
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#gateway_interface" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['GATEWAY_INTERFACE']" do
+ old_value, ENV['GATEWAY_INTERFACE'] = ENV['GATEWAY_INTERFACE'], "CGI/1.1"
+ begin
+ @cgi.gateway_interface.should == "CGI/1.1"
+ ensure
+ ENV['GATEWAY_INTERFACE'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/has_key_spec.rb b/spec/ruby/library/cgi/queryextension/has_key_spec.rb
new file mode 100644
index 0000000000..86ec3d0a29
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/has_key_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../shared/has_key', __FILE__)
+
+describe "CGI::QueryExtension#has_key?" do
+ it_behaves_like :cgi_query_extension_has_key_p, :has_key?
+end
diff --git a/spec/ruby/library/cgi/queryextension/host_spec.rb b/spec/ruby/library/cgi/queryextension/host_spec.rb
new file mode 100644
index 0000000000..89e2610ba7
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/host_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#host" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_HOST']" do
+ old_value, ENV['HTTP_HOST'] = ENV['HTTP_HOST'], "localhost"
+ begin
+ @cgi.host.should == "localhost"
+ ensure
+ ENV['HTTP_HOST'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/include_spec.rb b/spec/ruby/library/cgi/queryextension/include_spec.rb
new file mode 100644
index 0000000000..e8f1bf14ec
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/include_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../shared/has_key', __FILE__)
+
+describe "CGI::QueryExtension#include?" do
+ it_behaves_like :cgi_query_extension_has_key_p, :include?
+end
diff --git a/spec/ruby/library/cgi/queryextension/key_spec.rb b/spec/ruby/library/cgi/queryextension/key_spec.rb
new file mode 100644
index 0000000000..525a0210b2
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/key_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require File.expand_path('../shared/has_key', __FILE__)
+
+describe "CGI::QueryExtension#key?" do
+ it_behaves_like :cgi_query_extension_has_key_p, :key?
+end
diff --git a/spec/ruby/library/cgi/queryextension/keys_spec.rb b/spec/ruby/library/cgi/queryextension/keys_spec.rb
new file mode 100644
index 0000000000..f60b1fb369
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/keys_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#keys" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ ENV['QUERY_STRING'], @old_query_string = "one=a&two=b", ENV['QUERY_STRING']
+
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ ENV['QUERY_STRING'] = @old_query_string
+ end
+
+ it "returns all parameter keys as an Array" do
+ @cgi.keys.sort.should == ["one", "two"]
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/multipart_spec.rb b/spec/ruby/library/cgi/queryextension/multipart_spec.rb
new file mode 100644
index 0000000000..021c847fa3
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/multipart_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+require "stringio"
+
+describe "CGI::QueryExtension#multipart?" do
+ before :each do
+ @old_stdin = $stdin
+
+ @old_request_method = ENV['REQUEST_METHOD']
+ @old_content_type = ENV['CONTENT_TYPE']
+ @old_content_length = ENV['CONTENT_LENGTH']
+
+ ENV['REQUEST_METHOD'] = "POST"
+ ENV["CONTENT_TYPE"] = "multipart/form-data; boundary=---------------------------1137522503144128232716531729"
+ ENV["CONTENT_LENGTH"] = "222"
+
+ $stdin = StringIO.new <<-EOS
+-----------------------------1137522503144128232716531729\r
+Content-Disposition: form-data; name="file"; filename=""\r
+Content-Type: application/octet-stream\r
+\r
+\r
+-----------------------------1137522503144128232716531729--\r
+EOS
+
+ @cgi = CGI.new
+ end
+
+ after :each do
+ $stdin = @old_stdin
+
+ ENV['REQUEST_METHOD'] = @old_request_method
+ ENV['CONTENT_TYPE'] = @old_content_type
+ ENV['CONTENT_LENGTH'] = @old_content_length
+ end
+
+ it "returns true if the current Request is a multipart request" do
+ @cgi.multipart?.should be_true
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/negotiate_spec.rb b/spec/ruby/library/cgi/queryextension/negotiate_spec.rb
new file mode 100644
index 0000000000..503ae583bf
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/negotiate_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#negotiate" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_NEGOTIATE']" do
+ old_value, ENV['HTTP_NEGOTIATE'] = ENV['HTTP_NEGOTIATE'], "trans"
+ begin
+ @cgi.negotiate.should == "trans"
+ ensure
+ ENV['HTTP_NEGOTIATE'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/params_spec.rb b/spec/ruby/library/cgi/queryextension/params_spec.rb
new file mode 100644
index 0000000000..6d47b3eeee
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/params_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#params" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ ENV['QUERY_STRING'], @old_query_string = "one=a&two=b&two=c&three", ENV['QUERY_STRING']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['QUERY_STRING'] = @old_query_string
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns the parsed HTTP Query Params" do
+ @cgi.params.should == {"three"=>[], "two"=>["b", "c"], "one"=>["a"]}
+ end
+end
+
+describe "CGI::QueryExtension#params=" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "sets the HTTP Query Params to the passed argument" do
+ @cgi.params.should == {}
+
+ @cgi.params = {"one"=>["a"], "two"=>["b", "c"]}
+ @cgi.params.should == {"one"=>["a"], "two"=>["b", "c"]}
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/path_info_spec.rb b/spec/ruby/library/cgi/queryextension/path_info_spec.rb
new file mode 100644
index 0000000000..8c8af27fc9
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/path_info_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#path_info" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['PATH_INFO']" do
+ old_value, ENV['PATH_INFO'] = ENV['PATH_INFO'], "/test/path"
+ begin
+ @cgi.path_info.should == "/test/path"
+ ensure
+ ENV['PATH_INFO'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/path_translated_spec.rb b/spec/ruby/library/cgi/queryextension/path_translated_spec.rb
new file mode 100644
index 0000000000..6e9db707b3
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/path_translated_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#path_translated" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['PATH_TRANSLATED']" do
+ old_value, ENV['PATH_TRANSLATED'] = ENV['PATH_TRANSLATED'], "/full/path/to/dir"
+ begin
+ @cgi.path_translated.should == "/full/path/to/dir"
+ ensure
+ ENV['PATH_TRANSLATED'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/pragma_spec.rb b/spec/ruby/library/cgi/queryextension/pragma_spec.rb
new file mode 100644
index 0000000000..c0c7b20514
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/pragma_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#pragma" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_PRAGMA']" do
+ old_value, ENV['HTTP_PRAGMA'] = ENV['HTTP_PRAGMA'], "no-cache"
+ begin
+ @cgi.pragma.should == "no-cache"
+ ensure
+ ENV['HTTP_PRAGMA'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/query_string_spec.rb b/spec/ruby/library/cgi/queryextension/query_string_spec.rb
new file mode 100644
index 0000000000..1065bac7ef
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/query_string_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#query_string" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['QUERY_STRING']" do
+ old_value, ENV['QUERY_STRING'] = ENV['QUERY_STRING'], "one=a&two=b"
+ begin
+ @cgi.query_string.should == "one=a&two=b"
+ ensure
+ ENV['QUERY_STRING'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb b/spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb
new file mode 100644
index 0000000000..84b0e0c0dc
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#raw_cookie2" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_COOKIE2']" do
+ old_value, ENV['HTTP_COOKIE2'] = ENV['HTTP_COOKIE2'], "some_cookie=data"
+ begin
+ @cgi.raw_cookie2.should == "some_cookie=data"
+ ensure
+ ENV['HTTP_COOKIE2'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb b/spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb
new file mode 100644
index 0000000000..096bcf9fab
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#raw_cookie" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_COOKIE']" do
+ old_value, ENV['HTTP_COOKIE'] = ENV['HTTP_COOKIE'], "some_cookie=data"
+ begin
+ @cgi.raw_cookie.should == "some_cookie=data"
+ ensure
+ ENV['HTTP_COOKIE'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/referer_spec.rb b/spec/ruby/library/cgi/queryextension/referer_spec.rb
new file mode 100644
index 0000000000..d52b3a501a
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/referer_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#referer" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_REFERER']" do
+ old_value, ENV['HTTP_REFERER'] = ENV['HTTP_REFERER'], "example.com"
+ begin
+ @cgi.referer.should == "example.com"
+ ensure
+ ENV['HTTP_REFERER'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/remote_addr_spec.rb b/spec/ruby/library/cgi/queryextension/remote_addr_spec.rb
new file mode 100644
index 0000000000..dc94e2c953
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/remote_addr_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#remote_addr" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['REMOTE_ADDR']" do
+ old_value, ENV['REMOTE_ADDR'] = ENV['REMOTE_ADDR'], "127.0.0.1"
+ begin
+ @cgi.remote_addr.should == "127.0.0.1"
+ ensure
+ ENV['REMOTE_ADDR'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/remote_host_spec.rb b/spec/ruby/library/cgi/queryextension/remote_host_spec.rb
new file mode 100644
index 0000000000..f62664b9a7
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/remote_host_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#remote_host" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['REMOTE_HOST']" do
+ old_value, ENV['REMOTE_HOST'] = ENV['REMOTE_HOST'], "test.host"
+ begin
+ @cgi.remote_host.should == "test.host"
+ ensure
+ ENV['REMOTE_HOST'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/remote_ident_spec.rb b/spec/ruby/library/cgi/queryextension/remote_ident_spec.rb
new file mode 100644
index 0000000000..3aab059a7e
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/remote_ident_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#remote_ident" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['REMOTE_IDENT']" do
+ old_value, ENV['REMOTE_IDENT'] = ENV['REMOTE_IDENT'], "no-idea-what-this-is-for"
+ begin
+ @cgi.remote_ident.should == "no-idea-what-this-is-for"
+ ensure
+ ENV['REMOTE_IDENT'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/remote_user_spec.rb b/spec/ruby/library/cgi/queryextension/remote_user_spec.rb
new file mode 100644
index 0000000000..5aae6bc755
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/remote_user_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#remote_user" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['REMOTE_USER']" do
+ old_value, ENV['REMOTE_USER'] = ENV['REMOTE_USER'], "username"
+ begin
+ @cgi.remote_user.should == "username"
+ ensure
+ ENV['REMOTE_USER'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/request_method_spec.rb b/spec/ruby/library/cgi/queryextension/request_method_spec.rb
new file mode 100644
index 0000000000..7fa85a3b34
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/request_method_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#request_method" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['REQUEST_METHOD']" do
+ old_value, ENV['REQUEST_METHOD'] = ENV['REQUEST_METHOD'], "GET"
+ begin
+ @cgi.request_method.should == "GET"
+ ensure
+ ENV['REQUEST_METHOD'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/script_name_spec.rb b/spec/ruby/library/cgi/queryextension/script_name_spec.rb
new file mode 100644
index 0000000000..7509e002d4
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/script_name_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#script_name" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['SCRIPT_NAME']" do
+ old_value, ENV['SCRIPT_NAME'] = ENV['SCRIPT_NAME'], "/path/to/script.rb"
+ begin
+ @cgi.script_name.should == "/path/to/script.rb"
+ ensure
+ ENV['SCRIPT_NAME'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/server_name_spec.rb b/spec/ruby/library/cgi/queryextension/server_name_spec.rb
new file mode 100644
index 0000000000..acc8f9e4aa
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/server_name_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#server_name" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['SERVER_NAME']" do
+ old_value, ENV['SERVER_NAME'] = ENV['SERVER_NAME'], "localhost"
+ begin
+ @cgi.server_name.should == "localhost"
+ ensure
+ ENV['SERVER_NAME'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/server_port_spec.rb b/spec/ruby/library/cgi/queryextension/server_port_spec.rb
new file mode 100644
index 0000000000..adeabfda65
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/server_port_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#server_port" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['SERVER_PORT'] as Integer" do
+ old_value = ENV['SERVER_PORT']
+ begin
+ ENV['SERVER_PORT'] = nil
+ @cgi.server_port.should be_nil
+
+ ENV['SERVER_PORT'] = "3000"
+ @cgi.server_port.should eql(3000)
+ ensure
+ ENV['SERVER_PORT'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/server_protocol_spec.rb b/spec/ruby/library/cgi/queryextension/server_protocol_spec.rb
new file mode 100644
index 0000000000..f1285bbd20
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/server_protocol_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#server_protocol" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['SERVER_PROTOCOL']" do
+ old_value, ENV['SERVER_PROTOCOL'] = ENV['SERVER_PROTOCOL'], "HTTP/1.1"
+ begin
+ @cgi.server_protocol.should == "HTTP/1.1"
+ ensure
+ ENV['SERVER_PROTOCOL'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/server_software_spec.rb b/spec/ruby/library/cgi/queryextension/server_software_spec.rb
new file mode 100644
index 0000000000..e982a6f31c
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/server_software_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#server_software" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['SERVER_SOFTWARE']" do
+ old_value, ENV['SERVER_SOFTWARE'] = ENV['SERVER_SOFTWARE'], "Server/1.0.0"
+ begin
+ @cgi.server_software.should == "Server/1.0.0"
+ ensure
+ ENV['SERVER_SOFTWARE'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/shared/has_key.rb b/spec/ruby/library/cgi/queryextension/shared/has_key.rb
new file mode 100644
index 0000000000..cfac5865fa
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/shared/has_key.rb
@@ -0,0 +1,19 @@
+describe :cgi_query_extension_has_key_p, shared: true do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ ENV['QUERY_STRING'], @old_query_string = "one=a&two=b", ENV['QUERY_STRING']
+
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ ENV['QUERY_STRING'] = @old_query_string
+ end
+
+ it "returns true when the passed key exists in the HTTP Query" do
+ @cgi.send(@method, "one").should be_true
+ @cgi.send(@method, "two").should be_true
+ @cgi.send(@method, "three").should be_false
+ end
+end
diff --git a/spec/ruby/library/cgi/queryextension/user_agent_spec.rb b/spec/ruby/library/cgi/queryextension/user_agent_spec.rb
new file mode 100644
index 0000000000..8bbfed17c5
--- /dev/null
+++ b/spec/ruby/library/cgi/queryextension/user_agent_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI::QueryExtension#user_agent" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "returns ENV['HTTP_USER_AGENT']" do
+ old_value, ENV['HTTP_USER_AGENT'] = ENV['HTTP_USER_AGENT'], "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; de-de) AppleWebKit/527+ (KHTML, like Gecko) Version/3.1 Safari/525.13"
+ begin
+ @cgi.user_agent.should == "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; de-de) AppleWebKit/527+ (KHTML, like Gecko) Version/3.1 Safari/525.13"
+ ensure
+ ENV['HTTP_USER_AGENT'] = old_value
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/rfc1123_date_spec.rb b/spec/ruby/library/cgi/rfc1123_date_spec.rb
new file mode 100644
index 0000000000..73e07c6fbd
--- /dev/null
+++ b/spec/ruby/library/cgi/rfc1123_date_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI.rfc1123_date when passsed Time" do
+ it "returns the passed Time formatted in RFC1123 ('Sat, 01 Dec 2007 15:56:42 GMT')" do
+ input = Time.at(1196524602)
+ expected = 'Sat, 01 Dec 2007 15:56:42 GMT'
+ CGI.rfc1123_date(input).should == expected
+ end
+end
diff --git a/spec/ruby/library/cgi/shared/http_header.rb b/spec/ruby/library/cgi/shared/http_header.rb
new file mode 100644
index 0000000000..ed65b20abd
--- /dev/null
+++ b/spec/ruby/library/cgi/shared/http_header.rb
@@ -0,0 +1,112 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe :cgi_http_header, shared: true do
+ describe "CGI#http_header when passed no arguments" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+
+ it "returns a HTTP header specifiying the Content-Type as text/html" do
+ @cgi.send(@method).should == "Content-Type: text/html\r\n\r\n"
+ end
+
+ it "includes Cookies in the @output_cookies field" do
+ @cgi.instance_variable_set(:@output_cookies, ["multiple", "cookies"])
+ @cgi.send(@method).should == "Content-Type: text/html\r\nSet-Cookie: multiple\r\nSet-Cookie: cookies\r\n\r\n"
+ end
+ end
+
+ describe "CGI#http_header when passed String" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+
+ it "returns a HTTP header specifiying the Content-Type as the passed String's content" do
+ @cgi.send(@method, "text/plain").should == "Content-Type: text/plain\r\n\r\n"
+ end
+
+ it "includes Cookies in the @output_cookies field" do
+ @cgi.instance_variable_set(:@output_cookies, ["multiple", "cookies"])
+ @cgi.send(@method, "text/plain").should == "Content-Type: text/plain\r\nSet-Cookie: multiple\r\nSet-Cookie: cookies\r\n\r\n"
+ end
+ end
+
+ describe "CGI#http_header when passed Hash" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+
+ it "returns a HTTP header based on the Hash's key/value pairs" do
+ header = @cgi.send(@method, "type" => "text/plain")
+ header.should == "Content-Type: text/plain\r\n\r\n"
+
+ header = @cgi.send(@method, "type" => "text/plain", "charset" => "UTF-8")
+ header.should == "Content-Type: text/plain; charset=UTF-8\r\n\r\n"
+
+ header = @cgi.send(@method, "nph" => true)
+ header.should include("HTTP/1.0 200 OK\r\n")
+ header.should include("Date: ")
+ header.should include("Server: ")
+ header.should include("Connection: close\r\n")
+ header.should include("Content-Type: text/html\r\n")
+
+ header = @cgi.send(@method, "status" => "OK")
+ header.should == "Status: 200 OK\r\nContent-Type: text/html\r\n\r\n"
+
+ header = @cgi.send(@method, "status" => "PARTIAL_CONTENT")
+ header.should == "Status: 206 Partial Content\r\nContent-Type: text/html\r\n\r\n"
+
+ header = @cgi.send(@method, "status" => "MULTIPLE_CHOICES")
+ header.should == "Status: 300 Multiple Choices\r\nContent-Type: text/html\r\n\r\n"
+
+ header = @cgi.send(@method, "server" => "Server Software used")
+ header.should == "Server: Server Software used\r\nContent-Type: text/html\r\n\r\n"
+
+ header = @cgi.send(@method, "connection" => "connection type")
+ header.should == "Connection: connection type\r\nContent-Type: text/html\r\n\r\n"
+
+ header = @cgi.send(@method, "length" => 103)
+ header.should == "Content-Type: text/html\r\nContent-Length: 103\r\n\r\n"
+
+ header = @cgi.send(@method, "language" => "ja")
+ header.should == "Content-Type: text/html\r\nContent-Language: ja\r\n\r\n"
+
+ header = @cgi.send(@method, "expires" => Time.at(0))
+ header.should == "Content-Type: text/html\r\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\r\n\r\n"
+
+ header = @cgi.send(@method, "cookie" => "my cookie's content")
+ header.should == "Content-Type: text/html\r\nSet-Cookie: my cookie's content\r\n\r\n"
+
+ header = @cgi.send(@method, "cookie" => ["multiple", "cookies"])
+ header.should == "Content-Type: text/html\r\nSet-Cookie: multiple\r\nSet-Cookie: cookies\r\n\r\n"
+ end
+
+ it "includes Cookies in the @output_cookies field" do
+ @cgi.instance_variable_set(:@output_cookies, ["multiple", "cookies"])
+ @cgi.send(@method, {}).should == "Content-Type: text/html\r\nSet-Cookie: multiple\r\nSet-Cookie: cookies\r\n\r\n"
+ end
+
+ it "returns a HTTP header specifiying the Content-Type as text/html when passed an empty Hash" do
+ @cgi.send(@method, {}).should == "Content-Type: text/html\r\n\r\n"
+ end
+ end
+end
diff --git a/spec/ruby/library/cgi/unescapeElement_spec.rb b/spec/ruby/library/cgi/unescapeElement_spec.rb
new file mode 100644
index 0000000000..cc26f9b484
--- /dev/null
+++ b/spec/ruby/library/cgi/unescapeElement_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI.unescapeElement when passed String, elements, ..." do
+ it "unescapes only the tags of the passed elements in the passed String" do
+ res = CGI.unescapeElement("&lt;BR&gt;&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;", "A", "IMG")
+ res.should == '&lt;BR&gt;<A HREF="url"></A>'
+
+ res = CGI.unescapeElement('&lt;BR&gt;&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;', ["A", "IMG"])
+ res.should == '&lt;BR&gt;<A HREF="url"></A>'
+ end
+
+ it "is case-insensitive" do
+ res = CGI.unescapeElement("&lt;BR&gt;&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;", "a", "img")
+ res.should == '&lt;BR&gt;<A HREF="url"></A>'
+
+ res = CGI.unescapeElement("&lt;br&gt;&lt;a href=&quot;url&quot;&gt;&lt;/a&gt;", "A", "IMG")
+ res.should == '&lt;br&gt;<a href="url"></a>'
+ end
+end
diff --git a/spec/ruby/library/cgi/unescapeHTML_spec.rb b/spec/ruby/library/cgi/unescapeHTML_spec.rb
new file mode 100644
index 0000000000..611ce0a6f1
--- /dev/null
+++ b/spec/ruby/library/cgi/unescapeHTML_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI.unescapeHTML" do
+ it "unescapes '&amp; &lt; &gt; &quot;' to '& < > \"'" do
+ input = '&amp; &lt; &gt; &quot;'
+ expected = '& < > "'
+ CGI.unescapeHTML(input).should == expected
+ end
+
+ it "doesn't unescape other html entities such as '&copy;' or '&heart'" do
+ input = '&copy;&heart;'
+ expected = input
+ CGI.unescapeHTML(input).should == expected
+ end
+
+ it "unescapes '&#99' format entities" do
+ input = '&#34;&#38;&#39;&#60;&#62;'
+ expected = '"&\'<>'
+ CGI.unescapeHTML(input).should == expected
+ end
+
+ it "unescapes '&#x9999' format entities" do
+ input = '&#x0022;&#x0026;&#x0027;&#x003c;&#x003E;'
+ expected = '"&\'<>'
+ CGI.unescapeHTML(input).should == expected
+ end
+
+ it "leaves invalid formatted strings" do
+ input = '&&lt;&amp&gt;&quot&abcdefghijklmn'
+ expected = '&<&amp>&quot&abcdefghijklmn'
+ CGI.unescapeHTML(input).should == expected
+ end
+
+ it "leaves partial invalid &# at end of string" do
+ input = "fooooooo&#"
+ CGI.unescapeHTML(input).should == input
+ end
+end
diff --git a/spec/ruby/library/cgi/unescape_spec.rb b/spec/ruby/library/cgi/unescape_spec.rb
new file mode 100644
index 0000000000..8cf988b9dd
--- /dev/null
+++ b/spec/ruby/library/cgi/unescape_spec.rb
@@ -0,0 +1,15 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'cgi'
+
+describe "CGI.unescape" do
+ it "url-decodes the passed argument" do
+ input = "+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E"
+ expected = " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
+ CGI.unescape(input).should == expected
+
+ input = 'http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF'
+ expected = "http://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277"
+ CGI.unescape(input).should == expected
+ end
+end
diff --git a/spec/ruby/library/complex/math/acos_spec.rb b/spec/ruby/library/complex/math/acos_spec.rb
new file mode 100644
index 0000000000..84425dbaa1
--- /dev/null
+++ b/spec/ruby/library/complex/math/acos_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/acos', __FILE__)
+
+describe "Math#acos" do
+ it_behaves_like :complex_math_acos, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:acos)
+ end
+end
+
+describe "Math.acos" do
+ it_behaves_like :complex_math_acos, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/acosh_spec.rb b/spec/ruby/library/complex/math/acosh_spec.rb
new file mode 100644
index 0000000000..cda9ce38d6
--- /dev/null
+++ b/spec/ruby/library/complex/math/acosh_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/acosh', __FILE__)
+
+describe "Math#acosh" do
+ it_behaves_like :complex_math_acosh, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:acosh)
+ end
+end
+
+describe "Math.acosh" do
+ it_behaves_like :complex_math_acosh, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/asin_spec.rb b/spec/ruby/library/complex/math/asin_spec.rb
new file mode 100644
index 0000000000..aa26bed11d
--- /dev/null
+++ b/spec/ruby/library/complex/math/asin_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/asin', __FILE__)
+
+describe "Math#asin" do
+ it_behaves_like :complex_math_asin, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:asin)
+ end
+end
+
+describe "Math.asin" do
+ it_behaves_like :complex_math_asin, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/asinh_spec.rb b/spec/ruby/library/complex/math/asinh_spec.rb
new file mode 100644
index 0000000000..a1b0816b33
--- /dev/null
+++ b/spec/ruby/library/complex/math/asinh_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/asinh', __FILE__)
+
+describe "Math#asinh" do
+ it_behaves_like :complex_math_asinh, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:asinh)
+ end
+end
+
+describe "Math.asinh" do
+ it_behaves_like :complex_math_asinh, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/atan2_spec.rb b/spec/ruby/library/complex/math/atan2_spec.rb
new file mode 100644
index 0000000000..7111b4a8ec
--- /dev/null
+++ b/spec/ruby/library/complex/math/atan2_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/atan2', __FILE__)
+
+describe "Math#atan2" do
+ it_behaves_like :complex_math_atan2, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:atan2)
+ end
+end
+
+describe "Math.atan2" do
+ it_behaves_like :complex_math_atan2, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/atan_spec.rb b/spec/ruby/library/complex/math/atan_spec.rb
new file mode 100644
index 0000000000..6659b309e4
--- /dev/null
+++ b/spec/ruby/library/complex/math/atan_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/atan', __FILE__)
+
+describe "Math#atan" do
+ it_behaves_like :complex_math_atan, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:atan)
+ end
+end
+
+describe "Math.atan" do
+ it_behaves_like :complex_math_atan, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/atanh_spec.rb b/spec/ruby/library/complex/math/atanh_spec.rb
new file mode 100644
index 0000000000..a68674f82c
--- /dev/null
+++ b/spec/ruby/library/complex/math/atanh_spec.rb
@@ -0,0 +1,17 @@
+require 'complex'
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../../../fixtures/math/common', __FILE__)
+require File.expand_path('../../../../shared/math/atanh', __FILE__)
+require File.expand_path('../shared/atanh', __FILE__)
+
+describe "Math#atanh" do
+ it_behaves_like :math_atanh_base, :atanh, IncludesMath.new
+ it_behaves_like :complex_math_atanh_complex, :atanh, IncludesMath.new
+
+ it_behaves_like :math_atanh_private, :atanh, IncludesMath.new
+end
+
+describe "Math.atanh" do
+ it_behaves_like :math_atanh_base, :atanh, CMath
+ it_behaves_like :complex_math_atanh_complex, :atanh, CMath
+end
diff --git a/spec/ruby/library/complex/math/cos_spec.rb b/spec/ruby/library/complex/math/cos_spec.rb
new file mode 100644
index 0000000000..4267c601a6
--- /dev/null
+++ b/spec/ruby/library/complex/math/cos_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/cos', __FILE__)
+
+describe "Math#cos" do
+ it_behaves_like :complex_math_cos, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:cos)
+ end
+end
+
+describe "Math.cos" do
+ it_behaves_like :complex_math_cos, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/cosh_spec.rb b/spec/ruby/library/complex/math/cosh_spec.rb
new file mode 100644
index 0000000000..b3aa1bdb69
--- /dev/null
+++ b/spec/ruby/library/complex/math/cosh_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/cosh', __FILE__)
+
+describe "Math#cosh" do
+ it_behaves_like :complex_math_cosh, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:cosh)
+ end
+end
+
+describe "Math.cosh" do
+ it_behaves_like :complex_math_cosh, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/exp_spec.rb b/spec/ruby/library/complex/math/exp_spec.rb
new file mode 100644
index 0000000000..df1d12bbb5
--- /dev/null
+++ b/spec/ruby/library/complex/math/exp_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/exp', __FILE__)
+
+describe "Math#exp" do
+ it_behaves_like :complex_math_exp, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:exp)
+ end
+end
+
+describe "Math.exp" do
+ it_behaves_like :complex_math_exp, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/fixtures/classes.rb b/spec/ruby/library/complex/math/fixtures/classes.rb
new file mode 100644
index 0000000000..443c1a9ace
--- /dev/null
+++ b/spec/ruby/library/complex/math/fixtures/classes.rb
@@ -0,0 +1,4 @@
+require 'cmath'
+class IncludesMath
+ include CMath
+end
diff --git a/spec/ruby/library/complex/math/log10_spec.rb b/spec/ruby/library/complex/math/log10_spec.rb
new file mode 100644
index 0000000000..c7c5717873
--- /dev/null
+++ b/spec/ruby/library/complex/math/log10_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/log10', __FILE__)
+
+describe "Math#log10" do
+ it_behaves_like :complex_math_log10, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:log10)
+ end
+end
+
+describe "Math.log10" do
+ it_behaves_like :complex_math_log10, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/log_spec.rb b/spec/ruby/library/complex/math/log_spec.rb
new file mode 100644
index 0000000000..f55b406af8
--- /dev/null
+++ b/spec/ruby/library/complex/math/log_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/log', __FILE__)
+
+describe "Math#log" do
+ it_behaves_like :complex_math_log, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:log)
+ end
+end
+
+describe "Math.log" do
+ it_behaves_like :complex_math_log, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/shared/acos.rb b/spec/ruby/library/complex/math/shared/acos.rb
new file mode 100644
index 0000000000..7a9e0fe1b2
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/acos.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_acos, shared: true do
+ it "returns the arccosine of the passed argument" do
+ @object.send(:acos, 1).should be_close(0.0, TOLERANCE)
+ @object.send(:acos, 0).should be_close(1.5707963267949, TOLERANCE)
+ @object.send(:acos, -1).should be_close(Math::PI,TOLERANCE)
+ end
+
+ it "returns the arccosine for Complex numbers" do
+ @object.send(:acos, Complex(3, 4)).should be_close(Complex(0.93681246115572, -2.30550903124348), TOLERANCE)
+ end
+
+ it "returns the arccosine for numbers greater than 1.0 as a Complex number" do
+ @object.send(:acos, 1.0001).should be_close(Complex(0.0, 0.0141420177752494), TOLERANCE)
+ end
+
+ it "returns the arccosine for numbers less than -1.0 as a Complex number" do
+ @object.send(:acos, -1.0001).should be_close(Complex(3.14159265358979, -0.0141420177752495), TOLERANCE)
+ end
+end
+
+describe :complex_math_acos_bang, shared: true do
+ it "returns the arccosine of the argument" do
+ @object.send(:acos!, 1).should be_close(0.0, TOLERANCE)
+ @object.send(:acos!, 0).should be_close(1.5707963267949, TOLERANCE)
+ @object.send(:acos!, -1).should be_close(Math::PI,TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:acos!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+
+ it "raises an Errno::EDOM for numbers greater than 1.0" do
+ lambda { @object.send(:acos!, 1.0001) }.should raise_error(Errno::EDOM)
+ end
+
+ it "raises an Errno::EDOM for numbers less than -1.0" do
+ lambda { @object.send(:acos!, -1.0001) }.should raise_error(Errno::EDOM)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/acosh.rb b/spec/ruby/library/complex/math/shared/acosh.rb
new file mode 100644
index 0000000000..b8be750f13
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/acosh.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_acosh, shared: true do
+ it "returns the principle value of the inverse hyperbolic cosine of the argument" do
+ @object.send(:acosh, 14.2).should be_close(3.345146999647, TOLERANCE)
+ @object.send(:acosh, 1.0).should be_close(0.0, TOLERANCE)
+ end
+
+ it "returns the principle value of the inverse hyperbolic cosine for numbers less than 1.0 as a Complex number" do
+ @object.send(:acosh, 1.0 - TOLERANCE).should be_close(Complex(0.0, 0.00774598605746135), TOLERANCE)
+ @object.send(:acosh, 0).should be_close(Complex(0.0, 1.5707963267949), TOLERANCE)
+ @object.send(:acosh, -1.0).should be_close(Complex(0.0, 3.14159265358979), TOLERANCE)
+ end
+
+ it "returns the principle value of the inverse hyperbolic cosine for Complex numbers" do
+ @object.send(:acosh, Complex(3, 4))
+ @object.send(:acosh, Complex(3, 4)).imaginary.should be_close(0.93681246115572, TOLERANCE)
+ @object.send(:acosh, Complex(3, 4)).real.should be_close(2.305509031243477, TOLERANCE)
+ end
+end
+
+describe :complex_math_acosh_bang, shared: true do
+ it "returns the principle value of the inverse hyperbolic cosine of the argument" do
+ @object.send(:acosh!, 14.2).should be_close(3.345146999647, TOLERANCE)
+ @object.send(:acosh!, 1.0).should be_close(0.0, TOLERANCE)
+ end
+
+ it "raises Errno::EDOM for numbers less than 1.0" do
+ lambda { @object.send(:acosh!, 1.0 - TOLERANCE) }.should raise_error(Errno::EDOM)
+ lambda { @object.send(:acosh!, 0) }.should raise_error(Errno::EDOM)
+ lambda { @object.send(:acosh!, -1.0) }.should raise_error(Errno::EDOM)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:acosh!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/asin.rb b/spec/ruby/library/complex/math/shared/asin.rb
new file mode 100644
index 0000000000..3b446cbe24
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/asin.rb
@@ -0,0 +1,47 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_asin, shared: true do
+ it "returns the arcsine of the argument" do
+ @object.send(:asin, 1).should be_close(Math::PI/2, TOLERANCE)
+ @object.send(:asin, 0).should be_close(0.0, TOLERANCE)
+ @object.send(:asin, -1).should be_close(-Math::PI/2, TOLERANCE)
+ @object.send(:asin, 0.25).should be_close(0.252680255142079, TOLERANCE)
+ @object.send(:asin, 0.50).should be_close(0.523598775598299, TOLERANCE)
+ @object.send(:asin, 0.75).should be_close(0.8480620789814816,TOLERANCE)
+ end
+
+ it "returns the arcsine for Complex numbers" do
+ @object.send(:asin, Complex(3, 4)).should be_close(Complex(0.633983865639174, 2.30550903124347), TOLERANCE)
+ end
+
+ it "returns a Complex number when the argument is greater than 1.0" do
+ @object.send(:asin, 1.0001).should be_close(Complex(1.5707963267949, -0.0141420177752494), TOLERANCE)
+ end
+
+ it "returns a Complex number when the argument is less than -1.0" do
+ @object.send(:asin, -1.0001).should be_close(Complex(-1.5707963267949, 0.0141420177752494), TOLERANCE)
+ end
+end
+
+describe :complex_math_asin_bang, shared: true do
+ it "returns the arcsine of the argument" do
+ @object.send(:asin!, 1).should be_close(Math::PI/2, TOLERANCE)
+ @object.send(:asin!, 0).should be_close(0.0, TOLERANCE)
+ @object.send(:asin!, -1).should be_close(-Math::PI/2, TOLERANCE)
+ @object.send(:asin!, 0.25).should be_close(0.252680255142079, TOLERANCE)
+ @object.send(:asin!, 0.50).should be_close(0.523598775598299, TOLERANCE)
+ @object.send(:asin!, 0.75).should be_close(0.8480620789814816,TOLERANCE)
+ end
+
+ it "raises an Errno::EDOM if the argument is greater than 1.0" do
+ lambda { @object.send(:asin!, 1.0001) }.should raise_error( Errno::EDOM)
+ end
+
+ it "raises an Errno::EDOM if the argument is less than -1.0" do
+ lambda { @object.send(:asin!, -1.0001) }.should raise_error( Errno::EDOM)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:asin!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/asinh.rb b/spec/ruby/library/complex/math/shared/asinh.rb
new file mode 100644
index 0000000000..4c2f6c8b5d
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/asinh.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_asinh, shared: true do
+ it "returns the inverse hyperbolic sin of the argument" do
+ @object.send(:asinh, 1.5).should be_close(1.19476321728711, TOLERANCE)
+ @object.send(:asinh, -2.97).should be_close(-1.8089166921397, TOLERANCE)
+ @object.send(:asinh, 0.0).should == 0.0
+ @object.send(:asinh, -0.0).should == -0.0
+ @object.send(:asinh, 1.05367e-08).should be_close(1.05367e-08, TOLERANCE)
+ @object.send(:asinh, -1.05367e-08).should be_close(-1.05367e-08, TOLERANCE)
+ end
+
+ it "returns the inverse hyperbolic sin for Complex numbers" do
+ @object.send(:asinh, Complex(3, 4)).should be_close(Complex(2.29991404087927, 0.917616853351479), TOLERANCE)
+ @object.send(:asinh, Complex(3.5, -4)).should be_close(Complex(2.36263337274419, -0.843166327537659), TOLERANCE)
+ end
+end
+
+describe :complex_math_asinh_bang, shared: true do
+ it "returns the inverse hyperbolic sin of the argument" do
+ @object.send(:asinh!, 1.5).should be_close(1.19476321728711, TOLERANCE)
+ @object.send(:asinh!, -2.97).should be_close(-1.8089166921397, TOLERANCE)
+ @object.send(:asinh!, 0.0).should == 0.0
+ @object.send(:asinh!, -0.0).should == -0.0
+ @object.send(:asinh!, 1.05367e-08).should be_close(1.05367e-08, TOLERANCE)
+ @object.send(:asinh!, -1.05367e-08).should be_close(-1.05367e-08, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:asinh!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/atan.rb b/spec/ruby/library/complex/math/shared/atan.rb
new file mode 100644
index 0000000000..44fa65e1e9
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/atan.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_atan, shared: true do
+ it "returns the arctangent of the argument" do
+ @object.send(:atan, 1).should be_close(Math::PI/4, TOLERANCE)
+ @object.send(:atan, 0).should be_close(0.0, TOLERANCE)
+ @object.send(:atan, -1).should be_close(-Math::PI/4, TOLERANCE)
+ @object.send(:atan, 0.25).should be_close(0.244978663126864, TOLERANCE)
+ @object.send(:atan, 0.50).should be_close(0.463647609000806, TOLERANCE)
+ @object.send(:atan, 0.75).should be_close(0.643501108793284, TOLERANCE)
+ end
+
+ it "returns the arctangent for Complex numbers" do
+ @object.send(:atan, Complex(3, 4)).should be_close(Complex(1.44830699523146, 0.158997191679999), TOLERANCE)
+ @object.send(:atan, Complex(3.5, -4)).should be_close(Complex(1.44507428165589, -0.140323762363786), TOLERANCE)
+ end
+end
+
+describe :complex_math_atan_bang, shared: true do
+ it "returns the arctangent of the argument" do
+ @object.send(:atan!, 1).should be_close(Math::PI/4, TOLERANCE)
+ @object.send(:atan!, 0).should be_close(0.0, TOLERANCE)
+ @object.send(:atan!, -1).should be_close(-Math::PI/4, TOLERANCE)
+ @object.send(:atan!, 0.25).should be_close(0.244978663126864, TOLERANCE)
+ @object.send(:atan!, 0.50).should be_close(0.463647609000806, TOLERANCE)
+ @object.send(:atan!, 0.75).should be_close(0.643501108793284, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:atan!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/atan2.rb b/spec/ruby/library/complex/math/shared/atan2.rb
new file mode 100644
index 0000000000..add1dcd6fa
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/atan2.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_atan2, shared: true do
+ it "returns the arc tangent of the passed arguments" do
+ @object.send(:atan2, 4.2, 0.3).should be_close(1.49948886200961, TOLERANCE)
+ @object.send(:atan2, 0.0, 1.0).should be_close(0.0, TOLERANCE)
+ @object.send(:atan2, -9.1, 3.2).should be_close(-1.23265379809025, TOLERANCE)
+ @object.send(:atan2, 7.22, -3.3).should be_close(1.99950888779256, TOLERANCE)
+ end
+
+ it "returns the arc tangent for two Complex numbers" do
+ CMath.atan2(Complex(3, 4), Complex(3.5, -4)).should be_close(Complex(-0.641757436698881, 1.10829873031207), TOLERANCE)
+ end
+
+ it "returns the arc tangent for Complex and real numbers" do
+ CMath.atan2(Complex(3, 4), -7).should be_close(Complex(2.61576754731561, -0.494290673139855), TOLERANCE)
+ CMath.atan2(5, Complex(3.5, -4)).should be_close(Complex(0.739102348493673, 0.487821626522923), TOLERANCE)
+ end
+end
+
+describe :complex_math_atan2_bang, shared: true do
+ it "returns the arc tangent of the passed arguments" do
+ @object.send(:atan2!, 4.2, 0.3).should be_close(1.49948886200961, TOLERANCE)
+ @object.send(:atan2!, 0.0, 1.0).should be_close(0.0, TOLERANCE)
+ @object.send(:atan2!, -9.1, 3.2).should be_close(-1.23265379809025, TOLERANCE)
+ @object.send(:atan2!, 7.22, -3.3).should be_close(1.99950888779256, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:atan2!, Complex(4, 5), Complex(4, 5)) }.should raise_error(TypeError)
+ lambda { @object.send(:atan2!, 4, Complex(4, 5)) }.should raise_error(TypeError)
+ lambda { @object.send(:atan2!, Complex(4, 5), 5) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/atanh.rb b/spec/ruby/library/complex/math/shared/atanh.rb
new file mode 100644
index 0000000000..4051af081f
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/atanh.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_atanh_complex, shared: true do
+ it "returns the inverse hyperbolic tangent as a Complex number for arguments greater than 1.0" do
+ value = Complex(18.36840028483855, 1.5707963267948966)
+ @object.send(@method, 1.0 + Float::EPSILON).should be_close(value, TOLERANCE)
+
+ value = Complex(0.100335347731076, 1.5707963267949)
+ @object.send(@method, 10).should be_close(value, TOLERANCE)
+ end
+
+ it "returns the inverse hyperbolic tangent as a Complex number for arguments greater than 1.0" do
+ value = Complex(-18.36840028483855, 1.5707963267948966)
+ @object.send(@method, -1.0 - Float::EPSILON).should be_close(value, TOLERANCE)
+
+ value = Complex(0.100335347731076, 1.5707963267949)
+ @object.send(@method, 10).should be_close(value, TOLERANCE)
+ end
+
+ it "returns the inverse hyperbolic tangent for Complex numbers" do
+ value = Complex(0.117500907311434, 1.40992104959658)
+ @object.send(@method, Complex(3, 4)).should be_close(value, TOLERANCE)
+ end
+end
+
+describe :complex_math_atanh_no_complex, shared: true do
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:atanh!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/cos.rb b/spec/ruby/library/complex/math/shared/cos.rb
new file mode 100644
index 0000000000..ab198e1a3b
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/cos.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_cos, shared: true do
+ it "returns the cosine of the argument expressed in radians" do
+ @object.send(:cos, CMath::PI).should be_close(-1.0, TOLERANCE)
+ @object.send(:cos, 0).should be_close(1.0, TOLERANCE)
+ @object.send(:cos, CMath::PI/2).should be_close(0.0, TOLERANCE)
+ @object.send(:cos, 3*Math::PI/2).should be_close(0.0, TOLERANCE)
+ @object.send(:cos, 2*Math::PI).should be_close(1.0, TOLERANCE)
+ end
+
+ it "returns the cosine for Complex numbers" do
+ @object.send(:cos, Complex(0, CMath::PI)).should be_close(Complex(11.5919532755215, 0.0), TOLERANCE)
+ @object.send(:cos, Complex(3, 4)).should be_close(Complex(-27.0349456030742, -3.85115333481178), TOLERANCE)
+ end
+end
+
+describe :complex_math_cos_bang, shared: true do
+ it "returns the cosine of the argument expressed in radians" do
+ @object.send(:cos!, CMath::PI).should be_close(-1.0, TOLERANCE)
+ @object.send(:cos!, 0).should be_close(1.0, TOLERANCE)
+ @object.send(:cos!, CMath::PI/2).should be_close(0.0, TOLERANCE)
+ @object.send(:cos!, 3*Math::PI/2).should be_close(0.0, TOLERANCE)
+ @object.send(:cos!, 2*Math::PI).should be_close(1.0, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:cos!, Complex(3, 4)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/cosh.rb b/spec/ruby/library/complex/math/shared/cosh.rb
new file mode 100644
index 0000000000..a5f98e4e83
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/cosh.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_cosh, shared: true do
+ it "returns the hyperbolic cosine of the passed argument" do
+ @object.send(:cosh, 0.0).should == 1.0
+ @object.send(:cosh, -0.0).should == 1.0
+ @object.send(:cosh, 1.5).should be_close(2.35240961524325, TOLERANCE)
+ @object.send(:cosh, -2.99).should be_close(9.96798496414416, TOLERANCE)
+ end
+
+ it "returns the hyperbolic cosine for Complex numbers" do
+ @object.send(:cosh, Complex(0, CMath::PI)).should be_close(Complex(-1.0, 0.0), TOLERANCE)
+ @object.send(:cosh, Complex(3, 4)).should be_close(Complex(-6.58066304055116, -7.58155274274654), TOLERANCE)
+ end
+end
+
+describe :complex_math_cosh_bang, shared: true do
+ it "returns the hyperbolic cosine of the passed argument" do
+ @object.send(:cosh!, 0.0).should == 1.0
+ @object.send(:cosh!, -0.0).should == 1.0
+ @object.send(:cosh!, 1.5).should be_close(2.35240961524325, TOLERANCE)
+ @object.send(:cosh!, -2.99).should be_close(9.96798496414416, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:cosh!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/exp.rb b/spec/ruby/library/complex/math/shared/exp.rb
new file mode 100644
index 0000000000..f4e73dfb4d
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/exp.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_exp, shared: true do
+ it "returns the base-e exponential of the passed argument" do
+ @object.send(:exp, 0.0).should == 1.0
+ @object.send(:exp, -0.0).should == 1.0
+ @object.send(:exp, -1.8).should be_close(0.165298888221587, TOLERANCE)
+ @object.send(:exp, 1.25).should be_close(3.49034295746184, TOLERANCE)
+ end
+
+ it "returns the base-e exponential for Complex numbers" do
+ @object.send(:exp, Complex(0, 0)).should == Complex(1.0, 0.0)
+ @object.send(:exp, Complex(1, 3)).should be_close(Complex(-2.69107861381979, 0.383603953541131), TOLERANCE)
+ end
+end
+
+describe :complex_math_exp_bang, shared: true do
+ it "returns the base-e exponential of the passed argument" do
+ @object.send(:exp!, 0.0).should == 1.0
+ @object.send(:exp!, -0.0).should == 1.0
+ @object.send(:exp!, -1.8).should be_close(0.165298888221587, TOLERANCE)
+ @object.send(:exp!, 1.25).should be_close(3.49034295746184, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:exp!, Complex(1, 3)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/log.rb b/spec/ruby/library/complex/math/shared/log.rb
new file mode 100644
index 0000000000..4e5385748a
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/log.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_log, shared: true do
+ it "returns the natural logarithm of the passed argument" do
+ @object.send(:log, 0.0001).should be_close(-9.21034037197618, TOLERANCE)
+ @object.send(:log, 0.000000000001e-15).should be_close(-62.1697975108392, TOLERANCE)
+ @object.send(:log, 1).should be_close(0.0, TOLERANCE)
+ @object.send(:log, 10).should be_close( 2.30258509299405, TOLERANCE)
+ @object.send(:log, 10e15).should be_close(36.8413614879047, TOLERANCE)
+ end
+
+ it "returns the natural logarithm for Complex numbers" do
+ @object.send(:log, Complex(3, 4)).should be_close(Complex(1.6094379124341, 0.927295218001612), TOLERANCE)
+ @object.send(:log, Complex(-3, 4)).should be_close(Complex(1.6094379124341, 2.21429743558818), TOLERANCE)
+ end
+
+ it "returns the natural logarithm for negative numbers as a Complex number" do
+ @object.send(:log, -10).should be_close(Complex(2.30258509299405, 3.14159265358979), TOLERANCE)
+ @object.send(:log, -20).should be_close(Complex(2.99573227355399, 3.14159265358979), TOLERANCE)
+ end
+end
+
+describe :complex_math_log_bang, shared: true do
+ it "returns the natural logarithm of the argument" do
+ @object.send(:log!, 0.0001).should be_close(-9.21034037197618, TOLERANCE)
+ @object.send(:log!, 0.000000000001e-15).should be_close(-62.1697975108392, TOLERANCE)
+ @object.send(:log!, 1).should be_close(0.0, TOLERANCE)
+ @object.send(:log!, 10).should be_close( 2.30258509299405, TOLERANCE)
+ @object.send(:log!, 10e15).should be_close(36.8413614879047, TOLERANCE)
+ end
+
+ it "raises an Errno::EDOM if the argument is less than 0" do
+ lambda { @object.send(:log!, -10) }.should raise_error(Errno::EDOM)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:log!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/log10.rb b/spec/ruby/library/complex/math/shared/log10.rb
new file mode 100644
index 0000000000..13518f243e
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/log10.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_log10, shared: true do
+ it "returns the base-10 logarithm of the passed argument" do
+ @object.send(:log10, 0.0001).should be_close(-4.0, TOLERANCE)
+ @object.send(:log10, 0.000000000001e-15).should be_close(-27.0, TOLERANCE)
+ @object.send(:log10, 1).should be_close(0.0, TOLERANCE)
+ @object.send(:log10, 10).should be_close(1.0, TOLERANCE)
+ @object.send(:log10, 10e15).should be_close(16.0, TOLERANCE)
+ end
+
+ it "returns the base-10 logarithm for Complex numbers" do
+ @object.send(:log10, Complex(3, 4)).should be_close(Complex(0.698970004336019, 0.402719196273373), TOLERANCE)
+ @object.send(:log10, Complex(-3, 4)).should be_close(Complex(0.698970004336019, 0.961657157568468), TOLERANCE)
+ end
+
+ # BUG: does not work correctly, because Math#log10
+ # does not check for negative values
+ #it "returns the base-10 logarithm for negative numbers as a Complex number" do
+ # @object.send(:log10, -10).should be_close(Complex(2.30258509299405, 3.14159265358979), TOLERANCE)
+ # @object.send(:log10, -20).should be_close(Complex(2.99573227355399, 3.14159265358979), TOLERANCE)
+ #end
+end
+
+describe :complex_math_log10_bang, shared: true do
+ it "returns the base-10 logarithm of the argument" do
+ @object.send(:log10!, 0.0001).should be_close(-4.0, TOLERANCE)
+ @object.send(:log10!, 0.000000000001e-15).should be_close(-27.0, TOLERANCE)
+ @object.send(:log10!, 1).should be_close(0.0, TOLERANCE)
+ @object.send(:log10!, 10).should be_close(1.0, TOLERANCE)
+ @object.send(:log10!, 10e15).should be_close(16.0, TOLERANCE)
+ end
+
+ it "raises an Errno::EDOM when the passed argument is negative" do
+ lambda { @object.send(:log10!, -10) }.should raise_error(Errno::EDOM)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:log10!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/sin.rb b/spec/ruby/library/complex/math/shared/sin.rb
new file mode 100644
index 0000000000..e5b207b456
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/sin.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_sin, shared: true do
+ it "returns the sine of the passed argument expressed in radians" do
+ @object.send(:sin, CMath::PI).should be_close(0.0, TOLERANCE)
+ @object.send(:sin, 0).should be_close(0.0, TOLERANCE)
+ @object.send(:sin, CMath::PI/2).should be_close(1.0, TOLERANCE)
+ @object.send(:sin, 3*Math::PI/2).should be_close(-1.0, TOLERANCE)
+ @object.send(:sin, 2*Math::PI).should be_close(0.0, TOLERANCE)
+ end
+
+ it "returns the sine for Complex numbers" do
+ @object.send(:sin, Complex(0, CMath::PI)).should be_close(Complex(0.0, 11.5487393572577), TOLERANCE)
+ @object.send(:sin, Complex(3, 4)).should be_close(Complex(3.85373803791938, -27.0168132580039), TOLERANCE)
+ end
+end
+
+describe :complex_math_sin_bang, shared: true do
+ it "returns the sine of the passed argument expressed in radians" do
+ @object.send(:sin!, CMath::PI).should be_close(0.0, TOLERANCE)
+ @object.send(:sin!, 0).should be_close(0.0, TOLERANCE)
+ @object.send(:sin!, CMath::PI/2).should be_close(1.0, TOLERANCE)
+ @object.send(:sin!, 3*Math::PI/2).should be_close(-1.0, TOLERANCE)
+ @object.send(:sin!, 2*Math::PI).should be_close(0.0, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:sin!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/sinh.rb b/spec/ruby/library/complex/math/shared/sinh.rb
new file mode 100644
index 0000000000..abbe2c6da0
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/sinh.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_sinh, shared: true do
+ it "returns the hyperbolic sin of the argument" do
+ @object.send(:sinh, 0.0).should == 0.0
+ @object.send(:sinh, -0.0).should == 0.0
+ @object.send(:sinh, 1.5).should be_close(2.12927945509482, TOLERANCE)
+ @object.send(:sinh, -2.8).should be_close(-8.19191835423591, TOLERANCE)
+ end
+
+ it "returns the hyperbolic sin for Complex numbers" do
+ @object.send(:sinh, Complex(0, CMath::PI)).should be_close(Complex(-0.0, 1.22464679914735e-16), TOLERANCE)
+ @object.send(:sinh, Complex(3, 4)).should be_close(Complex(-6.548120040911, -7.61923172032141), TOLERANCE)
+ end
+end
+
+describe :complex_math_sinh_bang, shared: true do
+ it "returns the hyperbolic sin of the argument" do
+ @object.send(:sinh!, 0.0).should == 0.0
+ @object.send(:sinh!, -0.0).should == 0.0
+ @object.send(:sinh!, 1.5).should be_close(2.12927945509482, TOLERANCE)
+ @object.send(:sinh!, -2.8).should be_close(-8.19191835423591, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:sinh!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/sqrt.rb b/spec/ruby/library/complex/math/shared/sqrt.rb
new file mode 100644
index 0000000000..5125710119
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/sqrt.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_sqrt, shared: true do
+ it "returns the square root for positive numbers" do
+ @object.send(:sqrt, 4).should == 2
+ @object.send(:sqrt, 19.36).should == 4.4
+ end
+
+ it "returns the square root for negative numbers" do
+ @object.send(:sqrt, -4).should == Complex(0, 2.0)
+ @object.send(:sqrt, -19.36).should == Complex(0, 4.4)
+ end
+
+ it "returns the square root for Complex numbers" do
+ @object.send(:sqrt, Complex(4, 5)).should be_close(Complex(2.2806933416653, 1.09615788950152), TOLERANCE)
+ @object.send(:sqrt, Complex(4, -5)).should be_close(Complex(2.2806933416653, -1.09615788950152), TOLERANCE)
+ end
+end
+
+describe :complex_math_sqrt_bang, shared: true do
+ it "returns the square root for positive numbers" do
+ @object.send(:sqrt!, 4).should == 2
+ @object.send(:sqrt!, 19.36).should == 4.4
+ end
+
+ it "raises Errno::EDOM when the passed argument is negative" do
+ lambda { @object.send(:sqrt!, -4) }.should raise_error(Errno::EDOM)
+ lambda { @object.send(:sqrt!, -19.36) }.should raise_error(Errno::EDOM)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:sqrt!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/tan.rb b/spec/ruby/library/complex/math/shared/tan.rb
new file mode 100644
index 0000000000..02a1880d27
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/tan.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_tan, shared: true do
+ it "returns the tangent of the argument" do
+ @object.send(:tan, 0.0).should == 0.0
+ @object.send(:tan, -0.0).should == -0.0
+ @object.send(:tan, 4.22).should be_close(1.86406937682395, TOLERANCE)
+ @object.send(:tan, -9.65).should be_close(-0.229109052606441, TOLERANCE)
+ end
+
+ it "returns the tangent for Complex numbers" do
+ @object.send(:tan, Complex(0, CMath::PI)).should be_close(Complex(0.0, 0.99627207622075), TOLERANCE)
+ @object.send(:tan, Complex(3, 4)).should be_close(Complex(-0.000187346204629452, 0.999355987381473), TOLERANCE)
+ end
+end
+
+describe :complex_math_tan_bang, shared: true do
+ it "returns the tangent of the argument" do
+ @object.send(:tan!, 0.0).should == 0.0
+ @object.send(:tan!, -0.0).should == -0.0
+ @object.send(:tan!, 4.22).should be_close(1.86406937682395, TOLERANCE)
+ @object.send(:tan!, -9.65).should be_close(-0.229109052606441, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:tan!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/shared/tanh.rb b/spec/ruby/library/complex/math/shared/tanh.rb
new file mode 100644
index 0000000000..a26b1349f6
--- /dev/null
+++ b/spec/ruby/library/complex/math/shared/tanh.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :complex_math_tanh, shared: true do
+ it "returns the hyperbolic tangent of the argument" do
+ @object.send(:tanh, 0.0).should == 0.0
+ @object.send(:tanh, -0.0).should == -0.0
+ @object.send(:tanh, infinity_value).should == 1.0
+ @object.send(:tanh, -infinity_value).should == -1.0
+ @object.send(:tanh, 2.5).should be_close(0.98661429815143, TOLERANCE)
+ @object.send(:tanh, -4.892).should be_close(-0.999887314427707, TOLERANCE)
+ end
+
+ it "returns the hyperbolic tangent for Complex numbers" do
+ @object.send(:tanh, Complex(0, CMath::PI)).should be_close(Complex(0.0, -1.22464679914735e-16), TOLERANCE)
+ @object.send(:tanh, Complex(3, 4)).should be_close(Complex(1.00070953606723, 0.00490825806749599), TOLERANCE)
+ end
+end
+
+describe :complex_math_tanh_bang, shared: true do
+ it "returns the hyperbolic tangent of the argument" do
+ @object.send(:tanh!, 0.0).should == 0.0
+ @object.send(:tanh!, -0.0).should == -0.0
+ @object.send(:tanh!, infinity_value).should == 1.0
+ @object.send(:tanh!, -infinity_value).should == -1.0
+ @object.send(:tanh!, 2.5).should be_close(0.98661429815143, TOLERANCE)
+ @object.send(:tanh!, -4.892).should be_close(-0.999887314427707, TOLERANCE)
+ end
+
+ it "raises a TypeError when passed a Complex number" do
+ lambda { @object.send(:tanh!, Complex(4, 5)) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/complex/math/sin_spec.rb b/spec/ruby/library/complex/math/sin_spec.rb
new file mode 100644
index 0000000000..bbc36ecaab
--- /dev/null
+++ b/spec/ruby/library/complex/math/sin_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/sin', __FILE__)
+
+describe "Math#sin" do
+ it_behaves_like :complex_math_sin, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:sin)
+ end
+end
+
+describe "Math.sin" do
+ it_behaves_like :complex_math_sin, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/sinh_spec.rb b/spec/ruby/library/complex/math/sinh_spec.rb
new file mode 100644
index 0000000000..25a41fbc45
--- /dev/null
+++ b/spec/ruby/library/complex/math/sinh_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/sinh', __FILE__)
+
+describe "Math#sinh" do
+ it_behaves_like :complex_math_sinh, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:sinh)
+ end
+end
+
+describe "Math.sinh" do
+ it_behaves_like :complex_math_sinh, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/sqrt_spec.rb b/spec/ruby/library/complex/math/sqrt_spec.rb
new file mode 100644
index 0000000000..19d58ce373
--- /dev/null
+++ b/spec/ruby/library/complex/math/sqrt_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/sqrt', __FILE__)
+
+describe "Math#sqrt" do
+ it_behaves_like :complex_math_sqrt, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:sqrt)
+ end
+end
+
+describe "Math.sqrt" do
+ it_behaves_like :complex_math_sqrt, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/tan_spec.rb b/spec/ruby/library/complex/math/tan_spec.rb
new file mode 100644
index 0000000000..3c5bc6b129
--- /dev/null
+++ b/spec/ruby/library/complex/math/tan_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/tan', __FILE__)
+
+describe "Math#tan" do
+ it_behaves_like :complex_math_tan, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:tan)
+ end
+end
+
+describe "Math.tan" do
+ it_behaves_like :complex_math_tan, :_, CMath
+end
diff --git a/spec/ruby/library/complex/math/tanh_spec.rb b/spec/ruby/library/complex/math/tanh_spec.rb
new file mode 100644
index 0000000000..f9d99347b8
--- /dev/null
+++ b/spec/ruby/library/complex/math/tanh_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'complex'
+require File.expand_path('../shared/tanh', __FILE__)
+
+describe "Math#tanh" do
+ it_behaves_like :complex_math_tanh, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:tanh)
+ end
+end
+
+describe "Math.tanh" do
+ it_behaves_like :complex_math_tanh, :_, CMath
+end
diff --git a/spec/ruby/library/complex/numeric/im_spec.rb b/spec/ruby/library/complex/numeric/im_spec.rb
new file mode 100644
index 0000000000..f76796a947
--- /dev/null
+++ b/spec/ruby/library/complex/numeric/im_spec.rb
@@ -0,0 +1,3 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+require 'complex'
diff --git a/spec/ruby/library/conditionvariable/broadcast_spec.rb b/spec/ruby/library/conditionvariable/broadcast_spec.rb
new file mode 100644
index 0000000000..129b124c1a
--- /dev/null
+++ b/spec/ruby/library/conditionvariable/broadcast_spec.rb
@@ -0,0 +1,67 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'thread'
+
+describe "ConditionVariable#broadcast" do
+ it "returns self if nothing to broadcast to" do
+ cv = ConditionVariable.new
+ cv.broadcast.should == cv
+ end
+
+ it "returns self if something is waiting for a broadcast" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ in_synchronize = false
+
+ th = Thread.new do
+ m.synchronize do
+ in_synchronize = true
+ cv.wait(m)
+ end
+ end
+
+ # wait for m to acquire the mutex
+ Thread.pass until in_synchronize
+ # wait until th is sleeping (ie waiting)
+ Thread.pass while th.status and th.status != "sleep"
+
+ m.synchronize { cv.broadcast }.should == cv
+
+ th.join
+ end
+
+ it "releases all threads waiting in line for this resource" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ threads = []
+ r1 = []
+ r2 = []
+
+ # large number to attempt to cause race conditions
+ 100.times do |i|
+ threads << Thread.new(i) do |tid|
+ m.synchronize do
+ r1 << tid
+ cv.wait(m)
+ r2 << tid
+ end
+ end
+ end
+
+ # wait for all threads to acquire the mutex the first time
+ Thread.pass until m.synchronize { r1.size == threads.size }
+ # wait until all threads are sleeping (ie waiting)
+ Thread.pass until threads.all? {|th| th.status == "sleep" }
+
+ r2.should be_empty
+ m.synchronize do
+ cv.broadcast
+ end
+
+ threads.each {|t| t.join }
+
+ # ensure that all threads that enter cv.wait are released
+ r2.sort.should == r1.sort
+ # note that order is not specified as broadcast results in a race
+ # condition on regaining the lock m
+ end
+end
diff --git a/spec/ruby/library/conditionvariable/signal_spec.rb b/spec/ruby/library/conditionvariable/signal_spec.rb
new file mode 100644
index 0000000000..38bee8984b
--- /dev/null
+++ b/spec/ruby/library/conditionvariable/signal_spec.rb
@@ -0,0 +1,69 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'thread'
+
+describe "ConditionVariable#signal" do
+ it "returns self if nothing to signal" do
+ cv = ConditionVariable.new
+ cv.signal.should == cv
+ end
+
+ it "returns self if something is waiting for a signal" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ in_synchronize = false
+
+ th = Thread.new do
+ m.synchronize do
+ in_synchronize = true
+ cv.wait(m)
+ end
+ end
+
+ # wait for m to acquire the mutex
+ Thread.pass until in_synchronize
+ # wait until th is sleeping (ie waiting)
+ Thread.pass while th.status and th.status != "sleep"
+
+ m.synchronize { cv.signal }.should == cv
+
+ th.join
+ end
+
+ it "releases the first thread waiting in line for this resource" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ threads = []
+ r1 = []
+ r2 = []
+
+ # large number to attempt to cause race conditions
+ 100.times do |i|
+ threads << Thread.new(i) do |tid|
+ m.synchronize do
+ r1 << tid
+ cv.wait(m)
+ r2 << tid
+ end
+ end
+ end
+
+ # wait for all threads to acquire the mutex the first time
+ Thread.pass until m.synchronize { r1.size == threads.size }
+ # wait until all threads are sleeping (ie waiting)
+ Thread.pass until threads.all? {|th| th.status == "sleep" }
+
+ r2.should be_empty
+ 100.times do |i|
+ m.synchronize do
+ cv.signal
+ end
+ Thread.pass until r2.size == i+1
+ end
+
+ threads.each {|t| t.join }
+
+ # ensure that all the threads that went into the cv.wait are
+ # released in the same order
+ r2.should == r1
+ end
+end
diff --git a/spec/ruby/library/conditionvariable/wait_spec.rb b/spec/ruby/library/conditionvariable/wait_spec.rb
new file mode 100644
index 0000000000..ddf6474212
--- /dev/null
+++ b/spec/ruby/library/conditionvariable/wait_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'thread'
+
+describe "ConditionVariable#wait" do
+ it "returns self" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ in_synchronize = false
+
+ th = Thread.new do
+ m.synchronize do
+ in_synchronize = true
+ cv.wait(m).should == cv
+ end
+ end
+
+ # wait for m to acquire the mutex
+ Thread.pass until in_synchronize
+ # wait until th is sleeping (ie waiting)
+ Thread.pass while th.status and th.status != "sleep"
+
+ m.synchronize { cv.signal }
+ th.join
+ end
+end
diff --git a/spec/ruby/library/coverage/fixtures/second_class.rb b/spec/ruby/library/coverage/fixtures/second_class.rb
new file mode 100644
index 0000000000..0318ac26ff
--- /dev/null
+++ b/spec/ruby/library/coverage/fixtures/second_class.rb
@@ -0,0 +1,5 @@
+class SecondClass
+ def some_method
+ 42
+ end
+end
diff --git a/spec/ruby/library/coverage/fixtures/some_class.rb b/spec/ruby/library/coverage/fixtures/some_class.rb
new file mode 100644
index 0000000000..52629f0332
--- /dev/null
+++ b/spec/ruby/library/coverage/fixtures/some_class.rb
@@ -0,0 +1,16 @@
+
+#Class comment
+class SomeClass
+
+ # Method comment
+ def some_method
+
+ # Inline method comment
+ actual_code = true
+
+ end
+
+end
+
+# Trailing comment and extra blank line
+
diff --git a/spec/ruby/library/coverage/fixtures/spec_helper.rb b/spec/ruby/library/coverage/fixtures/spec_helper.rb
new file mode 100644
index 0000000000..19094e5c36
--- /dev/null
+++ b/spec/ruby/library/coverage/fixtures/spec_helper.rb
@@ -0,0 +1,11 @@
+module CoverageSpecs
+ # Clear old results from the result hash
+ # https://bugs.ruby-lang.org/issues/12220
+ def self.filtered_result
+ result = Coverage.result
+ ruby_version_is ""..."2.4" do
+ result = result.reject { |_k, v| v.empty? }
+ end
+ result
+ end
+end
diff --git a/spec/ruby/library/coverage/fixtures/start_coverage.rb b/spec/ruby/library/coverage/fixtures/start_coverage.rb
new file mode 100644
index 0000000000..8a0c56c50a
--- /dev/null
+++ b/spec/ruby/library/coverage/fixtures/start_coverage.rb
@@ -0,0 +1,3 @@
+2 + 2
+Coverage.start
+1 + 1
diff --git a/spec/ruby/library/coverage/peek_result_spec.rb b/spec/ruby/library/coverage/peek_result_spec.rb
new file mode 100644
index 0000000000..44a2e2b83e
--- /dev/null
+++ b/spec/ruby/library/coverage/peek_result_spec.rb
@@ -0,0 +1,67 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require fixture __FILE__, 'spec_helper'
+require 'coverage'
+
+ruby_version_is '2.3' do
+ describe 'Coverage.peek_result' do
+ before :all do
+ @class_file = fixture __FILE__, 'some_class.rb'
+ @second_class_file = fixture __FILE__, 'second_class.rb'
+ end
+
+ after :each do
+ $LOADED_FEATURES.delete(@class_file)
+ $LOADED_FEATURES.delete(@second_class_file)
+ end
+
+ it 'returns the result so far' do
+ Coverage.start
+ require @class_file.chomp('.rb')
+ result = Coverage.peek_result
+ Coverage.result
+
+ result.should == {
+ @class_file => [
+ nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
+ ]
+ }
+ end
+
+ it 'immediate second call returns same result' do
+ Coverage.start
+ require @class_file.chomp('.rb')
+ result1 = Coverage.peek_result
+ result2 = Coverage.peek_result
+ Coverage.result
+
+ result2.should == result1
+ end
+
+ it 'second call after require returns accumulated result' do
+ Coverage.start
+ require @class_file.chomp('.rb')
+ Coverage.peek_result
+ require @second_class_file.chomp('.rb')
+ result = Coverage.peek_result
+ Coverage.result
+
+ result.should == {
+ @class_file => [
+ nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
+ ],
+ @second_class_file => [
+ 1, 1, 0, nil, nil
+ ]
+ }
+ end
+
+ it 'call right before Coverage.result should give equal result' do
+ Coverage.start
+ require @class_file.chomp('.rb')
+ result1 = Coverage.peek_result
+ result2 = Coverage.result
+
+ result1.should == result2
+ end
+ end
+end
diff --git a/spec/ruby/library/coverage/result_spec.rb b/spec/ruby/library/coverage/result_spec.rb
new file mode 100644
index 0000000000..adcc51dc80
--- /dev/null
+++ b/spec/ruby/library/coverage/result_spec.rb
@@ -0,0 +1,78 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require fixture __FILE__, 'spec_helper'
+require 'coverage'
+
+describe 'Coverage.result' do
+ before :all do
+ @class_file = fixture __FILE__, 'some_class.rb'
+ @config_file = fixture __FILE__, 'start_coverage.rb'
+ end
+
+ after :each do
+ $LOADED_FEATURES.delete(@class_file)
+ $LOADED_FEATURES.delete(@config_file)
+ end
+
+ it 'gives the covered files as a hash with arrays of count or nil' do
+ Coverage.start
+ require @class_file.chomp('.rb')
+ result = CoverageSpecs.filtered_result
+
+ result.should == {
+ @class_file => [
+ nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
+ ]
+ }
+ end
+
+ it 'no requires/loads should give empty hash' do
+ Coverage.start
+ result = CoverageSpecs.filtered_result
+
+ result.should == {}
+ end
+
+ it 'second call should give exception' do
+ Coverage.start
+ require @class_file.chomp('.rb')
+ Coverage.result
+ -> { Coverage.result }
+ .should raise_error(RuntimeError, 'coverage measurement is not enabled')
+ end
+
+ it 'second run should give same result' do
+ Coverage.start
+ load @class_file
+ result1 = CoverageSpecs.filtered_result
+
+ Coverage.start
+ load @class_file
+ result2 = CoverageSpecs.filtered_result
+
+ result2.should == result1
+ end
+
+ it 'second run without load/require should give empty hash' do
+ Coverage.start
+ require @class_file.chomp('.rb')
+ Coverage.result
+
+ Coverage.start
+ result = CoverageSpecs.filtered_result
+
+ result.should == {}
+ end
+
+ it 'second Coverage.start does nothing' do
+ Coverage.start
+ require @config_file.chomp('.rb')
+ result = CoverageSpecs.filtered_result
+
+ result.should == { @config_file => [1, 1, 1] }
+ end
+
+ it 'does not include the file starting coverage since it is not tracked' do
+ require @config_file.chomp('.rb')
+ CoverageSpecs.filtered_result.should_not include(@config_file)
+ end
+end
diff --git a/spec/ruby/library/coverage/start_spec.rb b/spec/ruby/library/coverage/start_spec.rb
new file mode 100644
index 0000000000..6b4ccbb043
--- /dev/null
+++ b/spec/ruby/library/coverage/start_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'coverage'
+
+describe 'Coverage.start' do
+ it 'needs to be reviewed for spec completeness'
+end
diff --git a/spec/ruby/library/csv/basicwriter/close_on_terminate_spec.rb b/spec/ruby/library/csv/basicwriter/close_on_terminate_spec.rb
new file mode 100644
index 0000000000..3a5dc85ed7
--- /dev/null
+++ b/spec/ruby/library/csv/basicwriter/close_on_terminate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::BasicWriter#close_on_terminate" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/basicwriter/initialize_spec.rb b/spec/ruby/library/csv/basicwriter/initialize_spec.rb
new file mode 100644
index 0000000000..8ccef3fc0d
--- /dev/null
+++ b/spec/ruby/library/csv/basicwriter/initialize_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::BasicWriter#initialize" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/basicwriter/terminate_spec.rb b/spec/ruby/library/csv/basicwriter/terminate_spec.rb
new file mode 100644
index 0000000000..80581e4d61
--- /dev/null
+++ b/spec/ruby/library/csv/basicwriter/terminate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::BasicWriter#terminate" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/cell/data_spec.rb b/spec/ruby/library/csv/cell/data_spec.rb
new file mode 100644
index 0000000000..b2be38a5d6
--- /dev/null
+++ b/spec/ruby/library/csv/cell/data_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::Cell#data" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/cell/initialize_spec.rb b/spec/ruby/library/csv/cell/initialize_spec.rb
new file mode 100644
index 0000000000..3d10d7ada7
--- /dev/null
+++ b/spec/ruby/library/csv/cell/initialize_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::Cell#initialize" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/fixtures/one_line.csv b/spec/ruby/library/csv/fixtures/one_line.csv
new file mode 100644
index 0000000000..d72f2010a8
--- /dev/null
+++ b/spec/ruby/library/csv/fixtures/one_line.csv
@@ -0,0 +1 @@
+1,2
diff --git a/spec/ruby/library/csv/foreach_spec.rb b/spec/ruby/library/csv/foreach_spec.rb
new file mode 100644
index 0000000000..a967c450bf
--- /dev/null
+++ b/spec/ruby/library/csv/foreach_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV.foreach" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/generate_line_spec.rb b/spec/ruby/library/csv/generate_line_spec.rb
new file mode 100644
index 0000000000..cc7c8de4f0
--- /dev/null
+++ b/spec/ruby/library/csv/generate_line_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV.generate_line" do
+
+ it "generates an empty string" do
+ result = CSV.generate_line([])
+ result.should == "\n"
+ end
+
+ it "generates the string 'foo,bar'" do
+ result = CSV.generate_line(["foo", "bar"])
+ result.should == "foo,bar\n"
+ end
+
+ it "generates the string 'foo;bar'" do
+ result = CSV.generate_line(["foo", "bar"], col_sep: ?;)
+ result.should == "foo;bar\n"
+ end
+
+ it "generates the string 'foo,,bar'" do
+ result = CSV.generate_line(["foo", nil, "bar"])
+ result.should == "foo,,bar\n"
+ end
+
+ it "generates the string 'foo;;bar'" do
+ result = CSV.generate_line(["foo", nil, "bar"], col_sep: ?;)
+ result.should == "foo;;bar\n"
+ end
+end
diff --git a/spec/ruby/library/csv/generate_row_spec.rb b/spec/ruby/library/csv/generate_row_spec.rb
new file mode 100644
index 0000000000..d42c031ab1
--- /dev/null
+++ b/spec/ruby/library/csv/generate_row_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV.generate_row" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/generate_spec.rb b/spec/ruby/library/csv/generate_spec.rb
new file mode 100644
index 0000000000..f583b5f536
--- /dev/null
+++ b/spec/ruby/library/csv/generate_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'csv'
+require 'tempfile'
+
+describe "CSV.generate" do
+
+ it "returns CSV string" do
+ csv_str = CSV.generate do |csv|
+ csv.add_row [1, 2, 3]
+ csv << [4, 5, 6]
+ end
+ csv_str.should == "1,2,3\n4,5,6\n"
+ end
+
+ it "accepts a col separator" do
+ csv_str = CSV.generate(col_sep: ";") do |csv|
+ csv.add_row [1, 2, 3]
+ csv << [4, 5, 6]
+ end
+ csv_str.should == "1;2;3\n4;5;6\n"
+ end
+
+ it "appends and returns the argument itself" do
+ str = ""
+ csv_str = CSV.generate(str) do |csv|
+ csv.add_row [1, 2, 3]
+ csv << [4, 5, 6]
+ end
+ csv_str.object_id.should == str.object_id
+ str.should == "1,2,3\n4,5,6\n"
+ end
+end
diff --git a/spec/ruby/library/csv/iobuf/close_spec.rb b/spec/ruby/library/csv/iobuf/close_spec.rb
new file mode 100644
index 0000000000..d97841ad98
--- /dev/null
+++ b/spec/ruby/library/csv/iobuf/close_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::IOBuf#close" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/iobuf/initialize_spec.rb b/spec/ruby/library/csv/iobuf/initialize_spec.rb
new file mode 100644
index 0000000000..5155e9047a
--- /dev/null
+++ b/spec/ruby/library/csv/iobuf/initialize_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::IOBuf#initialize" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/iobuf/read_spec.rb b/spec/ruby/library/csv/iobuf/read_spec.rb
new file mode 100644
index 0000000000..0dbcccb7c2
--- /dev/null
+++ b/spec/ruby/library/csv/iobuf/read_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::IOBuf#read" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/iobuf/terminate_spec.rb b/spec/ruby/library/csv/iobuf/terminate_spec.rb
new file mode 100644
index 0000000000..b74108cedc
--- /dev/null
+++ b/spec/ruby/library/csv/iobuf/terminate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::IOBuf#terminate" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/ioreader/close_on_terminate_spec.rb b/spec/ruby/library/csv/ioreader/close_on_terminate_spec.rb
new file mode 100644
index 0000000000..75ce325a8b
--- /dev/null
+++ b/spec/ruby/library/csv/ioreader/close_on_terminate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::IOReader#close_on_terminate" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/ioreader/get_row_spec.rb b/spec/ruby/library/csv/ioreader/get_row_spec.rb
new file mode 100644
index 0000000000..91049f014a
--- /dev/null
+++ b/spec/ruby/library/csv/ioreader/get_row_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::IOReader#get_row" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/ioreader/initialize_spec.rb b/spec/ruby/library/csv/ioreader/initialize_spec.rb
new file mode 100644
index 0000000000..63a47eff73
--- /dev/null
+++ b/spec/ruby/library/csv/ioreader/initialize_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::IOReader#initialize" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/ioreader/terminate_spec.rb b/spec/ruby/library/csv/ioreader/terminate_spec.rb
new file mode 100644
index 0000000000..95259afd59
--- /dev/null
+++ b/spec/ruby/library/csv/ioreader/terminate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::IOReader#terminate" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/open_spec.rb b/spec/ruby/library/csv/open_spec.rb
new file mode 100644
index 0000000000..e0667921b9
--- /dev/null
+++ b/spec/ruby/library/csv/open_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV.open" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/parse_spec.rb b/spec/ruby/library/csv/parse_spec.rb
new file mode 100644
index 0000000000..41d37ca9a4
--- /dev/null
+++ b/spec/ruby/library/csv/parse_spec.rb
@@ -0,0 +1,81 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV.parse" do
+
+ it "parses '' into []" do
+ result = CSV.parse ''
+ result.should be_kind_of(Array)
+ result.should == []
+ end
+
+ it "parses '\n' into [[]]" do
+ result = CSV.parse "\n"
+ result.should == [[]]
+ end
+
+ it "parses 'foo' into [['foo']]" do
+ result = CSV.parse 'foo'
+ result.should == [['foo']]
+ end
+
+ it "parses 'foo,bar,baz' into [['foo','bar','baz']]" do
+ result = CSV.parse 'foo,bar,baz'
+ result.should == [['foo','bar','baz']]
+ end
+
+ it "parses 'foo,baz' into [[foo,nil,baz]]" do
+ result = CSV.parse 'foo,,baz'
+ result.should == [['foo',nil,'baz']]
+ end
+
+ it "parses '\nfoo' into [[],['foo']]" do
+ result = CSV.parse "\nfoo"
+ result.should == [[],['foo']]
+ end
+
+ it "parses 'foo\n' into [['foo']]" do
+ result = CSV.parse "foo\n"
+ result.should == [['foo']]
+ end
+
+ it "parses 'foo\nbar' into [['foo'],['bar']]" do
+ result = CSV.parse "foo\nbar"
+ result.should == [['foo'],['bar']]
+ end
+
+ it "parses 'foo,bar\nbaz,quz' into [['foo','bar'],['baz','quz']]" do
+ result = CSV.parse "foo,bar\nbaz,quz"
+ result.should == [['foo','bar'],['baz','quz']]
+ end
+
+ it "parses 'foo,bar'\nbaz' into [['foo','bar'],['baz']]" do
+ result = CSV.parse "foo,bar\nbaz"
+ result.should == [['foo','bar'],['baz']]
+ end
+
+ it "parses 'foo\nbar,baz' into [['foo'],['bar','baz']]" do
+ result = CSV.parse "foo\nbar,baz"
+ result.should == [['foo'],['bar','baz']]
+ end
+
+ it "parses '\n\nbar' into [[],[],'bar']]" do
+ result = CSV.parse "\n\nbar"
+ result.should == [[],[],['bar']]
+ end
+
+ it "parses 'foo' into [['foo']] with a separator of ;" do
+ result = CSV.parse "foo", col_sep: ?;
+ result.should == [['foo']]
+ end
+
+ it "parses 'foo;bar' into [['foo','bar']] with a separator of ;" do
+ result = CSV.parse "foo;bar", col_sep: ?;
+ result.should == [['foo','bar']]
+ end
+
+ it "parses 'foo;bar\nbaz;quz' into [['foo','bar'],['baz','quz']] with a separator of ;" do
+ result = CSV.parse "foo;bar\nbaz;quz", col_sep: ?;
+ result.should == [['foo','bar'],['baz','quz']]
+ end
+end
diff --git a/spec/ruby/library/csv/read_spec.rb b/spec/ruby/library/csv/read_spec.rb
new file mode 100644
index 0000000000..9bdb214a6a
--- /dev/null
+++ b/spec/ruby/library/csv/read_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV.read" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/readlines_spec.rb b/spec/ruby/library/csv/readlines_spec.rb
new file mode 100644
index 0000000000..387730db16
--- /dev/null
+++ b/spec/ruby/library/csv/readlines_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV.readlines" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "CSV#readlines" do
+ it "returns an Array of Array containing each element in a one-line CSV file" do
+ file = CSV.new "a, b, c"
+ file.readlines.should == [["a", " b", " c"]]
+ end
+
+ it "returns an Array of Arrays containing each element in a multi-line CSV file" do
+ file = CSV.new "a, b, c\nd, e, f"
+ file.readlines.should == [["a", " b", " c"], ["d", " e", " f"]]
+ end
+
+ it "returns nil for a missing value" do
+ file = CSV.new "a,, b, c"
+ file.readlines.should == [["a", nil, " b", " c"]]
+ end
+end
diff --git a/spec/ruby/library/csv/streambuf/add_buf_spec.rb b/spec/ruby/library/csv/streambuf/add_buf_spec.rb
new file mode 100644
index 0000000000..274f40d496
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/add_buf_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#add_buf" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/buf_size_spec.rb b/spec/ruby/library/csv/streambuf/buf_size_spec.rb
new file mode 100644
index 0000000000..30af8a44c0
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/buf_size_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#buf_size" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/drop_spec.rb b/spec/ruby/library/csv/streambuf/drop_spec.rb
new file mode 100644
index 0000000000..47f32fc8c5
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/drop_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#drop" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/element_reference_spec.rb b/spec/ruby/library/csv/streambuf/element_reference_spec.rb
new file mode 100644
index 0000000000..4e4bab9a1e
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/element_reference_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#[]" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/get_spec.rb b/spec/ruby/library/csv/streambuf/get_spec.rb
new file mode 100644
index 0000000000..4a8db3a970
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/get_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#get" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/idx_is_eos_spec.rb b/spec/ruby/library/csv/streambuf/idx_is_eos_spec.rb
new file mode 100644
index 0000000000..d48e6735f0
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/idx_is_eos_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#idx_is_eos?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/initialize_spec.rb b/spec/ruby/library/csv/streambuf/initialize_spec.rb
new file mode 100644
index 0000000000..0f76220d3d
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/initialize_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#initialize" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/is_eos_spec.rb b/spec/ruby/library/csv/streambuf/is_eos_spec.rb
new file mode 100644
index 0000000000..30167f30ff
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/is_eos_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#is_eos?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/read_spec.rb b/spec/ruby/library/csv/streambuf/read_spec.rb
new file mode 100644
index 0000000000..b07467bdb7
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/read_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#read" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/rel_buf_spec.rb b/spec/ruby/library/csv/streambuf/rel_buf_spec.rb
new file mode 100644
index 0000000000..e01dc39cf5
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/rel_buf_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#rel_buf" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/streambuf/terminate_spec.rb b/spec/ruby/library/csv/streambuf/terminate_spec.rb
new file mode 100644
index 0000000000..0c2bdedf6d
--- /dev/null
+++ b/spec/ruby/library/csv/streambuf/terminate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StreamBuf#terminate" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/stringreader/get_row_spec.rb b/spec/ruby/library/csv/stringreader/get_row_spec.rb
new file mode 100644
index 0000000000..8532fc234c
--- /dev/null
+++ b/spec/ruby/library/csv/stringreader/get_row_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StringReader#get_row" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/stringreader/initialize_spec.rb b/spec/ruby/library/csv/stringreader/initialize_spec.rb
new file mode 100644
index 0000000000..5ce8f652da
--- /dev/null
+++ b/spec/ruby/library/csv/stringreader/initialize_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::StringReader#initialize" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/writer/add_row_spec.rb b/spec/ruby/library/csv/writer/add_row_spec.rb
new file mode 100644
index 0000000000..2ff5bdeee6
--- /dev/null
+++ b/spec/ruby/library/csv/writer/add_row_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::Writer#add_row" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/writer/append_spec.rb b/spec/ruby/library/csv/writer/append_spec.rb
new file mode 100644
index 0000000000..c6d96c72d6
--- /dev/null
+++ b/spec/ruby/library/csv/writer/append_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::Writer#<<" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/writer/close_spec.rb b/spec/ruby/library/csv/writer/close_spec.rb
new file mode 100644
index 0000000000..f51b9de73d
--- /dev/null
+++ b/spec/ruby/library/csv/writer/close_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::Writer#close" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/writer/create_spec.rb b/spec/ruby/library/csv/writer/create_spec.rb
new file mode 100644
index 0000000000..18cff887a6
--- /dev/null
+++ b/spec/ruby/library/csv/writer/create_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::Writer.create" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/writer/generate_spec.rb b/spec/ruby/library/csv/writer/generate_spec.rb
new file mode 100644
index 0000000000..8930e26389
--- /dev/null
+++ b/spec/ruby/library/csv/writer/generate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::Writer.generate" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/writer/initialize_spec.rb b/spec/ruby/library/csv/writer/initialize_spec.rb
new file mode 100644
index 0000000000..31b7d0fad8
--- /dev/null
+++ b/spec/ruby/library/csv/writer/initialize_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::Writer#initialize" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/csv/writer/terminate_spec.rb b/spec/ruby/library/csv/writer/terminate_spec.rb
new file mode 100644
index 0000000000..9629c672b5
--- /dev/null
+++ b/spec/ruby/library/csv/writer/terminate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'csv'
+
+describe "CSV::Writer#terminate" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/accessor_spec.rb b/spec/ruby/library/date/accessor_spec.rb
new file mode 100644
index 0000000000..91e0c3fc88
--- /dev/null
+++ b/spec/ruby/library/date/accessor_spec.rb
@@ -0,0 +1,91 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date#ajd" do
+ it "determines the Astronomical Julian day" do
+ Date.civil(2007, 1, 17).ajd.should == 4908235.to_r / 2
+ end
+end
+
+describe "Date#amjd" do
+ it "determines the Astronomical Modified Julian day" do
+ Date.civil(2007, 1, 17).amjd.should == 54117
+ end
+end
+
+describe "Date#day_fraction" do
+ it "determines the day fraction" do
+ Date.civil(2007, 1, 17).day_fraction.should == 0
+ end
+end
+
+describe "Date#mjd" do
+ it "determines the Modified Julian day" do
+ Date.civil(2007, 1, 17).mjd.should == 54117
+ end
+end
+
+describe "Date#ld" do
+ it "determines the Modified Julian day" do
+ Date.civil(2007, 1, 17).ld.should == 154958
+ end
+end
+
+describe "Date#year" do
+ it "determines the year" do
+ Date.civil(2007, 1, 17).year.should == 2007
+ end
+end
+
+describe "Date#yday" do
+ it "determines the year" do
+ Date.civil(2007, 1, 17).yday.should == 17
+ Date.civil(2008, 10, 28).yday.should == 302
+ end
+end
+
+describe "Date#mon" do
+ it "determines the month" do
+ Date.civil(2007, 1, 17).mon.should == 1
+ Date.civil(2008, 10, 28).mon.should == 10
+ end
+end
+
+describe "Date#mday" do
+ it "determines the day of the month" do
+ Date.civil(2007, 1, 17).mday.should == 17
+ Date.civil(2008, 10, 28).mday.should == 28
+ end
+end
+
+describe "Date#wday" do
+ it "determines the week day" do
+ Date.civil(2007, 1, 17).wday.should == 3
+ Date.civil(2008, 10, 26).wday.should == 0
+ end
+end
+
+describe "Date#cwyear" do
+ it "determines the commercial year" do
+ Date.civil(2007, 1, 17).cwyear.should == 2007
+ Date.civil(2008, 10, 28).cwyear.should == 2008
+ Date.civil(2007, 12, 31).cwyear.should == 2008
+ Date.civil(2010, 1, 1).cwyear.should == 2009
+ end
+end
+
+describe "Date#cweek" do
+ it "determines the commercial week" do
+ Date.civil(2007, 1, 17).cweek.should == 3
+ Date.civil(2008, 10, 28).cweek.should == 44
+ Date.civil(2007, 12, 31).cweek.should == 1
+ Date.civil(2010, 1, 1).cweek.should == 53
+ end
+end
+
+describe "Date#cwday" do
+ it "determines the commercial week day" do
+ Date.civil(2007, 1, 17).cwday.should == 3
+ Date.civil(2008, 10, 26).cwday.should == 7
+ end
+end
diff --git a/spec/ruby/library/date/add_month_spec.rb b/spec/ruby/library/date/add_month_spec.rb
new file mode 100644
index 0000000000..46f1915b70
--- /dev/null
+++ b/spec/ruby/library/date/add_month_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#>>" do
+ it "adds the number of months to a Date" do
+ d = Date.civil(2007,2,27) >> 10
+ d.should == Date.civil(2007, 12, 27)
+ end
+
+ it "sets the day to the last day of a month if the day doesn't exist" do
+ d = Date.civil(2008,3,31) >> 1
+ d.should == Date.civil(2008, 4, 30)
+ end
+
+ it "returns the day of the reform if date falls within calendar reform" do
+ calendar_reform_italy = Date.new(1582, 10, 4)
+ d1 = Date.new(1582, 9, 9) >> 1
+ d2 = Date.new(1582, 9, 10) >> 1
+ d1.should == calendar_reform_italy
+ d2.should == calendar_reform_italy
+ end
+
+ it "raise a TypeError when passed a Symbol" do
+ lambda { Date.civil(2007,2,27) >> :hello }.should raise_error(TypeError)
+ end
+
+ it "raise a TypeError when passed a String" do
+ lambda { Date.civil(2007,2,27) >> "hello" }.should raise_error(TypeError)
+ end
+
+ it "raise a TypeError when passed a Date" do
+ lambda { Date.civil(2007,2,27) >> Date.new }.should raise_error(TypeError)
+ end
+
+ it "raise a TypeError when passed an Object" do
+ lambda { Date.civil(2007,2,27) >> Object.new }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/date/add_spec.rb b/spec/ruby/library/date/add_spec.rb
new file mode 100644
index 0000000000..022b793318
--- /dev/null
+++ b/spec/ruby/library/date/add_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#+" do
+ it "adds the number of days to a Date" do
+ d = Date.civil(2007,2,27) + 10
+ d.should == Date.civil(2007, 3, 9)
+ end
+
+ it "adds a negative number of days to a Date" do
+ d = Date.civil(2007,2,27).+(-10)
+ d.should == Date.civil(2007, 2, 17)
+ end
+
+ it "raises a TypeError when passed a Symbol" do
+ lambda { Date.civil(2007,2,27) + :hello }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed a String" do
+ lambda { Date.civil(2007,2,27) + "hello" }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed a Date" do
+ lambda { Date.civil(2007,2,27) + Date.new }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed an Object" do
+ lambda { Date.civil(2007,2,27) + Object.new }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/date/ajd_spec.rb b/spec/ruby/library/date/ajd_spec.rb
new file mode 100644
index 0000000000..fcbcea2426
--- /dev/null
+++ b/spec/ruby/library/date/ajd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#ajd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/ajd_to_amjd_spec.rb b/spec/ruby/library/date/ajd_to_amjd_spec.rb
new file mode 100644
index 0000000000..fc6a35d0c6
--- /dev/null
+++ b/spec/ruby/library/date/ajd_to_amjd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.ajd_to_amjd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/ajd_to_jd_spec.rb b/spec/ruby/library/date/ajd_to_jd_spec.rb
new file mode 100644
index 0000000000..1d8d6d0eb5
--- /dev/null
+++ b/spec/ruby/library/date/ajd_to_jd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.ajd_to_jd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/amjd_spec.rb b/spec/ruby/library/date/amjd_spec.rb
new file mode 100644
index 0000000000..212871ee18
--- /dev/null
+++ b/spec/ruby/library/date/amjd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#amjd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/amjd_to_ajd_spec.rb b/spec/ruby/library/date/amjd_to_ajd_spec.rb
new file mode 100644
index 0000000000..f45f202a40
--- /dev/null
+++ b/spec/ruby/library/date/amjd_to_ajd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.amjd_to_ajd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/append_spec.rb b/spec/ruby/library/date/append_spec.rb
new file mode 100644
index 0000000000..d90eff9a7a
--- /dev/null
+++ b/spec/ruby/library/date/append_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#<<" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/asctime_spec.rb b/spec/ruby/library/date/asctime_spec.rb
new file mode 100644
index 0000000000..13dede0f05
--- /dev/null
+++ b/spec/ruby/library/date/asctime_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#asctime" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/boat_spec.rb b/spec/ruby/library/date/boat_spec.rb
new file mode 100644
index 0000000000..3004c6bfbc
--- /dev/null
+++ b/spec/ruby/library/date/boat_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#<=>" do
+ it "returns 0 when two dates are equal" do
+ (Date.civil(2000, 04, 06) <=> Date.civil(2000, 04, 06)).should == 0
+ end
+
+ it "returns -1 when self is less than another date" do
+ (Date.civil(2000, 04, 05) <=> Date.civil(2000, 04, 06)).should == -1
+ end
+
+ it "returns -1 when self is less than a Numeric" do
+ (Date.civil(2000, 04, 05) <=> Date.civil(2000, 04, 06).jd).should == -1
+ end
+
+ it "returns 1 when self is greater than another date" do
+ (Date.civil(2001, 04, 05) <=> Date.civil(2000, 04, 06)).should == 1
+ end
+
+ it "returns 1 when self is greater than a Numeric" do
+ (Date.civil(2001, 04, 05) <=> Date.civil(2000, 04, 06).jd).should == 1
+ end
+end
diff --git a/spec/ruby/library/date/case_compare_spec.rb b/spec/ruby/library/date/case_compare_spec.rb
new file mode 100644
index 0000000000..2144a616a3
--- /dev/null
+++ b/spec/ruby/library/date/case_compare_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#===" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/civil_spec.rb b/spec/ruby/library/date/civil_spec.rb
new file mode 100644
index 0000000000..36e790aecd
--- /dev/null
+++ b/spec/ruby/library/date/civil_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/civil', __FILE__)
+require 'date'
+
+describe "Date#civil" do
+ it_behaves_like(:date_civil, :civil)
+end
+
+
+describe "Date.civil" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/commercial_spec.rb b/spec/ruby/library/date/commercial_spec.rb
new file mode 100644
index 0000000000..bb6671eda1
--- /dev/null
+++ b/spec/ruby/library/date/commercial_spec.rb
@@ -0,0 +1,18 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/commercial', __FILE__)
+
+describe "Date#commercial" do
+
+ it_behaves_like(:date_commercial, :commercial)
+
+end
+
+# reference:
+# October 1582 (the Gregorian calendar, Civil Date)
+# S M Tu W Th F S
+# 1 2 3 4 15 16
+# 17 18 19 20 21 22 23
+# 24 25 26 27 28 29 30
+# 31
+
diff --git a/spec/ruby/library/date/commercial_to_jd_spec.rb b/spec/ruby/library/date/commercial_to_jd_spec.rb
new file mode 100644
index 0000000000..61631a7977
--- /dev/null
+++ b/spec/ruby/library/date/commercial_to_jd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.commercial_to_jd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/comparison_spec.rb b/spec/ruby/library/date/comparison_spec.rb
new file mode 100644
index 0000000000..04bfa2e8f7
--- /dev/null
+++ b/spec/ruby/library/date/comparison_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#<=>" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/constants_spec.rb b/spec/ruby/library/date/constants_spec.rb
new file mode 100644
index 0000000000..8e564fe665
--- /dev/null
+++ b/spec/ruby/library/date/constants_spec.rb
@@ -0,0 +1,44 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date constants" do
+
+ it "defines JULIAN" do
+ (Date::JULIAN <=> Date::Infinity.new).should == 0
+ end
+
+ it "defines GREGORIAN" do
+ (Date::GREGORIAN <=> -Date::Infinity.new).should == 0
+ end
+
+ it "defines ITALY" do
+ Date::ITALY.should == 2299161 # 1582-10-15
+ end
+
+ it "defines ENGLAND" do
+ Date::ENGLAND.should == 2361222 # 1752-09-14
+ end
+
+ it "defines MONTHNAMES" do
+ Date::MONTHNAMES.should == [nil] + %w(January February March April May June July
+ August September October November December)
+ end
+
+ it "defines DAYNAMES" do
+ Date::DAYNAMES.should == %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
+ end
+
+ it "defines ABBR_MONTHNAMES" do
+ Date::ABBR_DAYNAMES.should == %w(Sun Mon Tue Wed Thu Fri Sat)
+ end
+
+ it "freezes MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYSNAMES" do
+ [Date::MONTHNAMES, Date::DAYNAMES, Date::ABBR_MONTHNAMES, Date::ABBR_DAYNAMES].each do |ary|
+ lambda { ary << "Unknown" }.should raise_error
+ ary.compact.each do |name|
+ lambda { name << "modified" }.should raise_error
+ end
+ end
+ end
+
+end
diff --git a/spec/ruby/library/date/conversions_spec.rb b/spec/ruby/library/date/conversions_spec.rb
new file mode 100644
index 0000000000..c52ade7012
--- /dev/null
+++ b/spec/ruby/library/date/conversions_spec.rb
@@ -0,0 +1,43 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+
+describe "Date#new_start" do
+ it "converts a date object into another with a new calendar reform" do
+ Date.civil(1582, 10, 14, Date::ENGLAND).new_start.should == Date.civil(1582, 10, 24)
+ Date.civil(1582, 10, 4, Date::ENGLAND).new_start.should == Date.civil(1582, 10, 4)
+ Date.civil(1582, 10, 15).new_start(Date::ENGLAND).should == Date.civil(1582, 10, 5, Date::ENGLAND)
+ Date.civil(1752, 9, 14).new_start(Date::ENGLAND).should == Date.civil(1752, 9, 14, Date::ENGLAND)
+ Date.civil(1752, 9, 13).new_start(Date::ENGLAND).should == Date.civil(1752, 9, 2, Date::ENGLAND)
+ end
+end
+
+describe "Date#italy" do
+ it "converts a date object into another with the Italian calendar reform" do
+ Date.civil(1582, 10, 14, Date::ENGLAND).italy.should == Date.civil(1582, 10, 24)
+ Date.civil(1582, 10, 4, Date::ENGLAND).italy.should == Date.civil(1582, 10, 4)
+ end
+end
+
+describe "Date#england" do
+ it "converts a date object into another with the English calendar reform" do
+ Date.civil(1582, 10, 15).england.should == Date.civil(1582, 10, 5, Date::ENGLAND)
+ Date.civil(1752, 9, 14).england.should == Date.civil(1752, 9, 14, Date::ENGLAND)
+ Date.civil(1752, 9, 13).england.should == Date.civil(1752, 9, 2, Date::ENGLAND)
+ end
+end
+
+describe "Date#julian" do
+ it "converts a date object into another with the Julian calendar" do
+ Date.civil(1582, 10, 15).julian.should == Date.civil(1582, 10, 5, Date::JULIAN)
+ Date.civil(1752, 9, 14).julian.should == Date.civil(1752, 9, 3, Date::JULIAN)
+ Date.civil(1752, 9, 13).julian.should == Date.civil(1752, 9, 2, Date::JULIAN)
+ end
+end
+
+describe "Date#gregorian" do
+ it "converts a date object into another with the Gregorian calendar" do
+ Date.civil(1582, 10, 4).gregorian.should == Date.civil(1582, 10, 14, Date::GREGORIAN)
+ Date.civil(1752, 9, 14).gregorian.should == Date.civil(1752, 9, 14, Date::GREGORIAN)
+ end
+end
diff --git a/spec/ruby/library/date/ctime_spec.rb b/spec/ruby/library/date/ctime_spec.rb
new file mode 100644
index 0000000000..0f5d594842
--- /dev/null
+++ b/spec/ruby/library/date/ctime_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#ctime" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/cwday_spec.rb b/spec/ruby/library/date/cwday_spec.rb
new file mode 100644
index 0000000000..33ede37b2c
--- /dev/null
+++ b/spec/ruby/library/date/cwday_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#cwday" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/cweek_spec.rb b/spec/ruby/library/date/cweek_spec.rb
new file mode 100644
index 0000000000..d988bdd9db
--- /dev/null
+++ b/spec/ruby/library/date/cweek_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#cweek" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/cwyear_spec.rb b/spec/ruby/library/date/cwyear_spec.rb
new file mode 100644
index 0000000000..00544927bc
--- /dev/null
+++ b/spec/ruby/library/date/cwyear_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#cwyear" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/day_fraction_spec.rb b/spec/ruby/library/date/day_fraction_spec.rb
new file mode 100644
index 0000000000..64896a421e
--- /dev/null
+++ b/spec/ruby/library/date/day_fraction_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#day_fraction" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/day_fraction_to_time_spec.rb b/spec/ruby/library/date/day_fraction_to_time_spec.rb
new file mode 100644
index 0000000000..609367371a
--- /dev/null
+++ b/spec/ruby/library/date/day_fraction_to_time_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.day_fraction_to_time" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/day_spec.rb b/spec/ruby/library/date/day_spec.rb
new file mode 100644
index 0000000000..7dfca4d77c
--- /dev/null
+++ b/spec/ruby/library/date/day_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#day" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/downto_spec.rb b/spec/ruby/library/date/downto_spec.rb
new file mode 100644
index 0000000000..ab9bf11952
--- /dev/null
+++ b/spec/ruby/library/date/downto_spec.rb
@@ -0,0 +1,18 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date#downto" do
+
+ it "creates earlier dates when passed a negative step" do
+ ds = Date.civil(2000, 4, 14)
+ de = Date.civil(2000, 3, 29)
+ count = 0
+ ds.step(de, -1) do |d|
+ d.should <= ds
+ d.should >= de
+ count += 1
+ end
+ count.should == 17
+ end
+
+end
diff --git a/spec/ruby/library/date/england_spec.rb b/spec/ruby/library/date/england_spec.rb
new file mode 100644
index 0000000000..6c67c6ee86
--- /dev/null
+++ b/spec/ruby/library/date/england_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#england" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/eql_spec.rb b/spec/ruby/library/date/eql_spec.rb
new file mode 100644
index 0000000000..efecde8944
--- /dev/null
+++ b/spec/ruby/library/date/eql_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#eql?" do
+ it "returns true if self is equal to another date" do
+ Date.civil(2007, 10, 11).eql?(Date.civil(2007, 10, 11)).should be_true
+ end
+
+ it "returns false if self is not equal to another date" do
+ Date.civil(2007, 10, 11).eql?(Date.civil(2007, 10, 12)).should be_false
+ end
+end
diff --git a/spec/ruby/library/date/format/bag/method_missing_spec.rb b/spec/ruby/library/date/format/bag/method_missing_spec.rb
new file mode 100644
index 0000000000..529fde05d2
--- /dev/null
+++ b/spec/ruby/library/date/format/bag/method_missing_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Format::Bag#method_missing" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/format/bag/to_hash_spec.rb b/spec/ruby/library/date/format/bag/to_hash_spec.rb
new file mode 100644
index 0000000000..ba9525e5e8
--- /dev/null
+++ b/spec/ruby/library/date/format/bag/to_hash_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Format::Bag#to_hash" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/gregorian_leap_spec.rb b/spec/ruby/library/date/gregorian_leap_spec.rb
new file mode 100644
index 0000000000..043d57aa93
--- /dev/null
+++ b/spec/ruby/library/date/gregorian_leap_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#gregorian_leap?" do
+ it "returns true if a year is a leap year in the Gregorian calendar" do
+ Date.gregorian_leap?(2000).should be_true
+ Date.gregorian_leap?(2004).should be_true
+ end
+
+ it "returns false if a year is not a leap year in the Gregorian calendar" do
+ Date.gregorian_leap?(1900).should be_false
+ Date.gregorian_leap?(1999).should be_false
+ Date.gregorian_leap?(2002).should be_false
+ end
+end
+
diff --git a/spec/ruby/library/date/gregorian_spec.rb b/spec/ruby/library/date/gregorian_spec.rb
new file mode 100644
index 0000000000..5d8b38b2d8
--- /dev/null
+++ b/spec/ruby/library/date/gregorian_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#gregorian?" do
+
+ it "marks a day before the calendar reform as Julian" do
+ Date.civil(1007, 2, 27).gregorian?.should be_false
+ Date.civil(1907, 2, 27, Date.civil(1930, 1, 1).jd).gregorian?.should be_false
+ end
+
+ it "marks a day after the calendar reform as Julian" do
+ Date.civil(2007, 2, 27).gregorian?.should == true
+ Date.civil(1607, 2, 27, Date.civil(1582, 1, 1).jd).gregorian?.should be_true
+ end
+
+end
diff --git a/spec/ruby/library/date/hash_spec.rb b/spec/ruby/library/date/hash_spec.rb
new file mode 100644
index 0000000000..271d565253
--- /dev/null
+++ b/spec/ruby/library/date/hash_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#hash" do
+ it "returns the same value for equal dates" do
+ Date.civil(2004, 7, 12).hash.should == Date.civil(2004, 7, 12).hash
+ end
+end
diff --git a/spec/ruby/library/date/infinity/abs_spec.rb b/spec/ruby/library/date/infinity/abs_spec.rb
new file mode 100644
index 0000000000..a1107679f6
--- /dev/null
+++ b/spec/ruby/library/date/infinity/abs_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#abs" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity/coerce_spec.rb b/spec/ruby/library/date/infinity/coerce_spec.rb
new file mode 100644
index 0000000000..e09b948064
--- /dev/null
+++ b/spec/ruby/library/date/infinity/coerce_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#coerce" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity/comparison_spec.rb b/spec/ruby/library/date/infinity/comparison_spec.rb
new file mode 100644
index 0000000000..7bf8fb7b9f
--- /dev/null
+++ b/spec/ruby/library/date/infinity/comparison_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#<=>" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity/d_spec.rb b/spec/ruby/library/date/infinity/d_spec.rb
new file mode 100644
index 0000000000..9ef1f71408
--- /dev/null
+++ b/spec/ruby/library/date/infinity/d_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#d" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity/finite_spec.rb b/spec/ruby/library/date/infinity/finite_spec.rb
new file mode 100644
index 0000000000..92806935fc
--- /dev/null
+++ b/spec/ruby/library/date/infinity/finite_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#finite?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity/infinite_spec.rb b/spec/ruby/library/date/infinity/infinite_spec.rb
new file mode 100644
index 0000000000..8c7e0bc86a
--- /dev/null
+++ b/spec/ruby/library/date/infinity/infinite_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#infinite?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity/nan_spec.rb b/spec/ruby/library/date/infinity/nan_spec.rb
new file mode 100644
index 0000000000..19c7ae0af3
--- /dev/null
+++ b/spec/ruby/library/date/infinity/nan_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#nan?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity/uminus_spec.rb b/spec/ruby/library/date/infinity/uminus_spec.rb
new file mode 100644
index 0000000000..110e197231
--- /dev/null
+++ b/spec/ruby/library/date/infinity/uminus_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#-@" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity/uplus_spec.rb b/spec/ruby/library/date/infinity/uplus_spec.rb
new file mode 100644
index 0000000000..dfc60b6b61
--- /dev/null
+++ b/spec/ruby/library/date/infinity/uplus_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#+@" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity/zero_spec.rb b/spec/ruby/library/date/infinity/zero_spec.rb
new file mode 100644
index 0000000000..2f4347255b
--- /dev/null
+++ b/spec/ruby/library/date/infinity/zero_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date::Infinity#zero?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/infinity_spec.rb b/spec/ruby/library/date/infinity_spec.rb
new file mode 100644
index 0000000000..127fb8c2f4
--- /dev/null
+++ b/spec/ruby/library/date/infinity_spec.rb
@@ -0,0 +1,67 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date::Infinity" do
+
+ it "should be able to check whether Infinity is zero" do
+ i = Date::Infinity.new
+ i.zero?.should == false
+ end
+
+ it "should be able to check whether Infinity is finite" do
+ i1 = Date::Infinity.new
+ i1.finite?.should == false
+ i2 = Date::Infinity.new(-1)
+ i2.finite?.should == false
+ i3 = Date::Infinity.new(0)
+ i3.finite?.should == false
+ end
+
+ it "should be able to check whether Infinity is infinite" do
+ i1 = Date::Infinity.new
+ i1.infinite?.should == 1
+ i2 = Date::Infinity.new(-1)
+ i2.infinite?.should == -1
+ i3 = Date::Infinity.new(0)
+ i3.infinite?.should == nil
+ end
+
+ it "should be able to check whether Infinity is not a number" do
+ i1 = Date::Infinity.new
+ i1.nan?.should == false
+ i2 = Date::Infinity.new(-1)
+ i2.nan?.should == false
+ i3 = Date::Infinity.new(0)
+ i3.nan?.should == true
+ end
+
+ it "should be able to compare Infinity objects" do
+ i1 = Date::Infinity.new
+ i2 = Date::Infinity.new(-1)
+ i3 = Date::Infinity.new(0)
+ i4 = Date::Infinity.new
+ (i4 <=> i1).should == 0
+ (i3 <=> i1).should == -1
+ (i2 <=> i1).should == -1
+ (i3 <=> i2).should == 1
+ end
+
+ it "should be able to return plus Infinity for abs" do
+ i1 = Date::Infinity.new
+ i2 = Date::Infinity.new(-1)
+ i3 = Date::Infinity.new(0)
+ (i2.abs <=> i1).should == 0
+ (i3.abs <=> i1).should == 0
+ end
+
+ it "should be able to use -@ and +@ for Date::Infinity" do
+ (Date::Infinity.new <=> +Date::Infinity.new).should == 0
+ (Date::Infinity.new(-1) <=> -Date::Infinity.new).should == 0
+ end
+
+ it "should be able to coerce a Date::Infinity object" do
+ Date::Infinity.new.coerce(1).should == [-1, 1]
+ Date::Infinity.new(0).coerce(2).should == [0, 0]
+ Date::Infinity.new(-1).coerce(1.5).should == [1, -1]
+ end
+end
diff --git a/spec/ruby/library/date/inspect_spec.rb b/spec/ruby/library/date/inspect_spec.rb
new file mode 100644
index 0000000000..150eb6bf24
--- /dev/null
+++ b/spec/ruby/library/date/inspect_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#inspect" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/italy_spec.rb b/spec/ruby/library/date/italy_spec.rb
new file mode 100644
index 0000000000..2d251db1b0
--- /dev/null
+++ b/spec/ruby/library/date/italy_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#italy" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/jd_spec.rb b/spec/ruby/library/date/jd_spec.rb
new file mode 100644
index 0000000000..ccf6b93e06
--- /dev/null
+++ b/spec/ruby/library/date/jd_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/jd', __FILE__)
+require 'date'
+
+describe "Date#jd" do
+
+ it "determines the Julian day for a Date object" do
+ Date.civil(2008, 1, 16).jd.should == 2454482
+ end
+
+end
+
+describe "Date.jd" do
+ it_behaves_like :date_jd, :jd
+end
diff --git a/spec/ruby/library/date/jd_to_ajd_spec.rb b/spec/ruby/library/date/jd_to_ajd_spec.rb
new file mode 100644
index 0000000000..38a12bd65d
--- /dev/null
+++ b/spec/ruby/library/date/jd_to_ajd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.jd_to_ajd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/jd_to_civil_spec.rb b/spec/ruby/library/date/jd_to_civil_spec.rb
new file mode 100644
index 0000000000..8608de2698
--- /dev/null
+++ b/spec/ruby/library/date/jd_to_civil_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.jd_to_civil" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/jd_to_commercial_spec.rb b/spec/ruby/library/date/jd_to_commercial_spec.rb
new file mode 100644
index 0000000000..97d76130f2
--- /dev/null
+++ b/spec/ruby/library/date/jd_to_commercial_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.jd_to_commercial" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/jd_to_ld_spec.rb b/spec/ruby/library/date/jd_to_ld_spec.rb
new file mode 100644
index 0000000000..d27ada6b6c
--- /dev/null
+++ b/spec/ruby/library/date/jd_to_ld_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.jd_to_ld" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/jd_to_mjd_spec.rb b/spec/ruby/library/date/jd_to_mjd_spec.rb
new file mode 100644
index 0000000000..064134c7ed
--- /dev/null
+++ b/spec/ruby/library/date/jd_to_mjd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.jd_to_mjd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/jd_to_ordinal_spec.rb b/spec/ruby/library/date/jd_to_ordinal_spec.rb
new file mode 100644
index 0000000000..a5f5c79641
--- /dev/null
+++ b/spec/ruby/library/date/jd_to_ordinal_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.jd_to_ordinal" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/jd_to_wday_spec.rb b/spec/ruby/library/date/jd_to_wday_spec.rb
new file mode 100644
index 0000000000..569a53e409
--- /dev/null
+++ b/spec/ruby/library/date/jd_to_wday_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.jd_to_wday" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/julian_leap_spec.rb b/spec/ruby/library/date/julian_leap_spec.rb
new file mode 100644
index 0000000000..3915f97693
--- /dev/null
+++ b/spec/ruby/library/date/julian_leap_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.julian_leap?" do
+ it "determines whether a year is a leap year in the Julian calendar" do
+ Date.julian_leap?(1900).should be_true
+ Date.julian_leap?(2000).should be_true
+ Date.julian_leap?(2004).should be_true
+ end
+
+ it "determines whether a year is not a leap year in the Julian calendar" do
+ Date.julian_leap?(1999).should be_false
+ Date.julian_leap?(2002).should be_false
+ end
+end
diff --git a/spec/ruby/library/date/julian_spec.rb b/spec/ruby/library/date/julian_spec.rb
new file mode 100644
index 0000000000..8cbe27b881
--- /dev/null
+++ b/spec/ruby/library/date/julian_spec.rb
@@ -0,0 +1,16 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date#julian?" do
+
+ it "marks a day before the calendar reform as Julian" do
+ Date.civil(1007, 2, 27).julian?.should == true
+ Date.civil(1907, 2, 27, Date.civil(1930, 1, 1).jd).julian?.should be_true
+ end
+
+ it "marks a day after the calendar reform as Julian" do
+ Date.civil(2007, 2, 27).julian?.should == false
+ Date.civil(1607, 2, 27, Date.civil(1582, 1, 1).jd).julian?.should be_false
+ end
+
+end
diff --git a/spec/ruby/library/date/ld_spec.rb b/spec/ruby/library/date/ld_spec.rb
new file mode 100644
index 0000000000..a59b519c04
--- /dev/null
+++ b/spec/ruby/library/date/ld_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#ld" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/ld_to_jd_spec.rb b/spec/ruby/library/date/ld_to_jd_spec.rb
new file mode 100644
index 0000000000..7adbbede37
--- /dev/null
+++ b/spec/ruby/library/date/ld_to_jd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.ld_to_jd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/leap_spec.rb b/spec/ruby/library/date/leap_spec.rb
new file mode 100644
index 0000000000..bb8e920a3e
--- /dev/null
+++ b/spec/ruby/library/date/leap_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#leap?" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "Date.leap?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/mday_spec.rb b/spec/ruby/library/date/mday_spec.rb
new file mode 100644
index 0000000000..8a1d6e8d59
--- /dev/null
+++ b/spec/ruby/library/date/mday_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#mday" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/minus_month_spec.rb b/spec/ruby/library/date/minus_month_spec.rb
new file mode 100644
index 0000000000..b6b20c5578
--- /dev/null
+++ b/spec/ruby/library/date/minus_month_spec.rb
@@ -0,0 +1,34 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date#<<" do
+
+ it "substracts a number of months from a date" do
+ d = Date.civil(2007,2,27) << 10
+ d.should == Date.civil(2006, 4, 27)
+ end
+
+ it "returns the last day of a month if the day doesn't exist" do
+ d = Date.civil(2008,3,31) << 1
+ d.should == Date.civil(2008, 2, 29)
+ end
+
+ ruby_version_is ""..."2.3" do
+ it "raises an error on non numeric parameters" do
+ lambda { Date.civil(2007,2,27) << :hello }.should raise_error
+ lambda { Date.civil(2007,2,27) << "hello" }.should raise_error
+ lambda { Date.civil(2007,2,27) << Date.new }.should raise_error
+ lambda { Date.civil(2007,2,27) << Object.new }.should raise_error
+ end
+ end
+
+ ruby_version_is "2.3" do
+ it "raises an error on non numeric parameters" do
+ lambda { Date.civil(2007,2,27) << :hello }.should raise_error(TypeError)
+ lambda { Date.civil(2007,2,27) << "hello" }.should raise_error(TypeError)
+ lambda { Date.civil(2007,2,27) << Date.new }.should raise_error(TypeError)
+ lambda { Date.civil(2007,2,27) << Object.new }.should raise_error(TypeError)
+ end
+ end
+
+end
diff --git a/spec/ruby/library/date/minus_spec.rb b/spec/ruby/library/date/minus_spec.rb
new file mode 100644
index 0000000000..09da595872
--- /dev/null
+++ b/spec/ruby/library/date/minus_spec.rb
@@ -0,0 +1,30 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date#-" do
+
+ it "substracts a number of days from a Date" do
+ d = Date.civil(2007, 5 ,2) - 13
+ d.should == Date.civil(2007, 4, 19)
+ end
+
+ it "substracts a negative number of days from a Date" do
+ d = Date.civil(2007, 4, 19).-(-13)
+ d.should == Date.civil(2007, 5 ,2)
+ end
+
+ it "computes the difference between two dates" do
+ (Date.civil(2007,2,27) - Date.civil(2007,2,27)).should == 0
+ (Date.civil(2007,2,27) - Date.civil(2007,2,26)).should == 1
+ (Date.civil(2006,2,27) - Date.civil(2007,2,27)).should == -365
+ (Date.civil(2008,2,27) - Date.civil(2007,2,27)).should == 365
+
+ end
+
+ it "raises an error for non Numeric arguments" do
+ lambda { Date.civil(2007,2,27) - :hello }.should raise_error(TypeError)
+ lambda { Date.civil(2007,2,27) - "hello" }.should raise_error(TypeError)
+ lambda { Date.civil(2007,2,27) - Object.new }.should raise_error(TypeError)
+ end
+
+end
diff --git a/spec/ruby/library/date/mjd_spec.rb b/spec/ruby/library/date/mjd_spec.rb
new file mode 100644
index 0000000000..7de39f0047
--- /dev/null
+++ b/spec/ruby/library/date/mjd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#mjd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/mjd_to_jd_spec.rb b/spec/ruby/library/date/mjd_to_jd_spec.rb
new file mode 100644
index 0000000000..fdda1330e5
--- /dev/null
+++ b/spec/ruby/library/date/mjd_to_jd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.mjd_to_jd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/mon_spec.rb b/spec/ruby/library/date/mon_spec.rb
new file mode 100644
index 0000000000..c3508b53bf
--- /dev/null
+++ b/spec/ruby/library/date/mon_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#mon" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/month_spec.rb b/spec/ruby/library/date/month_spec.rb
new file mode 100644
index 0000000000..7a98f572b6
--- /dev/null
+++ b/spec/ruby/library/date/month_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#month" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/new_spec.rb b/spec/ruby/library/date/new_spec.rb
new file mode 100644
index 0000000000..f468036a01
--- /dev/null
+++ b/spec/ruby/library/date/new_spec.rb
@@ -0,0 +1,8 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/civil', __FILE__)
+require File.expand_path('../shared/new_bang', __FILE__)
+
+describe "Date.new" do
+ it_behaves_like(:date_civil, :new)
+end
diff --git a/spec/ruby/library/date/new_start_spec.rb b/spec/ruby/library/date/new_start_spec.rb
new file mode 100644
index 0000000000..94ec6bee46
--- /dev/null
+++ b/spec/ruby/library/date/new_start_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#new_start" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/next_day_spec.rb b/spec/ruby/library/date/next_day_spec.rb
new file mode 100644
index 0000000000..1ccb4df257
--- /dev/null
+++ b/spec/ruby/library/date/next_day_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#next_day" do
+ it "returns the next day" do
+ d = Date.new(2000, 1, 5)
+ d1 = Date.new(2000, 1, 4).next_day
+ d1.should == d
+ end
+end
diff --git a/spec/ruby/library/date/next_spec.rb b/spec/ruby/library/date/next_spec.rb
new file mode 100644
index 0000000000..d88d31e974
--- /dev/null
+++ b/spec/ruby/library/date/next_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#next" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/next_year_spec.rb b/spec/ruby/library/date/next_year_spec.rb
new file mode 100644
index 0000000000..70f2f7ab77
--- /dev/null
+++ b/spec/ruby/library/date/next_year_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#next_year" do
+ it "returns the day of the reform if date falls within calendar reform" do
+ calendar_reform_italy = Date.new(1582, 10, 4)
+ d1 = Date.new(1581, 10, 9).next_year
+ d2 = Date.new(1581, 10, 10).next_year
+ d1.should == calendar_reform_italy
+ d2.should == calendar_reform_italy
+ end
+end
diff --git a/spec/ruby/library/date/ordinal_spec.rb b/spec/ruby/library/date/ordinal_spec.rb
new file mode 100644
index 0000000000..a373692a7b
--- /dev/null
+++ b/spec/ruby/library/date/ordinal_spec.rb
@@ -0,0 +1,8 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/ordinal', __FILE__)
+
+describe "Date.ordinal" do
+ it_behaves_like :date_ordinal, :ordinal
+end
+
diff --git a/spec/ruby/library/date/ordinal_to_jd_spec.rb b/spec/ruby/library/date/ordinal_to_jd_spec.rb
new file mode 100644
index 0000000000..0a76c69c00
--- /dev/null
+++ b/spec/ruby/library/date/ordinal_to_jd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.ordinal_to_jd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/parse_spec.rb b/spec/ruby/library/date/parse_spec.rb
new file mode 100644
index 0000000000..092c658809
--- /dev/null
+++ b/spec/ruby/library/date/parse_spec.rb
@@ -0,0 +1,137 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/parse', __FILE__)
+require File.expand_path('../shared/parse_us', __FILE__)
+require File.expand_path('../shared/parse_eu', __FILE__)
+require 'date'
+
+describe "Date#parse" do
+ # The space separator is also different, doesn't work for only numbers
+ it "parses a day name into a Date object" do
+ d = Date.parse("friday")
+ d.should == Date.commercial(d.cwyear, d.cweek, 5)
+ end
+
+ it "parses a month name into a Date object" do
+ d = Date.parse("october")
+ d.should == Date.civil(Date.today.year, 10)
+ end
+
+ it "parses a month day into a Date object" do
+ d = Date.parse("5th")
+ d.should == Date.civil(Date.today.year, Date.today.month, 5)
+ end
+
+ # Specs using numbers
+ it "throws an argument error for a single digit" do
+ lambda{ Date.parse("1") }.should raise_error(ArgumentError)
+ end
+
+ it "parses DD as month day number" do
+ d = Date.parse("10")
+ d.should == Date.civil(Date.today.year, Date.today.month, 10)
+ end
+
+ it "parses DDD as year day number" do
+ d = Date.parse("100")
+ if Date.gregorian_leap?(Date.today.year)
+ d.should == Date.civil(Date.today.year, 4, 9)
+ else
+ d.should == Date.civil(Date.today.year, 4, 10)
+ end
+ end
+
+ it "parses MMDD as month and day" do
+ d = Date.parse("1108")
+ d.should == Date.civil(Date.today.year, 11, 8)
+ end
+
+ it "parses YYDDD as year and day number in 1969--2068" do
+ d = Date.parse("10100")
+ d.should == Date.civil(2010, 4, 10)
+ end
+
+ it "parses YYMMDD as year, month and day in 1969--2068" do
+ d = Date.parse("201023")
+ d.should == Date.civil(2020, 10, 23)
+ end
+
+ it "parses YYYYDDD as year and day number" do
+ d = Date.parse("1910100")
+ d.should == Date.civil(1910, 4, 10)
+ end
+
+ it "parses YYYYMMDD as year, month and day number" do
+ d = Date.parse("19101101")
+ d.should == Date.civil(1910, 11, 1)
+ end
+end
+
+describe "Date#parse with '.' separator" do
+ before :all do
+ @sep = '.'
+ end
+
+ it_should_behave_like "date_parse"
+end
+
+describe "Date#parse with '/' separator" do
+ before :all do
+ @sep = '/'
+ end
+
+ it_should_behave_like "date_parse"
+end
+
+describe "Date#parse with ' ' separator" do
+ before :all do
+ @sep = ' '
+ end
+
+ it_should_behave_like "date_parse"
+end
+
+describe "Date#parse with '/' separator US-style" do
+ before :all do
+ @sep = '/'
+ end
+
+ it_should_behave_like "date_parse_us"
+end
+
+describe "Date#parse with '-' separator EU-style" do
+ before :all do
+ @sep = '-'
+ end
+
+ it_should_behave_like "date_parse_eu"
+end
+
+describe "Date#parse(.)" do
+ it "parses YYYY.MM.DD into a Date object" do
+ d = Date.parse("2007.10.01")
+ d.year.should == 2007
+ d.month.should == 10
+ d.day.should == 1
+ end
+
+ it "parses DD.MM.YYYY into a Date object" do
+ d = Date.parse("10.01.2007")
+ d.year.should == 2007
+ d.month.should == 1
+ d.day.should == 10
+ end
+
+ it "parses YY.MM.DD into a Date object using the year 20YY" do
+ d = Date.parse("10.01.07")
+ d.year.should == 2010
+ d.month.should == 1
+ d.day.should == 7
+ end
+
+ it "parses YY.MM.DD using the year digits as 20YY when given true as additional argument" do
+ d = Date.parse("10.01.07", true)
+ d.year.should == 2010
+ d.month.should == 1
+ d.day.should == 7
+ end
+end
diff --git a/spec/ruby/library/date/plus_spec.rb b/spec/ruby/library/date/plus_spec.rb
new file mode 100644
index 0000000000..e33fb199eb
--- /dev/null
+++ b/spec/ruby/library/date/plus_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#+" do
+ before :all do
+ @date = Date.civil(2000, 1, 1)
+ end
+
+ it "returns a new Date object that is n days later than the current one" do
+ (@date + 31).should == Date.civil(2000, 2, 1)
+ end
+
+ it "accepts a negative argument and returns a new Date that is earlier than the current one" do
+ (@date + -1).should == Date.civil(1999, 12, 31)
+ end
+
+ it "raises TypeError if argument is not Numeric" do
+ lambda { Date.today + Date.today }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/date/prev_year_spec.rb b/spec/ruby/library/date/prev_year_spec.rb
new file mode 100644
index 0000000000..4f27d1d1f9
--- /dev/null
+++ b/spec/ruby/library/date/prev_year_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#prev_year" do
+ it "returns the day of the reform if date falls within calendar reform" do
+ calendar_reform_italy = Date.new(1582, 10, 4)
+ d1 = Date.new(1583, 10, 9).prev_year
+ d2 = Date.new(1583, 10, 10).prev_year
+ d1.should == calendar_reform_italy
+ d2.should == calendar_reform_italy
+ end
+end
diff --git a/spec/ruby/library/date/relationship_spec.rb b/spec/ruby/library/date/relationship_spec.rb
new file mode 100644
index 0000000000..7c09457228
--- /dev/null
+++ b/spec/ruby/library/date/relationship_spec.rb
@@ -0,0 +1,20 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date#===" do
+
+ it "returns 0 when comparing two equal dates" do
+ (Date.civil(2000, 04, 06) <=> Date.civil(2000, 04, 06)).should == 0
+ end
+
+ it "computes the difference between two dates" do
+ (Date.civil(2000, 04, 05) <=> Date.civil(2000, 04, 06)).should == -1
+ (Date.civil(2001, 04, 05) <=> Date.civil(2000, 04, 06)).should == 1
+ end
+
+ it "compares to another numeric" do
+ (Date.civil(2000, 04, 05) <=> Date.civil(2000, 04, 06).jd).should == -1
+ (Date.civil(2001, 04, 05) <=> Date.civil(2000, 04, 06).jd).should == 1
+ end
+
+end
diff --git a/spec/ruby/library/date/right_shift_spec.rb b/spec/ruby/library/date/right_shift_spec.rb
new file mode 100644
index 0000000000..3d55e5abed
--- /dev/null
+++ b/spec/ruby/library/date/right_shift_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#>>" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/shared/civil.rb b/spec/ruby/library/date/shared/civil.rb
new file mode 100644
index 0000000000..47dbed49fc
--- /dev/null
+++ b/spec/ruby/library/date/shared/civil.rb
@@ -0,0 +1,57 @@
+describe :date_civil, shared: true do
+ it "creates a Date for -4712 by default" do
+ # the #chomp calls are necessary because of RSpec
+ d = Date.send(@method)
+ d.year.should == -4712
+ d.month.should == 1
+ d.day.should == 1
+ d.julian?.should == true
+ d.jd.should == 0
+ end
+
+ it "creates a date with arguments" do
+ d = Date.send(@method, 2000, 3, 5)
+ d.year.should == 2000
+ d.month.should == 3
+ d.day.should == 5
+ d.julian?.should == false
+ d.jd.should == 2451609
+
+ # Should also work with years far in the past and future
+
+ d = Date.send(@method, -9000, 7, 5)
+ d.year.should == -9000
+ d.month.should == 7
+ d.day.should == 5
+ d.julian?.should == true
+ d.jd.should == -1566006
+
+ d = Date.send(@method, 9000, 10, 14)
+ d.year.should == 9000
+ d.month.should == 10
+ d.day.should == 14
+ d.julian?.should == false
+ d.jd.should == 5008529
+
+ end
+
+ it "doesn't create dates for invalid arguments" do
+ lambda { Date.send(@method, 2000, 13, 31) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 2000, 12, 32) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 2000, 2, 30) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 1900, 2, 29) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 2000, 2, 29) }.should_not raise_error(ArgumentError)
+
+ lambda { Date.send(@method, 1582, 10, 14) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 1582, 10, 15) }.should_not raise_error(ArgumentError)
+
+ end
+
+ it "creates a Date for different calendar reform dates" do
+ d1 = Date.send(@method, 1582, 10, 4)
+ d1.succ.day.should == 15
+
+ d2 = Date.send(@method, 1582, 10, 4, Date::ENGLAND)
+ d2.succ.day.should == 5
+ end
+end
diff --git a/spec/ruby/library/date/shared/commercial.rb b/spec/ruby/library/date/shared/commercial.rb
new file mode 100644
index 0000000000..354a5d5cd0
--- /dev/null
+++ b/spec/ruby/library/date/shared/commercial.rb
@@ -0,0 +1,39 @@
+describe :date_commercial, shared: true do
+ it "creates a Date for Julian Day Number day 0 by default" do
+ d = Date.send(@method)
+ d.year.should == -4712
+ d.month.should == 1
+ d.day.should == 1
+ end
+
+ it "creates a Date for the monday in the year and week given" do
+ d = Date.send(@method, 2000, 1)
+ d.year.should == 2000
+ d.month.should == 1
+ d.day.should == 3
+ d.cwday.should == 1
+ end
+
+ it "creates a Date for the correct day given the year, week and day number" do
+ d = Date.send(@method, 2004, 1, 1)
+ d.year.should == 2003
+ d.month.should == 12
+ d.day.should == 29
+ d.cwday.should == 1
+ d.cweek.should == 1
+ d.cwyear.should == 2004
+ end
+
+ it "creates only Date objects for valid weeks" do
+ lambda { Date.send(@method, 2004, 53, 1) }.should_not raise_error(ArgumentError)
+ lambda { Date.send(@method, 2004, 53, 0) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 2004, 53, 8) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 2004, 54, 1) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 2004, 0, 1) }.should raise_error(ArgumentError)
+
+ lambda { Date.send(@method, 2003, 52, 1) }.should_not raise_error(ArgumentError)
+ lambda { Date.send(@method, 2003, 53, 1) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 2003, 52, 0) }.should raise_error(ArgumentError)
+ lambda { Date.send(@method, 2003, 52, 8) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/date/shared/jd.rb b/spec/ruby/library/date/shared/jd.rb
new file mode 100644
index 0000000000..511557b4f7
--- /dev/null
+++ b/spec/ruby/library/date/shared/jd.rb
@@ -0,0 +1,14 @@
+describe :date_jd, shared: true do
+ it "constructs a Date object if passed a Julian day" do
+ Date.send(@method, 2454482).should == Date.civil(2008, 1, 16)
+ end
+
+ it "returns a Date object representing Julian day 0 (-4712-01-01) if no arguments passed" do
+ Date.send(@method).should == Date.civil(-4712, 1, 1)
+ end
+
+ it "constructs a Date object if passed a negative number" do
+ Date.send(@method, -1).should == Date.civil(-4713, 12, 31)
+ end
+
+end
diff --git a/spec/ruby/library/date/shared/new_bang.rb b/spec/ruby/library/date/shared/new_bang.rb
new file mode 100644
index 0000000000..90f1b432f0
--- /dev/null
+++ b/spec/ruby/library/date/shared/new_bang.rb
@@ -0,0 +1,14 @@
+describe :date_new_bang, shared: true do
+
+ it "returns a new Date object set to Astronomical Julian Day 0 if no arguments passed" do
+ d = Date.send(@method)
+ d.ajd.should == 0
+ end
+
+ it "accepts astronomical julian day number, offset as a fraction of a day and returns a new Date object" do
+ d = Date.send(@method, 10, 0.5)
+ d.ajd.should == 10
+ d.jd.should == 11
+ end
+
+end
diff --git a/spec/ruby/library/date/shared/ordinal.rb b/spec/ruby/library/date/shared/ordinal.rb
new file mode 100644
index 0000000000..4b182d5a25
--- /dev/null
+++ b/spec/ruby/library/date/shared/ordinal.rb
@@ -0,0 +1,22 @@
+# reference:
+# October 1582 (the Gregorian calendar, Civil Date)
+# S M Tu W Th F S
+# 1 2 3 4 15 16
+# 17 18 19 20 21 22 23
+# 24 25 26 27 28 29 30
+# 31
+
+describe :date_ordinal, shared: true do
+ it "constructs a Date object from an ordinal date" do
+ # October 1582 (the Gregorian calendar, Ordinal Date)
+ # S M Tu W Th F S
+ # 274 275 276 277 278 279
+ # 280 281 282 283 284 285 286
+ # 287 288 289 290 291 292 293
+ # 294
+ Date.send(@method, 1582, 274).should == Date.civil(1582, 10, 1)
+ Date.send(@method, 1582, 277).should == Date.civil(1582, 10, 4)
+ Date.send(@method, 1582, 278).should == Date.civil(1582, 10, 15)
+ Date.send(@method, 1582, 287, Date::ENGLAND).should == Date.civil(1582, 10, 14, Date::ENGLAND)
+ end
+end
diff --git a/spec/ruby/library/date/shared/parse.rb b/spec/ruby/library/date/shared/parse.rb
new file mode 100644
index 0000000000..1015285e04
--- /dev/null
+++ b/spec/ruby/library/date/shared/parse.rb
@@ -0,0 +1,54 @@
+describe :date_parse, shared: true do
+ it "can parse a mmm-YYYY string into a Date object" do
+ d = Date.parse("feb#{@sep}2008")
+ d.year.should == 2008
+ d.month.should == 2
+ d.day.should == 1
+ end
+
+ it "can parse a 'DD mmm YYYY' string into a Date object" do
+ d = Date.parse("23#{@sep}feb#{@sep}2008")
+ d.year.should == 2008
+ d.month.should == 2
+ d.day.should == 23
+ end
+
+ it "can parse a 'mmm DD YYYY' string into a Date object" do
+ d = Date.parse("23#{@sep}feb#{@sep}2008")
+ d.year.should == 2008
+ d.month.should == 2
+ d.day.should == 23
+ end
+
+ it "can parse a 'YYYY mmm DD' string into a Date object" do
+ d = Date.parse("2008#{@sep}feb#{@sep}23")
+ d.year.should == 2008
+ d.month.should == 2
+ d.day.should == 23
+ end
+
+ it "can parse a month name and day into a Date object" do
+ d = Date.parse("november#{@sep}5th")
+ d.should == Date.civil(Date.today.year, 11, 5)
+ end
+
+ it "can parse a month name, day and year into a Date object" do
+ d = Date.parse("november#{@sep}5th#{@sep}2005")
+ d.should == Date.civil(2005, 11, 5)
+ end
+
+ it "can parse a year, month name and day into a Date object" do
+ d = Date.parse("2005#{@sep}november#{@sep}5th")
+ d.should == Date.civil(2005, 11, 5)
+ end
+
+ it "can parse a year, day and month name into a Date object" do
+ d = Date.parse("5th#{@sep}november#{@sep}2005")
+ d.should == Date.civil(2005, 11, 5)
+ end
+
+ it "can handle negative year numbers" do
+ d = Date.parse("5th#{@sep}november#{@sep}-2005")
+ d.should == Date.civil(-2005, 11, 5)
+ end
+end
diff --git a/spec/ruby/library/date/shared/parse_eu.rb b/spec/ruby/library/date/shared/parse_eu.rb
new file mode 100644
index 0000000000..ecb15e3c0e
--- /dev/null
+++ b/spec/ruby/library/date/shared/parse_eu.rb
@@ -0,0 +1,37 @@
+describe :date_parse_eu, shared: true do
+ # The - separator let's it work like European format, so it as a different spec
+ it "can parse a YYYY-MM-DD string into a Date object" do
+ d = Date.parse("2007#{@sep}10#{@sep}01")
+ d.year.should == 2007
+ d.month.should == 10
+ d.day.should == 1
+ end
+
+ it "can parse a MM-DD-YYYY string into a Date object" do
+ d = Date.parse("10#{@sep}01#{@sep}2007")
+ d.year.should == 2007
+ d.month.should == 1
+ d.day.should == 10
+ end
+
+ it "can parse a MM-DD-YY string into a Date object" do
+ d = Date.parse("10#{@sep}01#{@sep}07")
+ d.year.should == 2010
+ d.month.should == 1
+ d.day.should == 7
+ end
+
+ it "can parse a MM-DD-YY string into a Date object NOT using the year digits as 20XX" do
+ d = Date.parse("10#{@sep}01#{@sep}07", false)
+ d.year.should == 10
+ d.month.should == 1
+ d.day.should == 7
+ end
+
+ it "can parse a MM-DD-YY string into a Date object using the year digits as 20XX" do
+ d = Date.parse("10#{@sep}01#{@sep}07", true)
+ d.year.should == 2010
+ d.month.should == 1
+ d.day.should == 7
+ end
+end
diff --git a/spec/ruby/library/date/shared/parse_us.rb b/spec/ruby/library/date/shared/parse_us.rb
new file mode 100644
index 0000000000..7be62b1af1
--- /dev/null
+++ b/spec/ruby/library/date/shared/parse_us.rb
@@ -0,0 +1,36 @@
+describe :date_parse_us, shared: true do
+ it "parses a YYYY#{@sep}MM#{@sep}DD string into a Date object" do
+ d = Date.parse("2007#{@sep}10#{@sep}01")
+ d.year.should == 2007
+ d.month.should == 10
+ d.day.should == 1
+ end
+
+ it "parses a MM#{@sep}DD#{@sep}YYYY string into a Date object" do
+ d = Date.parse("10#{@sep}01#{@sep}2007")
+ d.year.should == 2007
+ d.month.should == 1
+ d.day.should == 10
+ end
+
+ it "parses a MM#{@sep}DD#{@sep}YY string into a Date object" do
+ d = Date.parse("10#{@sep}01#{@sep}07")
+ d.year.should == 2010
+ d.month.should == 1
+ d.day.should == 7
+ end
+
+ it "parses a MM#{@sep}DD#{@sep}YY string into a Date object NOT using the year digits as 20XX" do
+ d = Date.parse("10#{@sep}01#{@sep}07", false)
+ d.year.should == 10
+ d.month.should == 1
+ d.day.should == 7
+ end
+
+ it "parses a MM#{@sep}DD#{@sep}YY string into a Date object using the year digits as 20XX" do
+ d = Date.parse("10#{@sep}01#{@sep}07", true)
+ d.year.should == 2010
+ d.month.should == 1
+ d.day.should == 7
+ end
+end
diff --git a/spec/ruby/library/date/shared/valid_civil.rb b/spec/ruby/library/date/shared/valid_civil.rb
new file mode 100644
index 0000000000..545c207bbe
--- /dev/null
+++ b/spec/ruby/library/date/shared/valid_civil.rb
@@ -0,0 +1,36 @@
+describe :date_valid_civil?, shared: true do
+
+ # reference:
+ # October 1582 (the Gregorian calendar, Civil Date)
+ # S M Tu W Th F S
+ # 1 2 3 4 15 16
+ # 17 18 19 20 21 22 23
+ # 24 25 26 27 28 29 30
+ # 31
+
+ it "returns true if it is a valid civil date" do
+ Date.send(@method, 1582, 10, 15).should be_true
+ Date.send(@method, 1582, 10, 14, Date::ENGLAND).should be_true
+ end
+
+ it "returns false if it is not a valid civil date" do
+ Date.send(@method, 1582, 10, 14).should == false
+ end
+
+ it "handles negative months and days" do
+ # October 1582 (the Gregorian calendar, Civil Date)
+ # S M Tu W Th F S
+ # -21 -20 -19 -18 -17 -16
+ # -15 -14 -13 -12 -11 -10 -9
+ # -8 -7 -6 -5 -4 -3 -2
+ # -1
+ Date.send(@method, 1582, -3, -22).should be_false
+ Date.send(@method, 1582, -3, -21).should be_true
+ Date.send(@method, 1582, -3, -18).should be_true
+ Date.send(@method, 1582, -3, -17).should be_true
+
+ Date.send(@method, 2007, -11, -10).should be_true
+ Date.send(@method, 2008, -11, -10).should be_true
+ end
+
+end
diff --git a/spec/ruby/library/date/shared/valid_commercial.rb b/spec/ruby/library/date/shared/valid_commercial.rb
new file mode 100644
index 0000000000..117dfe1d3d
--- /dev/null
+++ b/spec/ruby/library/date/shared/valid_commercial.rb
@@ -0,0 +1,34 @@
+describe :date_valid_commercial?, shared: true do
+
+ it "returns true if it is a valid commercial date" do
+ # October 1582 (the Gregorian calendar, Commercial Date)
+ # M Tu W Th F Sa Su
+ # 39: 1 2 3 4 5 6 7
+ # 40: 1 2 3 4 5 6 7
+ # 41: 1 2 3 4 5 6 7
+ Date.send(@method, 1582, 39, 4).should be_true
+ Date.send(@method, 1582, 39, 5).should be_true
+ Date.send(@method, 1582, 41, 4).should be_true
+ Date.send(@method, 1582, 41, 5).should be_true
+ Date.send(@method, 1582, 41, 4, Date::ENGLAND).should be_true
+ Date.send(@method, 1752, 37, 4, Date::ENGLAND).should be_true
+ end
+
+ it "returns false it is not a valid commercial date" do
+ Date.send(@method, 1999, 53, 1).should be_false
+ end
+
+ it "handles negative week and day numbers" do
+ # October 1582 (the Gregorian calendar, Commercial Date)
+ # M Tu W Th F Sa Su
+ # -12: -7 -6 -5 -4 -3 -2 -1
+ # -11: -7 -6 -5 -4 -3 -2 -1
+ # -10: -7 -6 -5 -4 -3 -2 -1
+ Date.send(@method, 1582, -12, -4).should be_true
+ Date.send(@method, 1582, -12, -3).should be_true
+ Date.send(@method, 2007, -44, -2).should be_true
+ Date.send(@method, 2008, -44, -2).should be_true
+ Date.send(@method, 1999, -53, -1).should be_false
+ end
+
+end
diff --git a/spec/ruby/library/date/shared/valid_jd.rb b/spec/ruby/library/date/shared/valid_jd.rb
new file mode 100644
index 0000000000..d8a35992b3
--- /dev/null
+++ b/spec/ruby/library/date/shared/valid_jd.rb
@@ -0,0 +1,15 @@
+describe :date_valid_jd?, shared: true do
+ it "returns true if passed any value other than nil" do
+ Date.send(@method, -100).should be_true
+ Date.send(@method, :number).should be_true
+ Date.send(@method, Rational(1,2)).should be_true
+ end
+
+ it "returns false if passed nil" do
+ Date.send(@method, nil).should be_false
+ end
+
+ it "returns true if passed false" do
+ Date.send(@method, false).should be_true
+ end
+end
diff --git a/spec/ruby/library/date/shared/valid_ordinal.rb b/spec/ruby/library/date/shared/valid_ordinal.rb
new file mode 100644
index 0000000000..1ed961be23
--- /dev/null
+++ b/spec/ruby/library/date/shared/valid_ordinal.rb
@@ -0,0 +1,26 @@
+describe :date_valid_ordinal?, shared: true do
+ it "determines if the date is a valid ordinal date" do
+ # October 1582 (the Gregorian calendar, Ordinal Date)
+ # S M Tu W Th F S
+ # 274 275 276 277 278 279
+ # 280 281 282 283 284 285 286
+ # 287 288 289 290 291 292 293
+ # 294
+ Date.send(@method, 1582, 277).should == true
+ Date.send(@method, 1582, 278).should == true
+ Date.send(@method, 1582, 287).should == true
+ Date.send(@method, 1582, 288).should == true
+ end
+
+ it "handles negative day numbers" do
+ # October 1582 (the Gregorian calendar, Ordinal Date)
+ # S M Tu W Th F S
+ # -82 -81 -80 -79 -78 -77
+ # -76 -75 -74 -73 -72 -71 -70
+ # -69 -68 -67 -66 -65 -64 -63
+ # -62
+ Date.send(@method, 1582, -79).should == true
+ Date.send(@method, 1582, -78).should == true
+ Date.send(@method, 2007, -100).should == true
+ end
+end
diff --git a/spec/ruby/library/date/start_spec.rb b/spec/ruby/library/date/start_spec.rb
new file mode 100644
index 0000000000..285037b094
--- /dev/null
+++ b/spec/ruby/library/date/start_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#start" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/step_spec.rb b/spec/ruby/library/date/step_spec.rb
new file mode 100644
index 0000000000..249633e807
--- /dev/null
+++ b/spec/ruby/library/date/step_spec.rb
@@ -0,0 +1,56 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date#step" do
+
+ it "steps forward in time" do
+ ds = Date.civil(2008, 10, 11)
+ de = Date.civil(2008, 9, 29)
+ count = 0
+ de.step(ds) do |d|
+ d.should <= ds
+ d.should >= de
+ count += 1
+ end
+ count.should == 13
+
+ count = 0
+ de.step(ds, 5) do |d|
+ d.should <= ds
+ d.should >= de
+ count += 1
+ end
+ count.should == 3
+
+ count = 0
+ ds.step(de) do |d|; count += 1; end
+ count.should == 0
+
+ end
+
+ it "steps backward in time" do
+ ds = Date.civil(2000, 4, 14)
+ de = Date.civil(2000, 3, 29)
+ count = 0
+ ds.step(de, -1) do |d|
+ d.should <= ds
+ d.should >= de
+ count += 1
+ end
+ count.should == 17
+
+ count = 0
+ ds.step(de, -5) do |d|
+ d.should <= ds
+ d.should >= de
+ count += 1
+ end
+ count.should == 4
+
+ count = 0
+ de.step(ds, -1) do |d|; count += 1; end
+ count.should == 0
+
+ end
+
+end
diff --git a/spec/ruby/library/date/strftime_spec.rb b/spec/ruby/library/date/strftime_spec.rb
new file mode 100644
index 0000000000..81bb162ff7
--- /dev/null
+++ b/spec/ruby/library/date/strftime_spec.rb
@@ -0,0 +1,40 @@
+require 'date'
+require File.expand_path('../../../shared/time/strftime_for_date', __FILE__)
+
+describe "Date#strftime" do
+ before :all do
+ @new_date = lambda { |y,m,d| Date.civil(y,m,d) }
+
+ @date = Date.civil(2000, 4, 9)
+ end
+
+ it_behaves_like :strftime_date, :strftime
+
+ # Differences with Time
+ it "should be able to print the date with no argument" do
+ @date.strftime.should == "2000-04-09"
+ @date.strftime.should == @date.to_s
+ end
+
+ # %Z is %:z for Date/DateTime
+ it "should be able to show the timezone with a : separator" do
+ @date.strftime("%Z").should == "+00:00"
+ end
+
+ # %v is %e-%b-%Y for Date/DateTime
+ it "should be able to show the commercial week" do
+ @date.strftime("%v").should == " 9-Apr-2000"
+ @date.strftime("%v").should == @date.strftime('%e-%b-%Y')
+ end
+
+ # additional conversion specifiers only in Date/DateTime
+ it 'shows the number of milliseconds since epoch' do
+ DateTime.new(1970, 1, 1).strftime('%Q').should == "0"
+ @date.strftime("%Q").should == "955238400000"
+ end
+
+ it "should be able to show a full notation" do
+ @date.strftime("%+").should == "Sun Apr 9 00:00:00 +00:00 2000"
+ @date.strftime("%+").should == @date.strftime('%a %b %e %H:%M:%S %Z %Y')
+ end
+end
diff --git a/spec/ruby/library/date/strptime_spec.rb b/spec/ruby/library/date/strptime_spec.rb
new file mode 100644
index 0000000000..21a73da086
--- /dev/null
+++ b/spec/ruby/library/date/strptime_spec.rb
@@ -0,0 +1,149 @@
+require 'date'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Date#strptime" do
+
+ it "returns January 1, 4713 BCE when given no arguments" do
+ Date.strptime.should == Date.civil(-4712, 1, 1)
+ end
+
+ it "uses the default format when not given a date format" do
+ Date.strptime("2000-04-06").should == Date.civil(2000, 4, 6)
+ Date.civil(2000, 4, 6).strftime.should == Date.civil(2000, 4, 6).to_s
+ end
+
+ it "parses a full day name" do
+ d = Date.today
+ expected_date = Date.commercial(d.cwyear, d.cweek, 4)
+ # strptime assumed week that start on sunday, not monday
+ expected_date += 7 if d.cwday == 7
+ Date.strptime("Thursday", "%A").should == expected_date
+ end
+
+ it "parses a short day name" do
+ d = Date.today
+ expected_date = Date.commercial(d.cwyear, d.cweek, 4)
+ # strptime assumed week that start on sunday, not monday
+ expected_date += 7 if d.cwday == 7
+ Date.strptime("Thu", "%a").should == expected_date
+ end
+
+ it "parses a full month name" do
+ d = Date.today
+ Date.strptime("April", "%B").should == Date.civil(d.year, 4, 1)
+ end
+
+ it "parses a short month name" do
+ d = Date.today
+ Date.strptime("Apr", "%b").should == Date.civil(d.year, 4, 1)
+ Date.strptime("Apr", "%h").should == Date.civil(d.year, 4, 1)
+ end
+
+ it "parses a century" do
+ Date.strptime("06 20", "%y %C").should == Date.civil(2006, 1, 1)
+ end
+
+ it "parses a month day with leading zeroes" do
+ d = Date.today
+ Date.strptime("06", "%d").should == Date.civil(d.year, d.month, 6)
+ end
+
+ it "parses a month day with leading spaces" do
+ d = Date.today
+ Date.strptime(" 6", "%e").should == Date.civil(d.year, d.month, 6)
+ end
+
+ it "parses a commercial year with leading zeroes" do
+ Date.strptime("2000", "%G").should == Date.civil(2000, 1, 3)
+ Date.strptime("2002", "%G").should == Date.civil(2001, 12, 31)
+ end
+
+ it "parses a commercial year with only two digits" do
+ Date.strptime("68", "%g").should == Date.civil(2068, 1, 2)
+ Date.strptime("69", "%g").should == Date.civil(1968, 12, 30)
+ end
+
+ it "parses a year day with leading zeroes" do
+ d = Date.today
+ if Date.gregorian_leap?(Date.today.year)
+ Date.strptime("097", "%j").should == Date.civil(d.year, 4, 6)
+ else
+ Date.strptime("097", "%j").should == Date.civil(d.year, 4, 7)
+ end
+ end
+
+ it "parses a month with leading zeroes" do
+ d = Date.today
+ Date.strptime("04", "%m").should == Date.civil(d.year, 4, 1)
+ end
+
+ it "parses a week number for a week starting on Sunday" do
+ Date.strptime("2010/1", "%Y/%U").should == Date.civil(2010, 1, 3)
+ end
+
+ # See http://redmine.ruby-lang.org/repositories/diff/ruby-19?rev=24500
+ it "parses a week number for a week starting on Monday" do
+ Date.strptime("2010/1", "%Y/%W").should == Date.civil(2010, 1, 4)
+ end
+
+ it "parses a commercial week day" do
+ Date.strptime("2008 1", "%G %u").should == Date.civil(2007, 12, 31)
+ end
+
+ it "parses a commercial week" do
+ d = Date.commercial(Date.today.cwyear,1,1)
+ Date.strptime("1", "%V").should == d
+ Date.strptime("15", "%V").should == Date.commercial(d.cwyear, 15, 1)
+ end
+
+ it "parses a week day" do
+ Date.strptime("2007 4", "%Y %w").should == Date.civil(2007, 1, 4)
+ end
+
+ it "parses a year in YYYY format" do
+ Date.strptime("2007", "%Y").should == Date.civil(2007, 1, 1)
+ end
+
+ it "parses a year in YY format" do
+ Date.strptime("00", "%y").should == Date.civil(2000, 1, 1)
+ end
+
+ ############################
+ # Specs that combine stuff #
+ ############################
+
+ it "parses a full date" do
+ Date.strptime("Thu Apr 6 00:00:00 2000", "%c").should == Date.civil(2000, 4, 6)
+ Date.strptime("Thu Apr 6 00:00:00 2000", "%a %b %e %H:%M:%S %Y").should == Date.civil(2000, 4, 6)
+ end
+
+ it "parses a date with slashes" do
+ Date.strptime("04/06/00", "%D").should == Date.civil(2000, 4, 6)
+ Date.strptime("04/06/00", "%m/%d/%y").should == Date.civil(2000, 4, 6)
+ end
+
+ it "parses a date given as YYYY-MM-DD" do
+ Date.strptime("2000-04-06", "%F").should == Date.civil(2000, 4, 6)
+ Date.strptime("2000-04-06", "%Y-%m-%d").should == Date.civil(2000, 4, 6)
+ end
+
+ it "parses a commercial week" do
+ Date.strptime(" 9-Apr-2000", "%v").should == Date.civil(2000, 4, 9)
+ Date.strptime(" 9-Apr-2000", "%e-%b-%Y").should == Date.civil(2000, 4, 9)
+ end
+
+ it "parses a date given MM/DD/YY" do
+ Date.strptime("04/06/00", "%x").should == Date.civil(2000, 4, 6)
+ Date.strptime("04/06/00", "%m/%d/%y").should == Date.civil(2000, 4, 6)
+ end
+
+ it "parses a date given in full notation" do
+ Date.strptime("Sun Apr 9 00:00:00 +00:00 2000", "%+").should == Date.civil(2000, 4, 9)
+ Date.strptime("Sun Apr 9 00:00:00 +00:00 2000", "%a %b %e %H:%M:%S %Z %Y").should == Date.civil(2000, 4, 9)
+ end
+
+end
+
+describe "Date.strptime" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/succ_spec.rb b/spec/ruby/library/date/succ_spec.rb
new file mode 100644
index 0000000000..2650810e73
--- /dev/null
+++ b/spec/ruby/library/date/succ_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#succ" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/time_to_day_fraction_spec.rb b/spec/ruby/library/date/time_to_day_fraction_spec.rb
new file mode 100644
index 0000000000..06d477b601
--- /dev/null
+++ b/spec/ruby/library/date/time_to_day_fraction_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.time_to_day_fraction" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/to_s_spec.rb b/spec/ruby/library/date/to_s_spec.rb
new file mode 100644
index 0000000000..a81297d689
--- /dev/null
+++ b/spec/ruby/library/date/to_s_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#to_s" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/today_spec.rb b/spec/ruby/library/date/today_spec.rb
new file mode 100644
index 0000000000..09e8ed6006
--- /dev/null
+++ b/spec/ruby/library/date/today_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.today" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/upto_spec.rb b/spec/ruby/library/date/upto_spec.rb
new file mode 100644
index 0000000000..c99aabd1d7
--- /dev/null
+++ b/spec/ruby/library/date/upto_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#upto" do
+ it "returns future dates for the default step value" do
+ ds = Date.civil(2008, 10, 11)
+ de = Date.civil(2008, 9, 29)
+ count = 0
+ de.upto(ds) do |d|
+ d.should <= ds
+ d.should >= de
+ count += 1
+ end
+ count.should == 13
+ end
+end
diff --git a/spec/ruby/library/date/valid_civil_spec.rb b/spec/ruby/library/date/valid_civil_spec.rb
new file mode 100644
index 0000000000..09185674ee
--- /dev/null
+++ b/spec/ruby/library/date/valid_civil_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/valid_civil', __FILE__)
+require 'date'
+
+describe "Date#valid_civil?" do
+
+ it_behaves_like :date_valid_civil?, :valid_civil?
+
+end
+
diff --git a/spec/ruby/library/date/valid_commercial_spec.rb b/spec/ruby/library/date/valid_commercial_spec.rb
new file mode 100644
index 0000000000..187d818233
--- /dev/null
+++ b/spec/ruby/library/date/valid_commercial_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/valid_commercial', __FILE__)
+require 'date'
+
+describe "Date#valid_commercial?" do
+
+ it_behaves_like :date_valid_commercial?, :valid_commercial?
+end
+
+
diff --git a/spec/ruby/library/date/valid_date_spec.rb b/spec/ruby/library/date/valid_date_spec.rb
new file mode 100644
index 0000000000..ffaf007cd1
--- /dev/null
+++ b/spec/ruby/library/date/valid_date_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/valid_civil', __FILE__)
+require 'date'
+
+describe "Date#valid_date?" do
+ it_behaves_like :date_valid_civil?, :valid_date?
+end
diff --git a/spec/ruby/library/date/valid_jd_spec.rb b/spec/ruby/library/date/valid_jd_spec.rb
new file mode 100644
index 0000000000..9764c02f2b
--- /dev/null
+++ b/spec/ruby/library/date/valid_jd_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/valid_jd', __FILE__)
+require 'date'
+
+describe "Date.valid_jd?" do
+
+ it_behaves_like :date_valid_jd?, :valid_jd?
+
+end
+
diff --git a/spec/ruby/library/date/valid_ordinal_spec.rb b/spec/ruby/library/date/valid_ordinal_spec.rb
new file mode 100644
index 0000000000..e197bb2051
--- /dev/null
+++ b/spec/ruby/library/date/valid_ordinal_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/valid_ordinal', __FILE__)
+require 'date'
+
+describe "Date.valid_ordinal?" do
+
+ it_behaves_like :date_valid_ordinal?, :valid_ordinal?
+
+end
+
diff --git a/spec/ruby/library/date/valid_time_spec.rb b/spec/ruby/library/date/valid_time_spec.rb
new file mode 100644
index 0000000000..e96f9041b7
--- /dev/null
+++ b/spec/ruby/library/date/valid_time_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.valid_time?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/wday_spec.rb b/spec/ruby/library/date/wday_spec.rb
new file mode 100644
index 0000000000..1d40b0c96c
--- /dev/null
+++ b/spec/ruby/library/date/wday_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#wday" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/yday_spec.rb b/spec/ruby/library/date/yday_spec.rb
new file mode 100644
index 0000000000..92bf616406
--- /dev/null
+++ b/spec/ruby/library/date/yday_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#yday" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/year_spec.rb b/spec/ruby/library/date/year_spec.rb
new file mode 100644
index 0000000000..cca95dbe2a
--- /dev/null
+++ b/spec/ruby/library/date/year_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#year" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/date/zone_to_diff_spec.rb b/spec/ruby/library/date/zone_to_diff_spec.rb
new file mode 100644
index 0000000000..a39de0b58e
--- /dev/null
+++ b/spec/ruby/library/date/zone_to_diff_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date.zone_to_diff" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/_strptime_spec.rb b/spec/ruby/library/datetime/_strptime_spec.rb
new file mode 100644
index 0000000000..c8c910618d
--- /dev/null
+++ b/spec/ruby/library/datetime/_strptime_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime._strptime" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/civil_spec.rb b/spec/ruby/library/datetime/civil_spec.rb
new file mode 100644
index 0000000000..77df021e33
--- /dev/null
+++ b/spec/ruby/library/datetime/civil_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.civil" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/commercial_spec.rb b/spec/ruby/library/datetime/commercial_spec.rb
new file mode 100644
index 0000000000..2984dd5334
--- /dev/null
+++ b/spec/ruby/library/datetime/commercial_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.commercial" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/hour_spec.rb b/spec/ruby/library/datetime/hour_spec.rb
new file mode 100644
index 0000000000..db89016937
--- /dev/null
+++ b/spec/ruby/library/datetime/hour_spec.rb
@@ -0,0 +1,47 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#hour" do
+ it "returns 0 if no argument is passed" do
+ DateTime.new.hour.should == 0
+ end
+
+ it "returns the hour given as argument" do
+ new_datetime(hour: 5).hour.should == 5
+ end
+
+ it "adds 24 to negative hours" do
+ new_datetime(hour: -10).hour.should == 14
+ end
+
+ it "raises an error for Rational" do
+ lambda { new_datetime(hour: 1 + Rational(1,2)) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error for Float" do
+ lambda { new_datetime(hour: 1.5).hour }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error for Rational" do
+ lambda { new_datetime(day: 1 + Rational(1,2)) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error, when the hour is smaller than -24" do
+ lambda { new_datetime(hour: -25) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error, when the hour is larger than 24" do
+ lambda { new_datetime(hour: 25) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error for hour fractions smaller than -24" do
+ lambda { new_datetime(hour: -24 - Rational(1,2)) }.should(
+ raise_error(ArgumentError))
+ end
+
+ it "adds 1 to day, when 24 hours given" do
+ d = new_datetime day: 1, hour: 24
+ d.hour.should == 0
+ d.day.should == 2
+ end
+end
diff --git a/spec/ruby/library/datetime/httpdate_spec.rb b/spec/ruby/library/datetime/httpdate_spec.rb
new file mode 100644
index 0000000000..e97fda7fb4
--- /dev/null
+++ b/spec/ruby/library/datetime/httpdate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.httpdate" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/iso8601_spec.rb b/spec/ruby/library/datetime/iso8601_spec.rb
new file mode 100644
index 0000000000..44887148d3
--- /dev/null
+++ b/spec/ruby/library/datetime/iso8601_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.iso8601" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "DateTime#iso8601" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/jd_spec.rb b/spec/ruby/library/datetime/jd_spec.rb
new file mode 100644
index 0000000000..e8271089f7
--- /dev/null
+++ b/spec/ruby/library/datetime/jd_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.jd" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/jisx0301_spec.rb b/spec/ruby/library/datetime/jisx0301_spec.rb
new file mode 100644
index 0000000000..2402a21cb0
--- /dev/null
+++ b/spec/ruby/library/datetime/jisx0301_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.jisx0301" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "DateTime#jisx0301" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/min_spec.rb b/spec/ruby/library/datetime/min_spec.rb
new file mode 100644
index 0000000000..5f7d7e7810
--- /dev/null
+++ b/spec/ruby/library/datetime/min_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/min', __FILE__)
+
+describe "DateTime.min" do
+ it_behaves_like :datetime_min, :min
+end
diff --git a/spec/ruby/library/datetime/minute_spec.rb b/spec/ruby/library/datetime/minute_spec.rb
new file mode 100644
index 0000000000..3ab01572fe
--- /dev/null
+++ b/spec/ruby/library/datetime/minute_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/min', __FILE__)
+
+describe "DateTime.minute" do
+ it_behaves_like :datetime_min, :minute
+end
diff --git a/spec/ruby/library/datetime/new_offset_spec.rb b/spec/ruby/library/datetime/new_offset_spec.rb
new file mode 100644
index 0000000000..b900de6097
--- /dev/null
+++ b/spec/ruby/library/datetime/new_offset_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#new_offset" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/new_spec.rb b/spec/ruby/library/datetime/new_spec.rb
new file mode 100644
index 0000000000..a8275a1951
--- /dev/null
+++ b/spec/ruby/library/datetime/new_spec.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.new" do
+ it "sets all values to default if passed no arguments" do
+ d = DateTime.new
+ d.year.should == -4712
+ d.month.should == 1
+ d.day.should == 1
+ d.hour.should == 0
+ d.min.should == 0
+ d.sec.should == 0
+ d.sec_fraction.should == 0
+ d.offset.should == 0
+ end
+
+ it "takes the first argument as year" do
+ DateTime.new(2011).year.should == 2011
+ end
+
+ it "takes the second argument as month" do
+ DateTime.new(2011, 2).month.should == 2
+ end
+
+ it "takes the third argument as day" do
+ DateTime.new(2011, 2, 3).day.should == 3
+ end
+
+ it "takes the forth argument as hour" do
+ DateTime.new(2011, 2, 3, 4).hour.should == 4
+ end
+
+ it "takes the fifth argument as minute" do
+ DateTime.new(1, 2, 3, 4, 5).min.should == 5
+ end
+
+ it "takes the sixth argument as second" do
+ DateTime.new(1, 2, 3, 4, 5, 6).sec.should == 6
+ end
+
+ it "takes the seventh argument as an offset" do
+ DateTime.new(1, 2, 3, 4, 5, 6, 0.7).offset.should == 0.7
+ end
+
+ it "takes the eigth argument as the date of calendar reform" do
+ DateTime.new(1, 2, 3, 4, 5, 6, 0.7, Date::ITALY).start().should == Date::ITALY
+ end
+
+ it "raises an error on invalid arguments" do
+ lambda { new_datetime(minute: 999) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/datetime/now_spec.rb b/spec/ruby/library/datetime/now_spec.rb
new file mode 100644
index 0000000000..e8c93aa604
--- /dev/null
+++ b/spec/ruby/library/datetime/now_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.now" do
+ it "creates an instance of DateTime" do
+ DateTime.now.should be_an_instance_of(DateTime)
+ end
+end
diff --git a/spec/ruby/library/datetime/offset_spec.rb b/spec/ruby/library/datetime/offset_spec.rb
new file mode 100644
index 0000000000..c11d28bad2
--- /dev/null
+++ b/spec/ruby/library/datetime/offset_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#offset" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/ordinal_spec.rb b/spec/ruby/library/datetime/ordinal_spec.rb
new file mode 100644
index 0000000000..2ada512e05
--- /dev/null
+++ b/spec/ruby/library/datetime/ordinal_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.ordinal" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/parse_spec.rb b/spec/ruby/library/datetime/parse_spec.rb
new file mode 100644
index 0000000000..14a68f1499
--- /dev/null
+++ b/spec/ruby/library/datetime/parse_spec.rb
@@ -0,0 +1,127 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.parse" do
+
+ it "parses a day name into a DateTime object" do
+ d = DateTime.parse("friday")
+ d.should == DateTime.commercial(d.cwyear, d.cweek, 5)
+ end
+
+ it "parses a month name into a DateTime object" do
+ d = DateTime.parse("october")
+ d.should == DateTime.civil(Date.today.year, 10)
+ end
+
+ it "parses a month day into a DateTime object" do
+ d = DateTime.parse("5th")
+ d.should == DateTime.civil(Date.today.year, Date.today.month, 5)
+ end
+
+ # Specs using numbers
+ it "throws an argument error for a single digit" do
+ lambda{ DateTime.parse("1") }.should raise_error(ArgumentError)
+ end
+
+ it "parses DD as month day number" do
+ d = DateTime.parse("10")
+ d.should == DateTime.civil(Date.today.year, Date.today.month, 10)
+ end
+
+ it "parses DDD as year day number" do
+ d = DateTime.parse("100")
+ if DateTime.gregorian_leap?(Date.today.year)
+ d.should == DateTime.civil(Date.today.year, 4, 9)
+ else
+ d.should == DateTime.civil(Date.today.year, 4, 10)
+ end
+ end
+
+ it "parses MMDD as month and day" do
+ d = DateTime.parse("1108")
+ d.should == DateTime.civil(Date.today.year, 11, 8)
+ end
+
+ it "parses YYYYMMDD as year, month and day" do
+ d = DateTime.parse("20121108")
+ d.should == DateTime.civil(2012, 11, 8)
+ end
+
+ describe "YYYY-MM-DDTHH:MM:SS format" do
+ it "parses YYYY-MM-DDTHH:MM:SS into a DateTime object" do
+ d = DateTime.parse("2012-11-08T15:43:59")
+ d.should == DateTime.civil(2012, 11, 8, 15, 43, 59)
+ end
+
+ it "throws an argument error for invalid month values" do
+ lambda{DateTime.parse("2012-13-08T15:43:59")}.should raise_error(ArgumentError)
+ end
+
+ it "throws an argument error for invalid day values" do
+ lambda{DateTime.parse("2012-12-32T15:43:59")}.should raise_error(ArgumentError)
+ end
+
+ it "throws an argument error for invalid hour values" do
+ lambda{DateTime.parse("2012-12-31T25:43:59")}.should raise_error(ArgumentError)
+ end
+
+ it "throws an argument error for invalid minute values" do
+ lambda{DateTime.parse("2012-12-31T25:43:59")}.should raise_error(ArgumentError)
+ end
+
+ it "throws an argument error for invalid second values" do
+ lambda{DateTime.parse("2012-11-08T15:43:61")}.should raise_error(ArgumentError)
+ end
+
+ end
+
+ it "parses YYDDD as year and day number in 1969--2068" do
+ d = DateTime.parse("10100")
+ d.should == DateTime.civil(2010, 4, 10)
+ end
+
+ it "parses YYMMDD as year, month and day in 1969--2068" do
+ d = DateTime.parse("201023")
+ d.should == DateTime.civil(2020, 10, 23)
+ end
+
+ it "parses YYYYDDD as year and day number" do
+ d = DateTime.parse("1910100")
+ d.should == DateTime.civil(1910, 4, 10)
+ end
+
+ it "parses YYYYMMDD as year, month and day number" do
+ d = DateTime.parse("19101101")
+ d.should == DateTime.civil(1910, 11, 1)
+ end
+end
+
+describe "DateTime.parse(.)" do
+ it "parses YYYY.MM.DD into a DateTime object" do
+ d = DateTime.parse("2007.10.01")
+ d.year.should == 2007
+ d.month.should == 10
+ d.day.should == 1
+ end
+
+ it "parses DD.MM.YYYY into a DateTime object" do
+ d = DateTime.parse("10.01.2007")
+ d.year.should == 2007
+ d.month.should == 1
+ d.day.should == 10
+ end
+
+ it "parses YY.MM.DD into a DateTime object using the year 20YY" do
+ d = DateTime.parse("10.01.07")
+ d.year.should == 2010
+ d.month.should == 1
+ d.day.should == 7
+ end
+
+ it "parses YY.MM.DD using the year digits as 20YY when given true as additional argument" do
+ d = DateTime.parse("10.01.07", true)
+ d.year.should == 2010
+ d.month.should == 1
+ d.day.should == 7
+ end
+end
diff --git a/spec/ruby/library/datetime/rfc2822_spec.rb b/spec/ruby/library/datetime/rfc2822_spec.rb
new file mode 100644
index 0000000000..3fc4dc14b8
--- /dev/null
+++ b/spec/ruby/library/datetime/rfc2822_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.rfc2822" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/rfc3339_spec.rb b/spec/ruby/library/datetime/rfc3339_spec.rb
new file mode 100644
index 0000000000..4fea795d9e
--- /dev/null
+++ b/spec/ruby/library/datetime/rfc3339_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.rfc3339" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "DateTime#rfc3339" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/rfc822_spec.rb b/spec/ruby/library/datetime/rfc822_spec.rb
new file mode 100644
index 0000000000..f86ee77379
--- /dev/null
+++ b/spec/ruby/library/datetime/rfc822_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.rfc822" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/sec_fraction_spec.rb b/spec/ruby/library/datetime/sec_fraction_spec.rb
new file mode 100644
index 0000000000..3ed274a5bc
--- /dev/null
+++ b/spec/ruby/library/datetime/sec_fraction_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#sec_fraction" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/sec_spec.rb b/spec/ruby/library/datetime/sec_spec.rb
new file mode 100644
index 0000000000..c7e9af2650
--- /dev/null
+++ b/spec/ruby/library/datetime/sec_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/sec', __FILE__)
+
+describe "DateTime.sec" do
+ it_behaves_like :datetime_sec, :sec
+end
diff --git a/spec/ruby/library/datetime/second_fraction_spec.rb b/spec/ruby/library/datetime/second_fraction_spec.rb
new file mode 100644
index 0000000000..32dc9333f6
--- /dev/null
+++ b/spec/ruby/library/datetime/second_fraction_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#second_fraction" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/second_spec.rb b/spec/ruby/library/datetime/second_spec.rb
new file mode 100644
index 0000000000..08cdf463f7
--- /dev/null
+++ b/spec/ruby/library/datetime/second_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/sec', __FILE__)
+
+describe "DateTime#second" do
+ it_behaves_like :datetime_sec, :second
+end
diff --git a/spec/ruby/library/datetime/shared/min.rb b/spec/ruby/library/datetime/shared/min.rb
new file mode 100644
index 0000000000..e69d86ab02
--- /dev/null
+++ b/spec/ruby/library/datetime/shared/min.rb
@@ -0,0 +1,40 @@
+require 'date'
+
+describe :datetime_min, shared: true do
+ it "returns 0 if no argument is passed" do
+ DateTime.new.send(@method).should == 0
+ end
+
+ it "returns the minute passed as argument" do
+ new_datetime(minute: 5).send(@method).should == 5
+ end
+
+ it "adds 60 to negative minutes" do
+ new_datetime(minute: -20).send(@method).should == 40
+ end
+
+ it "raises an error for Rational" do
+ lambda { new_datetime minute: 5 + Rational(1,2) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error for Float" do
+ lambda { new_datetime minute: 5.5 }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error for Rational" do
+ lambda { new_datetime(hour: 2 + Rational(1,2)) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error, when the minute is smaller than -60" do
+ lambda { new_datetime(minute: -61) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error, when the minute is greater or equal than 60" do
+ lambda { new_datetime(minute: 60) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error for minute fractions smaller than -60" do
+ lambda { new_datetime(minute: -60 - Rational(1,2))}.should(
+ raise_error(ArgumentError))
+ end
+end
diff --git a/spec/ruby/library/datetime/shared/sec.rb b/spec/ruby/library/datetime/shared/sec.rb
new file mode 100644
index 0000000000..68e8af8e40
--- /dev/null
+++ b/spec/ruby/library/datetime/shared/sec.rb
@@ -0,0 +1,45 @@
+require 'date'
+
+describe :datetime_sec, shared: true do
+ it "returns 0 seconds if passed no arguments" do
+ d = DateTime.new
+ d.send(@method).should == 0
+ end
+
+ it "returns the seconds passed in the arguments" do
+ new_datetime(second: 5).send(@method).should == 5
+ end
+
+ it "adds 60 to negative values" do
+ new_datetime(second: -20).send(@method).should == 40
+ end
+
+ it "returns the absolute value of a Rational" do
+ new_datetime(second: 5 + Rational(1,2)).send(@method).should == 5
+ end
+
+ it "returns the absolute value of a float" do
+ new_datetime(second: 5.5).send(@method).should == 5
+ end
+
+ it "raises an error when minute is given as a rational" do
+ lambda { new_datetime(minute: 5 + Rational(1,2)) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error, when the second is smaller than -60" do
+ lambda { new_datetime(second: -61) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error, when the second is greater or equal than 60" do
+ lambda { new_datetime(second: 60) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error for second fractions smaller than -60" do
+ lambda { new_datetime(second: -60 - Rational(1,2))}.should(
+ raise_error(ArgumentError))
+ end
+
+ it "takes a second fraction near 60" do
+ new_datetime(second: 59 + Rational(1,2)).send(@method).should == 59
+ end
+end
diff --git a/spec/ruby/library/datetime/strftime_spec.rb b/spec/ruby/library/datetime/strftime_spec.rb
new file mode 100644
index 0000000000..37705788a1
--- /dev/null
+++ b/spec/ruby/library/datetime/strftime_spec.rb
@@ -0,0 +1,51 @@
+require 'date'
+require File.expand_path('../../../shared/time/strftime_for_date', __FILE__)
+require File.expand_path('../../../shared/time/strftime_for_time', __FILE__)
+
+describe "DateTime#strftime" do
+ before :all do
+ @new_date = lambda { |y,m,d| DateTime.civil(y,m,d) }
+ @new_time = lambda { |*args| DateTime.civil(*args) }
+ @new_time_in_zone = lambda { |zone,offset,*args|
+ y, m, d, h, min, s = args
+ DateTime.new(y, m||1, d||1, h||0, min||0, s||0, Rational(offset, 24))
+ }
+ @new_time_with_offset = lambda { |y,m,d,h,min,s,offset|
+ DateTime.new(y,m,d,h,min,s, Rational(offset, 86_400))
+ }
+
+ @time = DateTime.civil(2001, 2, 3, 4, 5, 6)
+ end
+
+ it_behaves_like :strftime_date, :strftime
+ it_behaves_like :strftime_time, :strftime
+
+ # Differences with Time
+ it "should be able to print the datetime with no argument" do
+ @time.strftime.should == "2001-02-03T04:05:06+00:00"
+ @time.strftime.should == @time.to_s
+ end
+
+ # %Z is %:z for Date/DateTime
+ it "should be able to show the timezone with a : separator" do
+ @time.strftime("%Z").should == "+00:00"
+ end
+
+ # %v is %e-%b-%Y for Date/DateTime
+ it "should be able to show the commercial week" do
+ @time.strftime("%v").should == " 3-Feb-2001"
+ @time.strftime("%v").should == @time.strftime('%e-%b-%Y')
+ end
+
+ # additional conversion specifiers only in Date/DateTime
+ it 'shows the number of milliseconds since epoch' do
+ DateTime.new(1970, 1, 1, 0, 0, 0).strftime("%Q").should == "0"
+ @time.strftime("%Q").should == "981173106000"
+ DateTime.civil(2001, 2, 3, 4, 5, Rational(6123, 1000)).strftime("%Q").should == "981173106123"
+ end
+
+ it "should be able to show a full notation" do
+ @time.strftime("%+").should == "Sat Feb 3 04:05:06 +00:00 2001"
+ @time.strftime("%+").should == @time.strftime('%a %b %e %H:%M:%S %Z %Y')
+ end
+end
diff --git a/spec/ruby/library/datetime/strptime_spec.rb b/spec/ruby/library/datetime/strptime_spec.rb
new file mode 100644
index 0000000000..f3098f6f6b
--- /dev/null
+++ b/spec/ruby/library/datetime/strptime_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.strptime" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/to_date_spec.rb b/spec/ruby/library/datetime/to_date_spec.rb
new file mode 100644
index 0000000000..915e1ac87a
--- /dev/null
+++ b/spec/ruby/library/datetime/to_date_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#to_date" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/to_datetime_spec.rb b/spec/ruby/library/datetime/to_datetime_spec.rb
new file mode 100644
index 0000000000..e289f8ce36
--- /dev/null
+++ b/spec/ruby/library/datetime/to_datetime_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#to_datetime" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/to_s_spec.rb b/spec/ruby/library/datetime/to_s_spec.rb
new file mode 100644
index 0000000000..893cc93283
--- /dev/null
+++ b/spec/ruby/library/datetime/to_s_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#to_s" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/to_time_spec.rb b/spec/ruby/library/datetime/to_time_spec.rb
new file mode 100644
index 0000000000..aa2902930c
--- /dev/null
+++ b/spec/ruby/library/datetime/to_time_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#to_time" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/xmlschema_spec.rb b/spec/ruby/library/datetime/xmlschema_spec.rb
new file mode 100644
index 0000000000..5f33d33436
--- /dev/null
+++ b/spec/ruby/library/datetime/xmlschema_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime.xmlschema" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "DateTime#xmlschema" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/datetime/zone_spec.rb b/spec/ruby/library/datetime/zone_spec.rb
new file mode 100644
index 0000000000..fa8c9a982d
--- /dev/null
+++ b/spec/ruby/library/datetime/zone_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "DateTime#zone" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/delegate/delegate_class/instance_method_spec.rb b/spec/ruby/library/delegate/delegate_class/instance_method_spec.rb
new file mode 100644
index 0000000000..61680b9d5a
--- /dev/null
+++ b/spec/ruby/library/delegate/delegate_class/instance_method_spec.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "DelegateClass.instance_method" do
+ before :all do
+ @klass = DelegateSpecs::DelegateClass
+ @obj = @klass.new(DelegateSpecs::Simple.new)
+ end
+
+ it "returns a method object for public instance methods of the delegated class" do
+ m = @klass.instance_method(:pub)
+ m.should be_an_instance_of(UnboundMethod)
+ m.bind(@obj).call.should == :foo
+ end
+
+ it "returns a method object for protected instance methods of the delegated class" do
+ m = @klass.instance_method(:prot)
+ m.should be_an_instance_of(UnboundMethod)
+ m.bind(@obj).call.should == :protected
+ end
+
+ it "raises a NameError for a private instance methods of the delegated class" do
+ lambda {
+ @klass.instance_method(:priv)
+ }.should raise_error(NameError)
+ end
+
+ it "returns a method object for public instance methods of the DelegateClass class" do
+ m = @klass.instance_method(:extra)
+ m.should be_an_instance_of(UnboundMethod)
+ m.bind(@obj).call.should == :cheese
+ end
+
+ it "returns a method object for protected instance methods of the DelegateClass class" do
+ m = @klass.instance_method(:extra_protected)
+ m.should be_an_instance_of(UnboundMethod)
+ m.bind(@obj).call.should == :baz
+ end
+
+ it "returns a method object for private instance methods of the DelegateClass class" do
+ m = @klass.instance_method(:extra_private)
+ m.should be_an_instance_of(UnboundMethod)
+ m.bind(@obj).call.should == :bar
+ end
+
+ it "raises a NameError for an invalid method name" do
+ lambda {
+ @klass.instance_method(:invalid_and_silly_method_name)
+ }.should raise_error(NameError)
+ end
+
+end
diff --git a/spec/ruby/library/delegate/delegate_class/instance_methods_spec.rb b/spec/ruby/library/delegate/delegate_class/instance_methods_spec.rb
new file mode 100644
index 0000000000..ae329ab8eb
--- /dev/null
+++ b/spec/ruby/library/delegate/delegate_class/instance_methods_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "DelegateClass.instance_methods" do
+ before :all do
+ @methods = DelegateSpecs::DelegateClass.instance_methods
+ end
+
+ it "includes all public methods of the delegated class" do
+ @methods.should include :pub
+ end
+
+ it "includes all protected methods of the delegated class" do
+ @methods.should include :prot
+ end
+
+ it "includes instance methods of the DelegateClass class" do
+ @methods.should include :extra
+ @methods.should include :extra_protected
+ end
+
+ it "does not include private methods" do
+ @methods.should_not include :priv
+ @methods.should_not include :extra_private
+ end
+end
diff --git a/spec/ruby/library/delegate/delegate_class/private_instance_methods_spec.rb b/spec/ruby/library/delegate/delegate_class/private_instance_methods_spec.rb
new file mode 100644
index 0000000000..d93b6d0e3d
--- /dev/null
+++ b/spec/ruby/library/delegate/delegate_class/private_instance_methods_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "DelegateClass.private_instance_methods" do
+ before :all do
+ @methods = DelegateSpecs::DelegateClass.private_instance_methods
+ end
+
+ it "does not include any instance methods of the delegated class" do
+ @methods.should_not include :pub
+ @methods.should_not include :prot
+ @methods.should_not include :priv # since these are not forwarded...
+ end
+
+ it "includes private instance methods of the DelegateClass class" do
+ @methods.should include :extra_private
+ end
+
+ it "does not include public or protected instance methods of the DelegateClass class" do
+ @methods.should_not include :extra
+ @methods.should_not include :extra_protected
+ end
+end
diff --git a/spec/ruby/library/delegate/delegate_class/protected_instance_methods_spec.rb b/spec/ruby/library/delegate/delegate_class/protected_instance_methods_spec.rb
new file mode 100644
index 0000000000..3ae0270dbd
--- /dev/null
+++ b/spec/ruby/library/delegate/delegate_class/protected_instance_methods_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "DelegateClass.protected_instance_methods" do
+ before :all do
+ @methods = DelegateSpecs::DelegateClass.protected_instance_methods
+ end
+
+ it "does not include public methods of the delegated class" do
+ @methods.should_not include :pub
+ end
+
+ it "includes the protected methods of the delegated class" do
+ @methods.should include :prot
+ end
+
+ it "includes protected instance methods of the DelegateClass class" do
+ @methods.should include :extra_protected
+ end
+
+ it "does not include public instance methods of the DelegateClass class" do
+ @methods.should_not include :extra
+ end
+
+ it "does not include private methods" do
+ @methods.should_not include :priv
+ @methods.should_not include :extra_private
+ end
+end
diff --git a/spec/ruby/library/delegate/delegate_class/public_instance_methods_spec.rb b/spec/ruby/library/delegate/delegate_class/public_instance_methods_spec.rb
new file mode 100644
index 0000000000..e06b55612e
--- /dev/null
+++ b/spec/ruby/library/delegate/delegate_class/public_instance_methods_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "DelegateClass.public_instance_methods" do
+ before :all do
+ @methods = DelegateSpecs::DelegateClass.public_instance_methods
+ end
+
+ it "includes all public methods of the delegated class" do
+ @methods.should include :pub
+ end
+
+ it "does not include the protected methods of the delegated class" do
+ @methods.should_not include :prot
+ end
+
+ it "includes public instance methods of the DelegateClass class" do
+ @methods.should include :extra
+ end
+
+ it "does not include private methods" do
+ @methods.should_not include :priv
+ @methods.should_not include :extra_private
+ end
+end
diff --git a/spec/ruby/library/delegate/delegate_class/respond_to_missing_spec.rb b/spec/ruby/library/delegate/delegate_class/respond_to_missing_spec.rb
new file mode 100644
index 0000000000..729cfc96c6
--- /dev/null
+++ b/spec/ruby/library/delegate/delegate_class/respond_to_missing_spec.rb
@@ -0,0 +1,23 @@
+require 'delegate'
+
+describe "DelegateClass#respond_to_missing?" do
+ it "is used for respond_to? behavior of late-bound delegated methods" do
+ # From jruby/jruby#3151:
+ # DelegateClass subtracts Delegate's public API from the target class's instance_methods
+ # to determine which methods to eagerly delegate. If respond_to_missing? shows up in
+ # instance_methods, it will get delegated and skip the delegate-aware implementation
+ # in Delegate. Any methods that must be delegated through method_missing, like methods
+ # defined after the DelegateClass is created, will fail to dispatch properly.
+
+ cls = Class.new
+ dcls = DelegateClass(cls)
+ cdcls = Class.new(dcls)
+ cdcls_obj = cdcls.new(cls.new)
+
+ cdcls_obj.respond_to?(:foo).should == false
+
+ cls.class_eval { def foo; end }
+
+ cdcls_obj.respond_to?(:foo).should == true
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/case_compare_spec.rb b/spec/ruby/library/delegate/delegator/case_compare_spec.rb
new file mode 100644
index 0000000000..8bf79c1425
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/case_compare_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#===" do
+ it "is delegated" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
+ base.should_receive(:===).with(42).and_return(:foo)
+ (delegator === 42).should == :foo
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/compare_spec.rb b/spec/ruby/library/delegate/delegator/compare_spec.rb
new file mode 100644
index 0000000000..93431bfeb2
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/compare_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#<=>" do
+ it "is delegated" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
+ base.should_receive(:<=>).with(42).and_return(1)
+ (delegator <=> 42).should == 1
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/complement_spec.rb b/spec/ruby/library/delegate/delegator/complement_spec.rb
new file mode 100644
index 0000000000..877a6e99c6
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/complement_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#~" do
+ it "is delegated" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
+ base.should_receive(:~).and_return(:foo)
+ (~delegator).should == :foo
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/eql_spec.rb b/spec/ruby/library/delegate/delegator/eql_spec.rb
new file mode 100644
index 0000000000..fd6824ec55
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/eql_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#eql?" do
+ ruby_version_is ""..."2.5" do
+ it "is delegated" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
+ base.should_receive(:eql?).with(42).and_return(:foo)
+ delegator.eql?(42).should == :foo
+ end
+ end
+
+ ruby_version_is "2.5" do
+ it "returns true when compared with same delegator" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
+
+ delegator.eql?(delegator).should be_true
+ end
+
+ it "returns true when compared with the inner object" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
+
+ delegator.eql?(base).should be_true
+ end
+
+ it "returns false when compared with the delegator with other object" do
+ base = mock('base')
+ other = mock('other')
+ delegator0 = DelegateSpecs::Delegator.new(base)
+ delegator1 = DelegateSpecs::Delegator.new(other)
+
+ delegator0.eql?(delegator1).should be_false
+ end
+
+ it "returns false when compared with the other object" do
+ base = mock('base')
+ other = mock('other')
+ delegator = DelegateSpecs::Delegator.new(base)
+
+ delegator.eql?(other).should be_false
+ end
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/equal_spec.rb b/spec/ruby/library/delegate/delegator/equal_spec.rb
new file mode 100644
index 0000000000..9333d6a303
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/equal_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#equal?" do
+ it "returns true only when compared with the delegator" do
+ obj = mock('base')
+ delegator = DelegateSpecs::Delegator.new(obj)
+ obj.should_not_receive(:equal?)
+ delegator.equal?(obj).should be_false
+ delegator.equal?(nil).should be_false
+ delegator.equal?(delegator).should be_true
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/equal_value_spec.rb b/spec/ruby/library/delegate/delegator/equal_value_spec.rb
new file mode 100644
index 0000000000..7c965d77d3
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/equal_value_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#==" do
+ before :all do
+ @base = mock('base')
+ @delegator = DelegateSpecs::Delegator.new(@base)
+ end
+
+ it "is not delegated when passed self" do
+ @base.should_not_receive(:==)
+ (@delegator == @delegator).should be_true
+ end
+
+ it "is delegated when passed the delegated object" do
+ @base.should_receive(:==).and_return(false)
+ (@delegator == @base).should be_false
+ end
+
+ it "is delegated in general" do
+ @base.should_receive(:==).and_return(true)
+ (@delegator == 42).should be_true
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/frozen_spec.rb b/spec/ruby/library/delegate/delegator/frozen_spec.rb
new file mode 100644
index 0000000000..1fb561a349
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/frozen_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator when frozen" do
+ before :all do
+ @array = [42, :hello]
+ @delegate = DelegateSpecs::Delegator.new(@array)
+ @delegate.freeze
+ end
+
+ it "is still readable" do
+ @delegate.should == [42, :hello]
+ @delegate.include?("bar").should be_false
+ end
+
+ it "is frozen" do
+ @delegate.frozen?.should be_true
+ end
+
+ it "is not writeable" do
+ lambda{ @delegate[0] += 2 }.should raise_error( RuntimeError )
+ end
+
+ it "creates a frozen clone" do
+ @delegate.clone.frozen?.should be_true
+ end
+
+ it "creates an unfrozen dup" do
+ @delegate.dup.frozen?.should be_false
+ end
+
+ it "causes mutative calls to raise RuntimeError" do
+ lambda{ @delegate.__setobj__("hola!") }.should raise_error( RuntimeError )
+ end
+
+ it "returns false if only the delegated object is frozen" do
+ DelegateSpecs::Delegator.new([1,2,3].freeze).frozen?.should be_false
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/hash_spec.rb b/spec/ruby/library/delegate/delegator/hash_spec.rb
new file mode 100644
index 0000000000..3719d1b249
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/hash_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#hash" do
+ it "is delegated" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
+ base.should_receive(:hash).and_return(42)
+ delegator.hash.should == 42
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/marshal_spec.rb b/spec/ruby/library/delegate/delegator/marshal_spec.rb
new file mode 100644
index 0000000000..5af32b5754
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/marshal_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'delegate'
+
+describe "SimpleDelegator" do
+ before :all do
+ @obj = "hello"
+ @delegate = SimpleDelegator.new(@obj)
+ end
+
+ it "can be marshalled" do
+ m = Marshal.load(Marshal.dump(@delegate))
+ m.class.should == SimpleDelegator
+ (m == @obj).should be_true
+ end
+
+ it "can be marshalled with its instance variables intact" do
+ @delegate.instance_variable_set(:@foo, "bar")
+ m = Marshal.load(Marshal.dump(@delegate))
+ m.instance_variable_get(:@foo).should == "bar"
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/method_spec.rb b/spec/ruby/library/delegate/delegator/method_spec.rb
new file mode 100644
index 0000000000..1760eda645
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/method_spec.rb
@@ -0,0 +1,69 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#method" do
+ before :each do
+ @simple = DelegateSpecs::Simple.new
+ @delegate = DelegateSpecs::Delegator.new(@simple)
+ end
+
+ it "returns a method object for public methods of the delegate object" do
+ m = @delegate.method(:pub)
+ m.should be_an_instance_of(Method)
+ m.call.should == :foo
+ end
+
+ it "raises a NameError for protected methods of the delegate object" do
+ lambda {
+ -> {
+ @delegate.method(:prot)
+ }.should complain(/delegator does not forward private method #prot/)
+ }.should raise_error(NameError)
+ end
+
+ it "raises a NameError for a private methods of the delegate object" do
+ lambda {
+ -> {
+ @delegate.method(:priv)
+ }.should complain(/delegator does not forward private method #priv/)
+ }.should raise_error(NameError)
+ end
+
+ it "returns a method object for public methods of the Delegator class" do
+ m = @delegate.method(:extra)
+ m.should be_an_instance_of(Method)
+ m.call.should == :cheese
+ end
+
+ it "returns a method object for protected methods of the Delegator class" do
+ m = @delegate.method(:extra_protected)
+ m.should be_an_instance_of(Method)
+ m.call.should == :baz
+ end
+
+ it "returns a method object for private methods of the Delegator class" do
+ m = @delegate.method(:extra_private)
+ m.should be_an_instance_of(Method)
+ m.call.should == :bar
+ end
+
+ it "raises a NameError for an invalid method name" do
+ lambda {
+ @delegate.method(:invalid_and_silly_method_name)
+ }.should raise_error(NameError)
+ end
+
+ it "returns a method that respond_to_missing?" do
+ m = @delegate.method(:pub_too)
+ m.should be_an_instance_of(Method)
+ m.call.should == :pub_too
+ end
+
+ it "raises a NameError if method is no longer valid because object has changed" do
+ m = @delegate.method(:pub)
+ @delegate.__setobj__([1,2,3])
+ lambda {
+ m.call
+ }.should raise_error(NameError)
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/methods_spec.rb b/spec/ruby/library/delegate/delegator/methods_spec.rb
new file mode 100644
index 0000000000..91a6d68bfa
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/methods_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#methods" do
+ before :all do
+ @simple = DelegateSpecs::Simple.new
+ class << @simple
+ def singleton_method
+ end
+ end
+
+ @delegate = DelegateSpecs::Delegator.new(@simple)
+ @methods = @delegate.methods
+ end
+
+ it "returns singleton methods when passed false" do
+ @delegate.methods(false).should include(:singleton_method)
+ end
+
+ it "includes all public methods of the delegate object" do
+ @methods.should include :pub
+ end
+
+ it "includes all protected methods of the delegate object" do
+ @methods.should include :prot
+ end
+
+ it "includes instance methods of the Delegator class" do
+ @methods.should include :extra
+ @methods.should include :extra_protected
+ end
+
+ it "does not include private methods" do
+ @methods.should_not include :priv
+ @methods.should_not include :extra_private
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/not_equal_spec.rb b/spec/ruby/library/delegate/delegator/not_equal_spec.rb
new file mode 100644
index 0000000000..c2f91dcfa1
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/not_equal_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#!=" do
+ before :all do
+ @base = mock('base')
+ @delegator = DelegateSpecs::Delegator.new(@base)
+ end
+
+ it "is not delegated when passed self" do
+ @base.should_not_receive(:"!=")
+ (@delegator != @delegator).should be_false
+ end
+
+ it "is delegated when passed the delegated object" do
+ @base.should_receive(:"!=").and_return(true)
+ (@delegator != @base).should be_true
+ end
+
+ it "is delegated in general" do
+ @base.should_receive(:"!=").and_return(false)
+ (@delegator != 42).should be_false
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/not_spec.rb b/spec/ruby/library/delegate/delegator/not_spec.rb
new file mode 100644
index 0000000000..678e07e418
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/not_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#!" do
+ it "is delegated" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
+ base.should_receive(:"!").and_return(:foo)
+ (!delegator).should == :foo
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/private_methods_spec.rb b/spec/ruby/library/delegate/delegator/private_methods_spec.rb
new file mode 100644
index 0000000000..557da9bd02
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/private_methods_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#private_methods" do
+ before :all do
+ @simple = DelegateSpecs::Simple.new
+ @delegate = DelegateSpecs::Delegator.new(@simple)
+ @methods = @delegate.private_methods
+ end
+
+ it "does not include any method of the delegate object" do # since delegates does not forward private calls
+ @methods.should_not include :priv
+ @methods.should_not include :prot
+ @methods.should_not include :pub
+ end
+
+ it "includes all private instance methods of the Delegate class" do
+ @methods.should include :extra_private
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/protected_methods_spec.rb b/spec/ruby/library/delegate/delegator/protected_methods_spec.rb
new file mode 100644
index 0000000000..5f03575f25
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/protected_methods_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#protected_methods" do
+ before :all do
+ @simple = DelegateSpecs::Simple.new
+ @delegate = DelegateSpecs::Delegator.new(@simple)
+ @methods = @delegate.protected_methods
+ end
+
+ it "includes protected methods of the delegate object" do
+ @methods.should include :prot
+ end
+
+ it "includes protected instance methods of the Delegator class" do
+ @methods.should include :extra_protected
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/public_methods_spec.rb b/spec/ruby/library/delegate/delegator/public_methods_spec.rb
new file mode 100644
index 0000000000..4ed626be33
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/public_methods_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#public_methods" do
+ before :all do
+ @simple = DelegateSpecs::Simple.new
+ @delegate = DelegateSpecs::Delegator.new(@simple)
+ @methods = @delegate.public_methods
+ end
+
+ it "includes public methods of the delegate object" do
+ @methods.should include :pub
+ end
+
+ it "includes public instance methods of the Delegator class" do
+ @methods.should include :extra
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/send_spec.rb b/spec/ruby/library/delegate/delegator/send_spec.rb
new file mode 100644
index 0000000000..b6e66cb74a
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/send_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "SimpleDelegator.new" do
+ before :all do
+ @simple = DelegateSpecs::Simple.new
+ @delegate = SimpleDelegator.new(@simple)
+ end
+
+ it "forwards public method calls" do
+ @delegate.pub.should == :foo
+ end
+
+ it "forwards protected method calls" do
+ lambda{ @delegate.prot }.should raise_error( NoMethodError )
+ end
+
+ it "doesn't forward private method calls" do
+ lambda{ @delegate.priv }.should raise_error( NoMethodError )
+ end
+
+ it "doesn't forward private method calls even via send or __send__" do
+ lambda{ @delegate.send(:priv, 42) }.should raise_error( NoMethodError )
+ lambda{ @delegate.__send__(:priv, 42) }.should raise_error( NoMethodError )
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/taint_spec.rb b/spec/ruby/library/delegate/delegator/taint_spec.rb
new file mode 100644
index 0000000000..f78446d018
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/taint_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#taint" do
+ before :each do
+ @delegate = DelegateSpecs::Delegator.new("")
+ end
+
+ it "returns self" do
+ @delegate.taint.equal?(@delegate).should be_true
+ end
+
+ it "taints the delegator" do
+ @delegate.__setobj__(nil)
+ @delegate.taint
+ @delegate.tainted?.should be_true
+ end
+
+ it "taints the delegated object" do
+ @delegate.taint
+ @delegate.__getobj__.tainted?.should be_true
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/tap_spec.rb b/spec/ruby/library/delegate/delegator/tap_spec.rb
new file mode 100644
index 0000000000..1da6d82b01
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/tap_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#tap" do
+ it "yield the delegator object" do
+ obj = mock('base')
+ delegator = DelegateSpecs::Delegator.new(obj)
+ obj.should_not_receive(:tap)
+ yielded = []
+ delegator.tap do |x|
+ yielded << x
+ end
+ yielded.size.should == 1
+ yielded[0].equal?(delegator).should be_true
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/trust_spec.rb b/spec/ruby/library/delegate/delegator/trust_spec.rb
new file mode 100644
index 0000000000..182395c26e
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/trust_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#trust" do
+ before :each do
+ @delegate = DelegateSpecs::Delegator.new([])
+ end
+
+ it "returns self" do
+ @delegate.trust.equal?(@delegate).should be_true
+ end
+
+ it "trusts the delegator" do
+ @delegate.trust
+ @delegate.untrusted?.should be_false
+ end
+
+ it "trusts the delegated object" do
+ @delegate.trust
+ @delegate.__getobj__.untrusted?.should be_false
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/untaint_spec.rb b/spec/ruby/library/delegate/delegator/untaint_spec.rb
new file mode 100644
index 0000000000..2cce99e206
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/untaint_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#untaint" do
+ before :each do
+ @delegate = lambda { DelegateSpecs::Delegator.new("") }.call
+ end
+
+ it "returns self" do
+ @delegate.untaint.equal?(@delegate).should be_true
+ end
+
+ it "untaints the delegator" do
+ @delegate.untaint
+ @delegate.tainted?.should be_false
+ # No additional meaningful test; that it does or not taint
+ # "for real" the delegator has no consequence
+ end
+
+ it "untaints the delegated object" do
+ @delegate.untaint
+ @delegate.__getobj__.tainted?.should be_false
+ end
+end
diff --git a/spec/ruby/library/delegate/delegator/untrust_spec.rb b/spec/ruby/library/delegate/delegator/untrust_spec.rb
new file mode 100644
index 0000000000..e2bbf1b294
--- /dev/null
+++ b/spec/ruby/library/delegate/delegator/untrust_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Delegator#untrust" do
+ before :each do
+ @delegate = DelegateSpecs::Delegator.new("")
+ end
+
+ it "returns self" do
+ @delegate.untrust.equal?(@delegate).should be_true
+ end
+
+ it "untrusts the delegator" do
+ @delegate.__setobj__(nil)
+ @delegate.untrust
+ @delegate.untrusted?.should be_true
+ end
+
+ it "untrusts the delegated object" do
+ @delegate.untrust
+ @delegate.__getobj__.untrusted?.should be_true
+ end
+end
diff --git a/spec/ruby/library/delegate/fixtures/classes.rb b/spec/ruby/library/delegate/fixtures/classes.rb
new file mode 100644
index 0000000000..3cb43eb8b1
--- /dev/null
+++ b/spec/ruby/library/delegate/fixtures/classes.rb
@@ -0,0 +1,60 @@
+require 'delegate'
+module DelegateSpecs
+ class Simple
+ def pub
+ :foo
+ end
+
+ def respond_to_missing?(method, priv=false)
+ method == :pub_too ||
+ (priv && method == :priv_too)
+ end
+
+ def method_missing(method, *args)
+ super unless respond_to_missing?(method, true)
+ method
+ end
+
+ def priv(arg=nil)
+ yield arg if block_given?
+ [:priv, arg]
+ end
+ private :priv
+
+ def prot
+ :protected
+ end
+ protected :prot
+ end
+
+ module Extra
+ def extra
+ :cheese
+ end
+
+ def extra_private
+ :bar
+ end
+ private :extra_private
+
+ def extra_protected
+ :baz
+ end
+ protected :extra_protected
+ end
+
+ class Delegator < ::Delegator
+ attr_accessor :data
+
+ attr_reader :__getobj__
+ def __setobj__(o)
+ @__getobj__ = o
+ end
+
+ include Extra
+ end
+
+ class DelegateClass < DelegateClass(Simple)
+ include Extra
+ end
+end
diff --git a/spec/ruby/library/digest/bubblebabble_spec.rb b/spec/ruby/library/digest/bubblebabble_spec.rb
new file mode 100644
index 0000000000..49cc77e623
--- /dev/null
+++ b/spec/ruby/library/digest/bubblebabble_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'digest/bubblebabble'
+
+describe "Digest.bubblebabble" do
+ it "returns a String" do
+ Digest.bubblebabble('').should be_an_instance_of(String)
+ end
+
+ it "returns a String in the The Bubble Babble Binary Data Encoding format" do
+ Digest.bubblebabble('').should == 'xexax'
+ Digest.bubblebabble('foo').should == 'xinik-zorox'
+ Digest.bubblebabble('bar').should == 'ximik-cosex'
+ Digest.bubblebabble('1234567890').should == 'xesef-disof-gytuf-katof-movif-baxux'
+ end
+
+ it "calls #to_str on an object and returns the bubble babble value of the result" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return('foo')
+ Digest.bubblebabble(obj).should == 'xinik-zorox'
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { Digest.bubblebabble(nil) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed a Fixnum" do
+ lambda { Digest.bubblebabble(9001) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/digest/hexencode_spec.rb b/spec/ruby/library/digest/hexencode_spec.rb
new file mode 100644
index 0000000000..9e59e69fce
--- /dev/null
+++ b/spec/ruby/library/digest/hexencode_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'digest'
+
+describe "Digest.hexencode" do
+ before :each do
+ @string = 'sample string'
+ @encoded = "73616d706c6520737472696e67"
+ end
+
+ it "returns '' when passed an empty String" do
+ Digest.hexencode('').should == ''
+ end
+
+ it "returns the hex-encoded value of a non-empty String" do
+ Digest.hexencode(@string).should == @encoded
+ end
+
+ it "calls #to_str on an object and returns the hex-encoded value of the result" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return(@string)
+ Digest.hexencode(obj).should == @encoded
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { Digest.hexencode(nil) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed a Fixnum" do
+ lambda { Digest.hexencode(9001) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/digest/md5/append_spec.rb b/spec/ruby/library/digest/md5/append_spec.rb
new file mode 100644
index 0000000000..ad828c83c1
--- /dev/null
+++ b/spec/ruby/library/digest/md5/append_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/update', __FILE__)
+
+describe "Digest::MD5#<<" do
+ it_behaves_like(:md5_update, :<<)
+end
diff --git a/spec/ruby/library/digest/md5/block_length_spec.rb b/spec/ruby/library/digest/md5/block_length_spec.rb
new file mode 100644
index 0000000000..acc3108da4
--- /dev/null
+++ b/spec/ruby/library/digest/md5/block_length_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#block_length" do
+
+ it "returns the length of digest block" do
+ cur_digest = Digest::MD5.new
+ cur_digest.block_length.should == MD5Constants::BlockLength
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/md5/digest_bang_spec.rb b/spec/ruby/library/digest/md5/digest_bang_spec.rb
new file mode 100644
index 0000000000..88b865dcba
--- /dev/null
+++ b/spec/ruby/library/digest/md5/digest_bang_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#digest!" do
+
+ it "returns a digest and can digest!" do
+ cur_digest = Digest::MD5.new
+ cur_digest << MD5Constants::Contents
+ cur_digest.digest!().should == MD5Constants::Digest
+ cur_digest.digest().should == MD5Constants::BlankDigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/md5/digest_length_spec.rb b/spec/ruby/library/digest/md5/digest_length_spec.rb
new file mode 100644
index 0000000000..426e42af76
--- /dev/null
+++ b/spec/ruby/library/digest/md5/digest_length_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#digest_length" do
+
+ it "returns the length of computed digests" do
+ cur_digest = Digest::MD5.new
+ cur_digest.digest_length.should == MD5Constants::DigestLength
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/md5/digest_spec.rb b/spec/ruby/library/digest/md5/digest_spec.rb
new file mode 100644
index 0000000000..1568c630aa
--- /dev/null
+++ b/spec/ruby/library/digest/md5/digest_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#digest" do
+
+ it "returns a digest" do
+ cur_digest = Digest::MD5.new
+ cur_digest.digest().should == MD5Constants::BlankDigest
+
+ # add something to check that the state is reset later
+ cur_digest << "test"
+
+ cur_digest.digest(MD5Constants::Contents).should == MD5Constants::Digest
+ # second invocation is intentional, to make sure there are no side-effects
+ cur_digest.digest(MD5Constants::Contents).should == MD5Constants::Digest
+
+ # after all is done, verify that the digest is in the original, blank state
+ cur_digest.digest.should == MD5Constants::BlankDigest
+ end
+
+end
+
+describe "Digest::MD5.digest" do
+
+ it "returns a digest" do
+ Digest::MD5.digest(MD5Constants::Contents).should == MD5Constants::Digest
+ # second invocation is intentional, to make sure there are no side-effects
+ Digest::MD5.digest(MD5Constants::Contents).should == MD5Constants::Digest
+ Digest::MD5.digest("").should == MD5Constants::BlankDigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/md5/equal_spec.rb b/spec/ruby/library/digest/md5/equal_spec.rb
new file mode 100644
index 0000000000..0b776f53c0
--- /dev/null
+++ b/spec/ruby/library/digest/md5/equal_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#==" do
+
+ it "equals itself" do
+ cur_digest = Digest::MD5.new
+ cur_digest.should == cur_digest
+ end
+
+ it "equals the string representing its hexdigest" do
+ cur_digest = Digest::MD5.new
+ cur_digest.should == MD5Constants::BlankHexdigest
+ end
+
+ it "equals the appropriate object that responds to to_str" do
+ # blank digest
+ cur_digest = Digest::MD5.new
+ obj = mock(MD5Constants::BlankHexdigest)
+ obj.should_receive(:to_str).and_return(MD5Constants::BlankHexdigest)
+ cur_digest.should == obj
+
+ # non-blank digest
+ cur_digest = Digest::MD5.new
+ cur_digest << "test"
+ d_value = cur_digest.hexdigest
+ (obj = mock(d_value)).should_receive(:to_str).and_return(d_value)
+ cur_digest.should == obj
+ end
+
+ it "equals the same digest for a different object" do
+ cur_digest = Digest::MD5.new
+ cur_digest2 = Digest::MD5.new
+ cur_digest.should == cur_digest2
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/md5/file_spec.rb b/spec/ruby/library/digest/md5/file_spec.rb
new file mode 100644
index 0000000000..c7f4328546
--- /dev/null
+++ b/spec/ruby/library/digest/md5/file_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../../../../core/file/shared/read', __FILE__)
+
+describe "Digest::MD5.file" do
+
+ describe "when passed a path to a file that exists" do
+ before :each do
+ @file = tmp("md5_temp")
+ touch(@file, 'wb') {|f| f.write MD5Constants::Contents }
+ end
+
+ after :each do
+ rm_r @file
+ end
+
+ it "returns a Digest::MD5 object" do
+ Digest::MD5.file(@file).should be_kind_of(Digest::MD5)
+ end
+
+ it "returns a Digest::MD5 object with the correct digest" do
+ Digest::MD5.file(@file).digest.should == MD5Constants::Digest
+ end
+
+ it "calls #to_str on an object and returns the Digest::MD5 with the result" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return(@file)
+ result = Digest::MD5.file(obj)
+ result.should be_kind_of(Digest::MD5)
+ result.digest.should == MD5Constants::Digest
+ end
+ end
+
+ it_behaves_like :file_read_directory, :file, Digest::MD5
+
+ it "raises a Errno::ENOENT when passed a path that does not exist" do
+ lambda { Digest::MD5.file("") }.should raise_error(Errno::ENOENT)
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { Digest::MD5.file(nil) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/digest/md5/hexdigest_bang_spec.rb b/spec/ruby/library/digest/md5/hexdigest_bang_spec.rb
new file mode 100644
index 0000000000..fe67136c97
--- /dev/null
+++ b/spec/ruby/library/digest/md5/hexdigest_bang_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#hexdigest!" do
+
+ it "returns a hexdigest and resets the state" do
+ cur_digest = Digest::MD5.new
+
+ cur_digest << MD5Constants::Contents
+ cur_digest.hexdigest!.should == MD5Constants::Hexdigest
+ cur_digest.hexdigest.should == MD5Constants::BlankHexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/md5/hexdigest_spec.rb b/spec/ruby/library/digest/md5/hexdigest_spec.rb
new file mode 100644
index 0000000000..9caec29f38
--- /dev/null
+++ b/spec/ruby/library/digest/md5/hexdigest_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#hexdigest" do
+
+ it "returns a hexdigest" do
+ cur_digest = Digest::MD5.new
+ cur_digest.hexdigest.should == MD5Constants::BlankHexdigest
+
+ # add something to check that the state is reset later
+ cur_digest << "test"
+
+ cur_digest.hexdigest(MD5Constants::Contents).should == MD5Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ cur_digest.hexdigest(MD5Constants::Contents).should == MD5Constants::Hexdigest
+
+ # after all is done, verify that the digest is in the original, blank state
+ cur_digest.hexdigest.should == MD5Constants::BlankHexdigest
+ end
+
+end
+
+describe "Digest::MD5.hexdigest" do
+
+ it "returns a hexdigest" do
+ Digest::MD5.hexdigest(MD5Constants::Contents).should == MD5Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ Digest::MD5.hexdigest(MD5Constants::Contents).should == MD5Constants::Hexdigest
+ Digest::MD5.hexdigest("").should == MD5Constants::BlankHexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/md5/inspect_spec.rb b/spec/ruby/library/digest/md5/inspect_spec.rb
new file mode 100644
index 0000000000..e23465337a
--- /dev/null
+++ b/spec/ruby/library/digest/md5/inspect_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#inspect" do
+
+ it "returns a Ruby object representation" do
+ cur_digest = Digest::MD5.new
+ cur_digest.inspect.should == "#<#{MD5Constants::Klass}: #{cur_digest.hexdigest()}>"
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/md5/length_spec.rb b/spec/ruby/library/digest/md5/length_spec.rb
new file mode 100644
index 0000000000..13eaf2e8d5
--- /dev/null
+++ b/spec/ruby/library/digest/md5/length_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "Digest::MD5#length" do
+ it_behaves_like :md5_length, :length
+end
+
diff --git a/spec/ruby/library/digest/md5/reset_spec.rb b/spec/ruby/library/digest/md5/reset_spec.rb
new file mode 100644
index 0000000000..d95ecfaf8c
--- /dev/null
+++ b/spec/ruby/library/digest/md5/reset_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#reset" do
+
+ it "returns digest state to initial conditions" do
+ cur_digest = Digest::MD5.new
+ cur_digest.update MD5Constants::Contents
+ cur_digest.digest().should_not == MD5Constants::BlankDigest
+ cur_digest.reset
+ cur_digest.digest().should == MD5Constants::BlankDigest
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/md5/shared/constants.rb b/spec/ruby/library/digest/md5/shared/constants.rb
new file mode 100644
index 0000000000..fdfae56d63
--- /dev/null
+++ b/spec/ruby/library/digest/md5/shared/constants.rb
@@ -0,0 +1,16 @@
+# -*- encoding: binary -*-
+require 'digest/md5'
+
+module MD5Constants
+
+ Contents = "Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. \nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. \nIt was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
+
+ Klass = ::Digest::MD5
+ BlockLength = 64
+ DigestLength = 16
+ BlankDigest = "\324\035\214\331\217\000\262\004\351\200\t\230\354\370B~"
+ Digest = "\2473\267qw\276\364\343\345\320\304\350\313\314\217n"
+ BlankHexdigest = "d41d8cd98f00b204e9800998ecf8427e"
+ Hexdigest = "a733b77177bef4e3e5d0c4e8cbcc8f6e"
+
+end
diff --git a/spec/ruby/library/digest/md5/shared/length.rb b/spec/ruby/library/digest/md5/shared/length.rb
new file mode 100644
index 0000000000..c5b2b97b58
--- /dev/null
+++ b/spec/ruby/library/digest/md5/shared/length.rb
@@ -0,0 +1,8 @@
+describe :md5_length, shared: true do
+ it "returns the length of the digest" do
+ cur_digest = Digest::MD5.new
+ cur_digest.send(@method).should == MD5Constants::BlankDigest.size
+ cur_digest << MD5Constants::Contents
+ cur_digest.send(@method).should == MD5Constants::Digest.size
+ end
+end
diff --git a/spec/ruby/library/digest/md5/shared/sample.rb b/spec/ruby/library/digest/md5/shared/sample.rb
new file mode 100644
index 0000000000..2bb4f658b1
--- /dev/null
+++ b/spec/ruby/library/digest/md5/shared/sample.rb
@@ -0,0 +1,17 @@
+# -*- encoding: binary -*-
+
+require 'digest/md5'
+
+module MD5Constants
+
+ Contents = "Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. \nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. \nIt was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
+
+ Klass = ::Digest::MD5
+ BlockLength = 64
+ DigestLength = 16
+ BlankDigest = "\324\035\214\331\217\000\262\004\351\200\t\230\354\370B~"
+ Digest = "\2473\267qw\276\364\343\345\320\304\350\313\314\217n"
+ BlankHexdigest = "d41d8cd98f00b204e9800998ecf8427e"
+ Hexdigest = "a733b77177bef4e3e5d0c4e8cbcc8f6e"
+
+end
diff --git a/spec/ruby/library/digest/md5/shared/update.rb b/spec/ruby/library/digest/md5/shared/update.rb
new file mode 100644
index 0000000000..be8622aed5
--- /dev/null
+++ b/spec/ruby/library/digest/md5/shared/update.rb
@@ -0,0 +1,7 @@
+describe :md5_update, shared: true do
+ it "can update" do
+ cur_digest = Digest::MD5.new
+ cur_digest.send @method, MD5Constants::Contents
+ cur_digest.digest.should == MD5Constants::Digest
+ end
+end
diff --git a/spec/ruby/library/digest/md5/size_spec.rb b/spec/ruby/library/digest/md5/size_spec.rb
new file mode 100644
index 0000000000..311286e679
--- /dev/null
+++ b/spec/ruby/library/digest/md5/size_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "Digest::MD5#size" do
+ it_behaves_like :md5_length, :size
+end
+
diff --git a/spec/ruby/library/digest/md5/to_s_spec.rb b/spec/ruby/library/digest/md5/to_s_spec.rb
new file mode 100644
index 0000000000..59c17ec821
--- /dev/null
+++ b/spec/ruby/library/digest/md5/to_s_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+require 'digest/md5'
+
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::MD5#to_s" do
+
+ it "returns a hexdigest" do
+ cur_digest = Digest::MD5.new
+ cur_digest.to_s.should == MD5Constants::BlankHexdigest
+ end
+
+ it "does not change the internal state" do
+ cur_digest = Digest::MD5.new
+ cur_digest.to_s.should == MD5Constants::BlankHexdigest
+ cur_digest.to_s.should == MD5Constants::BlankHexdigest
+
+ cur_digest << MD5Constants::Contents
+ cur_digest.to_s.should == MD5Constants::Hexdigest
+ cur_digest.to_s.should == MD5Constants::Hexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/md5/update_spec.rb b/spec/ruby/library/digest/md5/update_spec.rb
new file mode 100644
index 0000000000..5a271481f7
--- /dev/null
+++ b/spec/ruby/library/digest/md5/update_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/update', __FILE__)
+
+describe "Digest::MD5#update" do
+ it_behaves_like :md5_update, :update
+end
diff --git a/spec/ruby/library/digest/sha1/digest_spec.rb b/spec/ruby/library/digest/sha1/digest_spec.rb
new file mode 100644
index 0000000000..abb4034a69
--- /dev/null
+++ b/spec/ruby/library/digest/sha1/digest_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA1#digest" do
+
+ it "returns a digest" do
+ cur_digest = Digest::SHA1.new
+ cur_digest.digest().should == SHA1Constants::BlankDigest
+ cur_digest.digest(SHA1Constants::Contents).should == SHA1Constants::Digest
+ end
+
+end
+
+describe "Digest::SHA1.digest" do
+
+ it "returns a digest" do
+ Digest::SHA1.digest(SHA1Constants::Contents).should == SHA1Constants::Digest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha1/file_spec.rb b/spec/ruby/library/digest/sha1/file_spec.rb
new file mode 100644
index 0000000000..2c9fd2cb52
--- /dev/null
+++ b/spec/ruby/library/digest/sha1/file_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../../../../core/file/shared/read', __FILE__)
+
+describe "Digest::SHA1.file" do
+
+ describe "when passed a path to a file that exists" do
+ before :each do
+ @file = tmp("md5_temp")
+ touch(@file, 'wb') {|f| f.write SHA1Constants::Contents }
+ end
+
+ after :each do
+ rm_r @file
+ end
+
+ it "returns a Digest::SHA1 object" do
+ Digest::SHA1.file(@file).should be_kind_of(Digest::SHA1)
+ end
+
+ it "returns a Digest::SHA1 object with the correct digest" do
+ Digest::SHA1.file(@file).digest.should == SHA1Constants::Digest
+ end
+
+ it "calls #to_str on an object and returns the Digest::SHA1 with the result" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return(@file)
+ result = Digest::SHA1.file(obj)
+ result.should be_kind_of(Digest::SHA1)
+ result.digest.should == SHA1Constants::Digest
+ end
+ end
+
+ it_behaves_like :file_read_directory, :file, Digest::SHA1
+
+ it "raises a Errno::ENOENT when passed a path that does not exist" do
+ lambda { Digest::SHA1.file("") }.should raise_error(Errno::ENOENT)
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { Digest::SHA1.file(nil) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/digest/sha1/shared/constants.rb b/spec/ruby/library/digest/sha1/shared/constants.rb
new file mode 100644
index 0000000000..add86b1dd3
--- /dev/null
+++ b/spec/ruby/library/digest/sha1/shared/constants.rb
@@ -0,0 +1,17 @@
+# -*- encoding: binary -*-
+
+require 'digest/sha1'
+
+module SHA1Constants
+
+ Contents = "Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. \nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. \nIt was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
+
+ Klass = ::Digest::SHA1
+ BlockLength = 64
+ DigestLength = 20
+ BlankDigest = "\3329\243\356^kK\r2U\277\357\225`\030\220\257\330\a\t"
+ Digest = "X!\255b\323\035\352\314a|q\344+\376\317\361V9\324\343"
+ BlankHexdigest = "da39a3ee5e6b4b0d3255bfef95601890afd80709"
+ Hexdigest = "e907d2ba21c6c74bc0efd76e44d11fb9bbb7a75e"
+
+end
diff --git a/spec/ruby/library/digest/sha256/append_spec.rb b/spec/ruby/library/digest/sha256/append_spec.rb
new file mode 100644
index 0000000000..53e623743a
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/append_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/update', __FILE__)
+
+describe "Digest::SHA256#<<" do
+ it_behaves_like(:sha256_update, :<<)
+end
diff --git a/spec/ruby/library/digest/sha256/block_length_spec.rb b/spec/ruby/library/digest/sha256/block_length_spec.rb
new file mode 100644
index 0000000000..4fea959da1
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/block_length_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#block_length" do
+
+ it "returns the length of digest block" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.block_length.should == SHA256Constants::BlockLength
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha256/digest_bang_spec.rb b/spec/ruby/library/digest/sha256/digest_bang_spec.rb
new file mode 100644
index 0000000000..b876c2ceed
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/digest_bang_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#digest!" do
+
+ it "returns a digest and can digest!" do
+ cur_digest = Digest::SHA256.new
+ cur_digest << SHA256Constants::Contents
+ cur_digest.digest!().should == SHA256Constants::Digest
+ cur_digest.digest().should == SHA256Constants::BlankDigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha256/digest_length_spec.rb b/spec/ruby/library/digest/sha256/digest_length_spec.rb
new file mode 100644
index 0000000000..f3d0d66877
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/digest_length_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#digest_length" do
+
+ it "returns the length of computed digests" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.digest_length.should == SHA256Constants::DigestLength
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha256/digest_spec.rb b/spec/ruby/library/digest/sha256/digest_spec.rb
new file mode 100644
index 0000000000..de30916d57
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/digest_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#digest" do
+
+ it "returns a digest" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.digest().should == SHA256Constants::BlankDigest
+
+ # add something to check that the state is reset later
+ cur_digest << "test"
+
+ cur_digest.digest(SHA256Constants::Contents).should == SHA256Constants::Digest
+ # second invocation is intentional, to make sure there are no side-effects
+ cur_digest.digest(SHA256Constants::Contents).should == SHA256Constants::Digest
+
+ # after all is done, verify that the digest is in the original, blank state
+ cur_digest.digest.should == SHA256Constants::BlankDigest
+ end
+
+end
+
+describe "Digest::SHA256.digest" do
+
+ it "returns a digest" do
+ Digest::SHA256.digest(SHA256Constants::Contents).should == SHA256Constants::Digest
+ # second invocation is intentional, to make sure there are no side-effects
+ Digest::SHA256.digest(SHA256Constants::Contents).should == SHA256Constants::Digest
+ Digest::SHA256.digest("").should == SHA256Constants::BlankDigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha256/equal_spec.rb b/spec/ruby/library/digest/sha256/equal_spec.rb
new file mode 100644
index 0000000000..7932b6c13d
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/equal_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#==" do
+
+ it "equals itself" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.should == cur_digest
+ end
+
+ it "equals the string representing its hexdigest" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.should == SHA256Constants::BlankHexdigest
+ end
+
+ it "equals the appropriate object that responds to to_str" do
+ # blank digest
+ cur_digest = Digest::SHA256.new
+ (obj = mock(SHA256Constants::BlankHexdigest)).should_receive(:to_str).and_return(SHA256Constants::BlankHexdigest)
+ cur_digest.should == obj
+
+ # non-blank digest
+ cur_digest = Digest::SHA256.new
+ cur_digest << "test"
+ d_value = cur_digest.hexdigest
+ (obj = mock(d_value)).should_receive(:to_str).and_return(d_value)
+ cur_digest.should == obj
+ end
+
+ it "equals the same digest for a different object" do
+ cur_digest = Digest::SHA256.new
+ cur_digest2 = Digest::SHA256.new
+ cur_digest.should == cur_digest2
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha256/file_spec.rb b/spec/ruby/library/digest/sha256/file_spec.rb
new file mode 100644
index 0000000000..a52b7939f3
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/file_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../../../../core/file/shared/read', __FILE__)
+
+describe "Digest::SHA256.file" do
+
+ describe "when passed a path to a file that exists" do
+ before :each do
+ @file = tmp("md5_temp")
+ touch(@file, 'wb') {|f| f.write SHA256Constants::Contents }
+ end
+
+ after :each do
+ rm_r @file
+ end
+
+ it "returns a Digest::SHA256 object" do
+ Digest::SHA256.file(@file).should be_kind_of(Digest::SHA256)
+ end
+
+ it "returns a Digest::SHA256 object with the correct digest" do
+ Digest::SHA256.file(@file).digest.should == SHA256Constants::Digest
+ end
+
+ it "calls #to_str on an object and returns the Digest::SHA256 with the result" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return(@file)
+ result = Digest::SHA256.file(obj)
+ result.should be_kind_of(Digest::SHA256)
+ result.digest.should == SHA256Constants::Digest
+ end
+ end
+
+ it_behaves_like :file_read_directory, :file, Digest::SHA256
+
+ it "raises a Errno::ENOENT when passed a path that does not exist" do
+ lambda { Digest::SHA256.file("") }.should raise_error(Errno::ENOENT)
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { Digest::SHA256.file(nil) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/digest/sha256/hexdigest_bang_spec.rb b/spec/ruby/library/digest/sha256/hexdigest_bang_spec.rb
new file mode 100644
index 0000000000..98bf38f773
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/hexdigest_bang_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#hexdigest!" do
+
+ it "returns a hexdigest and resets the state" do
+ cur_digest = Digest::SHA256.new
+
+ cur_digest << SHA256Constants::Contents
+ cur_digest.hexdigest!.should == SHA256Constants::Hexdigest
+ cur_digest.hexdigest.should == SHA256Constants::BlankHexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha256/hexdigest_spec.rb b/spec/ruby/library/digest/sha256/hexdigest_spec.rb
new file mode 100644
index 0000000000..3ee7844a93
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/hexdigest_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#hexdigest" do
+
+ it "returns a hexdigest" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.hexdigest.should == SHA256Constants::BlankHexdigest
+
+ # add something to check that the state is reset later
+ cur_digest << "test"
+
+ cur_digest.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ cur_digest.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest
+
+ # after all is done, verify that the digest is in the original, blank state
+ cur_digest.hexdigest.should == SHA256Constants::BlankHexdigest
+ end
+
+end
+
+describe "Digest::SHA256.hexdigest" do
+
+ it "returns a hexdigest" do
+ Digest::SHA256.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ Digest::SHA256.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest
+ Digest::SHA256.hexdigest("").should == SHA256Constants::BlankHexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha256/inspect_spec.rb b/spec/ruby/library/digest/sha256/inspect_spec.rb
new file mode 100644
index 0000000000..5e44b58c63
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/inspect_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#inspect" do
+
+ it "returns a Ruby object representation" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.inspect.should == "#<#{SHA256Constants::Klass}: #{cur_digest.hexdigest()}>"
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha256/length_spec.rb b/spec/ruby/library/digest/sha256/length_spec.rb
new file mode 100644
index 0000000000..6760511093
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/length_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "Digest::SHA256#length" do
+ it_behaves_like :sha256_length, :length
+end
+
diff --git a/spec/ruby/library/digest/sha256/reset_spec.rb b/spec/ruby/library/digest/sha256/reset_spec.rb
new file mode 100644
index 0000000000..82bb08d354
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/reset_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#reset" do
+
+ it "returns digest state to initial conditions" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.update SHA256Constants::Contents
+ cur_digest.digest().should_not == SHA256Constants::BlankDigest
+ cur_digest.reset
+ cur_digest.digest().should == SHA256Constants::BlankDigest
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha256/shared/constants.rb b/spec/ruby/library/digest/sha256/shared/constants.rb
new file mode 100644
index 0000000000..dd5b48dca9
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/shared/constants.rb
@@ -0,0 +1,17 @@
+# -*- encoding: binary -*-
+
+require 'digest/sha2'
+
+module SHA256Constants
+
+ Contents = "Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. \nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. \nIt was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
+
+ Klass = ::Digest::SHA256
+ BlockLength = 64
+ DigestLength = 32
+ BlankDigest = "\343\260\304B\230\374\034\024\232\373\364\310\231o\271$'\256A\344d\233\223L\244\225\231\exR\270U"
+ Digest = "\230b\265\344_\337\357\337\242\004\314\311A\211jb\350\373\254\370\365M\230B\002\372\020j\as\270\376"
+ BlankHexdigest = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ Hexdigest = "9862b5e45fdfefdfa204ccc941896a62e8fbacf8f54d984202fa106a0773b8fe"
+
+end
diff --git a/spec/ruby/library/digest/sha256/shared/length.rb b/spec/ruby/library/digest/sha256/shared/length.rb
new file mode 100644
index 0000000000..996673a5bd
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/shared/length.rb
@@ -0,0 +1,8 @@
+describe :sha256_length, shared: true do
+ it "returns the length of the digest" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.send(@method).should == SHA256Constants::BlankDigest.size
+ cur_digest << SHA256Constants::Contents
+ cur_digest.send(@method).should == SHA256Constants::Digest.size
+ end
+end
diff --git a/spec/ruby/library/digest/sha256/shared/update.rb b/spec/ruby/library/digest/sha256/shared/update.rb
new file mode 100644
index 0000000000..0edc07935b
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/shared/update.rb
@@ -0,0 +1,7 @@
+describe :sha256_update, shared: true do
+ it "can update" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.send @method, SHA256Constants::Contents
+ cur_digest.digest.should == SHA256Constants::Digest
+ end
+end
diff --git a/spec/ruby/library/digest/sha256/size_spec.rb b/spec/ruby/library/digest/sha256/size_spec.rb
new file mode 100644
index 0000000000..77db876956
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/size_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "Digest::SHA256#size" do
+ it_behaves_like :sha256_length, :size
+end
+
diff --git a/spec/ruby/library/digest/sha256/to_s_spec.rb b/spec/ruby/library/digest/sha256/to_s_spec.rb
new file mode 100644
index 0000000000..b91983d157
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/to_s_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA256#to_s" do
+
+ it "returns a hexdigest" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.to_s.should == SHA256Constants::BlankHexdigest
+ end
+
+ it "does not change the internal state" do
+ cur_digest = Digest::SHA256.new
+ cur_digest.to_s.should == SHA256Constants::BlankHexdigest
+ cur_digest.to_s.should == SHA256Constants::BlankHexdigest
+
+ cur_digest << SHA256Constants::Contents
+ cur_digest.to_s.should == SHA256Constants::Hexdigest
+ cur_digest.to_s.should == SHA256Constants::Hexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha256/update_spec.rb b/spec/ruby/library/digest/sha256/update_spec.rb
new file mode 100644
index 0000000000..3e3eaf57a3
--- /dev/null
+++ b/spec/ruby/library/digest/sha256/update_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/update', __FILE__)
+
+describe "Digest::SHA256#update" do
+ it_behaves_like :sha256_update, :update
+end
diff --git a/spec/ruby/library/digest/sha384/append_spec.rb b/spec/ruby/library/digest/sha384/append_spec.rb
new file mode 100644
index 0000000000..d694812e85
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/append_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/update', __FILE__)
+
+describe "Digest::SHA384#<<" do
+ it_behaves_like(:sha384_update, :<<)
+end
diff --git a/spec/ruby/library/digest/sha384/block_length_spec.rb b/spec/ruby/library/digest/sha384/block_length_spec.rb
new file mode 100644
index 0000000000..070715b27e
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/block_length_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#block_length" do
+
+ it "returns the length of digest block" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.block_length.should == SHA384Constants::BlockLength
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha384/digest_bang_spec.rb b/spec/ruby/library/digest/sha384/digest_bang_spec.rb
new file mode 100644
index 0000000000..83b68ae7c2
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/digest_bang_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#digest!" do
+
+ it "returns a digest and can digest!" do
+ cur_digest = Digest::SHA384.new
+ cur_digest << SHA384Constants::Contents
+ cur_digest.digest!().should == SHA384Constants::Digest
+ cur_digest.digest().should == SHA384Constants::BlankDigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha384/digest_length_spec.rb b/spec/ruby/library/digest/sha384/digest_length_spec.rb
new file mode 100644
index 0000000000..a57616b44c
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/digest_length_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#digest_length" do
+
+ it "returns the length of computed digests" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.digest_length.should == SHA384Constants::DigestLength
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha384/digest_spec.rb b/spec/ruby/library/digest/sha384/digest_spec.rb
new file mode 100644
index 0000000000..3a5cd3a5d7
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/digest_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#digest" do
+
+ it "returns a digest" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.digest().should == SHA384Constants::BlankDigest
+
+ # add something to check that the state is reset later
+ cur_digest << "test"
+
+ cur_digest.digest(SHA384Constants::Contents).should == SHA384Constants::Digest
+ # second invocation is intentional, to make sure there are no side-effects
+ cur_digest.digest(SHA384Constants::Contents).should == SHA384Constants::Digest
+
+ # after all is done, verify that the digest is in the original, blank state
+ cur_digest.digest.should == SHA384Constants::BlankDigest
+ end
+
+end
+
+describe "Digest::SHA384.digest" do
+
+ it "returns a digest" do
+ Digest::SHA384.digest(SHA384Constants::Contents).should == SHA384Constants::Digest
+ # second invocation is intentional, to make sure there are no side-effects
+ Digest::SHA384.digest(SHA384Constants::Contents).should == SHA384Constants::Digest
+ Digest::SHA384.digest("").should == SHA384Constants::BlankDigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha384/equal_spec.rb b/spec/ruby/library/digest/sha384/equal_spec.rb
new file mode 100644
index 0000000000..a54d328edc
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/equal_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#==" do
+
+ it "equals itself" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.should == cur_digest
+ end
+
+ it "equals the string representing its hexdigest" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.should == SHA384Constants::BlankHexdigest
+ end
+
+ it "equals the appropriate object that responds to to_str" do
+ # blank digest
+ cur_digest = Digest::SHA384.new
+ (obj = mock(SHA384Constants::BlankHexdigest)).should_receive(:to_str).and_return(SHA384Constants::BlankHexdigest)
+ cur_digest.should == obj
+
+ # non-blank digest
+ cur_digest = Digest::SHA384.new
+ cur_digest << "test"
+ d_value = cur_digest.hexdigest
+ (obj = mock(d_value)).should_receive(:to_str).and_return(d_value)
+ cur_digest.should == obj
+ end
+
+ it "equals the same digest for a different object" do
+ cur_digest = Digest::SHA384.new
+ cur_digest2 = Digest::SHA384.new
+ cur_digest.should == cur_digest2
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha384/file_spec.rb b/spec/ruby/library/digest/sha384/file_spec.rb
new file mode 100644
index 0000000000..7e7c8f9565
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/file_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../../../../core/file/shared/read', __FILE__)
+
+describe "Digest::SHA384.file" do
+
+ describe "when passed a path to a file that exists" do
+ before :each do
+ @file = tmp("md5_temp")
+ touch(@file, 'wb') {|f| f.write SHA384Constants::Contents }
+ end
+
+ after :each do
+ rm_r @file
+ end
+
+ it "returns a Digest::SHA384 object" do
+ Digest::SHA384.file(@file).should be_kind_of(Digest::SHA384)
+ end
+
+ it "returns a Digest::SHA384 object with the correct digest" do
+ Digest::SHA384.file(@file).digest.should == SHA384Constants::Digest
+ end
+
+ it "calls #to_str on an object and returns the Digest::SHA384 with the result" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return(@file)
+ result = Digest::SHA384.file(obj)
+ result.should be_kind_of(Digest::SHA384)
+ result.digest.should == SHA384Constants::Digest
+ end
+ end
+
+ it_behaves_like :file_read_directory, :file, Digest::SHA384
+
+ it "raises a Errno::ENOENT when passed a path that does not exist" do
+ lambda { Digest::SHA384.file("") }.should raise_error(Errno::ENOENT)
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { Digest::SHA384.file(nil) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/digest/sha384/hexdigest_bang_spec.rb b/spec/ruby/library/digest/sha384/hexdigest_bang_spec.rb
new file mode 100644
index 0000000000..68da8c7200
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/hexdigest_bang_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#hexdigest!" do
+
+ it "returns a hexdigest and resets the state" do
+ cur_digest = Digest::SHA384.new
+
+ cur_digest << SHA384Constants::Contents
+ cur_digest.hexdigest!.should == SHA384Constants::Hexdigest
+ cur_digest.hexdigest.should == SHA384Constants::BlankHexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha384/hexdigest_spec.rb b/spec/ruby/library/digest/sha384/hexdigest_spec.rb
new file mode 100644
index 0000000000..a7724d1663
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/hexdigest_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#hexdigest" do
+
+ it "returns a hexdigest" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.hexdigest.should == SHA384Constants::BlankHexdigest
+
+ # add something to check that the state is reset later
+ cur_digest << "test"
+
+ cur_digest.hexdigest(SHA384Constants::Contents).should == SHA384Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ cur_digest.hexdigest(SHA384Constants::Contents).should == SHA384Constants::Hexdigest
+
+ # after all is done, verify that the digest is in the original, blank state
+ cur_digest.hexdigest.should == SHA384Constants::BlankHexdigest
+ end
+
+end
+
+describe "Digest::SHA384.hexdigest" do
+
+ it "returns a hexdigest" do
+ Digest::SHA384.hexdigest(SHA384Constants::Contents).should == SHA384Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ Digest::SHA384.hexdigest(SHA384Constants::Contents).should == SHA384Constants::Hexdigest
+ Digest::SHA384.hexdigest("").should == SHA384Constants::BlankHexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha384/inspect_spec.rb b/spec/ruby/library/digest/sha384/inspect_spec.rb
new file mode 100644
index 0000000000..554a22d135
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/inspect_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#inspect" do
+
+ it "returns a Ruby object representation" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.inspect.should == "#<#{SHA384Constants::Klass}: #{cur_digest.hexdigest()}>"
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha384/length_spec.rb b/spec/ruby/library/digest/sha384/length_spec.rb
new file mode 100644
index 0000000000..63a57ce9ca
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/length_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "Digest::SHA384#length" do
+ it_behaves_like :sha384_length, :length
+end
+
diff --git a/spec/ruby/library/digest/sha384/reset_spec.rb b/spec/ruby/library/digest/sha384/reset_spec.rb
new file mode 100644
index 0000000000..8abe39d7e2
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/reset_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#reset" do
+
+ it "returns digest state to initial conditions" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.update SHA384Constants::Contents
+ cur_digest.digest().should_not == SHA384Constants::BlankDigest
+ cur_digest.reset
+ cur_digest.digest().should == SHA384Constants::BlankDigest
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha384/shared/constants.rb b/spec/ruby/library/digest/sha384/shared/constants.rb
new file mode 100644
index 0000000000..3697384fc3
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/shared/constants.rb
@@ -0,0 +1,18 @@
+# -*- encoding: binary -*-
+
+require 'digest/sha2'
+
+module SHA384Constants
+
+ Contents = "Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. \nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. \nIt was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
+
+
+ Klass = ::Digest::SHA384
+ BlockLength = 128
+ DigestLength = 48
+ BlankDigest = "8\260`\247Q\254\2268L\3312~\261\261\343j!\375\267\021\024\276\aCL\f\307\277c\366\341\332'N\336\277\347oe\373\325\032\322\361H\230\271["
+ Digest = "B&\266:\314\216z\361!TD\001{`\355\323\320MW%\270\272\0034n\034\026g\a\217\"\333s\202\275\002Y*\217]\207u\f\034\244\231\266f"
+ BlankHexdigest = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
+ Hexdigest = "4226b63acc8e7af1215444017b60edd3d04d5725b8ba03346e1c1667078f22db7382bd02592a8f5d87750c1ca499b666"
+
+end
diff --git a/spec/ruby/library/digest/sha384/shared/length.rb b/spec/ruby/library/digest/sha384/shared/length.rb
new file mode 100644
index 0000000000..0c88288bcf
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/shared/length.rb
@@ -0,0 +1,8 @@
+describe :sha384_length, shared: true do
+ it "returns the length of the digest" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.send(@method).should == SHA384Constants::BlankDigest.size
+ cur_digest << SHA384Constants::Contents
+ cur_digest.send(@method).should == SHA384Constants::Digest.size
+ end
+end
diff --git a/spec/ruby/library/digest/sha384/shared/update.rb b/spec/ruby/library/digest/sha384/shared/update.rb
new file mode 100644
index 0000000000..1c6e31cf6a
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/shared/update.rb
@@ -0,0 +1,7 @@
+describe :sha384_update, shared: true do
+ it "can update" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.send @method, SHA384Constants::Contents
+ cur_digest.digest.should == SHA384Constants::Digest
+ end
+end
diff --git a/spec/ruby/library/digest/sha384/size_spec.rb b/spec/ruby/library/digest/sha384/size_spec.rb
new file mode 100644
index 0000000000..9aea3ef592
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/size_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "Digest::SHA384#size" do
+ it_behaves_like :sha384_length, :size
+end
+
diff --git a/spec/ruby/library/digest/sha384/to_s_spec.rb b/spec/ruby/library/digest/sha384/to_s_spec.rb
new file mode 100644
index 0000000000..f45f2ee915
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/to_s_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA384#to_s" do
+
+ it "returns a hexdigest" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.to_s.should == SHA384Constants::BlankHexdigest
+ end
+
+ it "does not change the internal state" do
+ cur_digest = Digest::SHA384.new
+ cur_digest.to_s.should == SHA384Constants::BlankHexdigest
+ cur_digest.to_s.should == SHA384Constants::BlankHexdigest
+
+ cur_digest << SHA384Constants::Contents
+ cur_digest.to_s.should == SHA384Constants::Hexdigest
+ cur_digest.to_s.should == SHA384Constants::Hexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha384/update_spec.rb b/spec/ruby/library/digest/sha384/update_spec.rb
new file mode 100644
index 0000000000..9917f86b86
--- /dev/null
+++ b/spec/ruby/library/digest/sha384/update_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/update', __FILE__)
+
+describe "Digest::SHA384#update" do
+ it_behaves_like :sha384_update, :update
+end
diff --git a/spec/ruby/library/digest/sha512/append_spec.rb b/spec/ruby/library/digest/sha512/append_spec.rb
new file mode 100644
index 0000000000..642e565bf6
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/append_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/update', __FILE__)
+
+describe "Digest::SHA512#<<" do
+ it_behaves_like(:sha512_update, :<<)
+end
diff --git a/spec/ruby/library/digest/sha512/block_length_spec.rb b/spec/ruby/library/digest/sha512/block_length_spec.rb
new file mode 100644
index 0000000000..95bb98548a
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/block_length_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#block_length" do
+
+ it "returns the length of digest block" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.block_length.should == SHA512Constants::BlockLength
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha512/digest_bang_spec.rb b/spec/ruby/library/digest/sha512/digest_bang_spec.rb
new file mode 100644
index 0000000000..260595152d
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/digest_bang_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#digest!" do
+
+ it "returns a digest and can digest!" do
+ cur_digest = Digest::SHA512.new
+ cur_digest << SHA512Constants::Contents
+ cur_digest.digest!().should == SHA512Constants::Digest
+ cur_digest.digest().should == SHA512Constants::BlankDigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha512/digest_length_spec.rb b/spec/ruby/library/digest/sha512/digest_length_spec.rb
new file mode 100644
index 0000000000..5185b6e906
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/digest_length_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#digest_length" do
+
+ it "returns the length of computed digests" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.digest_length.should == SHA512Constants::DigestLength
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha512/digest_spec.rb b/spec/ruby/library/digest/sha512/digest_spec.rb
new file mode 100644
index 0000000000..9f4264579f
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/digest_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#digest" do
+
+ it "returns a digest" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.digest().should == SHA512Constants::BlankDigest
+
+ # add something to check that the state is reset later
+ cur_digest << "test"
+
+ cur_digest.digest(SHA512Constants::Contents).should == SHA512Constants::Digest
+ # second invocation is intentional, to make sure there are no side-effects
+ cur_digest.digest(SHA512Constants::Contents).should == SHA512Constants::Digest
+
+ # after all is done, verify that the digest is in the original, blank state
+ cur_digest.digest.should == SHA512Constants::BlankDigest
+ end
+
+end
+
+describe "Digest::SHA512.digest" do
+
+ it "returns a digest" do
+ Digest::SHA512.digest(SHA512Constants::Contents).should == SHA512Constants::Digest
+ # second invocation is intentional, to make sure there are no side-effects
+ Digest::SHA512.digest(SHA512Constants::Contents).should == SHA512Constants::Digest
+ Digest::SHA512.digest("").should == SHA512Constants::BlankDigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha512/equal_spec.rb b/spec/ruby/library/digest/sha512/equal_spec.rb
new file mode 100644
index 0000000000..ec4c55f118
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/equal_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#==" do
+
+ it "equals itself" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.should == cur_digest
+ end
+
+ it "equals the string representing its hexdigest" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.should == SHA512Constants::BlankHexdigest
+ end
+
+ it "equals the appropriate object that responds to to_str" do
+ # blank digest
+ cur_digest = Digest::SHA512.new
+ (obj = mock(SHA512Constants::BlankHexdigest)).should_receive(:to_str).and_return(SHA512Constants::BlankHexdigest)
+ cur_digest.should == obj
+
+ # non-blank digest
+ cur_digest = Digest::SHA512.new
+ cur_digest << "test"
+ d_value = cur_digest.hexdigest
+ (obj = mock(d_value)).should_receive(:to_str).and_return(d_value)
+ cur_digest.should == obj
+ end
+
+ it "equals the same digest for a different object" do
+ cur_digest = Digest::SHA512.new
+ cur_digest2 = Digest::SHA512.new
+ cur_digest.should == cur_digest2
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha512/file_spec.rb b/spec/ruby/library/digest/sha512/file_spec.rb
new file mode 100644
index 0000000000..365f3625b6
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/file_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../../../../core/file/shared/read', __FILE__)
+
+describe "Digest::SHA512.file" do
+
+ describe "when passed a path to a file that exists" do
+ before :each do
+ @file = tmp("md5_temp")
+ touch(@file, 'wb') {|f| f.write SHA512Constants::Contents }
+ end
+
+ after :each do
+ rm_r @file
+ end
+
+ it "returns a Digest::SHA512 object" do
+ Digest::SHA512.file(@file).should be_kind_of(Digest::SHA512)
+ end
+
+ it "returns a Digest::SHA512 object with the correct digest" do
+ Digest::SHA512.file(@file).digest.should == SHA512Constants::Digest
+ end
+
+ it "calls #to_str on an object and returns the Digest::SHA512 with the result" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return(@file)
+ result = Digest::SHA512.file(obj)
+ result.should be_kind_of(Digest::SHA512)
+ result.digest.should == SHA512Constants::Digest
+ end
+ end
+
+ it_behaves_like :file_read_directory, :file, Digest::SHA512
+
+ it "raises a Errno::ENOENT when passed a path that does not exist" do
+ lambda { Digest::SHA512.file("") }.should raise_error(Errno::ENOENT)
+ end
+
+ it "raises a TypeError when passed nil" do
+ lambda { Digest::SHA512.file(nil) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/digest/sha512/hexdigest_bang_spec.rb b/spec/ruby/library/digest/sha512/hexdigest_bang_spec.rb
new file mode 100644
index 0000000000..6eda150949
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/hexdigest_bang_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#hexdigest!" do
+
+ it "returns a hexdigest and resets the state" do
+ cur_digest = Digest::SHA512.new
+
+ cur_digest << SHA512Constants::Contents
+ cur_digest.hexdigest!.should == SHA512Constants::Hexdigest
+ cur_digest.hexdigest.should == SHA512Constants::BlankHexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha512/hexdigest_spec.rb b/spec/ruby/library/digest/sha512/hexdigest_spec.rb
new file mode 100644
index 0000000000..405d380490
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/hexdigest_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#hexdigest" do
+
+ it "returns a hexdigest" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.hexdigest.should == SHA512Constants::BlankHexdigest
+
+ # add something to check that the state is reset later
+ cur_digest << "test"
+
+ cur_digest.hexdigest(SHA512Constants::Contents).should == SHA512Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ cur_digest.hexdigest(SHA512Constants::Contents).should == SHA512Constants::Hexdigest
+
+ # after all is done, verify that the digest is in the original, blank state
+ cur_digest.hexdigest.should == SHA512Constants::BlankHexdigest
+ end
+
+end
+
+describe "Digest::SHA512.hexdigest" do
+
+ it "returns a hexdigest" do
+ Digest::SHA512.hexdigest(SHA512Constants::Contents).should == SHA512Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ Digest::SHA512.hexdigest(SHA512Constants::Contents).should == SHA512Constants::Hexdigest
+ Digest::SHA512.hexdigest("").should == SHA512Constants::BlankHexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha512/inspect_spec.rb b/spec/ruby/library/digest/sha512/inspect_spec.rb
new file mode 100644
index 0000000000..97806000d2
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/inspect_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#inspect" do
+
+ it "returns a Ruby object representation" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.inspect.should == "#<#{SHA512Constants::Klass}: #{cur_digest.hexdigest()}>"
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha512/length_spec.rb b/spec/ruby/library/digest/sha512/length_spec.rb
new file mode 100644
index 0000000000..b0b4d7e56c
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/length_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "Digest::SHA512#length" do
+ it_behaves_like :sha512_length, :length
+end
+
diff --git a/spec/ruby/library/digest/sha512/reset_spec.rb b/spec/ruby/library/digest/sha512/reset_spec.rb
new file mode 100644
index 0000000000..b2f28dc670
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/reset_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#reset" do
+
+ it "returns digest state to initial conditions" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.update SHA512Constants::Contents
+ cur_digest.digest().should_not == SHA512Constants::BlankDigest
+ cur_digest.reset
+ cur_digest.digest().should == SHA512Constants::BlankDigest
+ end
+
+end
+
diff --git a/spec/ruby/library/digest/sha512/shared/constants.rb b/spec/ruby/library/digest/sha512/shared/constants.rb
new file mode 100644
index 0000000000..80f5b7bc1d
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/shared/constants.rb
@@ -0,0 +1,17 @@
+# -*- encoding: binary -*-
+
+require 'digest/sha2'
+
+module SHA512Constants
+
+ Contents = "Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. \nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. \nIt was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
+
+ Klass = ::Digest::SHA512
+ BlockLength = 128
+ DigestLength = 64
+ BlankDigest = "\317\203\3415~\357\270\275\361T(P\326m\200\a\326 \344\005\vW\025\334\203\364\251!\323l\351\316G\320\321<]\205\362\260\377\203\030\322\207~\354/c\2711\275GAz\201\24582z\371'\332>"
+ Digest = "\241\231\232\365\002z\241\331\242\310=\367F\272\004\326\331g\315n\251Q\222\250\374E\257\254=\325\225\003SM\350\244\234\220\233=\031\230A;\000\203\233\340\323t\333\271\222w\266\307\2678\344\255j\003\216\300"
+ BlankHexdigest = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
+ Hexdigest = "a1999af5027aa1d9a2c83df746ba04d6d967cd6ea95192a8fc45afac3dd59503534de8a49c909b3d1998413b00839be0d374dbb99277b6c7b738e4ad6a038ec0"
+
+end
diff --git a/spec/ruby/library/digest/sha512/shared/length.rb b/spec/ruby/library/digest/sha512/shared/length.rb
new file mode 100644
index 0000000000..c0609d5386
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/shared/length.rb
@@ -0,0 +1,8 @@
+describe :sha512_length, shared: true do
+ it "returns the length of the digest" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.send(@method).should == SHA512Constants::BlankDigest.size
+ cur_digest << SHA512Constants::Contents
+ cur_digest.send(@method).should == SHA512Constants::Digest.size
+ end
+end
diff --git a/spec/ruby/library/digest/sha512/shared/update.rb b/spec/ruby/library/digest/sha512/shared/update.rb
new file mode 100644
index 0000000000..ca74dbf4df
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/shared/update.rb
@@ -0,0 +1,7 @@
+describe :sha512_update, shared: true do
+ it "can update" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.send @method, SHA512Constants::Contents
+ cur_digest.digest.should == SHA512Constants::Digest
+ end
+end
diff --git a/spec/ruby/library/digest/sha512/size_spec.rb b/spec/ruby/library/digest/sha512/size_spec.rb
new file mode 100644
index 0000000000..a882fe55a1
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/size_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "Digest::SHA512#size" do
+ it_behaves_like :sha512_length, :size
+end
+
diff --git a/spec/ruby/library/digest/sha512/to_s_spec.rb b/spec/ruby/library/digest/sha512/to_s_spec.rb
new file mode 100644
index 0000000000..b45f553e8c
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/to_s_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+
+describe "Digest::SHA512#to_s" do
+
+ it "returns a hexdigest" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.to_s.should == SHA512Constants::BlankHexdigest
+ end
+
+ it "does not change the internal state" do
+ cur_digest = Digest::SHA512.new
+ cur_digest.to_s.should == SHA512Constants::BlankHexdigest
+ cur_digest.to_s.should == SHA512Constants::BlankHexdigest
+
+ cur_digest << SHA512Constants::Contents
+ cur_digest.to_s.should == SHA512Constants::Hexdigest
+ cur_digest.to_s.should == SHA512Constants::Hexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha512/update_spec.rb b/spec/ruby/library/digest/sha512/update_spec.rb
new file mode 100644
index 0000000000..3b82f51853
--- /dev/null
+++ b/spec/ruby/library/digest/sha512/update_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require File.expand_path('../shared/update', __FILE__)
+
+describe "Digest::SHA512#update" do
+ it_behaves_like :sha512_update, :update
+end
diff --git a/spec/ruby/library/drb/fixtures/test_server.rb b/spec/ruby/library/drb/fixtures/test_server.rb
new file mode 100644
index 0000000000..9d412f4ac7
--- /dev/null
+++ b/spec/ruby/library/drb/fixtures/test_server.rb
@@ -0,0 +1,8 @@
+class TestServer
+ def add(*args)
+ args.inject {|n,v| n+v}
+ end
+ def add_yield(x)
+ return (yield x)+1
+ end
+end
diff --git a/spec/ruby/library/drb/start_service_spec.rb b/spec/ruby/library/drb/start_service_spec.rb
new file mode 100644
index 0000000000..f64021f0bd
--- /dev/null
+++ b/spec/ruby/library/drb/start_service_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/test_server', __FILE__)
+require 'drb'
+
+describe "DRb.start_service" do
+ before :each do
+ @server = DRb.start_service("druby://localhost:0", TestServer.new)
+ end
+
+ after :each do
+ DRb.stop_service if @server
+ end
+
+ it "runs a basic remote call" do
+ DRb.current_server.should == @server
+ obj = DRbObject.new(nil, @server.uri)
+ obj.add(1,2,3).should == 6
+ end
+
+ it "runs a basic remote call passing a block" do
+ DRb.current_server.should == @server
+ obj = DRbObject.new(nil, @server.uri)
+ obj.add_yield(2) do |i|
+ i.should == 2
+ i+1
+ end.should == 4
+ end
+end
diff --git a/spec/ruby/library/erb/def_class_spec.rb b/spec/ruby/library/erb/def_class_spec.rb
new file mode 100644
index 0000000000..ae2dcbd1e4
--- /dev/null
+++ b/spec/ruby/library/erb/def_class_spec.rb
@@ -0,0 +1,29 @@
+require 'erb'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "ERB#def_class" do
+
+ it "return an unnamed class which has instance method to render eRuby script" do
+ input = <<'END'
+@arg1=<%=@arg1.inspect%>
+@arg2=<%=@arg2.inspect%>
+END
+ expected = <<'END'
+@arg1="foo"
+@arg2=123
+END
+ class MyClass1ForErb_
+ def initialize(arg1, arg2)
+ @arg1 = arg1; @arg2 = arg2
+ end
+ end
+ filename = 'example.rhtml'
+ #erb = ERB.new(File.read(filename))
+ erb = ERB.new(input)
+ erb.filename = filename
+ MyClass1ForErb = erb.def_class(MyClass1ForErb_, 'render()')
+ MyClass1ForErb.method_defined?(:render).should == true
+ MyClass1ForErb.new('foo', 123).render().should == expected
+ end
+
+end
diff --git a/spec/ruby/library/erb/def_method_spec.rb b/spec/ruby/library/erb/def_method_spec.rb
new file mode 100644
index 0000000000..e4ddedea4c
--- /dev/null
+++ b/spec/ruby/library/erb/def_method_spec.rb
@@ -0,0 +1,26 @@
+require 'erb'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "ERB#def_method" do
+
+ it "define module's instance method to render eRuby file" do
+ input = <<'END'
+arg1=<%= arg1.inspect %>
+arg2=<%= arg2.inspect %>
+END
+ expected = <<'END'
+arg1="foo"
+arg2=123
+END
+ #
+ filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml
+ #erb = ERB.new(File.read(filename))
+ erb = ERB.new(input)
+ class MyClass0ForErb
+ end
+ erb.def_method(MyClass0ForErb, 'render(arg1, arg2)', filename)
+ MyClass0ForErb.method_defined?(:render)
+ MyClass0ForErb.new.render('foo', 123).should == expected
+ end
+
+end
diff --git a/spec/ruby/library/erb/def_module_spec.rb b/spec/ruby/library/erb/def_module_spec.rb
new file mode 100644
index 0000000000..ed52fdfc15
--- /dev/null
+++ b/spec/ruby/library/erb/def_module_spec.rb
@@ -0,0 +1,27 @@
+require 'erb'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "ERB#def_module" do
+
+ it "return unnamed module which has instance method to render eRuby" do
+ input = <<'END'
+arg1=<%= arg1.inspect %>
+arg2=<%= arg2.inspect %>
+END
+ expected = <<'END'
+arg1="foo"
+arg2=123
+END
+ filename = 'example.rhtml'
+ #erb = ERB.new(File.read(filename))
+ erb = ERB.new(input)
+ erb.filename = filename
+ MyModule2ForErb = erb.def_module('render(arg1, arg2)')
+ MyModule2ForErb.method_defined?(':render')
+ class MyClass2ForErb
+ include MyModule2ForErb
+ end
+ MyClass2ForErb.new.render('foo', 123).should == expected
+ end
+
+end
diff --git a/spec/ruby/library/erb/defmethod/def_erb_method_spec.rb b/spec/ruby/library/erb/defmethod/def_erb_method_spec.rb
new file mode 100644
index 0000000000..e1eca2fbef
--- /dev/null
+++ b/spec/ruby/library/erb/defmethod/def_erb_method_spec.rb
@@ -0,0 +1,63 @@
+require 'erb'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "ERB::DefMethod.def_erb_method" do
+
+
+ input = <<'END'
+<% for item in @items %>
+<b><%= item %></b>
+<% end %>
+END
+
+
+ it "define method to render eRuby file as an instance method of current module" do
+ expected = <<'END'
+
+<b>10</b>
+
+<b>20</b>
+
+<b>30</b>
+
+END
+ #
+ begin
+ file = tmp('_example.rhtml')
+ File.open(file, 'w') {|f| f.write(input) }
+ klass = Class.new do
+ extend ERB::DefMethod
+ def_erb_method('render()', file)
+ def initialize(items)
+ @items = items
+ end
+ end
+ klass.new([10,20,30]).render().should == expected
+ ensure
+ rm_r file
+ end
+
+ end
+
+
+ it "define method to render eRuby object as an instance method of current module" do
+ expected = <<'END'
+<b>10</b>
+<b>20</b>
+<b>30</b>
+END
+ #
+ MY_INPUT4_FOR_ERB = input
+ class MyClass4ForErb
+ extend ERB::DefMethod
+ erb = ERB.new(MY_INPUT4_FOR_ERB, nil, '<>')
+ def_erb_method('render()', erb)
+ def initialize(items)
+ @items = items
+ end
+ end
+ MyClass4ForErb.new([10,20,30]).render().should == expected
+ end
+
+
+end
diff --git a/spec/ruby/library/erb/filename_spec.rb b/spec/ruby/library/erb/filename_spec.rb
new file mode 100644
index 0000000000..4615f5d808
--- /dev/null
+++ b/spec/ruby/library/erb/filename_spec.rb
@@ -0,0 +1,40 @@
+require 'erb'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "ERB#filename" do
+ it "raises an exception if there are errors processing content" do
+ filename = 'foobar.rhtml'
+ erb = ERB.new('<% if true %>') # will raise SyntaxError
+ erb.filename = filename
+ lambda {
+ begin
+ erb.result(binding)
+ rescue Exception => e
+ @ex = e
+ raise e
+ end
+ }.should raise_error(SyntaxError)
+ expected = filename
+
+ @ex.message =~ /^(.*?):(\d+): /
+ $1.should == expected
+ $2.to_i.should == 1
+ end
+
+ it "uses '(erb)' as filename when filename is not set" do
+ erb = ERB.new('<% if true %>') # will raise SyntaxError
+ lambda {
+ begin
+ erb.result(binding)
+ rescue Exception => e
+ @ex = e
+ raise e
+ end
+ }.should raise_error(SyntaxError)
+ expected = '(erb)'
+
+ @ex.message =~ /^(.*?):(\d+): /
+ $1.should == expected
+ $2.to_i.should == 1
+ end
+end
diff --git a/spec/ruby/library/erb/new_spec.rb b/spec/ruby/library/erb/new_spec.rb
new file mode 100644
index 0000000000..917fd470b7
--- /dev/null
+++ b/spec/ruby/library/erb/new_spec.rb
@@ -0,0 +1,132 @@
+require 'erb'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "ERB.new" do
+ before :all do
+ @eruby_str = <<'END'
+<ul>
+<% list = [1,2,3] %>
+<% for item in list %>
+<% if item %>
+<li><%= item %></li>
+<% end %>
+<% end %>
+</ul>
+END
+
+ @eruby_str2 = <<'END'
+<ul>
+% list = [1,2,3]
+%for item in list
+% if item
+ <li><%= item %>
+ <% end %>
+<% end %>
+</ul>
+%%%
+END
+
+ end
+
+ it "compiles eRuby script into ruby code when trim mode is 0 or not specified" do
+ expected = "<ul>\n\n\n\n<li>1</li>\n\n\n\n<li>2</li>\n\n\n\n<li>3</li>\n\n\n</ul>\n"
+ [0, '', nil].each do |trim_mode|
+ ERB.new(@eruby_str, nil, trim_mode).result.should == expected
+ end
+ end
+
+ it "removes '\n' when trim_mode is 1 or '>'" do
+ expected = "<ul>\n<li>1</li>\n<li>2</li>\n<li>3</li>\n</ul>\n"
+ [1, '>'].each do |trim_mode|
+ ERB.new(@eruby_str, nil, trim_mode).result.should == expected
+ end
+ end
+
+ it "removes spaces at beginning of line and '\n' when trim_mode is 2 or '<>'" do
+ expected = "<ul>\n<li>1</li>\n<li>2</li>\n<li>3</li>\n</ul>\n"
+ [2, '<>'].each do |trim_mode|
+ ERB.new(@eruby_str, nil, trim_mode).result.should == expected
+ end
+ end
+
+ it "removes spaces around '<%- -%>' when trim_mode is '-'" do
+ expected = "<ul>\n <li>1 <li>2 <li>3</ul>\n"
+ input = <<'END'
+<ul>
+<%- for item in [1,2,3] -%>
+ <%- if item -%>
+ <li><%= item -%>
+ <%- end -%>
+<%- end -%>
+</ul>
+END
+
+ ERB.new(input, nil, '-').result.should == expected
+ end
+
+
+ it "not support '<%-= expr %> even when trim_mode is '-'" do
+
+ input = <<'END'
+<p>
+ <%= expr -%>
+ <%-= expr -%>
+</p>
+END
+
+ lambda { ERB.new(input, nil, '-').result }.should raise_error
+ end
+
+ it "regards lines starting with '%' as '<% ... %>' when trim_mode is '%'" do
+ expected = "<ul>\n <li>1\n \n <li>2\n \n <li>3\n \n\n</ul>\n%%\n"
+ ERB.new(@eruby_str2, nil, "%").result.should == expected
+ end
+ it "regards lines starting with '%' as '<% ... %>' and remove \"\\n\" when trim_mode is '%>'" do
+ expected = "<ul>\n <li>1 <li>2 <li>3 </ul>\n%%\n"
+ ERB.new(@eruby_str2, nil, '%>').result.should == expected
+ end
+
+
+ it "regard lines starting with '%' as '<% ... %>' and remove \"\\n\" when trim_mode is '%<>'" do
+ expected = "<ul>\n <li>1\n \n <li>2\n \n <li>3\n \n</ul>\n%%\n"
+ ERB.new(@eruby_str2, nil, '%<>').result.should == expected
+ end
+
+
+ it "regard lines starting with '%' as '<% ... %>' and spaces around '<%- -%>' when trim_mode is '%-'" do
+ expected = "<ul>\n<li>1</li>\n<li>2</li>\n</ul>\n%%\n"
+ input = <<'END'
+<ul>
+%list = [1,2]
+%for item in list
+<li><%= item %></li>
+<% end %></ul>
+%%%
+END
+
+ ERB.new(input, nil, '%-').result.should == expected
+ end
+
+ it "changes '_erbout' variable name in the produced source" do
+ input = @eruby_str
+ match_erbout = ERB.new(input, nil, nil).src
+ match_buf = ERB.new(input, nil, nil, 'buf').src
+ match_erbout.gsub("_erbout", "buf").should == match_buf
+ end
+
+
+ it "ignores '<%# ... %>'" do
+ input = <<'END'
+<%# for item in list %>
+<b><%#= item %></b>
+<%# end %>
+END
+ ERB.new(input).result.should == "\n<b></b>\n\n"
+ ERB.new(input, nil, '<>').result.should == "<b></b>\n"
+ end
+
+ it "forget local variables defined previous one" do
+ ERB.new(@eruby_str).result
+ lambda{ ERB.new("<%= list %>").result }.should raise_error(NameError)
+ end
+end
diff --git a/spec/ruby/library/erb/result_spec.rb b/spec/ruby/library/erb/result_spec.rb
new file mode 100644
index 0000000000..d79584b221
--- /dev/null
+++ b/spec/ruby/library/erb/result_spec.rb
@@ -0,0 +1,86 @@
+require 'erb'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "ERB#result" do
+
+
+ it "return the result of compiled ruby code" do
+ input = <<'END'
+<ul>
+<% for item in list %>
+ <li><%= item %>
+<% end %>
+</ul>
+END
+ expected = <<'END'
+<ul>
+
+ <li>AAA
+
+ <li>BBB
+
+ <li>CCC
+
+</ul>
+END
+ erb = ERB.new(input)
+ list = %w[AAA BBB CCC]
+ actual = erb.result(binding)
+ actual.should == expected
+ end
+
+
+ it "share local variables" do
+ input = "<% var = 456 %>"
+ expected = 456
+ var = 123
+ ERB.new(input).result(binding)
+ var.should == expected
+ end
+
+
+ it "is not able to h() or u() unless including ERB::Util" do
+ input = "<%=h '<>' %>"
+ lambda {
+ ERB.new(input).result()
+ }.should raise_error(NameError)
+ end
+
+
+ it "is able to h() or u() if ERB::Util is included" do
+ myerb1 = Class.new do
+ include ERB::Util
+ def main
+ input = "<%=h '<>' %>"
+ return ERB.new(input).result(binding)
+ end
+ end
+ expected = '&lt;&gt;'
+ actual = myerb1.new.main()
+ actual.should == expected
+ end
+
+
+ it "use TOPLEVEL_BINDING if binding is not passed" do
+ myerb2 = Class.new do
+ include ERB::Util
+ def main1
+ #input = "<%= binding.to_s %>"
+ input = "<%= _xxx_var_ %>"
+ return ERB.new(input).result()
+ end
+ def main2
+ input = "<%=h '<>' %>"
+ return ERB.new(input).result()
+ end
+ end
+
+ eval '_xxx_var_ = 123', TOPLEVEL_BINDING
+ expected = '123'
+ myerb2.new.main1().should == expected
+
+ lambda {
+ myerb2.new.main2()
+ }.should raise_error(NameError)
+ end
+end
diff --git a/spec/ruby/library/erb/run_spec.rb b/spec/ruby/library/erb/run_spec.rb
new file mode 100644
index 0000000000..6ad3808a16
--- /dev/null
+++ b/spec/ruby/library/erb/run_spec.rb
@@ -0,0 +1,97 @@
+require 'erb'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "ERB#run" do
+ # TODO: what is this? why does it not use
+ # lambda { ... }.should output
+ def _steal_stdout
+ orig = $stdout
+ s = ''
+ def s.write(arg); self << arg.to_s; end
+ $stdout = s
+ begin
+ yield
+ ensure
+ $stdout = orig
+ end
+ return s
+ end
+
+ it "print the result of compiled ruby code" do
+ input = <<END
+<ul>
+<% for item in list %>
+ <li><%= item %>
+<% end %>
+</ul>
+END
+ expected = <<END
+<ul>
+
+ <li>AAA
+
+ <li>BBB
+
+ <li>CCC
+
+</ul>
+END
+ erb = ERB.new(input)
+ list = %w[AAA BBB CCC]
+ actual = _steal_stdout { erb.run(binding) }
+ actual.should == expected
+ end
+
+ it "share local variables" do
+ input = "<% var = 456 %>"
+ expected = 456
+ var = 123
+ _steal_stdout { ERB.new(input).run(binding) }
+ var.should == expected
+ end
+
+ it "is not able to h() or u() unless including ERB::Util" do
+ input = "<%=h '<>' %>"
+ lambda {
+ _steal_stdout { ERB.new(input).run() }
+ }.should raise_error(NameError)
+ end
+
+ it "is able to h() or u() if ERB::Util is included" do
+ myerb1 = Class.new do
+ include ERB::Util
+ def main
+ input = "<%=h '<>' %>"
+ ERB.new(input).run(binding)
+ end
+ end
+ expected = '&lt;&gt;'
+ actual = _steal_stdout { myerb1.new.main() }
+ actual.should == expected
+ end
+
+ it "use TOPLEVEL_BINDING if binding is not passed" do
+ myerb2 = Class.new do
+ include ERB::Util
+ def main1
+ #input = "<%= binding.to_s %>"
+ input = "<%= _xxx_var_ %>"
+ return ERB.new(input).run()
+ end
+ def main2
+ input = "<%=h '<>' %>"
+ return ERB.new(input).run()
+ end
+ end
+
+ eval '_xxx_var_ = 123', TOPLEVEL_BINDING
+ expected = '123'
+ actual = _steal_stdout { myerb2.new.main1() }
+ actual.should == expected
+
+ lambda {
+ _steal_stdout { myerb2.new.main2() }
+ }.should raise_error(NameError)
+ end
+end
+
diff --git a/spec/ruby/library/erb/src_spec.rb b/spec/ruby/library/erb/src_spec.rb
new file mode 100644
index 0000000000..cf5b67dcbf
--- /dev/null
+++ b/spec/ruby/library/erb/src_spec.rb
@@ -0,0 +1,33 @@
+require 'erb'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "ERB#src" do
+
+ it "returns the compiled ruby code evaluated to a String" do
+ # note that what concrete code is emitted is not guaranteed.
+
+ input = <<'END'
+<ul>
+<% for item in list %>
+ <li><%= item %>
+<% end %>
+</ul>
+END
+
+ expected = <<'END'
+<ul>
+
+ <li>AAA
+
+ <li>BBB
+
+ <li>CCC
+
+</ul>
+END
+
+ list = %w[AAA BBB CCC]
+ eval(ERB.new(input).src).should == expected
+ end
+
+end
diff --git a/spec/ruby/library/erb/util/h_spec.rb b/spec/ruby/library/erb/util/h_spec.rb
new file mode 100644
index 0000000000..ba36574433
--- /dev/null
+++ b/spec/ruby/library/erb/util/h_spec.rb
@@ -0,0 +1,7 @@
+require 'erb'
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/html_escape', __FILE__)
+
+describe "ERB::Util.h" do
+ it_behaves_like :erb_util_html_escape, :h
+end
diff --git a/spec/ruby/library/erb/util/html_escape_spec.rb b/spec/ruby/library/erb/util/html_escape_spec.rb
new file mode 100644
index 0000000000..9bc9359f2c
--- /dev/null
+++ b/spec/ruby/library/erb/util/html_escape_spec.rb
@@ -0,0 +1,8 @@
+require 'erb'
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/html_escape', __FILE__)
+
+describe "ERB::Util.html_escape" do
+ it_behaves_like :erb_util_html_escape, :html_escape
+end
+
diff --git a/spec/ruby/library/erb/util/shared/html_escape.rb b/spec/ruby/library/erb/util/shared/html_escape.rb
new file mode 100644
index 0000000000..71b378755e
--- /dev/null
+++ b/spec/ruby/library/erb/util/shared/html_escape.rb
@@ -0,0 +1,42 @@
+describe :erb_util_html_escape, shared: true do
+ it "escape (& < > \" ') to (&amp; &lt; &gt; &quot; &#39;)" do
+ input = '& < > " \''
+ expected = '&amp; &lt; &gt; &quot; &#39;'
+ ERB::Util.__send__(@method, input).should == expected
+ end
+
+ it "not escape characters except (& < > \" ')" do
+ input = (0x20..0x7E).to_a.collect {|ch| ch.chr}.join('')
+ expected = input.
+ gsub(/&/,'&amp;').
+ gsub(/</,'&lt;').
+ gsub(/>/,'&gt;').
+ gsub(/'/,'&#39;').
+ gsub(/"/,'&quot;')
+ ERB::Util.__send__(@method, input).should == expected
+ end
+
+ it "return empty string when argument is nil" do
+ input = nil
+ expected = ''
+ ERB::Util.__send__(@method, input).should == expected
+ end
+
+ it "returns string when argument is number" do
+ input = 123
+ expected = '123'
+ ERB::Util.__send__(@method, input).should == expected
+ input = 3.14159
+ expected = '3.14159'
+ ERB::Util.__send__(@method, input).should == expected
+ end
+
+ it "returns string when argument is boolean" do
+ input = true
+ expected = 'true'
+ ERB::Util.__send__(@method, input).should == expected
+ input = false
+ expected = 'false'
+ ERB::Util.__send__(@method, input).should == expected
+ end
+end
diff --git a/spec/ruby/library/erb/util/shared/url_encode.rb b/spec/ruby/library/erb/util/shared/url_encode.rb
new file mode 100644
index 0000000000..5ac6215523
--- /dev/null
+++ b/spec/ruby/library/erb/util/shared/url_encode.rb
@@ -0,0 +1,50 @@
+describe :erb_util_url_encode, shared: true do
+ it "encode characters" do
+ #input = (0x20..0x7E).to_a.collect{|ch| ch.chr}.join
+ input = " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}"
+ expected = "%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D"
+ ERB::Util.__send__(@method, input).should == expected
+ end
+
+ ruby_version_is ""..."2.5" do
+ it "escapes tilde" do
+ ERB::Util.__send__(@method, "~").should == "%7E"
+ end
+ end
+
+ ruby_version_is "2.5" do
+ it "does not escape tilde" do
+ ERB::Util.__send__(@method, "~").should == "~"
+ end
+ end
+
+ it "encode unicode string" do
+ input = "http://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277"
+ expected = 'http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF'
+ ERB::Util.__send__(@method, input).should == expected
+ end
+
+ it "returns empty string when argument is nil" do
+ input = nil
+ expected = ''
+ ERB::Util.__send__(@method, input).should == expected
+ end
+
+ it "returns string when argument is number" do
+ input = 123
+ expected = '123'
+ ERB::Util.__send__(@method, input).should == expected
+ input = 3.14159
+ expected = '3.14159'
+ ERB::Util.__send__(@method, input).should == expected
+ end
+
+ it "returns string when argument is boolean" do
+ input = true
+ expected = 'true'
+ ERB::Util.__send__(@method, input).should == expected
+ input = false
+ expected = 'false'
+ ERB::Util.__send__(@method, input).should == expected
+ end
+end
diff --git a/spec/ruby/library/erb/util/u_spec.rb b/spec/ruby/library/erb/util/u_spec.rb
new file mode 100644
index 0000000000..9200244c8e
--- /dev/null
+++ b/spec/ruby/library/erb/util/u_spec.rb
@@ -0,0 +1,8 @@
+require 'erb'
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/url_encode', __FILE__)
+
+describe "ERB::Util.u" do
+ it_behaves_like :erb_util_url_encode, :u
+end
+
diff --git a/spec/ruby/library/erb/util/url_encode_spec.rb b/spec/ruby/library/erb/util/url_encode_spec.rb
new file mode 100644
index 0000000000..303a2e3cd7
--- /dev/null
+++ b/spec/ruby/library/erb/util/url_encode_spec.rb
@@ -0,0 +1,7 @@
+require 'erb'
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/url_encode', __FILE__)
+
+describe "ERB::Util.url_encode" do
+ it_behaves_like :erb_util_url_encode, :url_encode
+end
diff --git a/spec/ruby/library/etc/endgrent_spec.rb b/spec/ruby/library/etc/endgrent_spec.rb
new file mode 100644
index 0000000000..95f0dc05e3
--- /dev/null
+++ b/spec/ruby/library/etc/endgrent_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/windows', __FILE__)
+require 'etc'
+
+describe "Etc.endgrent" do
+ it_behaves_like(:etc_on_windows, :endgrent)
+end
diff --git a/spec/ruby/library/etc/endpwent_spec.rb b/spec/ruby/library/etc/endpwent_spec.rb
new file mode 100644
index 0000000000..7ce8f1925b
--- /dev/null
+++ b/spec/ruby/library/etc/endpwent_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/windows', __FILE__)
+require 'etc'
+
+describe "Etc.endpwent" do
+ it_behaves_like(:etc_on_windows, :endpwent)
+end
diff --git a/spec/ruby/library/etc/getgrent_spec.rb b/spec/ruby/library/etc/getgrent_spec.rb
new file mode 100644
index 0000000000..96225e351a
--- /dev/null
+++ b/spec/ruby/library/etc/getgrent_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/windows', __FILE__)
+require 'etc'
+
+describe "Etc.getgrent" do
+ it_behaves_like(:etc_on_windows, :getgrent)
+end
diff --git a/spec/ruby/library/etc/getgrgid_spec.rb b/spec/ruby/library/etc/getgrgid_spec.rb
new file mode 100644
index 0000000000..9b6b283d52
--- /dev/null
+++ b/spec/ruby/library/etc/getgrgid_spec.rb
@@ -0,0 +1,70 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'etc'
+
+platform_is :windows do
+ describe "Etc.getgrgid" do
+ it "returns nil" do
+ Etc.getgrgid(1).should == nil
+ Etc.getgrgid(nil).should == nil
+ Etc.getgrgid('nil').should == nil
+ end
+ end
+end
+
+# TODO: verify these on non-windows, non-darwin OS
+platform_is_not :windows do
+ describe "Etc.getgrgid" do
+ before :all do
+ @gid = `id -g`.strip.to_i
+ @name = `id -gn`.strip
+ end
+
+ it "returns a Etc::Group struct instance for the given user" do
+ gr = Etc.getgrgid(@gid)
+
+ gr.is_a?(Etc::Group).should == true
+ gr.gid.should == @gid
+ gr.name.should == @name
+ end
+
+ it "returns the Etc::Group for a given gid if it exists" do
+ grp = Etc.getgrgid(@gid)
+ grp.should be_kind_of(Etc::Group)
+ grp.gid.should == @gid
+ grp.name.should == @name
+ end
+
+ it "uses Process.gid as the default value for the argument" do
+ gr = Etc.getgrgid
+
+ gr.gid.should == @gid
+ gr.name.should == @name
+ end
+
+ it "returns the Group for a given gid if it exists" do
+ grp = Etc.getgrgid(@gid)
+ grp.should be_kind_of(Struct::Group)
+ grp.gid.should == @gid
+ grp.name.should == @name
+ end
+
+ it "raises if the group does not exist" do
+ lambda { Etc.getgrgid(9876)}.should raise_error(ArgumentError)
+ end
+
+ it "raises a TypeError if not passed an Integer" do
+ lambda { Etc.getgrgid("foo") }.should raise_error(TypeError)
+ lambda { Etc.getgrgid(nil) }.should raise_error(TypeError)
+ end
+
+ it "can be called safely by multiple threads" do
+ 20.times.map do
+ Thread.new do
+ 100.times do
+ Etc.getgrgid(@gid).gid.should == @gid
+ end
+ end
+ end.each(&:join)
+ end
+ end
+end
diff --git a/spec/ruby/library/etc/getgrnam_spec.rb b/spec/ruby/library/etc/getgrnam_spec.rb
new file mode 100644
index 0000000000..46193f49d6
--- /dev/null
+++ b/spec/ruby/library/etc/getgrnam_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'etc'
+
+platform_is :windows do
+ describe "Etc.getgrnam" do
+ it "returns nil" do
+ Etc.getgrnam(1).should == nil
+ Etc.getgrnam(nil).should == nil
+ Etc.getgrnam('nil').should == nil
+ end
+ end
+end
+
+platform_is_not :windows do
+ describe "Etc.getgrnam" do
+ it "returns a Etc::Group struct instance for the given group" do
+ gr_name = Etc.getgrent.name
+ Etc.endgrent
+ gr = Etc.getgrnam(gr_name)
+ gr.is_a?(Etc::Group).should == true
+ end
+
+ it "only accepts strings as argument" do
+ lambda {
+ Etc.getgrnam(123)
+ Etc.getgrnam(nil)
+ }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/ruby/library/etc/getlogin_spec.rb b/spec/ruby/library/etc/getlogin_spec.rb
new file mode 100644
index 0000000000..ae52942a92
--- /dev/null
+++ b/spec/ruby/library/etc/getlogin_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'etc'
+
+describe "Etc.getlogin" do
+ it "returns the name associated with the current login activity" do
+ getlogin_null = false
+
+ # POSIX logname(1) shows getlogin(2)'s result
+ # NOTE: Etc.getlogin returns ENV['USER'] if getlogin(2) returns NULL
+ begin
+ # make Etc.getlogin to return nil if getlogin(3) returns NULL
+ envuser, ENV['USER'] = ENV['USER'], nil
+ if Etc.getlogin
+ # Etc.getlogin returns the same result of logname(2)
+ # if it returns non NULL
+ Etc.getlogin.should == `id -un`.chomp
+ else
+ # Etc.getlogin may return nil if the login name is not set
+ # because of chroot or sudo or something.
+ Etc.getlogin.should be_nil
+ getlogin_null = true
+ end
+ ensure
+ ENV['USER'] = envuser
+ end
+
+ # if getlogin(2) returns NULL, Etc.getlogin returns ENV['USER']
+ if getlogin_null
+ Etc.getlogin.should == ENV['USER']
+ end
+ end
+end
diff --git a/spec/ruby/library/etc/getpwent_spec.rb b/spec/ruby/library/etc/getpwent_spec.rb
new file mode 100644
index 0000000000..1c8057c9e5
--- /dev/null
+++ b/spec/ruby/library/etc/getpwent_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/windows', __FILE__)
+require 'etc'
+
+describe "Etc.getpwent" do
+ it_behaves_like(:etc_on_windows, :getpwent)
+end
diff --git a/spec/ruby/library/etc/getpwnam_spec.rb b/spec/ruby/library/etc/getpwnam_spec.rb
new file mode 100644
index 0000000000..8610b5da91
--- /dev/null
+++ b/spec/ruby/library/etc/getpwnam_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'etc'
+
+platform_is :windows do
+ describe "Etc.getpwnam" do
+ it "returns nil" do
+ Etc.getpwnam(1).should == nil
+ Etc.getpwnam(nil).should == nil
+ Etc.getpwnam('nil').should == nil
+ end
+ end
+end
+
+platform_is_not :windows do
+ describe "Etc.getpwnam" do
+ it "returns a Etc::Passwd struct instance for the given user" do
+ pw = Etc.getpwnam(`whoami`.strip)
+ pw.is_a?(Etc::Passwd).should == true
+ end
+
+ it "only accepts strings as argument" do
+ lambda {
+ Etc.getpwnam(123)
+ Etc.getpwnam(nil)
+ }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/ruby/library/etc/getpwuid_spec.rb b/spec/ruby/library/etc/getpwuid_spec.rb
new file mode 100644
index 0000000000..f1c7218c0b
--- /dev/null
+++ b/spec/ruby/library/etc/getpwuid_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'etc'
+
+platform_is :windows do
+ describe "Etc.getpwuid" do
+ it "returns nil" do
+ Etc.getpwuid(1).should == nil
+ Etc.getpwuid(nil).should == nil
+ Etc.getpwuid('nil').should == nil
+ end
+ end
+end
+
+platform_is_not :windows do
+ describe "Etc.getpwuid" do
+ before :all do
+ @pw = Etc.getpwuid(`id -u`.strip.to_i)
+ end
+
+ it "returns a Etc::Passwd struct instance for the given user" do
+ @pw.is_a?(Etc::Passwd).should == true
+ end
+
+ it "uses Process.uid as the default value for the argument" do
+ pw = Etc.getpwuid
+ pw.should == @pw
+ end
+
+ it "only accepts integers as argument" do
+ lambda {
+ Etc.getpwuid("foo")
+ Etc.getpwuid(nil)
+ }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/ruby/library/etc/group_spec.rb b/spec/ruby/library/etc/group_spec.rb
new file mode 100644
index 0000000000..8b92cb7bf0
--- /dev/null
+++ b/spec/ruby/library/etc/group_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/windows', __FILE__)
+require 'etc'
+
+describe "Etc.group" do
+ it_behaves_like(:etc_on_windows, :group)
+
+ platform_is_not :windows do
+ it "raises a RuntimeError for parallel iteration" do
+ proc {
+ Etc.group do | group |
+ Etc.group do | group2 |
+ end
+ end
+ }.should raise_error(RuntimeError)
+ end
+ end
+end
diff --git a/spec/ruby/library/etc/nprocessors_spec.rb b/spec/ruby/library/etc/nprocessors_spec.rb
new file mode 100644
index 0000000000..bce11d06c5
--- /dev/null
+++ b/spec/ruby/library/etc/nprocessors_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'etc'
+
+ruby_version_is "2.2" do
+ describe "Etc.nprocessors" do
+ it "returns the number of online processors" do
+ Etc.nprocessors.should be_kind_of(Integer)
+ Etc.nprocessors.should >= 1
+ end
+ end
+end
diff --git a/spec/ruby/library/etc/shared/windows.rb b/spec/ruby/library/etc/shared/windows.rb
new file mode 100644
index 0000000000..8bae235199
--- /dev/null
+++ b/spec/ruby/library/etc/shared/windows.rb
@@ -0,0 +1,7 @@
+describe :etc_on_windows, shared: true do
+ platform_is :windows do
+ it "returns nil" do
+ Etc.send(@method).should == nil
+ end
+ end
+end
diff --git a/spec/ruby/library/etc/struct_group_spec.rb b/spec/ruby/library/etc/struct_group_spec.rb
new file mode 100644
index 0000000000..c33a177a98
--- /dev/null
+++ b/spec/ruby/library/etc/struct_group_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'etc'
+
+describe "Struct::Group" do
+ platform_is_not :windows do
+ before :all do
+ @g = Etc.getgrgid(`id -g`.strip.to_i)
+ end
+
+ it "returns group name" do
+ @g.name.should == `id -gn`.strip
+ end
+
+ it "returns group password" do
+ @g.passwd.is_a?(String).should == true
+ end
+
+ it "returns group id" do
+ @g.gid.should == `id -g`.strip.to_i
+ end
+
+ it "returns an array of users belonging to the group" do
+ @g.mem.is_a?(Array).should == true
+ end
+
+ it "can be compared to another object" do
+ (@g == nil).should == false
+ (@g == Object.new).should == false
+ end
+ end
+end
diff --git a/spec/ruby/library/etc/struct_passwd_spec.rb b/spec/ruby/library/etc/struct_passwd_spec.rb
new file mode 100644
index 0000000000..3e4bfee828
--- /dev/null
+++ b/spec/ruby/library/etc/struct_passwd_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'etc'
+
+describe "Struct::Passwd" do
+ platform_is_not :windows do
+ before :all do
+ @pw = Etc.getpwuid(`id -u`.strip.to_i)
+ end
+
+ it "returns user name" do
+ @pw.name.should == `id -un`.strip
+ end
+
+ it "returns user password" do
+ @pw.passwd.is_a?(String).should == true
+ end
+
+ it "returns user id" do
+ @pw.uid.should == `id -u`.strip.to_i
+ end
+
+ it "returns user group id" do
+ @pw.gid.should == `id -g`.strip.to_i
+ end
+
+ it "returns user personal information (gecos field)" do
+ @pw.gecos.is_a?(String).should == true
+ end
+
+ it "returns user home directory" do
+ @pw.dir.is_a?(String).should == true
+ end
+
+ it "returns user shell" do
+ @pw.shell.is_a?(String).should == true
+ end
+
+ it "can be compared to another object" do
+ (@pw == nil).should == false
+ (@pw == Object.new).should == false
+ end
+ end
+end
diff --git a/spec/ruby/library/expect/expect_spec.rb b/spec/ruby/library/expect/expect_spec.rb
new file mode 100644
index 0000000000..080f3d7af4
--- /dev/null
+++ b/spec/ruby/library/expect/expect_spec.rb
@@ -0,0 +1,62 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'expect'
+
+ describe "IO#expect" do
+ before :each do
+ @read, @write = IO.pipe
+ end
+
+ after :each do
+ @read.close unless @read.closed?
+ @write.close unless @write.closed?
+ end
+
+ it "matches data against a Regexp" do
+ @write << "prompt> hello"
+
+ result = @read.expect(/[pf]rompt>/)
+ result.should == ["prompt>"]
+ end
+
+ it "matches data against a String" do
+ @write << "prompt> hello"
+
+ result = @read.expect("prompt>")
+ result.should == ["prompt>"]
+ end
+
+ it "returns any captures of the Regexp" do
+ @write << "prompt> hello"
+
+ result = @read.expect(/(pro)mpt(>)/)
+ result.should == ["prompt>", "pro", ">"]
+ end
+
+ it "returns raises IOError if the IO is closed" do
+ @write << "prompt> hello"
+ @read.close
+
+ lambda {
+ @read.expect("hello")
+ }.should raise_error(IOError)
+ end
+
+ it "returns nil if eof is hit" do
+ @write << "pro"
+ @write.close
+
+ @read.expect("prompt").should be_nil
+ end
+
+ it "yields the result if a block is given" do
+ @write << "prompt> hello"
+
+ res = nil
+
+ @read.expect("prompt>") { |x| res = x }
+
+ res.should == ["prompt>"]
+ end
+ end
+end
diff --git a/spec/ruby/library/fiber/alive_spec.rb b/spec/ruby/library/fiber/alive_spec.rb
new file mode 100644
index 0000000000..fbd5c4bc1a
--- /dev/null
+++ b/spec/ruby/library/fiber/alive_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+with_feature :fiber_library do
+ require 'fiber'
+
+ describe "Fiber#alive?" do
+ it "returns true for a Fiber that hasn't had #resume called" do
+ fiber = Fiber.new { true }
+ fiber.alive?.should be_true
+ end
+
+ # FIXME: Better description?
+ it "returns true for a Fiber that's yielded to the caller" do
+ fiber = Fiber.new { Fiber.yield }
+ fiber.resume
+ fiber.alive?.should be_true
+ end
+
+ it "returns true when called from its Fiber" do
+ fiber = Fiber.new { fiber.alive?.should be_true }
+ fiber.resume
+ end
+
+ it "doesn't invoke the block associated with the Fiber" do
+ offthehook = mock('do not call')
+ offthehook.should_not_receive(:ring)
+ fiber = Fiber.new { offthehook.ring }
+ fiber.alive?
+ end
+
+ it "returns false for a Fiber that's dead" do
+ fiber = Fiber.new { true }
+ fiber.resume
+ lambda { fiber.resume }.should raise_error(FiberError)
+ fiber.alive?.should be_false
+ end
+
+ it "always returns false for a dead Fiber" do
+ fiber = Fiber.new { true }
+ fiber.resume
+ lambda { fiber.resume }.should raise_error(FiberError)
+ fiber.alive?.should be_false
+ lambda { fiber.resume }.should raise_error(FiberError)
+ fiber.alive?.should be_false
+ fiber.alive?.should be_false
+ end
+ end
+end
diff --git a/spec/ruby/library/fiber/current_spec.rb b/spec/ruby/library/fiber/current_spec.rb
new file mode 100644
index 0000000000..48345fb7cf
--- /dev/null
+++ b/spec/ruby/library/fiber/current_spec.rb
@@ -0,0 +1,61 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+with_feature :fiber_library do
+ require 'fiber'
+
+ describe "Fiber.current" do
+ it "returns the root Fiber when called outside of a Fiber" do
+ root = Fiber.current
+ root.should be_an_instance_of(Fiber)
+ # We can always transfer to the root Fiber; it will never die
+ 5.times do
+ root.transfer.should be_nil
+ root.alive?.should_not be_false #Workaround for bug #1547
+ end
+ end
+
+ it "returns the current Fiber when called from a Fiber" do
+ fiber = Fiber.new do
+ this = Fiber.current
+ this.should be_an_instance_of(Fiber)
+ this.should == fiber
+ this.alive?.should_not be_false # Workaround for bug #1547
+ end
+ fiber.resume
+ end
+
+ it "returns the current Fiber when called from a Fiber that transferred to another" do
+
+ states = []
+ fiber = Fiber.new do
+ states << :fiber
+ this = Fiber.current
+ this.should be_an_instance_of(Fiber)
+ this.should === fiber
+ this.alive?.should_not be_false # Workaround for bug #1547
+ end
+
+ fiber2 = Fiber.new do
+ states << :fiber2
+ fiber.transfer
+ this = Fiber.current
+ this.should be_an_instance_of(Fiber)
+ this.should === fiber2
+ this.alive?.should_not be_false # Workaround for bug #1547
+ end
+
+ fiber3 = Fiber.new do
+ states << :fiber3
+ fiber2.transfer
+ this = Fiber.current
+ this.should be_an_instance_of(Fiber)
+ this.should === fiber3
+ this.alive?.should_not be_false # Workaround for bug #1547
+ fiber2.transfer
+ end
+
+ fiber3.resume
+ states.should == [:fiber3, :fiber2, :fiber]
+ end
+ end
+end
diff --git a/spec/ruby/library/fiber/resume_spec.rb b/spec/ruby/library/fiber/resume_spec.rb
new file mode 100644
index 0000000000..8709d01142
--- /dev/null
+++ b/spec/ruby/library/fiber/resume_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+with_feature :fiber_library do
+ require 'fiber'
+
+ describe "Fiber#resume" do
+ it "raises a FiberError if the Fiber has transfered control to another Fiber" do
+ fiber1 = Fiber.new { true }
+ fiber2 = Fiber.new { fiber1.transfer; Fiber.yield }
+ fiber2.resume
+ lambda { fiber2.resume }.should raise_error(FiberError)
+ end
+ end
+end
diff --git a/spec/ruby/library/fiber/transfer_spec.rb b/spec/ruby/library/fiber/transfer_spec.rb
new file mode 100644
index 0000000000..79319a7d39
--- /dev/null
+++ b/spec/ruby/library/fiber/transfer_spec.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/fiber/resume', __FILE__)
+
+with_feature :fiber_library do
+ require 'fiber'
+
+ describe "Fiber#transfer" do
+ it_behaves_like :fiber_resume, :transfer
+ end
+
+ describe "Fiber#transfer" do
+ it "transfers control from one Fiber to another when called from a Fiber" do
+ fiber1 = Fiber.new { :fiber1 }
+ fiber2 = Fiber.new { fiber1.transfer; :fiber2 }
+ fiber2.resume.should == :fiber1
+ end
+
+ it "returns to the root Fiber when finished" do
+ f1 = Fiber.new { :fiber_1 }
+ f2 = Fiber.new { f1.transfer; :fiber_2 }
+
+ f2.transfer.should == :fiber_1
+ f2.transfer.should == :fiber_2
+ end
+
+ it "can be invoked from the same Fiber it transfers control to" do
+ states = []
+ fiber = Fiber.new { states << :start; fiber.transfer; states << :end }
+ fiber.transfer
+ states.should == [:start, :end]
+
+ states = []
+ fiber = Fiber.new { states << :start; fiber.transfer; states << :end }
+ fiber.resume
+ states.should == [:start, :end]
+ end
+
+ it "can transfer control to a Fiber that has transfered to another Fiber" do
+ states = []
+ fiber1 = Fiber.new { states << :fiber1 }
+ fiber2 = Fiber.new { states << :fiber2_start; fiber1.transfer; states << :fiber2_end}
+ fiber2.resume.should == [:fiber2_start, :fiber1]
+ fiber2.transfer.should == [:fiber2_start, :fiber1, :fiber2_end]
+ end
+
+ it "raises a FiberError when transferring to a Fiber which resumes itself" do
+ fiber = Fiber.new { fiber.resume }
+ lambda { fiber.transfer }.should raise_error(FiberError)
+ end
+ end
+end
diff --git a/spec/ruby/library/find/find_spec.rb b/spec/ruby/library/find/find_spec.rb
new file mode 100644
index 0000000000..14c9e2926e
--- /dev/null
+++ b/spec/ruby/library/find/find_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+require 'find'
+
+describe "Find.find" do
+ before :each do
+ FindDirSpecs.create_mock_dirs
+ end
+
+ after :each do
+ FindDirSpecs.delete_mock_dirs
+ end
+
+ describe "when called without a block" do
+ it "returns an Enumerator" do
+ Find.find(FindDirSpecs.mock_dir).should be_an_instance_of(Enumerator)
+ Find.find(FindDirSpecs.mock_dir).to_a.sort.should == FindDirSpecs.expected_paths
+ end
+ end
+
+ it "should recursively yield every file in the directory" do
+ a = []
+
+ Find.find(FindDirSpecs.mock_dir) do |file|
+ a << file
+ end
+
+ a.sort.should == FindDirSpecs.expected_paths
+ end
+end
diff --git a/spec/ruby/library/find/fixtures/common.rb b/spec/ruby/library/find/fixtures/common.rb
new file mode 100644
index 0000000000..14a7edb09a
--- /dev/null
+++ b/spec/ruby/library/find/fixtures/common.rb
@@ -0,0 +1,174 @@
+module FindDirSpecs
+ def self.mock_dir(dirs = ['find_specs_mock'])
+ @mock_dir ||= tmp("")
+ File.join @mock_dir, dirs
+ end
+
+ # The names of the fixture directories and files used by
+ # various Find specs.
+ def self.mock_dir_files
+ unless @mock_dir_files
+ @mock_dir_files = %w[
+ .dotfile
+ .dotsubdir/.dotfile
+ .dotsubdir/nondotfile
+
+ deeply/.dotfile
+ deeply/nested/.dotfile.ext
+ deeply/nested/directory/structure/.ext
+ deeply/nested/directory/structure/bar
+ deeply/nested/directory/structure/baz
+ deeply/nested/directory/structure/file_one
+ deeply/nested/directory/structure/file_one.ext
+ deeply/nested/directory/structure/foo
+ deeply/nondotfile
+
+ file_one.ext
+ file_two.ext
+
+ dir_filename_ordering
+ dir/filename_ordering
+
+ nondotfile
+
+ subdir_one/.dotfile
+ subdir_one/nondotfile
+ subdir_two/nondotfile
+ subdir_two/nondotfile.ext
+
+ brace/a
+ brace/a.js
+ brace/a.erb
+ brace/a.js.rjs
+ brace/a.html.erb
+
+ special/+
+
+ special/^
+ special/$
+
+ special/(
+ special/)
+ special/[
+ special/]
+ special/{
+ special/}
+
+ special/test{1}/file[1]
+ ]
+
+ platform_is_not :windows do
+ @mock_dir_files += %w[
+ special/*
+ special/?
+
+ special/|
+ ]
+ end
+ end
+
+ @mock_dir_files
+ end
+
+ def self.create_mock_dirs
+ umask = File.umask 0
+ mock_dir_files.each do |name|
+ file = File.join mock_dir, name
+ mkdir_p File.dirname(file)
+ touch file
+ end
+ File.umask umask
+ end
+
+ def self.delete_mock_dirs
+ rm_r mock_dir
+ end
+
+ def self.expected_paths
+ unless @expected_paths
+ @expected_paths = %w[
+ .dotfile
+
+ .dotsubdir
+ .dotsubdir/.dotfile
+ .dotsubdir/nondotfile
+
+ deeply
+ deeply/.dotfile
+
+ deeply/nested
+ deeply/nested/.dotfile.ext
+
+ deeply/nested/directory
+
+ deeply/nested/directory/structure
+ deeply/nested/directory/structure/.ext
+ deeply/nested/directory/structure/bar
+ deeply/nested/directory/structure/baz
+ deeply/nested/directory/structure/file_one
+ deeply/nested/directory/structure/file_one.ext
+ deeply/nested/directory/structure/foo
+ deeply/nondotfile
+
+ file_one.ext
+ file_two.ext
+
+ dir_filename_ordering
+
+ dir
+ dir/filename_ordering
+
+ nondotfile
+
+ subdir_one
+ subdir_one/.dotfile
+ subdir_one/nondotfile
+
+ subdir_two
+ subdir_two/nondotfile
+ subdir_two/nondotfile.ext
+
+ brace
+ brace/a
+ brace/a.js
+ brace/a.erb
+ brace/a.js.rjs
+ brace/a.html.erb
+
+ special
+ special/+
+
+ special/^
+ special/$
+
+ special/(
+ special/)
+ special/[
+ special/]
+ special/{
+ special/}
+
+ special/test{1}
+ special/test{1}/file[1]
+ ]
+
+ platform_is_not :windows do
+ @expected_paths += %w[
+ special/*
+ special/?
+
+ special/|
+ ]
+ end
+
+ @expected_paths.map! do |file|
+ File.join(mock_dir, file)
+ end
+
+ @expected_paths << mock_dir
+ @expected_paths.sort!
+ end
+
+ @expected_paths
+ end
+end
diff --git a/spec/ruby/library/find/prune_spec.rb b/spec/ruby/library/find/prune_spec.rb
new file mode 100644
index 0000000000..1aef7d3d23
--- /dev/null
+++ b/spec/ruby/library/find/prune_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'find'
+
+describe "Find.prune" do
+ it "should throw :prune" do
+ msg = catch(:prune) do
+ Find.prune
+ end
+
+ msg.should == nil
+ end
+end
diff --git a/spec/ruby/library/getoptlong/each_option_spec.rb b/spec/ruby/library/getoptlong/each_option_spec.rb
new file mode 100644
index 0000000000..c58815bfa9
--- /dev/null
+++ b/spec/ruby/library/getoptlong/each_option_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+require File.expand_path('../shared/each', __FILE__)
+
+describe "GetoptLong#each_option" do
+ it_behaves_like(:getoptlong_each, :each_option)
+end
diff --git a/spec/ruby/library/getoptlong/each_spec.rb b/spec/ruby/library/getoptlong/each_spec.rb
new file mode 100644
index 0000000000..d09f84a6db
--- /dev/null
+++ b/spec/ruby/library/getoptlong/each_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+require File.expand_path('../shared/each', __FILE__)
+
+describe "GetoptLong#each" do
+ it_behaves_like(:getoptlong_each, :each)
+end
diff --git a/spec/ruby/library/getoptlong/error_message_spec.rb b/spec/ruby/library/getoptlong/error_message_spec.rb
new file mode 100644
index 0000000000..3f44f538c6
--- /dev/null
+++ b/spec/ruby/library/getoptlong/error_message_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+
+describe "GetoptLong#error_message" do
+ it "returns nil if no error occurred" do
+ opts = GetoptLong.new
+ opts.error_message.should == nil
+ end
+
+ it "returns the error message of the last error that occurred" do
+ argv [] do
+ opts = GetoptLong.new
+ opts.quiet = true
+ opts.get
+ -> {
+ opts.ordering = GetoptLong::PERMUTE
+ }.should raise_error(ArgumentError) { |e|
+ e.message.should == "argument error"
+ opts.error_message.should == "argument error"
+ }
+ end
+ end
+end
diff --git a/spec/ruby/library/getoptlong/get_option_spec.rb b/spec/ruby/library/getoptlong/get_option_spec.rb
new file mode 100644
index 0000000000..c56903e68e
--- /dev/null
+++ b/spec/ruby/library/getoptlong/get_option_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+require File.expand_path('../shared/get', __FILE__)
+
+describe "GetoptLong#get_option" do
+ it_behaves_like(:getoptlong_get, :get_option)
+end
diff --git a/spec/ruby/library/getoptlong/get_spec.rb b/spec/ruby/library/getoptlong/get_spec.rb
new file mode 100644
index 0000000000..ba1a1be6ad
--- /dev/null
+++ b/spec/ruby/library/getoptlong/get_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+require File.expand_path('../shared/get', __FILE__)
+
+describe "GetoptLong#get" do
+ it_behaves_like(:getoptlong_get, :get)
+end
diff --git a/spec/ruby/library/getoptlong/initialize_spec.rb b/spec/ruby/library/getoptlong/initialize_spec.rb
new file mode 100644
index 0000000000..6ac46b8b5d
--- /dev/null
+++ b/spec/ruby/library/getoptlong/initialize_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+
+describe "GetoptLong#initialize" do
+ it "sets ordering to REQUIRE_ORDER if ENV['POSIXLY_CORRECT'] is set" do
+ begin
+ old_env_value = ENV["POSIXLY_CORRECT"]
+ ENV["POSIXLY_CORRECT"] = ""
+
+ opt = GetoptLong.new
+ opt.ordering.should == GetoptLong::REQUIRE_ORDER
+ ensure
+ ENV["POSIXLY_CORRECT"] = old_env_value
+ end
+ end
+
+ it "sets ordering to PERMUTE if ENV['POSIXLY_CORRECT'] is not set" do
+ begin
+ old_env_value = ENV["POSIXLY_CORRECT"]
+ ENV["POSIXLY_CORRECT"] = nil
+
+ opt = GetoptLong.new
+ opt.ordering.should == GetoptLong::PERMUTE
+ ensure
+ ENV["POSIXLY_CORRECT"] = old_env_value
+ end
+ end
+end
diff --git a/spec/ruby/library/getoptlong/ordering_spec.rb b/spec/ruby/library/getoptlong/ordering_spec.rb
new file mode 100644
index 0000000000..e445de2255
--- /dev/null
+++ b/spec/ruby/library/getoptlong/ordering_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+
+describe "GetoptLong#ordering=" do
+ it "raises an ArgumentError if called after processing has started" do
+ argv [ "--size", "10k", "--verbose" ] do
+ opts = GetoptLong.new([ '--size', GetoptLong::REQUIRED_ARGUMENT ],
+ [ '--verbose', GetoptLong::NO_ARGUMENT ])
+ opts.quiet = true
+ opts.get
+
+ lambda {
+ opts.ordering = GetoptLong::PERMUTE
+ }.should raise_error(ArgumentError)
+ end
+ end
+
+ it "raises an ArgumentError if given an invalid value" do
+ opts = GetoptLong.new
+
+ lambda {
+ opts.ordering = 12345
+ }.should raise_error(ArgumentError)
+ end
+
+ it "does not allow changing ordering to PERMUTE if ENV['POSIXLY_CORRECT'] is set" do
+ begin
+ old_env_value = ENV['POSIXLY_CORRECT']
+ ENV['POSIXLY_CORRECT'] = ""
+
+ opts = GetoptLong.new
+ opts.ordering = GetoptLong::PERMUTE
+ opts.ordering.should == GetoptLong::REQUIRE_ORDER
+ ensure
+ ENV['POSIXLY_CORRECT'] = old_env_value
+ end
+ end
+end
diff --git a/spec/ruby/library/getoptlong/set_options_spec.rb b/spec/ruby/library/getoptlong/set_options_spec.rb
new file mode 100644
index 0000000000..39d6991bf5
--- /dev/null
+++ b/spec/ruby/library/getoptlong/set_options_spec.rb
@@ -0,0 +1,98 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+
+describe "GetoptLong#set_options" do
+ before :each do
+ @opts = GetoptLong.new
+ end
+
+ it "allows setting command line options" do
+ argv ["--size", "10k", "-v", "arg1", "arg2"] do
+ @opts.set_options(
+ ["--size", GetoptLong::REQUIRED_ARGUMENT],
+ ["--verbose", "-v", GetoptLong::NO_ARGUMENT]
+ )
+
+ @opts.get.should == ["--size", "10k"]
+ @opts.get.should == ["--verbose", ""]
+ @opts.get.should == nil
+ end
+ end
+
+ it "discards previously defined command line options" do
+ argv ["--size", "10k", "-v", "arg1", "arg2"] do
+ @opts.set_options(
+ ["--size", GetoptLong::REQUIRED_ARGUMENT],
+ ["--verbose", "-v", GetoptLong::NO_ARGUMENT]
+ )
+
+ @opts.set_options(
+ ["-s", "--size", GetoptLong::REQUIRED_ARGUMENT],
+ ["-v", GetoptLong::NO_ARGUMENT]
+ )
+
+ @opts.get.should == ["-s", "10k"]
+ @opts.get.should == ["-v", ""]
+ @opts.get.should == nil
+ end
+ end
+
+ it "raises an ArgumentError if too many argument flags where given" do
+ argv [] do
+ lambda {
+ @opts.set_options(["--size", GetoptLong::NO_ARGUMENT, GetoptLong::REQUIRED_ARGUMENT])
+ }.should raise_error(ArgumentError)
+ end
+ end
+
+ it "raises a RuntimeError if processing has already started" do
+ argv [] do
+ @opts.get
+ lambda {
+ @opts.set_options()
+ }.should raise_error(RuntimeError)
+ end
+ end
+
+ it "raises an ArgumentError if no argument flag was given" do
+ argv [] do
+ lambda {
+ @opts.set_options(["--size"])
+ }.should raise_error(ArgumentError)
+ end
+ end
+
+ it "raises an ArgumentError if one of the given arguments is not an Array" do
+ argv [] do
+ lambda {
+ @opts.set_options(
+ ["--size", GetoptLong::REQUIRED_ARGUMENT],
+ "test")
+ }.should raise_error(ArgumentError)
+ end
+ end
+
+ it "raises an ArgumentError if the same option is given twice" do
+ argv [] do
+ lambda {
+ @opts.set_options(
+ ["--size", GetoptLong::NO_ARGUMENT],
+ ["--size", GetoptLong::OPTIONAL_ARGUMENT])
+ }.should raise_error(ArgumentError)
+
+ lambda {
+ @opts.set_options(
+ ["--size", GetoptLong::NO_ARGUMENT],
+ ["-s", "--size", GetoptLong::OPTIONAL_ARGUMENT])
+ }.should raise_error(ArgumentError)
+ end
+ end
+
+ it "raises an ArgumentError if the given option is invalid" do
+ argv [] do
+ lambda {
+ @opts.set_options(["-size", GetoptLong::NO_ARGUMENT])
+ }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/ruby/library/getoptlong/shared/each.rb b/spec/ruby/library/getoptlong/shared/each.rb
new file mode 100644
index 0000000000..b534e24c0f
--- /dev/null
+++ b/spec/ruby/library/getoptlong/shared/each.rb
@@ -0,0 +1,18 @@
+describe :getoptlong_each, shared: true do
+ before :each do
+ @opts = GetoptLong.new(
+ [ '--size', '-s', GetoptLong::REQUIRED_ARGUMENT ],
+ [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
+ [ '--query', '-q', GetoptLong::NO_ARGUMENT ],
+ [ '--check', '--valid', '-c', GetoptLong::NO_ARGUMENT ]
+ )
+ end
+
+ it "passes each argument/value pair to the block" do
+ argv [ "--size", "10k", "-v", "-q", "a.txt", "b.txt" ] do
+ pairs = []
+ @opts.send(@method) { |arg, val| pairs << [ arg, val ] }
+ pairs.should == [ [ "--size", "10k" ], [ "--verbose", "" ], [ "--query", ""] ]
+ end
+ end
+end
diff --git a/spec/ruby/library/getoptlong/shared/get.rb b/spec/ruby/library/getoptlong/shared/get.rb
new file mode 100644
index 0000000000..91a0fbaacc
--- /dev/null
+++ b/spec/ruby/library/getoptlong/shared/get.rb
@@ -0,0 +1,64 @@
+describe :getoptlong_get, shared: true do
+ before :each do
+ @opts = GetoptLong.new(
+ [ '--size', '-s', GetoptLong::REQUIRED_ARGUMENT ],
+ [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
+ [ '--query', '-q', GetoptLong::NO_ARGUMENT ],
+ [ '--check', '--valid', '-c', GetoptLong::NO_ARGUMENT ]
+ )
+ @opts.quiet = true # silence using $deferr
+ end
+
+ it "returns the next option name and its argument as an Array" do
+ argv [ "--size", "10k", "-v", "-q", "a.txt", "b.txt" ] do
+ @opts.send(@method).should == [ "--size", "10k" ]
+ @opts.send(@method).should == [ "--verbose", "" ]
+ @opts.send(@method).should == [ "--query", ""]
+ @opts.send(@method).should == nil
+ end
+ end
+
+ it "shifts ARGV on each call" do
+ argv [ "--size", "10k", "-v", "-q", "a.txt", "b.txt" ] do
+ @opts.send(@method)
+ ARGV.should == [ "-v", "-q", "a.txt", "b.txt" ]
+
+ @opts.send(@method)
+ ARGV.should == [ "-q", "a.txt", "b.txt" ]
+
+ @opts.send(@method)
+ ARGV.should == [ "a.txt", "b.txt" ]
+
+ @opts.send(@method)
+ ARGV.should == [ "a.txt", "b.txt" ]
+ end
+ end
+
+ it "terminates processing when encountering '--'" do
+ argv [ "--size", "10k", "--", "-v", "-q", "a.txt", "b.txt" ] do
+ @opts.send(@method)
+ ARGV.should == ["--", "-v", "-q", "a.txt", "b.txt"]
+
+ @opts.send(@method)
+ ARGV.should == ["-v", "-q", "a.txt", "b.txt"]
+
+ @opts.send(@method)
+ ARGV.should == ["-v", "-q", "a.txt", "b.txt"]
+ end
+ end
+
+ it "raises a if an argument was required, but none given" do
+ argv [ "--size" ] do
+ lambda { @opts.send(@method) }.should raise_error(GetoptLong::MissingArgument)
+ end
+ end
+
+ ruby_version_is "2.5" do
+ # https://bugs.ruby-lang.org/issues/13858
+ it "returns multiline argument" do
+ argv [ "--size=\n10k\n" ] do
+ @opts.send(@method).should == [ "--size", "\n10k\n" ]
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/getoptlong/terminate_spec.rb b/spec/ruby/library/getoptlong/terminate_spec.rb
new file mode 100644
index 0000000000..ad9f9a1623
--- /dev/null
+++ b/spec/ruby/library/getoptlong/terminate_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+
+describe "GetoptLong#terminate" do
+ before :each do
+ @opts = GetoptLong.new(
+ [ '--size', '-s', GetoptLong::REQUIRED_ARGUMENT ],
+ [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
+ [ '--query', '-q', GetoptLong::NO_ARGUMENT ],
+ [ '--check', '--valid', '-c', GetoptLong::NO_ARGUMENT ]
+ )
+ end
+
+ it "terminates option proccessing" do
+ argv [ "--size", "10k", "-v", "-q", "a.txt", "b.txt" ] do
+ @opts.get.should == [ "--size", "10k" ]
+ @opts.terminate
+ @opts.get.should == nil
+ end
+ end
+
+ it "returns self when option processsing is terminated" do
+ @opts.terminate.should == @opts
+ end
+
+ it "returns nil when option processing was already terminated" do
+ @opts.terminate
+ @opts.terminate.should == nil
+ end
+end
diff --git a/spec/ruby/library/getoptlong/terminated_spec.rb b/spec/ruby/library/getoptlong/terminated_spec.rb
new file mode 100644
index 0000000000..feaf2bc09e
--- /dev/null
+++ b/spec/ruby/library/getoptlong/terminated_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'getoptlong'
+
+describe "GetoptLong#terminated?" do
+ it "returns true if option processing has terminated" do
+ argv [ "--size", "10k" ] do
+ opts = GetoptLong.new(["--size", GetoptLong::REQUIRED_ARGUMENT])
+ opts.terminated?.should == false
+
+ opts.get.should == ["--size", "10k"]
+ opts.terminated?.should == false
+
+ opts.get.should == nil
+ opts.terminated?.should == true
+ end
+ end
+end
diff --git a/spec/ruby/library/ipaddr/hton_spec.rb b/spec/ruby/library/ipaddr/hton_spec.rb
new file mode 100644
index 0000000000..037bb3d328
--- /dev/null
+++ b/spec/ruby/library/ipaddr/hton_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ipaddr'
+
+describe "IPAddr#hton" do
+
+ it "converts IPAddr to network byte order" do
+ addr = ''
+ IPAddr.new("1234:5678:9abc:def0:1234:5678:9abc:def0").hton.each_byte do |c|
+ addr += sprintf("%02x", c)
+ end
+ addr.should == "123456789abcdef0123456789abcdef0"
+ addr = ''
+ IPAddr.new("123.45.67.89").hton.each_byte do |c|
+ addr += sprintf("%02x", c)
+ end
+ addr.should == sprintf("%02x%02x%02x%02x", 123, 45, 67, 89)
+ end
+
+end
+
+describe "IPAddr#new_ntoh" do
+
+ it "creates a new IPAddr using hton notation" do
+ a = IPAddr.new("3ffe:505:2::")
+ IPAddr.new_ntoh(a.hton).to_s.should == "3ffe:505:2::"
+ a = IPAddr.new("192.168.2.1")
+ IPAddr.new_ntoh(a.hton).to_s.should == "192.168.2.1"
+ end
+
+end
diff --git a/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb b/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb
new file mode 100644
index 0000000000..b69be82c13
--- /dev/null
+++ b/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ipaddr'
+
+describe "IPAddr#ipv4_compat" do
+
+ it "should ipv4_compat?" do
+ a = IPAddr.new("::192.168.1.2")
+ a.to_s.should == "::192.168.1.2"
+ a.to_string.should == "0000:0000:0000:0000:0000:0000:c0a8:0102"
+ a.family.should == Socket::AF_INET6
+ a.ipv4_compat?.should == true
+ b = a.native
+ b.to_s.should == "192.168.1.2"
+ b.family.should == Socket::AF_INET
+ b.ipv4_compat?.should == false
+
+ a = IPAddr.new("192.168.1.2")
+ b = a.ipv4_compat
+ b.to_s.should == "::192.168.1.2"
+ b.family.should == Socket::AF_INET6
+ end
+
+end
+
+describe "IPAddr#ipv4_mapped" do
+
+ it "should ipv4_mapped" do
+ a = IPAddr.new("::ffff:192.168.1.2")
+ a.to_s.should == "::ffff:192.168.1.2"
+ a.to_string.should == "0000:0000:0000:0000:0000:ffff:c0a8:0102"
+ a.family.should == Socket::AF_INET6
+ a.ipv4_mapped?.should == true
+ b = a.native
+ b.to_s.should == "192.168.1.2"
+ b.family.should == Socket::AF_INET
+ b.ipv4_mapped?.should == false
+
+ a = IPAddr.new("192.168.1.2")
+ b = a.ipv4_mapped
+ b.to_s.should == "::ffff:192.168.1.2"
+ b.family.should == Socket::AF_INET6
+ end
+
+end
+
+
diff --git a/spec/ruby/library/ipaddr/new_spec.rb b/spec/ruby/library/ipaddr/new_spec.rb
new file mode 100644
index 0000000000..d0b91af87d
--- /dev/null
+++ b/spec/ruby/library/ipaddr/new_spec.rb
@@ -0,0 +1,93 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ipaddr'
+
+describe "IPAddr#new" do
+ it "initializes IPAddr" do
+ lambda{ IPAddr.new("3FFE:505:ffff::/48") }.should_not raise_error
+ lambda{ IPAddr.new("0:0:0:1::") }.should_not raise_error
+ lambda{ IPAddr.new("2001:200:300::/48") }.should_not raise_error
+ end
+
+ it "initializes IPAddr ipv6 address with short notation" do
+ a = IPAddr.new
+ a.to_s.should == "::"
+ a.to_string.should == "0000:0000:0000:0000:0000:0000:0000:0000"
+ a.family.should == Socket::AF_INET6
+ end
+
+ it "initializes IPAddr ipv6 address with long notation" do
+ a = IPAddr.new("0123:4567:89ab:cdef:0ABC:DEF0:1234:5678")
+ a.to_s.should == "123:4567:89ab:cdef:abc:def0:1234:5678"
+ a.to_string.should == "0123:4567:89ab:cdef:0abc:def0:1234:5678"
+ a.family.should == Socket::AF_INET6
+ end
+
+ it "initializes IPAddr ipv6 address with / subnet notation" do
+ a = IPAddr.new("3ffe:505:2::/48")
+ a.to_s.should == "3ffe:505:2::"
+ a.to_string.should == "3ffe:0505:0002:0000:0000:0000:0000:0000"
+ a.family.should == Socket::AF_INET6
+ a.ipv4?.should == false
+ a.ipv6?.should == true
+ a.inspect.should == "#<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000>"
+ end
+
+ it "initializes IPAddr ipv6 address with mask subnet notation" do
+ a = IPAddr.new("3ffe:505:2::/ffff:ffff:ffff::")
+ a.to_s.should == "3ffe:505:2::"
+ a.to_string.should == "3ffe:0505:0002:0000:0000:0000:0000:0000"
+ a.family.should == Socket::AF_INET6
+ end
+
+ it "initializes IPAddr ipv4 address with all zeroes" do
+ a = IPAddr.new("0.0.0.0")
+ a.to_s.should == "0.0.0.0"
+ a.to_string.should == "0.0.0.0"
+ a.family.should == Socket::AF_INET
+ end
+
+ it "initializes IPAddr ipv4 address" do
+ a = IPAddr.new("192.168.1.2")
+ a.to_s.should == "192.168.1.2"
+ a.to_string.should == "192.168.1.2"
+ a.family.should == Socket::AF_INET
+ a.ipv4?.should == true
+ a.ipv6?.should == false
+ end
+
+ it "initializes IPAddr ipv4 address with / subnet notation" do
+ a = IPAddr.new("192.168.1.2/24")
+ a.to_s.should == "192.168.1.0"
+ a.to_string.should == "192.168.1.0"
+ a.family.should == Socket::AF_INET
+ a.inspect.should == "#<IPAddr: IPv4:192.168.1.0/255.255.255.0>"
+ end
+
+ it "initializes IPAddr ipv4 address with subnet mask" do
+ a = IPAddr.new("192.168.1.2/255.255.255.0")
+ a.to_s.should == "192.168.1.0"
+ a.to_string.should == "192.168.1.0"
+ a.family.should == Socket::AF_INET
+ end
+
+ it "initializes IPAddr ipv4 mapped address with subnet mask" do
+ a = IPAddr.new("::1:192.168.1.2/120")
+ a.to_s.should == "::1:c0a8:100"
+ a.to_string.should == "0000:0000:0000:0000:0000:0001:c0a8:0100"
+ a.family.should == Socket::AF_INET6
+ end
+
+ it "raises on incorrect IPAddr strings" do
+ [
+ ["fe80::1%fxp0"],
+ ["::1/255.255.255.0"],
+ [IPAddr.new("::1").to_i],
+ ["::ffff:192.168.1.2/120", Socket::AF_INET],
+ ["[192.168.1.2]/120"],
+ ].each { |args|
+ lambda{
+ IPAddr.new(*args)
+ }.should raise_error(ArgumentError)
+ }
+ end
+end
diff --git a/spec/ruby/library/ipaddr/operator_spec.rb b/spec/ruby/library/ipaddr/operator_spec.rb
new file mode 100644
index 0000000000..3f54efd486
--- /dev/null
+++ b/spec/ruby/library/ipaddr/operator_spec.rb
@@ -0,0 +1,80 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ipaddr'
+
+describe "IPAddr Operator" do
+ IN6MASK32 = "ffff:ffff::"
+ IN6MASK128 = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
+
+ before do
+ @in6_addr_any = IPAddr.new()
+ @a = IPAddr.new("3ffe:505:2::/48")
+ @b = IPAddr.new("0:0:0:1::")
+ @c = IPAddr.new(IN6MASK32)
+ end
+
+ it "bitwises or" do
+ (@a | @b).to_s.should == "3ffe:505:2:1::"
+ a = @a
+ a |= @b
+ a.to_s.should == "3ffe:505:2:1::"
+ @a.to_s.should == "3ffe:505:2::"
+ (@a | 0x00000000000000010000000000000000).to_s.should == "3ffe:505:2:1::"
+ end
+
+ it "bitwises and" do
+ (@a & @c).to_s.should == "3ffe:505::"
+ a = @a
+ a &= @c
+ a.to_s.should == "3ffe:505::"
+ @a.to_s.should == "3ffe:505:2::"
+ (@a & 0xffffffff000000000000000000000000).to_s.should == "3ffe:505::"
+ end
+
+ it "bitshifts right" do
+ (@a >> 16).to_s.should == "0:3ffe:505:2::"
+ a = @a
+ a >>= 16
+ a.to_s.should == "0:3ffe:505:2::"
+ @a.to_s.should == "3ffe:505:2::"
+ end
+
+ it "bitshifts left" do
+ (@a << 16).to_s.should == "505:2::"
+ a = @a
+ a <<= 16
+ a.to_s.should == "505:2::"
+ @a.to_s.should == "3ffe:505:2::"
+ end
+
+ it "inverts" do
+ a = ~@in6_addr_any
+ a.to_s.should == IN6MASK128
+ @in6_addr_any.to_s.should == "::"
+ end
+
+ it "tests for equality" do
+ @a.should == IPAddr.new("3ffe:505:2::")
+ @a.should_not == IPAddr.new("3ffe:505:3::")
+ end
+
+ it "sets a mask" do
+ a = @a.mask(32)
+ a.to_s.should == "3ffe:505::"
+ @a.to_s.should == "3ffe:505:2::"
+ end
+
+ it "checks whether an addres is included in a range" do
+ @a.should include(IPAddr.new("3ffe:505:2::"))
+ @a.should include(IPAddr.new("3ffe:505:2::1"))
+ @a.should_not include(IPAddr.new("3ffe:505:3::"))
+ net1 = IPAddr.new("192.168.2.0/24")
+ net1.should include(IPAddr.new("192.168.2.0"))
+ net1.should include(IPAddr.new("192.168.2.255"))
+ net1.should_not include(IPAddr.new("192.168.3.0"))
+ # test with integer parameter
+ int = (192 << 24) + (168 << 16) + (2 << 8) + 13
+
+ net1.should include(int)
+ net1.should_not include(int+255)
+ end
+end
diff --git a/spec/ruby/library/ipaddr/reverse_spec.rb b/spec/ruby/library/ipaddr/reverse_spec.rb
new file mode 100644
index 0000000000..dec5c65178
--- /dev/null
+++ b/spec/ruby/library/ipaddr/reverse_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ipaddr'
+
+describe "IPAddr#reverse" do
+ it "generates the reverse DNS lookup entry" do
+ IPAddr.new("3ffe:505:2::f").reverse.should == "f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.arpa"
+ IPAddr.new("192.168.2.1").reverse.should == "1.2.168.192.in-addr.arpa"
+ end
+end
+
+describe "IPAddr#ip6_arpa" do
+ it "converts an IPv6 address into the reverse DNS lookup representation according to RFC3172" do
+ IPAddr.new("3ffe:505:2::f").ip6_arpa.should == "f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.arpa"
+ lambda{
+ IPAddr.new("192.168.2.1").ip6_arpa
+ }.should raise_error(ArgumentError)
+ end
+end
+
+describe "IPAddr#ip6_int" do
+ it "converts an IPv6 address into the reverse DNS lookup representation according to RFC1886" do
+ IPAddr.new("3ffe:505:2::f").ip6_int.should == "f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.int"
+ lambda{
+ IPAddr.new("192.168.2.1").ip6_int
+ }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/ipaddr/to_s_spec.rb b/spec/ruby/library/ipaddr/to_s_spec.rb
new file mode 100644
index 0000000000..30e5237436
--- /dev/null
+++ b/spec/ruby/library/ipaddr/to_s_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ipaddr'
+
+describe "IPAddr#to_s" do
+
+ it "displays IPAddr using short notation" do
+ IPAddr.new("0:0:0:1::").to_s.should == "0:0:0:1::"
+ IPAddr.new("2001:200:300::/48").to_s.should == "2001:200:300::"
+ IPAddr.new("[2001:200:300::]/48").to_s.should == "2001:200:300::"
+ IPAddr.new("3ffe:505:2::1").to_s.should == "3ffe:505:2::1"
+ end
+
+end
+
+describe "IPAddr#to_string" do
+ it "displays an IPAddr using full notation" do
+ IPAddr.new("3ffe:505:2::1").to_string.should == "3ffe:0505:0002:0000:0000:0000:0000:0001"
+ end
+
+end
diff --git a/spec/ruby/library/logger/device/close_spec.rb b/spec/ruby/library/logger/device/close_spec.rb
new file mode 100644
index 0000000000..777b20baf0
--- /dev/null
+++ b/spec/ruby/library/logger/device/close_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger::LogDevice#close" do
+ before :each do
+ @file_path = tmp("test_log.log")
+ @log_file = File.open(@file_path, "w+")
+
+ # Avoid testing this with STDERR, we don't want to be closing that.
+ @device = Logger::LogDevice.new(@log_file)
+ end
+
+ after :each do
+ @log_file.close unless @log_file.closed?
+ rm_r @file_path
+ end
+
+ it "closes the LogDevice's stream" do
+ @device.close
+ lambda { @device.write("Test") }.should complain(/\Alog writing failed\./)
+ end
+end
diff --git a/spec/ruby/library/logger/device/new_spec.rb b/spec/ruby/library/logger/device/new_spec.rb
new file mode 100644
index 0000000000..0e08b743ed
--- /dev/null
+++ b/spec/ruby/library/logger/device/new_spec.rb
@@ -0,0 +1,47 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger::LogDevice#new" do
+ before :each do
+ @file_path = tmp("test_log.log")
+ @log_file = File.open(@file_path, "w+")
+ end
+
+ after :each do
+ @log_file.close unless @log_file.closed?
+ rm_r @file_path
+ end
+
+ it "creates a new log device" do
+ l = Logger::LogDevice.new(@log_file)
+ l.dev.should be_kind_of(File)
+ end
+
+ it "receives an IO object to log there as first argument" do
+ @log_file.should be_kind_of(IO)
+ l = Logger::LogDevice.new(@log_file)
+ l.write("foo")
+ @log_file.rewind
+ @log_file.readlines.first.should == "foo"
+ end
+
+ it "creates a File if the IO object does not exist" do
+ path = tmp("test_logger_file")
+ l = Logger::LogDevice.new(path)
+ l.write("Test message")
+ l.close
+
+ File.exist?(path).should be_true
+ File.open(path) do |f|
+ f.readlines.should_not be_empty
+ end
+
+ rm_r path
+ end
+
+ it "receives options via a hash as second argument" do
+ lambda { Logger::LogDevice.new(STDERR,
+ { shift_age: 8, shift_size: 10
+ })}.should_not raise_error
+ end
+end
diff --git a/spec/ruby/library/logger/device/write_spec.rb b/spec/ruby/library/logger/device/write_spec.rb
new file mode 100644
index 0000000000..e3ddd61b1f
--- /dev/null
+++ b/spec/ruby/library/logger/device/write_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger::LogDevice#write" do
+ before :each do
+ @file_path = tmp("test_log.log")
+ @log_file = File.open(@file_path, "w+")
+ # Avoid testing this with STDERR, we don't want to be closing that.
+ @device = Logger::LogDevice.new(@log_file)
+ end
+
+ after :each do
+ @log_file.close unless @log_file.closed?
+ rm_r @file_path
+ end
+
+ it "writes a message to the device" do
+ @device.write "This is a test message"
+ @log_file.rewind
+ @log_file.readlines.first.should == "This is a test message"
+ end
+
+ it "can create a file and writes empty message" do
+ path = tmp("you_should_not_see_me")
+ logdevice = Logger::LogDevice.new(path)
+ logdevice.write("")
+ logdevice.close
+
+ File.open(path) do |f|
+ messages = f.readlines
+ messages.size.should == 1
+ messages.first.should =~ /#.*/ # only a comment
+ end
+
+ rm_r path
+ end
+
+ it "fails if the device is already closed" do
+ @device.close
+ lambda { @device.write "foo" }.should complain(/\Alog writing failed\./)
+ end
+end
diff --git a/spec/ruby/library/logger/fixtures/common.rb b/spec/ruby/library/logger/fixtures/common.rb
new file mode 100644
index 0000000000..d369c64a24
--- /dev/null
+++ b/spec/ruby/library/logger/fixtures/common.rb
@@ -0,0 +1,9 @@
+require 'logger'
+
+module LoggerSpecs
+
+ def self.strip_date(str)
+ str.gsub(/[A-Z].*\[.*\]/, "").lstrip
+ end
+
+end
diff --git a/spec/ruby/library/logger/logger/add_spec.rb b/spec/ruby/library/logger/logger/add_spec.rb
new file mode 100644
index 0000000000..235247e9e8
--- /dev/null
+++ b/spec/ruby/library/logger/logger/add_spec.rb
@@ -0,0 +1,81 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#add" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "writes a new message to the logger" do
+ @logger.add(Logger::WARN, "Test")
+ @log_file.rewind
+ message = @log_file.readlines.last
+ LoggerSpecs.strip_date(message).should == "WARN -- : Test\n"
+ end
+
+ it "receives a severity" do
+ @logger.log(Logger::INFO, "Info message")
+ @logger.log(Logger::DEBUG, "Debug message")
+ @logger.log(Logger::WARN, "Warn message")
+ @logger.log(Logger::ERROR, "Error message")
+ @logger.log(Logger::FATAL, "Fatal message")
+
+ @log_file.rewind
+
+ info, debug, warn, error, fatal = @log_file.readlines
+
+ LoggerSpecs.strip_date(info).should == "INFO -- : Info message\n"
+ LoggerSpecs.strip_date(debug).should == "DEBUG -- : Debug message\n"
+ LoggerSpecs.strip_date(warn).should == "WARN -- : Warn message\n"
+ LoggerSpecs.strip_date(error).should == "ERROR -- : Error message\n"
+ LoggerSpecs.strip_date(fatal).should == "FATAL -- : Fatal message\n"
+ end
+
+ it "receives a message" do
+ @logger.log(nil, "test")
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readline).should == "ANY -- : test\n"
+ end
+
+ it "receives a program name" do
+ @logger.log(nil, "test", "TestApp")
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readline).should == "ANY -- TestApp: test\n"
+ end
+
+ it "receives a block" do
+ lambda {
+ @logger.log(nil, "test", "TestApp") do
+ 1+1
+ end
+ }.should_not raise_error
+ end
+
+ it "calls the block if message is nil" do
+ temp = 0
+ lambda {
+ @logger.log(nil, nil, "TestApp") do
+ temp = 1+1
+ end
+ }.should_not raise_error
+ temp.should == 2
+ end
+
+ it "ignores the block if the message is not nil" do
+ temp = 0
+ lambda {
+ @logger.log(nil, "not nil", "TestApp") do
+ temp = 1+1
+ end
+ }.should_not raise_error
+ temp.should == 0
+ end
+end
diff --git a/spec/ruby/library/logger/logger/close_spec.rb b/spec/ruby/library/logger/logger/close_spec.rb
new file mode 100644
index 0000000000..a4c006150b
--- /dev/null
+++ b/spec/ruby/library/logger/logger/close_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#close" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "closes the logging device" do
+ @logger.close
+ lambda { @logger.add(nil, "Foo") }.should complain(/\Alog writing failed\./)
+ end
+end
diff --git a/spec/ruby/library/logger/logger/datetime_format_spec.rb b/spec/ruby/library/logger/logger/datetime_format_spec.rb
new file mode 100644
index 0000000000..2bc1f867c3
--- /dev/null
+++ b/spec/ruby/library/logger/logger/datetime_format_spec.rb
@@ -0,0 +1,60 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#datetime_format" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "returns the date format used for the logs" do
+ format = "%Y-%d"
+ @logger.datetime_format = format
+ @logger.datetime_format.should == format
+ end
+
+ it "returns nil logger is using the default date format" do
+ @logger.datetime_format.should == nil
+ end
+end
+
+describe "Logger#datetime_format=" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "sets the date format for the logs" do
+ @logger.datetime_format = "%Y"
+ @logger.datetime_format.should == "%Y"
+ @logger.add(Logger::WARN, "Test message")
+ @log_file.rewind
+
+ regex = /2[0-9]{3}.*Test message/
+ @log_file.readlines.first.should =~ regex
+ end
+
+ it "follows the Time#strftime format" do
+ lambda { @logger.datetime_format = "%Y-%m" }.should_not raise_error
+
+ regex = /\d{4}-\d{2}-\d{2}oo-\w+ar/
+ @logger.datetime_format = "%Foo-%Bar"
+ @logger.add(nil, "Test message")
+ @log_file.rewind
+ @log_file.readlines.first.should =~ regex
+ end
+end
diff --git a/spec/ruby/library/logger/logger/debug_spec.rb b/spec/ruby/library/logger/logger/debug_spec.rb
new file mode 100644
index 0000000000..2260587b23
--- /dev/null
+++ b/spec/ruby/library/logger/logger/debug_spec.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#debug?" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "returns true if severity level allows debug messages" do
+ @logger.level = Logger::DEBUG
+ @logger.debug?.should == true
+ end
+
+ it "returns false if severity level does not allow debug messages" do
+ @logger.level = Logger::WARN
+ @logger.debug?.should == false
+ end
+end
+
+describe "Logger#debug" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "logs a DEBUG message" do
+ @logger.debug("test")
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "DEBUG -- : test\n"
+ end
+
+ it "accepts an application name with a block" do
+ @logger.debug("MyApp") { "Test message" }
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "DEBUG -- MyApp: Test message\n"
+ end
+end
diff --git a/spec/ruby/library/logger/logger/error_spec.rb b/spec/ruby/library/logger/logger/error_spec.rb
new file mode 100644
index 0000000000..e165396bab
--- /dev/null
+++ b/spec/ruby/library/logger/logger/error_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#error?" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "returns true if severity level allows printing errors" do
+ @logger.level = Logger::INFO
+ @logger.error?.should == true
+ end
+
+ it "returns false if severity level does not allow errors" do
+ @logger.level = Logger::FATAL
+ @logger.error?.should == false
+ end
+end
+
+describe "Logger#error" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "logs a ERROR message" do
+ @logger.error("test")
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "ERROR -- : test\n"
+ end
+
+ it "accepts an application name with a block" do
+ @logger.error("MyApp") { "Test message" }
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "ERROR -- MyApp: Test message\n"
+ end
+
+end
diff --git a/spec/ruby/library/logger/logger/fatal_spec.rb b/spec/ruby/library/logger/logger/fatal_spec.rb
new file mode 100644
index 0000000000..ebbe8a04a5
--- /dev/null
+++ b/spec/ruby/library/logger/logger/fatal_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#fatal?" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "returns true if severity level allows fatal messages" do
+ @logger.level = Logger::FATAL
+ @logger.fatal?.should == true
+ end
+
+ it "returns false if severity level does not allow fatal messages" do
+ @logger.level = Logger::UNKNOWN
+ @logger.fatal?.should == false
+ end
+end
+
+describe "Logger#fatal" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "logs a FATAL message" do
+ @logger.fatal("test")
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "FATAL -- : test\n"
+ end
+
+ it "accepts an application name with a block" do
+ @logger.fatal("MyApp") { "Test message" }
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "FATAL -- MyApp: Test message\n"
+ end
+
+end
diff --git a/spec/ruby/library/logger/logger/info_spec.rb b/spec/ruby/library/logger/logger/info_spec.rb
new file mode 100644
index 0000000000..7f299ea0da
--- /dev/null
+++ b/spec/ruby/library/logger/logger/info_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#info?" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "returns true if severity level allows info messages" do
+ @logger.level = Logger::INFO
+ @logger.info?.should == true
+ end
+
+ it "returns false if severity level does not allow info messages" do
+ @logger.level = Logger::FATAL
+ @logger.info?.should == false
+ end
+end
+
+describe "Logger#info" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "logs a INFO message" do
+ @logger.info("test")
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "INFO -- : test\n"
+ end
+
+ it "accepts an application name with a block" do
+ @logger.info("MyApp") { "Test message" }
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "INFO -- MyApp: Test message\n"
+ end
+
+end
diff --git a/spec/ruby/library/logger/logger/new_spec.rb b/spec/ruby/library/logger/logger/new_spec.rb
new file mode 100644
index 0000000000..255f686d25
--- /dev/null
+++ b/spec/ruby/library/logger/logger/new_spec.rb
@@ -0,0 +1,63 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#new" do
+
+ before :each do
+ @file_path = tmp("test_log.log")
+ @log_file = File.open(@file_path, "w+")
+ end
+
+ after :each do
+ @log_file.close unless @log_file.closed?
+ rm_r @file_path
+ end
+
+ it "creates a new logger object" do
+ l = Logger.new(STDERR)
+ lambda { l.add(Logger::WARN, "Foo") }.should output_to_fd(/Foo/, STDERR)
+ end
+
+ it "receives a logging device as first argument" do
+ l = Logger.new(@log_file)
+ l.add(Logger::WARN, "Test message")
+
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readline).should == "WARN -- : Test message\n"
+ l.close
+ end
+
+ it "receives a frequency rotation as second argument" do
+ lambda { Logger.new(@log_file, "daily") }.should_not raise_error
+ lambda { Logger.new(@log_file, "weekly") }.should_not raise_error
+ lambda { Logger.new(@log_file, "monthly") }.should_not raise_error
+ end
+
+ it "also receives a number of log files to keep as second argument" do
+ lambda { Logger.new(@log_file, 1).close }.should_not raise_error
+ end
+
+ it "receivs a maximum logfile size as third argument" do
+ # This should create 2 small log files, logfile_test and logfile_test.0
+ # in /tmp, each one with a different message.
+ path = tmp("logfile_test.log")
+
+ l = Logger.new(path, 2, 5)
+ l.add Logger::WARN, "foo"
+ l.add Logger::WARN, "bar"
+
+ File.exist?(path).should be_true
+ File.exist?(path + ".0").should be_true
+
+ # first line will be a comment so we'll have to skip it.
+ f = File.open(path)
+ f1 = File.open("#{path}.0")
+ LoggerSpecs.strip_date(f1.readlines.last).should == "WARN -- : foo\n"
+ LoggerSpecs.strip_date(f.readlines.last).should == "WARN -- : bar\n"
+
+ l.close
+ f.close
+ f1.close
+ rm_r path, "#{path}.0"
+ end
+end
diff --git a/spec/ruby/library/logger/logger/unknown_spec.rb b/spec/ruby/library/logger/logger/unknown_spec.rb
new file mode 100644
index 0000000000..5ef9659a9c
--- /dev/null
+++ b/spec/ruby/library/logger/logger/unknown_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#unknown" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "logs a message with unknown severity" do
+ @logger.unknown "Test"
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "ANY -- : Test\n"
+ end
+
+ it "defaults the priority value to 5 and text value to ANY" do
+ @logger.unknown "Test"
+ @log_file.rewind
+ message = LoggerSpecs.strip_date(@log_file.readlines.first)[0..2]
+ message.should == "ANY"
+ Logger::UNKNOWN.should == 5
+ end
+
+ it "receives empty messages" do
+ lambda { @logger.unknown("") }.should_not raise_error
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "ANY -- : \n"
+ end
+end
diff --git a/spec/ruby/library/logger/logger/warn_spec.rb b/spec/ruby/library/logger/logger/warn_spec.rb
new file mode 100644
index 0000000000..d34f19fb8e
--- /dev/null
+++ b/spec/ruby/library/logger/logger/warn_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/common', __FILE__)
+
+describe "Logger#warn?" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "returns true if severity level allows printing warn messages" do
+ @logger.level = Logger::WARN
+ @logger.warn?.should == true
+ end
+
+ it "returns false if severity level does not allow printing warn messages" do
+ @logger.level = Logger::FATAL
+ @logger.warn?.should == false
+ end
+end
+
+describe "Logger#warn" do
+ before :each do
+ @path = tmp("test_log.log")
+ @log_file = File.open(@path, "w+")
+ @logger = Logger.new(@path)
+ end
+
+ after :each do
+ @logger.close
+ @log_file.close unless @log_file.closed?
+ rm_r @path
+ end
+
+ it "logs a WARN message" do
+ @logger.warn("test")
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "WARN -- : test\n"
+ end
+
+ it "accepts an application name with a block" do
+ @logger.warn("MyApp") { "Test message" }
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readlines.first).should == "WARN -- MyApp: Test message\n"
+ end
+
+end
diff --git a/spec/ruby/library/logger/severity_spec.rb b/spec/ruby/library/logger/severity_spec.rb
new file mode 100644
index 0000000000..a4219365dd
--- /dev/null
+++ b/spec/ruby/library/logger/severity_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'logger'
+
+describe "Logger::Severity" do
+ it "defines Logger severity constants" do
+ Logger::DEBUG.should == 0
+ Logger::INFO.should == 1
+ Logger::WARN.should == 2
+ Logger::ERROR.should == 3
+ Logger::FATAL.should == 4
+ Logger::UNKNOWN.should == 5
+ end
+end
diff --git a/spec/ruby/library/mathn/bignum/exponent_spec.rb b/spec/ruby/library/mathn/bignum/exponent_spec.rb
new file mode 100644
index 0000000000..758c2f27fd
--- /dev/null
+++ b/spec/ruby/library/mathn/bignum/exponent_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require 'mathn'
+
+ describe "Bignum#**" do
+ before :each do
+ @bignum = bignum_value(47)
+ end
+
+ it "returns self raised to other (positive) power" do
+ (@bignum ** 4).should == 7237005577332262361485077344629993318496048279512298547155833600056910050625
+ (@bignum ** 1.2).should be_close(57262152889751597425762.57804, TOLERANCE)
+ end
+
+ it "returns a complex number when negative and raised to a fractional power" do
+ ((-@bignum) ** (1/3)).should be_close(Complex(1048576,1816186.907597341), TOLERANCE)
+ ((-@bignum) ** (1.0/3)).should be_close(Complex(1048576,1816186.907597341), TOLERANCE)
+ end
+ end
+end
diff --git a/spec/ruby/library/mathn/complex/Complex_spec.rb b/spec/ruby/library/mathn/complex/Complex_spec.rb
new file mode 100644
index 0000000000..93bb3f0c60
--- /dev/null
+++ b/spec/ruby/library/mathn/complex/Complex_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require 'mathn'
+
+ describe "Kernel#Complex" do
+ it "returns an Integer if imaginary part is 0" do
+ Complex(42,0).should == 42
+ Complex(42,0).should be_kind_of(Fixnum)
+ Complex(bignum_value,0).should == bignum_value
+ Complex(bignum_value,0).should be_kind_of(Bignum)
+ end
+ end
+end
diff --git a/spec/ruby/library/mathn/fixnum/exponent_spec.rb b/spec/ruby/library/mathn/fixnum/exponent_spec.rb
new file mode 100644
index 0000000000..d72bc5aa00
--- /dev/null
+++ b/spec/ruby/library/mathn/fixnum/exponent_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require 'mathn'
+
+ describe "Fixnum#**" do
+ it "returns self raised to other (positive) power" do
+ (2 ** 4).should == 16
+ (2 ** 1.2).should be_close(2.2973967, TOLERANCE)
+ end
+
+ it "returns a complex number when negative and raised to a fractional power" do
+ ((-8) ** (1/3)).should be_close(Complex(1, 1.73205), TOLERANCE)
+ ((-8) ** (1.0/3)).should be_close(Complex(1, 1.73205), TOLERANCE)
+ end
+ end
+end
diff --git a/spec/ruby/library/mathn/float/exponent_spec.rb b/spec/ruby/library/mathn/float/exponent_spec.rb
new file mode 100644
index 0000000000..55af43ce5b
--- /dev/null
+++ b/spec/ruby/library/mathn/float/exponent_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require 'mathn'
+
+ describe "Float#**" do
+ it "returns self raised to other (positive) power" do
+ (2.0 ** 4).should == 16.0
+ (2.0 ** 1.2).should be_close(2.2973967, TOLERANCE)
+ end
+
+ it "returns a complex number when negative and raised to a fractional power" do
+ ((-8.0) ** (1/3)).should be_close(Complex(1, 1.73205), TOLERANCE)
+ ((-8.0) ** (1.0/3)).should be_close(Complex(1, 1.73205), TOLERANCE)
+ end
+ end
+end
diff --git a/spec/ruby/library/mathn/integer/from_prime_division_spec.rb b/spec/ruby/library/mathn/integer/from_prime_division_spec.rb
new file mode 100644
index 0000000000..47aaf47797
--- /dev/null
+++ b/spec/ruby/library/mathn/integer/from_prime_division_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require 'mathn'
+
+ describe "Integer.from_prime_division" do
+ it "reverses a prime factorization of an integer" do
+ Integer.from_prime_division([[2, 1], [3, 2], [7, 1]]).should == 126
+ end
+ end
+end
diff --git a/spec/ruby/library/mathn/integer/prime_division_spec.rb b/spec/ruby/library/mathn/integer/prime_division_spec.rb
new file mode 100644
index 0000000000..63a5c39733
--- /dev/null
+++ b/spec/ruby/library/mathn/integer/prime_division_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require 'mathn'
+
+ describe "Integer#prime_division" do
+ it "performs a prime factorization of a positive integer" do
+ 100.prime_division.should == [[2, 2], [5, 2]]
+ end
+
+ # Proper handling of negative integers has been added to MRI trunk
+ # in revision 24091. Prior to that, all versions of MRI returned nonsense.
+ it "performs a prime factorization of a negative integer" do
+ -26.prime_division.should == [[-1, 1], [2, 1], [13, 1]]
+ end
+
+ it "raises a ZeroDivisionError when is called on zero" do
+ lambda { 0.prime_division }.should raise_error(ZeroDivisionError)
+ end
+ end
+end
diff --git a/spec/ruby/library/mathn/math/fixtures/classes.rb b/spec/ruby/library/mathn/math/fixtures/classes.rb
new file mode 100644
index 0000000000..024732fa7a
--- /dev/null
+++ b/spec/ruby/library/mathn/math/fixtures/classes.rb
@@ -0,0 +1,3 @@
+class IncludesMath
+ include Math
+end
diff --git a/spec/ruby/library/mathn/math/rsqrt_spec.rb b/spec/ruby/library/mathn/math/rsqrt_spec.rb
new file mode 100644
index 0000000000..a49efa6ff9
--- /dev/null
+++ b/spec/ruby/library/mathn/math/rsqrt_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require File.expand_path('../shared/rsqrt', __FILE__)
+
+ describe "Math#rsqrt" do
+ it_behaves_like :mathn_math_rsqrt, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:rsqrt)
+ end
+ end
+
+ describe "Math.rsqrt" do
+ it_behaves_like :mathn_math_rsqrt, :_, Math
+ end
+end
diff --git a/spec/ruby/library/mathn/math/shared/rsqrt.rb b/spec/ruby/library/mathn/math/shared/rsqrt.rb
new file mode 100644
index 0000000000..68e2f7d02f
--- /dev/null
+++ b/spec/ruby/library/mathn/math/shared/rsqrt.rb
@@ -0,0 +1,21 @@
+require 'mathn'
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :mathn_math_rsqrt, shared: true do
+ it "returns the square root for Rational numbers" do
+ @object.send(:rsqrt, Rational(9, 25)).should == Rational(3, 5)
+ @object.send(:rsqrt, 16/64).should == Rational(1, 2)
+ end
+
+ it "returns the square root for positive numbers" do
+ @object.send(:rsqrt, 1).should == 1
+ @object.send(:rsqrt, 4.0).should == 2.0
+ @object.send(:rsqrt, 12.34).should == Math.sqrt!(12.34)
+ end
+
+ it "raises an Math::DomainError if the argument is a negative number" do
+ lambda { @object.send(:rsqrt, -1) }.should raise_error(Math::DomainError)
+ lambda { @object.send(:rsqrt, -4.0) }.should raise_error(Math::DomainError)
+ lambda { @object.send(:rsqrt, -16/64) }.should raise_error(Math::DomainError)
+ end
+end
diff --git a/spec/ruby/library/mathn/math/shared/sqrt.rb b/spec/ruby/library/mathn/math/shared/sqrt.rb
new file mode 100644
index 0000000000..6aab25fc5d
--- /dev/null
+++ b/spec/ruby/library/mathn/math/shared/sqrt.rb
@@ -0,0 +1,25 @@
+require 'mathn'
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe :mathn_math_sqrt, shared: true do
+ it "returns the square root for Rational numbers" do
+ @object.send(:sqrt, Rational(9, 25)).should == Rational(3, 5)
+ @object.send(:sqrt, 16/64).should == Rational(1, 2)
+ end
+
+ it "returns the square root for Complex numbers" do
+ @object.send(:sqrt, Complex(1, 0)).should == 1
+ end
+
+ it "returns the square root for positive numbers" do
+ @object.send(:sqrt, 1).should == 1
+ @object.send(:sqrt, 4.0).should == 2.0
+ @object.send(:sqrt, 12.34).should == Math.sqrt!(12.34)
+ end
+
+ it "returns the square root for negative numbers" do
+ @object.send(:sqrt, -9).should == Complex(0, 3)
+ @object.send(:sqrt, -5.29).should == Complex(0, 2.3)
+ @object.send(:sqrt, -16/64).should == Complex(0, 1/2)
+ end
+end
diff --git a/spec/ruby/library/mathn/math/sqrt_spec.rb b/spec/ruby/library/mathn/math/sqrt_spec.rb
new file mode 100644
index 0000000000..b723360891
--- /dev/null
+++ b/spec/ruby/library/mathn/math/sqrt_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require File.expand_path('../shared/sqrt', __FILE__)
+
+ describe "Math#rsqrt" do
+ it_behaves_like :mathn_math_sqrt, :_, IncludesMath.new
+
+ it "is a private instance method" do
+ IncludesMath.should have_private_instance_method(:sqrt)
+ end
+ end
+
+ describe "Math.rsqrt" do
+ it_behaves_like :mathn_math_sqrt, :_, Math
+ end
+end
diff --git a/spec/ruby/library/mathn/rational/Rational_spec.rb b/spec/ruby/library/mathn/rational/Rational_spec.rb
new file mode 100644
index 0000000000..71433529c5
--- /dev/null
+++ b/spec/ruby/library/mathn/rational/Rational_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require 'mathn'
+
+ describe "Kernel#Rational" do
+ it "returns an Integer if denominator divides numerator evenly" do
+ Rational(42,6).should == 7
+ Rational(42,6).should be_kind_of(Fixnum)
+ Rational(bignum_value,1).should == bignum_value
+ Rational(bignum_value,1).should be_kind_of(Bignum)
+ end
+ end
+end
diff --git a/spec/ruby/library/mathn/rational/inspect_spec.rb b/spec/ruby/library/mathn/rational/inspect_spec.rb
new file mode 100644
index 0000000000..ce1205faaa
--- /dev/null
+++ b/spec/ruby/library/mathn/rational/inspect_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ require 'mathn'
+
+ describe "Rational#inspect" do
+ it "returns a string representation of self" do
+ Rational(3, 4).inspect.should == "(3/4)"
+ Rational(-5, 8).inspect.should == "(-5/8)"
+ Rational(-1, -2).inspect.should == "(1/2)"
+ Rational(0, 2).inspect.should == "0"
+ Rational(bignum_value, 1).inspect.should == "#{bignum_value}"
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/I_spec.rb b/spec/ruby/library/matrix/I_spec.rb
new file mode 100644
index 0000000000..f83cc3cec4
--- /dev/null
+++ b/spec/ruby/library/matrix/I_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/identity', __FILE__)
+
+describe "Matrix.I" do
+ it_behaves_like(:matrix_identity, :I)
+end
diff --git a/spec/ruby/library/matrix/build_spec.rb b/spec/ruby/library/matrix/build_spec.rb
new file mode 100644
index 0000000000..29fd72206f
--- /dev/null
+++ b/spec/ruby/library/matrix/build_spec.rb
@@ -0,0 +1,73 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix.build" do
+
+ it "returns a Matrix object of the given size" do
+ m = Matrix.build(3, 4){1}
+ m.should be_an_instance_of(Matrix)
+ m.row_size.should == 3
+ m.column_size.should == 4
+ end
+
+ it "builds the Matrix using the given block" do
+ Matrix.build(2, 3){|col, row| 10*col - row}.should ==
+ Matrix[[0, -1, -2], [10, 9, 8]]
+ end
+
+ it "iterates through the first row, then the second, ..." do
+ acc = []
+ Matrix.build(2, 3){|*args| acc << args}
+ acc.should == [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2]]
+ end
+
+ it "returns an Enumerator is no block is given" do
+ enum = Matrix.build(2, 1)
+ enum.should be_an_instance_of(Enumerator)
+ enum.each{1}.should == Matrix[[1], [1]]
+ end
+
+ it "requires integers as parameters" do
+ lambda { Matrix.build("1", "2"){1} }.should raise_error(TypeError)
+ lambda { Matrix.build(nil, nil){1} }.should raise_error(TypeError)
+ lambda { Matrix.build(1..2){1} }.should raise_error(TypeError)
+ end
+
+ it "requires non-negative integers" do
+ lambda { Matrix.build(-1, 1){1} }.should raise_error(ArgumentError)
+ lambda { Matrix.build(+1,-1){1} }.should raise_error(ArgumentError)
+ end
+
+ it "returns empty Matrix if one argument is zero" do
+ m = Matrix.build(0, 3){
+ raise "Should not yield"
+ }
+ m.should be_empty
+ m.column_size.should == 3
+
+ m = Matrix.build(3, 0){
+ raise "Should not yield"
+ }
+ m.should be_empty
+ m.row_size.should == 3
+ end
+
+ it "tries to calls :to_int on arguments" do
+ int = mock('int')
+ int.should_receive(:to_int).twice.and_return(2)
+ Matrix.build(int, int){ 1 }.should == Matrix[ [1,1], [1,1] ]
+ end
+
+ it "builds an nxn Matrix when given only one argument" do
+ m = Matrix.build(3){1}
+ m.row_size.should == 3
+ m.column_size.should == 3
+ end
+end
+
+describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.build(3){1}.should be_an_instance_of(MatrixSub)
+ end
+end
diff --git a/spec/ruby/library/matrix/clone_spec.rb b/spec/ruby/library/matrix/clone_spec.rb
new file mode 100644
index 0000000000..8819fc9b40
--- /dev/null
+++ b/spec/ruby/library/matrix/clone_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#clone" do
+ before :each do
+ @a = Matrix[[1, 2], [3, 4], [5, 6]]
+ end
+
+ it "returns a shallow copy of the matrix" do
+ b = @a.clone
+ @a.should_not equal(b)
+ b.should be_kind_of(Matrix)
+ b.should == @a
+ 0.upto(@a.row_size - 1) do |i|
+ @a.row(i).should_not equal(b.row(i))
+ end
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.ins.clone.should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/coerce_spec.rb b/spec/ruby/library/matrix/coerce_spec.rb
new file mode 100644
index 0000000000..6e653315a6
--- /dev/null
+++ b/spec/ruby/library/matrix/coerce_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#coerce" do
+ it "needs to be reviewed for spec completeness"
+
+ it "allows the division of fixnum by a Matrix " do
+ (1/Matrix[[0,1],[-1,0]]).should == Matrix[[0,-1],[1,0]]
+ end
+end
diff --git a/spec/ruby/library/matrix/collect_spec.rb b/spec/ruby/library/matrix/collect_spec.rb
new file mode 100644
index 0000000000..1830aed103
--- /dev/null
+++ b/spec/ruby/library/matrix/collect_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/collect', __FILE__)
+
+describe "Matrix#collect" do
+ it_behaves_like(:collect, :collect)
+end
diff --git a/spec/ruby/library/matrix/column_size_spec.rb b/spec/ruby/library/matrix/column_size_spec.rb
new file mode 100644
index 0000000000..b1aae01bbc
--- /dev/null
+++ b/spec/ruby/library/matrix/column_size_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#column_size" do
+ it "returns the number of columns" do
+ Matrix[ [1,2], [3,4] ].column_size.should == 2
+ end
+
+ it "returns 0 for empty matrices" do
+ Matrix[ [], [] ].column_size.should == 0
+ Matrix[ ].column_size.should == 0
+ end
+end
diff --git a/spec/ruby/library/matrix/column_spec.rb b/spec/ruby/library/matrix/column_spec.rb
new file mode 100644
index 0000000000..de84e33e8d
--- /dev/null
+++ b/spec/ruby/library/matrix/column_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#column" do
+ before :all do
+ @m = Matrix[[1,2,3], [2,3,4]]
+ end
+
+ it "returns a Vector when called without a block" do
+ @m.column(1).should == Vector[2,3]
+ end
+
+ it "yields each element in the column to the block" do
+ a = []
+ @m.column(1) {|n| a << n }
+ a.should == [2,3]
+ end
+
+ it "counts backwards for negative argument" do
+ @m.column(-1).should == Vector[3, 4]
+ end
+
+ it "returns self when called with a block" do
+ @m.column(0) { |x| x }.should equal(@m)
+ end
+
+ it "returns nil when out of bounds" do
+ @m.column(3).should == nil
+ end
+
+ it "never yields when out of bounds" do
+ lambda { @m.column(3){ raise } }.should_not raise_error
+ lambda { @m.column(-4){ raise } }.should_not raise_error
+ end
+end
diff --git a/spec/ruby/library/matrix/column_vector_spec.rb b/spec/ruby/library/matrix/column_vector_spec.rb
new file mode 100644
index 0000000000..f0cc46d646
--- /dev/null
+++ b/spec/ruby/library/matrix/column_vector_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix.column_vector" do
+
+ it "returns a single column Matrix when called with an Array" do
+ m = Matrix.column_vector([4,5,6])
+ m.should be_an_instance_of(Matrix)
+ m.should == Matrix[ [4],[5],[6] ]
+ end
+
+ it "returns an empty Matrix when called with an empty Array" do
+ m = Matrix.column_vector([])
+ m.should be_an_instance_of(Matrix)
+ m.row_size.should == 0
+ m.column_size.should == 1
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.column_vector([4,5,6]).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/column_vectors_spec.rb b/spec/ruby/library/matrix/column_vectors_spec.rb
new file mode 100644
index 0000000000..8af64f83c8
--- /dev/null
+++ b/spec/ruby/library/matrix/column_vectors_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#column_vectors" do
+
+ before :each do
+ @vectors = Matrix[ [1,2], [3,4] ].column_vectors
+ end
+
+ it "returns an Array" do
+ Matrix[ [1,2], [3,4] ].column_vectors.should be_an_instance_of(Array)
+ end
+
+ it "returns an Array of Vectors" do
+ @vectors.all? {|v| v.should be_an_instance_of(Vector)}
+ end
+
+ it "returns each column as a Vector" do
+ @vectors.should == [Vector[1,3], Vector[2,4]]
+ end
+
+ it "returns an empty Array for empty matrices" do
+ Matrix[ [] ].column_vectors.should == []
+ end
+
+end
diff --git a/spec/ruby/library/matrix/columns_spec.rb b/spec/ruby/library/matrix/columns_spec.rb
new file mode 100644
index 0000000000..b5fd5633bf
--- /dev/null
+++ b/spec/ruby/library/matrix/columns_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix.columns" do
+ before :each do
+ @a = [1, 2]
+ @b = [3, 4]
+ @m = Matrix.columns([@a, @b])
+ end
+
+ it "creates a Matrix from argument columns" do
+ @m.should be_an_instance_of(Matrix)
+ @m.column(0).to_a.should == @a
+ @m.column(1).to_a.should == @b
+ end
+
+ it "accepts Vectors as argument columns" do
+ m = Matrix.columns([Vector[*@a], Vector[*@b]])
+ m.should == @m
+ m.column(0).to_a.should == @a
+ m.column(1).to_a.should == @b
+ end
+
+ it "handles empty matrices" do
+ e = Matrix.columns([])
+ e.row_size.should == 0
+ e.column_size.should == 0
+ e.should == Matrix[]
+
+ v = Matrix.columns([[],[],[]])
+ v.row_size.should == 0
+ v.column_size.should == 3
+ v.should == Matrix[[], [], []].transpose
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.columns([[1]]).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/conj_spec.rb b/spec/ruby/library/matrix/conj_spec.rb
new file mode 100644
index 0000000000..33221f7055
--- /dev/null
+++ b/spec/ruby/library/matrix/conj_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/conjugate', __FILE__)
+
+describe "Matrix#conj" do
+ it_behaves_like(:matrix_conjugate, :conj)
+end
diff --git a/spec/ruby/library/matrix/conjugate_spec.rb b/spec/ruby/library/matrix/conjugate_spec.rb
new file mode 100644
index 0000000000..fd19f7689c
--- /dev/null
+++ b/spec/ruby/library/matrix/conjugate_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/conjugate', __FILE__)
+
+describe "Matrix#conjugate" do
+ it_behaves_like(:matrix_conjugate, :conjugate)
+end
diff --git a/spec/ruby/library/matrix/constructor_spec.rb b/spec/ruby/library/matrix/constructor_spec.rb
new file mode 100644
index 0000000000..ae707166cd
--- /dev/null
+++ b/spec/ruby/library/matrix/constructor_spec.rb
@@ -0,0 +1,65 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix.[]" do
+
+ it "requires arrays as parameters" do
+ lambda { Matrix[5] }.should raise_error(TypeError)
+ lambda { Matrix[nil] }.should raise_error(TypeError)
+ lambda { Matrix[1..2] }.should raise_error(TypeError)
+ lambda { Matrix[[1, 2], 3] }.should raise_error(TypeError)
+ end
+
+ it "creates an empty Matrix with no arguments" do
+ m = Matrix[]
+ m.column_size.should == 0
+ m.row_size.should == 0
+ end
+
+ it "raises for non-rectangular matrices" do
+ lambda{ Matrix[ [0], [0,1] ] }.should \
+ raise_error(Matrix::ErrDimensionMismatch)
+ lambda{ Matrix[ [0,1], [0,1,2], [0,1] ]}.should \
+ raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+ it "accepts vector arguments" do
+ a = Matrix[Vector[1, 2], Vector[3, 4]]
+ a.should be_an_instance_of(Matrix)
+ a.should == Matrix[ [1, 2], [3, 4] ]
+ end
+
+ it "tries to calls :to_ary on arguments" do
+ array = mock('ary')
+ array.should_receive(:to_ary).and_return([1,2])
+ Matrix[array, [3,4] ].should == Matrix[ [1,2], [3,4] ]
+ end
+
+
+ it "returns a Matrix object" do
+ Matrix[ [1] ].should be_an_instance_of(Matrix)
+ end
+
+ it "can create an nxn Matrix" do
+ m = Matrix[ [20,30], [40.5, 9] ]
+ m.row_size.should == 2
+ m.column_size.should == 2
+ m.column(0).should == Vector[20, 40.5]
+ m.column(1).should == Vector[30, 9]
+ m.row(0).should == Vector[20, 30]
+ m.row(1).should == Vector[40.5, 9]
+ end
+
+ it "can create a 0xn Matrix" do
+ m = Matrix[ [], [], [] ]
+ m.row_size.should == 3
+ m.column_size.should == 0
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub[ [20,30], [40.5, 9] ].should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/det_spec.rb b/spec/ruby/library/matrix/det_spec.rb
new file mode 100644
index 0000000000..698de34fd1
--- /dev/null
+++ b/spec/ruby/library/matrix/det_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/determinant', __FILE__)
+require 'matrix'
+
+describe "Matrix#det" do
+ it_behaves_like(:determinant, :det)
+end
diff --git a/spec/ruby/library/matrix/determinant_spec.rb b/spec/ruby/library/matrix/determinant_spec.rb
new file mode 100644
index 0000000000..9ad34c6fc3
--- /dev/null
+++ b/spec/ruby/library/matrix/determinant_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/determinant', __FILE__)
+require 'matrix'
+
+describe "Matrix#determinant" do
+ it_behaves_like(:determinant, :determinant)
+end
diff --git a/spec/ruby/library/matrix/diagonal_spec.rb b/spec/ruby/library/matrix/diagonal_spec.rb
new file mode 100644
index 0000000000..c88a92b5cd
--- /dev/null
+++ b/spec/ruby/library/matrix/diagonal_spec.rb
@@ -0,0 +1,72 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix.diagonal" do
+ before :each do
+ @m = Matrix.diagonal(10, 11, 12, 13, 14)
+ end
+
+ it "returns an object of type Matrix" do
+ @m.should be_kind_of(Matrix)
+ end
+
+ it "returns a square Matrix of the right size" do
+ @m.column_size.should == 5
+ @m.row_size.should == 5
+ end
+
+ it "sets the diagonal to the arguments" do
+ (0..4).each do |i|
+ @m[i, i].should == i + 10
+ end
+ end
+
+ it "fills all non-diagonal cells with 0" do
+ (0..4).each do |i|
+ (0..4).each do |j|
+ if i != j
+ @m[i, j].should == 0
+ end
+ end
+ end
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.diagonal(1).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
+
+describe "Matrix.diagonal?" do
+ it "returns true for a diagonal Matrix" do
+ Matrix.diagonal([1, 2, 3]).diagonal?.should be_true
+ end
+
+ it "returns true for a zero square Matrix" do
+ Matrix.zero(3).diagonal?.should be_true
+ end
+
+ it "returns false for a non diagonal square Matrix" do
+ Matrix[[0, 1], [0, 0]].diagonal?.should be_false
+ Matrix[[1, 2, 3], [1, 2, 3], [1, 2, 3]].diagonal?.should be_false
+ end
+
+ it "returns true for an empty 0x0 matrix" do
+ Matrix.empty(0,0).diagonal?.should be_true
+ end
+
+ it "raises an error for rectangular matrices" do
+ [
+ Matrix[[0], [0]],
+ Matrix[[0, 0]],
+ Matrix.empty(0, 2),
+ Matrix.empty(2, 0),
+ ].each do |rectangual_matrix|
+ lambda {
+ rectangual_matrix.diagonal?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/divide_spec.rb b/spec/ruby/library/matrix/divide_spec.rb
new file mode 100644
index 0000000000..b602d7d10f
--- /dev/null
+++ b/spec/ruby/library/matrix/divide_spec.rb
@@ -0,0 +1,55 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#/" do
+ before :each do
+ @a = Matrix[ [1, 2], [3, 4] ]
+ @b = Matrix[ [4, 5], [6, 7] ]
+ @c = Matrix[ [1.2, 2.4], [3.6, 4.8] ]
+ end
+
+ it "returns the result of dividing self by another Matrix" do
+ (@a / @b).should be_close_to_matrix([[2.5, -1.5], [1.5, -0.5]])
+ end
+
+ conflicts_with :Prime do
+ it "returns the result of dividing self by a Fixnum" do
+ (@a / 2).should == Matrix[ [0, 1], [1, 2] ]
+ end
+ end
+
+ conflicts_with :Prime do
+ it "returns the result of dividing self by a Bignum" do
+ (@a / bignum_value).should == Matrix[ [0, 0], [0, 0] ]
+ end
+ end
+
+ it "returns the result of dividing self by a Float" do
+ (@c / 1.2).should == Matrix[ [1, 2], [3, 4] ]
+ end
+
+ it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do
+ lambda { @a / Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+ it "returns an instance of Matrix" do
+ (@a / @b).should be_kind_of(Matrix)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ m = MatrixSub.ins
+ (m/m).should be_an_instance_of(MatrixSub)
+ (m/1).should be_an_instance_of(MatrixSub)
+ end
+ end
+
+ it "raises a TypeError if other is of wrong type" do
+ lambda { @a / nil }.should raise_error(TypeError)
+ lambda { @a / "a" }.should raise_error(TypeError)
+ lambda { @a / [ [1, 2] ] }.should raise_error(TypeError)
+ lambda { @a / Object.new }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/matrix/each_spec.rb b/spec/ruby/library/matrix/each_spec.rb
new file mode 100644
index 0000000000..18875692e6
--- /dev/null
+++ b/spec/ruby/library/matrix/each_spec.rb
@@ -0,0 +1,74 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#each" do
+ before :all do
+ @m = Matrix[ [1, 2, 3], [4, 5, 6] ]
+ @result = (1..6).to_a
+ end
+
+ it "returns an Enumerator when called without a block" do
+ enum = @m.each
+ enum.should be_an_instance_of(Enumerator)
+ enum.to_a.should == @result
+ end
+
+ it "returns self" do
+ @m.each{}.should equal(@m)
+ end
+
+ it "yields the elements starting with the those of the first row" do
+ a = []
+ @m.each {|x| a << x}
+ a.should == @result
+ end
+end
+
+describe "Matrix#each with an argument" do
+ before :all do
+ @m = Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ]
+ @t = Matrix[ [1, 2], [3, 4], [5, 6], [7, 8] ]
+ end
+
+ it "raises an ArgumentError for unrecognized argument" do
+ lambda {
+ @m.each("all"){}
+ }.should raise_error(ArgumentError)
+ lambda {
+ @m.each(nil){}
+ }.should raise_error(ArgumentError)
+ lambda {
+ @m.each(:left){}
+ }.should raise_error(ArgumentError)
+ end
+
+ it "yields the rights elements when passed :diagonal" do
+ @m.each(:diagonal).to_a.should == [1, 6]
+ @t.each(:diagonal).to_a.should == [1, 4]
+ end
+
+ it "yields the rights elements when passed :off_diagonal" do
+ @m.each(:off_diagonal).to_a.should == [2, 3, 4, 5, 7, 8]
+ @t.each(:off_diagonal).to_a.should == [2, 3, 5, 6, 7, 8]
+ end
+
+ it "yields the rights elements when passed :lower" do
+ @m.each(:lower).to_a.should == [1, 5, 6]
+ @t.each(:lower).to_a.should == [1, 3, 4, 5, 6, 7, 8]
+ end
+
+ it "yields the rights elements when passed :strict_lower" do
+ @m.each(:strict_lower).to_a.should == [5]
+ @t.each(:strict_lower).to_a.should == [3, 5, 6, 7, 8]
+ end
+
+ it "yields the rights elements when passed :strict_upper" do
+ @m.each(:strict_upper).to_a.should == [2, 3, 4, 7, 8]
+ @t.each(:strict_upper).to_a.should == [2]
+ end
+
+ it "yields the rights elements when passed :upper" do
+ @m.each(:upper).to_a.should == [1, 2, 3, 4, 6, 7, 8]
+ @t.each(:upper).to_a.should == [1, 2, 4]
+ end
+end
diff --git a/spec/ruby/library/matrix/each_with_index_spec.rb b/spec/ruby/library/matrix/each_with_index_spec.rb
new file mode 100644
index 0000000000..796a6c2a96
--- /dev/null
+++ b/spec/ruby/library/matrix/each_with_index_spec.rb
@@ -0,0 +1,81 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#each_with_index" do
+ before :all do
+ @m = Matrix[ [1, 2, 3], [4, 5, 6] ]
+ @result = [
+ [1, 0, 0],
+ [2, 0, 1],
+ [3, 0, 2],
+ [4, 1, 0],
+ [5, 1, 1],
+ [6, 1, 2]
+ ]
+ end
+
+ it "returns an Enumerator when called without a block" do
+ enum = @m.each_with_index
+ enum.should be_an_instance_of(Enumerator)
+ enum.to_a.should == @result
+ end
+
+ it "returns self" do
+ @m.each_with_index{}.should equal(@m)
+ end
+
+ it "yields the elements starting with the those of the first row" do
+ a = []
+ @m.each_with_index {|x, r, c| a << [x, r, c]}
+ a.should == @result
+ end
+end
+
+describe "Matrix#each_with_index with an argument" do
+ before :all do
+ @m = Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ]
+ @t = Matrix[ [1, 2], [3, 4], [5, 6], [7, 8] ]
+ end
+
+ it "raises an ArgumentError for unrecognized argument" do
+ lambda {
+ @m.each_with_index("all"){}
+ }.should raise_error(ArgumentError)
+ lambda {
+ @m.each_with_index(nil){}
+ }.should raise_error(ArgumentError)
+ lambda {
+ @m.each_with_index(:left){}
+ }.should raise_error(ArgumentError)
+ end
+
+ it "yields the rights elements when passed :diagonal" do
+ @m.each_with_index(:diagonal).to_a.should == [[1, 0, 0], [6, 1, 1]]
+ @t.each_with_index(:diagonal).to_a.should == [[1, 0, 0], [4, 1, 1]]
+ end
+
+ it "yields the rights elements when passed :off_diagonal" do
+ @m.each_with_index(:off_diagonal).to_a.should == [[2, 0, 1], [3, 0, 2], [4, 0, 3], [5, 1, 0], [7, 1, 2], [8, 1, 3]]
+ @t.each_with_index(:off_diagonal).to_a.should == [[2, 0, 1], [3, 1, 0], [5, 2, 0], [6, 2, 1], [7, 3, 0], [8, 3, 1]]
+ end
+
+ it "yields the rights elements when passed :lower" do
+ @m.each_with_index(:lower).to_a.should == [[1, 0, 0], [5, 1, 0], [6, 1, 1]]
+ @t.each_with_index(:lower).to_a.should == [[1, 0, 0], [3, 1, 0], [4, 1, 1], [5, 2, 0], [6, 2, 1], [7, 3, 0], [8, 3, 1]]
+ end
+
+ it "yields the rights elements when passed :strict_lower" do
+ @m.each_with_index(:strict_lower).to_a.should == [[5, 1, 0]]
+ @t.each_with_index(:strict_lower).to_a.should == [[3, 1, 0], [5, 2, 0], [6, 2, 1], [7, 3, 0], [8, 3, 1]]
+ end
+
+ it "yields the rights elements when passed :strict_upper" do
+ @m.each_with_index(:strict_upper).to_a.should == [[2, 0, 1], [3, 0, 2], [4, 0, 3], [7, 1, 2], [8, 1, 3]]
+ @t.each_with_index(:strict_upper).to_a.should == [[2, 0, 1]]
+ end
+
+ it "yields the rights elements when passed :upper" do
+ @m.each_with_index(:upper).to_a.should == [[1, 0, 0], [2, 0, 1], [3, 0, 2], [4, 0, 3], [6, 1, 1], [7, 1, 2], [8, 1, 3]]
+ @t.each_with_index(:upper).to_a.should == [[1, 0, 0], [2, 0, 1], [4, 1, 1]]
+ end
+end
diff --git a/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb b/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb
new file mode 100644
index 0000000000..3443eeaaf9
--- /dev/null
+++ b/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::EigenvalueDecomposition#eigenvalue_matrix" do
+ it "returns a diagonal matrix with the eigenvalues on the diagonal" do
+ Matrix[[14, 16], [-6, -6]].eigensystem.eigenvalue_matrix.should == Matrix[[6, 0],[0, 2]]
+ Matrix[[1, 1], [-1, 1]].eigensystem.eigenvalue_matrix.should == Matrix[[Complex(1,1), 0],[0, Complex(1,-1)]]
+ end
+end
diff --git a/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb b/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb
new file mode 100644
index 0000000000..c175a29947
--- /dev/null
+++ b/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::EigenvalueDecomposition#eigenvalues" do
+ it "returns an array of complex eigenvalues for a rotation matrix" do
+ Matrix[[ 1, 1],
+ [-1, 1]].eigensystem.eigenvalues.sort_by{|v| v.imag}.should ==
+ [ Complex(1, -1), Complex(1, 1)]
+ end
+
+ it "returns an array of real eigenvalues for a symetric matrix" do
+ Matrix[[1, 2],
+ [2, 1]].eigensystem.eigenvalues.sort.map!{|x| x.round(10)}.should ==
+ [ -1, 3 ]
+ end
+
+ it "returns an array of real eigenvalues for a matrix" do
+ Matrix[[14, 16],
+ [-6, -6]].eigensystem.eigenvalues.sort.map!{|x| x.round(10)}.should ==
+ [ 2, 6 ]
+ end
+end
diff --git a/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb b/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb
new file mode 100644
index 0000000000..709ec68d0c
--- /dev/null
+++ b/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::EigenvalueDecomposition#eigenvector_matrix" do
+ it "returns a complex eigenvector matrix given a rotation matrix" do
+ # Fix me: should test for linearity, not for equality
+ Matrix[[ 1, 1],
+ [-1, 1]].eigensystem.eigenvector_matrix.should ==
+ Matrix[[1, 1],
+ [Complex(0, 1), Complex(0, -1)]]
+ end
+
+ it "returns an real eigenvector matrix for a symetric matrix" do
+ # Fix me: should test for linearity, not for equality
+ Matrix[[1, 2],
+ [2, 1]].eigensystem.eigenvector_matrix.should ==
+ Matrix[[0.7071067811865475, 0.7071067811865475],
+ [-0.7071067811865475, 0.7071067811865475]]
+ end
+end
diff --git a/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb b/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb
new file mode 100644
index 0000000000..163bebe709
--- /dev/null
+++ b/spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::EigenvalueDecomposition#eigenvectors" do
+ it "returns an array of complex eigenvectors for a rotation matrix" do
+ # Fix me: should test for linearity, not for equality
+ Matrix[[ 1, 1],
+ [-1, 1]].eigensystem.eigenvectors.should ==
+ [ Vector[1, Complex(0, 1)],
+ Vector[1, Complex(0, -1)]
+ ]
+ end
+
+ it "returns an array of real eigenvectors for a symetric matrix" do
+ # Fix me: should test for linearity, not for equality
+ Matrix[[1, 2],
+ [2, 1]].eigensystem.eigenvectors.should ==
+ [ Vector[0.7071067811865475, -0.7071067811865475],
+ Vector[0.7071067811865475, 0.7071067811865475]
+ ]
+ end
+end
diff --git a/spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb b/spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb
new file mode 100644
index 0000000000..97d9be8f2d
--- /dev/null
+++ b/spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::EigenvalueDecomposition#initialize" do
+ it "raises an error if argument is not a matrix" do
+ lambda {
+ Matrix::EigenvalueDecomposition.new([[]])
+ }.should raise_error(TypeError)
+ lambda {
+ Matrix::EigenvalueDecomposition.new(42)
+ }.should raise_error(TypeError)
+ end
+
+ it "raises an error if matrix is not square" do
+ lambda {
+ Matrix::EigenvalueDecomposition.new(Matrix[[1, 2]])
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+ it "never hangs" do
+ m = Matrix[ [0,0,0,0,0], [0,0,0,0,1], [0,0,0,1,0], [1,1,0,0,1], [1,0,1,0,1] ]
+ Matrix::EigenvalueDecomposition.new(m).should_not == "infinite loop"
+ end
+end
diff --git a/spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb b/spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb
new file mode 100644
index 0000000000..e9b849eb97
--- /dev/null
+++ b/spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::EigenvalueDecomposition#to_a" do
+ before :each do
+ @a = Matrix[[14, 16], [-6, -6]]
+ @e = Matrix::EigenvalueDecomposition.new(@a)
+ end
+
+ it "returns an array of with [V, D, V.inv]" do
+ @e.to_a.should == [@e.v, @e.d, @e.v_inv]
+ end
+
+ it "returns a factorization" do
+ v, d, v_inv = @e.to_a
+ (v * d * v_inv).map{|e| e.round(10)}.should == @a
+ end
+end
diff --git a/spec/ruby/library/matrix/element_reference_spec.rb b/spec/ruby/library/matrix/element_reference_spec.rb
new file mode 100644
index 0000000000..f4f63c0f65
--- /dev/null
+++ b/spec/ruby/library/matrix/element_reference_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#[]" do
+
+ before :all do
+ @m = Matrix[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
+ end
+
+ it "returns element at (i, j)" do
+ (0..3).each do |i|
+ (0..2).each do |j|
+ @m[i, j].should == (i * 3) + j
+ end
+ end
+ end
+
+ it "returns nil for an invalid index pair" do
+ @m[8,1].should be_nil
+ @m[1,8].should be_nil
+ end
+
+end
diff --git a/spec/ruby/library/matrix/empty_spec.rb b/spec/ruby/library/matrix/empty_spec.rb
new file mode 100644
index 0000000000..cead6126ff
--- /dev/null
+++ b/spec/ruby/library/matrix/empty_spec.rb
@@ -0,0 +1,68 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#empty?" do
+ it "returns true when the Matrix is empty" do
+ Matrix[ ].empty?.should be_true
+ Matrix[ [], [], [] ].empty?.should be_true
+ Matrix[ [], [], [] ].transpose.empty?.should be_true
+ end
+
+ it "returns false when the Matrix has elements" do
+ Matrix[ [1, 2] ].empty?.should be_false
+ Matrix[ [1], [2] ].empty?.should be_false
+ end
+
+ it "doesn't accept any parameter" do
+ lambda{
+ Matrix[ [1, 2] ].empty?(42)
+ }.should raise_error(ArgumentError)
+ end
+end
+
+describe "Matrix.empty" do
+ it "returns an empty matrix of the requested size" do
+ m = Matrix.empty(3, 0)
+ m.row_size.should == 3
+ m.column_size.should == 0
+
+ m = Matrix.empty(0, 3)
+ m.row_size.should == 0
+ m.column_size.should == 3
+ end
+
+ it "has arguments defaulting to 0" do
+ Matrix.empty.should == Matrix.empty(0, 0)
+ Matrix.empty(42).should == Matrix.empty(42, 0)
+ end
+
+ it "does not accept more than two parameters" do
+ lambda{
+ Matrix.empty(1, 2, 3)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error if both dimensions are > 0" do
+ lambda{
+ Matrix.empty(1, 2)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error if any dimension is < 0" do
+ lambda{
+ Matrix.empty(-2, 0)
+ }.should raise_error(ArgumentError)
+
+ lambda{
+ Matrix.empty(0, -2)
+ }.should raise_error(ArgumentError)
+ end
+
+end
+
+describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.empty(0, 1).should be_an_instance_of(MatrixSub)
+ end
+end
diff --git a/spec/ruby/library/matrix/eql_spec.rb b/spec/ruby/library/matrix/eql_spec.rb
new file mode 100644
index 0000000000..e76d26753a
--- /dev/null
+++ b/spec/ruby/library/matrix/eql_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/equal_value', __FILE__)
+require 'matrix'
+
+describe "Matrix#eql?" do
+ it_behaves_like(:equal, :eql?)
+
+ it "returns false if some elements are == but not eql?" do
+ Matrix[[1, 2],[3, 4]].eql?(Matrix[[1, 2],[3, 4.0]]).should be_false
+ end
+end
diff --git a/spec/ruby/library/matrix/equal_value_spec.rb b/spec/ruby/library/matrix/equal_value_spec.rb
new file mode 100644
index 0000000000..e14a38b872
--- /dev/null
+++ b/spec/ruby/library/matrix/equal_value_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/equal_value', __FILE__)
+require 'matrix'
+
+describe "Matrix#==" do
+ it_behaves_like(:equal, :==)
+
+ it "returns true if some elements are == but not eql?" do
+ Matrix[[1, 2],[3, 4]].should == Matrix[[1, 2],[3, 4.0]]
+ end
+end
diff --git a/spec/ruby/library/matrix/exponent_spec.rb b/spec/ruby/library/matrix/exponent_spec.rb
new file mode 100644
index 0000000000..188a1b34d2
--- /dev/null
+++ b/spec/ruby/library/matrix/exponent_spec.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#**" do
+
+ describe "given an integer _n_" do
+ it "multiples the Matrix by itself _n_ times" do
+ m = Matrix[ [7,6], [3,9] ]
+ (m ** 1).should == m
+ (m ** 2).should == Matrix[ [67, 96], [48,99] ]
+ (m ** 2).should == m * m
+ (m ** 3).should == m * m * m
+ (m ** 4).should == m * m * m * m
+ (m ** 5).should == m * m * m * m * m
+ end
+
+ it "raises a ErrDimensionMismatch for non square matrices" do
+ m = Matrix[ [1, 1], [1, 2], [2, 3]]
+ lambda { m ** 3 }.should raise_error(Matrix::ErrDimensionMismatch)
+ lambda { m ** 0 }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+ describe "that is <= 0" do
+ it "returns the inverse of **(-n)" do
+ m = Matrix[ [1, 1], [1, 2] ]
+ (m ** -2).should == Matrix[ [5, -3], [-3, 2]]
+ (m ** -4).should == (m.inverse ** 4)
+ end
+
+ it "raises a ErrDimensionMismatch for irregular matrices" do
+ m = Matrix[ [1, 1], [1, 1] ]
+ lambda { m ** -2 }.should raise_error(Matrix::ErrNotRegular)
+ lambda { m ** 0 }.should raise_error(Matrix::ErrNotRegular)
+ end
+ end
+ end
+
+ it "returns the power for non integer powers" do
+ a = Matrix[[5, 4], [4, 5]]
+ ((a ** 0.5) ** 2).round(8).should == a
+ a = Matrix[[7, 10], [15, 22]]
+ ((a ** 0.25) ** 4).round(8).should == a
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ (MatrixSub.ins ** 1).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/find_index_spec.rb b/spec/ruby/library/matrix/find_index_spec.rb
new file mode 100644
index 0000000000..8ea891644a
--- /dev/null
+++ b/spec/ruby/library/matrix/find_index_spec.rb
@@ -0,0 +1,146 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#find_index without any argument" do
+ before :all do
+ @m = Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ]
+ end
+
+ it "returns an Enumerator when called without a block" do
+ enum = @m.find_index
+ enum.should be_an_instance_of(Enumerator)
+ enum.to_a.should == [1, 2, 3, 4, 5, 6, 7, 8]
+ end
+
+ it "returns nil if the block is always false" do
+ @m.find_index{false}.should be_nil
+ end
+
+ it "returns the first index for which the block is true" do
+ @m.find_index{|x| x >= 3}.should == [0, 2]
+ end
+end
+
+describe "Matrix#find_index with a subselection argument" do
+ before :all do
+ @tests = [
+ [ Matrix[ [1, 2, 3, 4], [5, 6, 7, 8] ], {
+ diagonal: [1, 6] ,
+ off_diagonal: [2, 3, 4, 5, 7, 8],
+ lower: [1, 5, 6] ,
+ strict_lower: [5] ,
+ strict_upper: [2, 3, 4, 7, 8] ,
+ upper: [1, 2, 3, 4, 6, 7, 8] ,
+ }
+ ],
+ [ Matrix[ [1, 2], [3, 4], [5, 6], [7, 8] ], {
+ diagonal: [1, 4] ,
+ off_diagonal: [2, 3, 5, 6, 7, 8],
+ lower: [1, 3, 4, 5, 6, 7, 8] ,
+ strict_lower: [3, 5, 6, 7, 8] ,
+ strict_upper: [2] ,
+ upper: [1, 2, 4] ,
+ }
+ ]]
+ end
+
+ describe "and no generic argument" do
+ it "returns an Enumerator when called without a block" do
+ @tests.each do |matrix, h|
+ h.each do |selector, result|
+ matrix.find_index(selector).should be_an_instance_of(Enumerator)
+ end
+ end
+ end
+
+ it "yields the rights elements" do
+ @tests.each do |matrix, h|
+ h.each do |selector, result|
+ matrix.find_index(selector).to_a.should == result
+ end
+ end
+ end
+
+ it "returns the first index for which the block returns true" do
+ @tests.each do |matrix, h|
+ h.each do |selector, result|
+ cnt = result.size.div 2
+ which = result[cnt]
+ idx = matrix.find_index(selector){|x| cnt -= 1; x == which}
+ matrix[*idx].should == which
+ cnt.should == -1
+ end
+ end
+ end
+
+ it "returns nil if the block is always false" do
+ @tests.each do |matrix, h|
+ h.each do |selector, result|
+ matrix.find_index(selector){ nil }.should == nil
+ end
+ end
+ end
+
+ end
+
+ describe "and a generic argument" do
+ it "ignores a block" do
+ @m.find_index(42, :diagonal){raise "oups"}.should == nil
+ end
+
+ it "returns the index of the requested value" do
+ @tests.each do |matrix, h|
+ h.each do |selector, result|
+ cnt = result.size / 2
+ which = result[cnt]
+ idx = matrix.find_index(which, selector)
+ matrix[*idx].should == which
+ end
+ end
+ end
+
+ it "returns nil if the requested value is not found" do
+ @tests.each do |matrix, h|
+ h.each do |selector, result|
+ matrix.find_index(42, selector).should == nil
+ end
+ end
+ end
+ end
+
+end
+
+describe "Matrix#find_index with only a generic argument" do
+ before :all do
+ @m = Matrix[ [1, 2, 3, 4], [1, 2, 3, 4] ]
+ end
+
+ it "returns nil if the value is not found" do
+ @m.find_index(42).should be_nil
+ end
+
+ it "returns the first index for of the requested value" do
+ @m.find_index(3).should == [0, 2]
+ end
+
+ it "ignores a block" do
+ @m.find_index(4){raise "oups"}.should == [0, 3]
+ end
+end
+
+describe "Matrix#find_index with two arguments" do
+ it "raises an ArgumentError for an unrecognized last argument" do
+ lambda {
+ @m.find_index(1, "all"){}
+ }.should raise_error(ArgumentError)
+ lambda {
+ @m.find_index(1, nil){}
+ }.should raise_error(ArgumentError)
+ lambda {
+ @m.find_index(1, :left){}
+ }.should raise_error(ArgumentError)
+ lambda {
+ @m.find_index(:diagonal, 1){}
+ }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/matrix/fixtures/classes.rb b/spec/ruby/library/matrix/fixtures/classes.rb
new file mode 100644
index 0000000000..394377135f
--- /dev/null
+++ b/spec/ruby/library/matrix/fixtures/classes.rb
@@ -0,0 +1,7 @@
+require 'matrix'
+
+class MatrixSub < Matrix
+ def self.ins
+ rows([[1, 0], [0, 1]])
+ end
+end
diff --git a/spec/ruby/library/matrix/hash_spec.rb b/spec/ruby/library/matrix/hash_spec.rb
new file mode 100644
index 0000000000..b2e5b579b7
--- /dev/null
+++ b/spec/ruby/library/matrix/hash_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#hash" do
+
+ it "returns a Fixnum" do
+ Matrix[ [1,2] ].hash.should be_an_instance_of(Fixnum)
+ end
+
+ it "returns the same value for the same matrix" do
+ data = [ [40,5], [2,7] ]
+ Matrix[ *data ].hash.should == Matrix[ *data ].hash
+ end
+
+end
diff --git a/spec/ruby/library/matrix/hermitian_spec.rb b/spec/ruby/library/matrix/hermitian_spec.rb
new file mode 100644
index 0000000000..cbfea433c2
--- /dev/null
+++ b/spec/ruby/library/matrix/hermitian_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix.hermitian?" do
+ it "returns true for a hermitian Matrix" do
+ Matrix[[1, 2, Complex(0, 3)], [2, 4, 5], [Complex(0, -3), 5, 6]].hermitian?.should be_true
+ end
+
+ it "returns true for a 0x0 empty matrix" do
+ Matrix.empty.hermitian?.should be_true
+ end
+
+ it "returns false for an assymetric Matrix" do
+ Matrix[[1, 2],[-2, 1]].hermitian?.should be_false
+ end
+
+ it "raises an error for rectangular matrices" do
+ [
+ Matrix[[0], [0]],
+ Matrix[[0, 0]],
+ Matrix.empty(0, 2),
+ Matrix.empty(2, 0),
+ ].each do |rectangual_matrix|
+ lambda {
+ rectangual_matrix.hermitian?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+ end
+
+ it "returns false for a matrix with complex values on the diagonal" do
+ Matrix[[Complex(1,1)]].hermitian?.should be_false
+ Matrix[[Complex(1,0)]].hermitian?.should be_true
+ end
+end
diff --git a/spec/ruby/library/matrix/identity_spec.rb b/spec/ruby/library/matrix/identity_spec.rb
new file mode 100644
index 0000000000..bc7df98dde
--- /dev/null
+++ b/spec/ruby/library/matrix/identity_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/identity', __FILE__)
+
+describe "Matrix.identity" do
+ it_behaves_like(:matrix_identity, :identity)
+end
diff --git a/spec/ruby/library/matrix/imag_spec.rb b/spec/ruby/library/matrix/imag_spec.rb
new file mode 100644
index 0000000000..41083879e4
--- /dev/null
+++ b/spec/ruby/library/matrix/imag_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/imaginary', __FILE__)
+
+describe "Matrix#imag" do
+ it_behaves_like(:matrix_imaginary, :imag)
+end
diff --git a/spec/ruby/library/matrix/imaginary_spec.rb b/spec/ruby/library/matrix/imaginary_spec.rb
new file mode 100644
index 0000000000..2a05f1d5c3
--- /dev/null
+++ b/spec/ruby/library/matrix/imaginary_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/imaginary', __FILE__)
+
+describe "Matrix#imaginary" do
+ it_behaves_like(:matrix_imaginary, :imaginary)
+end
diff --git a/spec/ruby/library/matrix/inspect_spec.rb b/spec/ruby/library/matrix/inspect_spec.rb
new file mode 100644
index 0000000000..bf623e1a85
--- /dev/null
+++ b/spec/ruby/library/matrix/inspect_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#inspect" do
+
+ it "returns a stringified representation of the Matrix" do
+ Matrix[ [1,2], [2,1] ].inspect.should == "Matrix[[1, 2], [2, 1]]"
+ end
+
+ it "returns 'Matrix.empty(...)' for empty matrices" do
+ Matrix[ [], [], [] ].inspect.should == "Matrix.empty(3, 0)"
+ Matrix.columns([ [], [], [] ]).inspect.should == "Matrix.empty(0, 3)"
+ end
+
+ it "calls inspect on its contents" do
+ obj = mock("some_value")
+ obj.should_receive(:inspect).and_return("some_value")
+ Matrix[ [1, 2], [3, obj] ].inspect.should == "Matrix[[1, 2], [3, some_value]]"
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns a string using the subclass' name" do
+ MatrixSub.ins.inspect.should == "MatrixSub[[1, 0], [0, 1]]"
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/inv_spec.rb b/spec/ruby/library/matrix/inv_spec.rb
new file mode 100644
index 0000000000..0491aa7b07
--- /dev/null
+++ b/spec/ruby/library/matrix/inv_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../shared/inverse', __FILE__)
+
+describe "Matrix#inv" do
+ it_behaves_like(:inverse, :inv)
+end
diff --git a/spec/ruby/library/matrix/inverse_from_spec.rb b/spec/ruby/library/matrix/inverse_from_spec.rb
new file mode 100644
index 0000000000..958b3b7408
--- /dev/null
+++ b/spec/ruby/library/matrix/inverse_from_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#inverse_from" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/inverse_spec.rb b/spec/ruby/library/matrix/inverse_spec.rb
new file mode 100644
index 0000000000..33a1f2f5de
--- /dev/null
+++ b/spec/ruby/library/matrix/inverse_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../shared/inverse', __FILE__)
+
+describe "Matrix#inverse" do
+ it_behaves_like(:inverse, :inverse)
+end
diff --git a/spec/ruby/library/matrix/lower_triangular_spec.rb b/spec/ruby/library/matrix/lower_triangular_spec.rb
new file mode 100644
index 0000000000..62b3df2104
--- /dev/null
+++ b/spec/ruby/library/matrix/lower_triangular_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix.lower_triangular?" do
+ it "returns true for a square lower triangular Matrix" do
+ Matrix[[1, 0, 0], [1, 2, 0], [1, 2, 3]].lower_triangular?.should be_true
+ Matrix.diagonal([1, 2, 3]).lower_triangular?.should be_true
+ Matrix[[1, 0], [1, 2], [1, 2], [1, 2]].lower_triangular?.should be_true
+ Matrix[[1, 0, 0, 0], [1, 2, 0, 0]].lower_triangular?.should be_true
+ end
+
+ it "returns true for an empty Matrix" do
+ Matrix.empty(3, 0).lower_triangular?.should be_true
+ Matrix.empty(0, 3).lower_triangular?.should be_true
+ Matrix.empty(0, 0).lower_triangular?.should be_true
+ end
+
+ it "returns false for a non lower triangular square Matrix" do
+ Matrix[[0, 1], [0, 0]].lower_triangular?.should be_false
+ Matrix[[1, 2, 3], [1, 2, 3], [1, 2, 3]].lower_triangular?.should be_false
+ Matrix[[0, 1], [0, 0], [0, 0], [0, 0]].lower_triangular?.should be_false
+ Matrix[[0, 0, 0, 1], [0, 0, 0, 0]].lower_triangular?.should be_false
+ end
+end
diff --git a/spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb b/spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb
new file mode 100644
index 0000000000..f73c65ba8f
--- /dev/null
+++ b/spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::LUPDecomposition#determinant" do
+ it "returns the determinant when the matrix is square" do
+ a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]]
+ a.lup.determinant.should == 15120 # == a.determinant
+ end
+
+ it "raises an error for rectangular matrices" do
+ [
+ Matrix[[7, 8, 9], [14, 46, 51]],
+ Matrix[[7, 8], [14, 46], [28, 82]],
+ ].each do |m|
+ lup = m.lup
+ lambda {
+ lup.determinant
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb b/spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb
new file mode 100644
index 0000000000..953389083f
--- /dev/null
+++ b/spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::LUPDecomposition#initialize" do
+ it "raises an error if argument is not a matrix" do
+ lambda {
+ Matrix::LUPDecomposition.new([[]])
+ }.should raise_error(TypeError)
+ lambda {
+ Matrix::LUPDecomposition.new(42)
+ }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/matrix/lup_decomposition/l_spec.rb b/spec/ruby/library/matrix/lup_decomposition/l_spec.rb
new file mode 100644
index 0000000000..c50b5f712e
--- /dev/null
+++ b/spec/ruby/library/matrix/lup_decomposition/l_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::LUPDecomposition#l" do
+ before :each do
+ @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]]
+ @lu = Matrix::LUPDecomposition.new(@a)
+ @l = @lu.l
+ end
+
+ it "returns the first element of to_a" do
+ @l.should == @lu.to_a[0]
+ end
+
+ it "returns a lower triangular matrix" do
+ @l.lower_triangular?.should be_true
+ end
+end
diff --git a/spec/ruby/library/matrix/lup_decomposition/p_spec.rb b/spec/ruby/library/matrix/lup_decomposition/p_spec.rb
new file mode 100644
index 0000000000..837b65a915
--- /dev/null
+++ b/spec/ruby/library/matrix/lup_decomposition/p_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::LUPDecomposition#p" do
+ before :each do
+ @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]]
+ @lu = Matrix::LUPDecomposition.new(@a)
+ @p = @lu.p
+ end
+
+ it "returns the third element of to_a" do
+ @p.should == @lu.to_a[2]
+ end
+
+ it "returns a permutation matrix" do
+ @p.permutation?.should be_true
+ end
+end
diff --git a/spec/ruby/library/matrix/lup_decomposition/solve_spec.rb b/spec/ruby/library/matrix/lup_decomposition/solve_spec.rb
new file mode 100644
index 0000000000..c4ef42bcea
--- /dev/null
+++ b/spec/ruby/library/matrix/lup_decomposition/solve_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::LUPDecomposition#solve" do
+ describe "for rectangular matrices" do
+ it "raises an error for singular matrices" do
+ a = Matrix[[1, 2, 3], [1, 3, 5], [2, 5, 8]]
+ lu = Matrix::LUPDecomposition.new(a)
+ lambda {
+ lu.solve(a)
+ }.should raise_error(Matrix::ErrNotRegular)
+ end
+
+ describe "for non singular matrices" do
+ before :each do
+ @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]]
+ @lu = Matrix::LUPDecomposition.new(@a)
+ end
+
+ it "returns the appropriate empty matrix when given an empty matrix" do
+ @lu.solve(Matrix.empty(3,0)).should == Matrix.empty(3,0)
+ empty = Matrix::LUPDecomposition.new(Matrix.empty(0, 0))
+ empty.solve(Matrix.empty(0,3)).should == Matrix.empty(0,3)
+ end
+
+ it "returns the right matrix when given a matrix of the appropriate size" do
+ solution = Matrix[[1, 2, 3, 4], [0, 1, 2, 3], [-1, -2, -3, -4]]
+ values = Matrix[[-2, 4, 10, 16], [-37, -28, -19, -10], [-135, -188, -241, -294]] # == @a * solution
+ @lu.solve(values).should == solution
+ end
+
+ it "raises an error when given a matrix of the wrong size" do
+ values = Matrix[[1, 2, 3, 4], [0, 1, 2, 3]]
+ lambda {
+ @lu.solve(values)
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+ it "returns the right vector when given a vector of the appropriate size" do
+ solution = Vector[1, 2, -1]
+ values = Vector[14, 55, 29] # == @a * solution
+ @lu.solve(values).should == solution
+ end
+
+ it "raises an error when given a vector of the wrong size" do
+ values = Vector[14, 55]
+ lambda {
+ @lu.solve(values)
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb b/spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb
new file mode 100644
index 0000000000..20be26eb9c
--- /dev/null
+++ b/spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::LUPDecomposition#to_a" do
+ before :each do
+ @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]]
+ @lu = Matrix::LUPDecomposition.new(@a)
+ @to_a = @lu.to_a
+ @l, @u, @p = @to_a
+ end
+
+ it "returns an array of three matrices" do
+ @to_a.should be_kind_of(Array)
+ @to_a.length.should == 3
+ @to_a.each{|m| m.should be_kind_of(Matrix)}
+ end
+
+ it "returns [l, u, p] such that l*u == a*p" do
+ (@l * @u).should == (@p * @a)
+ end
+
+ it "returns the right values for rectangular matrices" do
+ [
+ Matrix[[7, 8, 9], [14, 46, 51]],
+ Matrix[[4, 11], [5, 8], [3, 4]],
+ ].each do |a|
+ l, u, p = Matrix::LUPDecomposition.new(a).to_a
+ (l * u).should == (p * a)
+ end
+ end
+
+ it "has other properties implied by the specs of #l, #u and #p"
+end
diff --git a/spec/ruby/library/matrix/lup_decomposition/u_spec.rb b/spec/ruby/library/matrix/lup_decomposition/u_spec.rb
new file mode 100644
index 0000000000..97e8580c58
--- /dev/null
+++ b/spec/ruby/library/matrix/lup_decomposition/u_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::LUPDecomposition#u" do
+ before :each do
+ @a = Matrix[[7, 8, 9], [14, 46, 51], [28, 82, 163]]
+ @lu = Matrix::LUPDecomposition.new(@a)
+ @u = @lu.u
+ end
+
+ it "returns the second element of to_a" do
+ @u.should == @lu.to_a[1]
+ end
+
+ it "returns an upper triangular matrix" do
+ @u.upper_triangular?.should be_true
+ end
+end
diff --git a/spec/ruby/library/matrix/map_spec.rb b/spec/ruby/library/matrix/map_spec.rb
new file mode 100644
index 0000000000..e18ab6eb7a
--- /dev/null
+++ b/spec/ruby/library/matrix/map_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/collect', __FILE__)
+
+describe "Matrix#map" do
+ it_behaves_like(:collect, :map)
+end
diff --git a/spec/ruby/library/matrix/minor_spec.rb b/spec/ruby/library/matrix/minor_spec.rb
new file mode 100644
index 0000000000..e02e0de07d
--- /dev/null
+++ b/spec/ruby/library/matrix/minor_spec.rb
@@ -0,0 +1,85 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#minor" do
+ before :each do
+ @matrix = Matrix[ [1,2], [3,4], [5,6] ]
+ end
+
+ describe "with start_row, nrows, start_col, ncols" do
+ it "returns the given portion of the Matrix" do
+ @matrix.minor(0,1,0,2).should == Matrix[ [1, 2] ]
+ @matrix.minor(1,2,1,1).should == Matrix[ [4], [6] ]
+ end
+
+ it "returns an empty Matrix if nrows or ncols is 0" do
+ @matrix.minor(0,0,0,0).should == Matrix[]
+ @matrix.minor(1,0,1,0).should == Matrix[]
+ @matrix.minor(1,0,1,1).should == Matrix.columns([[]])
+ @matrix.minor(1,1,1,0).should == Matrix[[]]
+ end
+
+ it "returns nil for out-of-bounds start_row/col" do
+ r = @matrix.row_size + 1
+ c = @matrix.column_size + 1
+ @matrix.minor(r,0,0,10).should == nil
+ @matrix.minor(0,10,c,9).should == nil
+ @matrix.minor(-r,0,0,10).should == nil
+ @matrix.minor(0,10,-c,9).should == nil
+ end
+
+ it "returns nil for negative nrows or ncols" do
+ @matrix.minor(0,1,0,-1).should == nil
+ @matrix.minor(0,-1,0,1).should == nil
+ end
+
+ it "start counting backwards for start_row or start_col below zero" do
+ @matrix.minor(0, 1, -1, 1).should == @matrix.minor(0, 1, 1, 1)
+ @matrix.minor(-1, 1, 0, 1).should == @matrix.minor(2, 1, 0, 1)
+ end
+
+ it "returns empty matrices for extreme start_row/col" do
+ @matrix.minor(3,10,1,10).should == Matrix.columns([[]])
+ @matrix.minor(1,10,2,10).should == Matrix[[], []]
+ @matrix.minor(3,0,0,10).should == Matrix.columns([[], []])
+ end
+
+ it "ignores big nrows or ncols" do
+ @matrix.minor(0,1,0,20).should == Matrix[ [1, 2] ]
+ @matrix.minor(1,20,1,1).should == Matrix[ [4], [6] ]
+ end
+ end
+
+ describe "with col_range, row_range" do
+ it "returns the given portion of the Matrix" do
+ @matrix.minor(0..0, 0..1).should == Matrix[ [1, 2] ]
+ @matrix.minor(1..2, 1..2).should == Matrix[ [4], [6] ]
+ @matrix.minor(1...3, 1...3).should == Matrix[ [4], [6] ]
+ end
+
+ it "returns nil if col_range or row_range is out of range" do
+ r = @matrix.row_size + 1
+ c = @matrix.column_size + 1
+ @matrix.minor(r..6, c..6).should == nil
+ @matrix.minor(0..1, c..6).should == nil
+ @matrix.minor(r..6, 0..1).should == nil
+ @matrix.minor(-r..6, -c..6).should == nil
+ @matrix.minor(0..1, -c..6).should == nil
+ @matrix.minor(-r..6, 0..1).should == nil
+ end
+
+ it "start counting backwards for col_range or row_range below zero" do
+ @matrix.minor(0..1, -2..-1).should == @matrix.minor(0..1, 0..1)
+ @matrix.minor(0..1, -2..1).should == @matrix.minor(0..1, 0..1)
+ @matrix.minor(-2..-1, 0..1).should == @matrix.minor(1..2, 0..1)
+ @matrix.minor(-2..2, 0..1).should == @matrix.minor(1..2, 0..1)
+ end
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.ins.minor(0, 1, 0, 1).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/minus_spec.rb b/spec/ruby/library/matrix/minus_spec.rb
new file mode 100644
index 0000000000..fe2d716882
--- /dev/null
+++ b/spec/ruby/library/matrix/minus_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#-" do
+ before :each do
+ @a = Matrix[ [1, 2], [3, 4] ]
+ @b = Matrix[ [4, 5], [6, 7] ]
+ end
+
+ it "returns the result of subtracting the corresponding elements of other from self" do
+ (@a - @b).should == Matrix[ [-3,-3], [-3,-3] ]
+ end
+
+ it "returns an instance of Matrix" do
+ (@a - @b).should be_kind_of(Matrix)
+ end
+
+ it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do
+ lambda { @a - Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+ it "raises a ExceptionForMatrix::ErrOperationNotDefined if other is a Numeric Type" do
+ lambda { @a - 2 }.should raise_error(Matrix::ErrOperationNotDefined)
+ lambda { @a - 1.2 }.should raise_error(Matrix::ErrOperationNotDefined)
+ lambda { @a - bignum_value }.should raise_error(Matrix::ErrOperationNotDefined)
+ end
+
+ it "raises a TypeError if other is of wrong type" do
+ lambda { @a - nil }.should raise_error(TypeError)
+ lambda { @a - "a" }.should raise_error(TypeError)
+ lambda { @a - [ [1, 2] ] }.should raise_error(TypeError)
+ lambda { @a - Object.new }.should raise_error(TypeError)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ m = MatrixSub.ins
+ (m-m).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/multiply_spec.rb b/spec/ruby/library/matrix/multiply_spec.rb
new file mode 100644
index 0000000000..dae87f5434
--- /dev/null
+++ b/spec/ruby/library/matrix/multiply_spec.rb
@@ -0,0 +1,68 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#*" do
+ before :each do
+ @a = Matrix[ [1, 2], [3, 4] ]
+ @b = Matrix[ [4, 5], [6, 7] ]
+ end
+
+ it "returns the result of multiplying the corresponding elements of self and a Matrix" do
+ (@a * @b).should == Matrix[ [16,19], [36,43] ]
+ end
+
+ it "returns the result of multiplying the corresponding elements of self and a Vector" do
+ (@a * Vector[1,2]).should == Vector[5, 11]
+ end
+
+ it "returns the result of multiplying the elements of self and a Fixnum" do
+ (@a * 2).should == Matrix[ [2, 4], [6, 8] ]
+ end
+
+ it "returns the result of multiplying the elements of self and a Bignum" do
+ (@a * bignum_value).should == Matrix[
+ [9223372036854775808, 18446744073709551616],
+ [27670116110564327424, 36893488147419103232]
+ ]
+ end
+
+ it "returns the result of multiplying the elements of self and a Float" do
+ (@a * 2.0).should == Matrix[ [2.0, 4.0], [6.0, 8.0] ]
+ end
+
+ it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do
+ lambda { @a * Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+ it "returns a zero matrix if (nx0) * (0xn)" do
+ (Matrix[[],[],[]] * Matrix.columns([[],[],[]])).should == Matrix.zero(3)
+ end
+
+ it "returns an empty matrix if (0xn) * (nx0)" do
+ (Matrix.columns([[],[],[]]) * Matrix[[],[],[]]).should == Matrix[]
+ end
+
+ it "returns a mx0 matrix if (mxn) * (nx0)" do
+ (Matrix[[1,2],[3,4],[5,6]] * Matrix[[],[]]).should == Matrix[[],[],[]]
+ end
+
+ it "returns a 0xm matrix if (0xm) * (mxn)" do
+ (Matrix.columns([[], [], []]) * Matrix[[1,2],[3,4],[5,6]]).should == Matrix.columns([[],[]])
+ end
+
+ it "raises a TypeError if other is of wrong type" do
+ lambda { @a * nil }.should raise_error(TypeError)
+ lambda { @a * "a" }.should raise_error(TypeError)
+ lambda { @a * [ [1, 2] ] }.should raise_error(TypeError)
+ lambda { @a * Object.new }.should raise_error(TypeError)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ m = MatrixSub.ins
+ (m*m).should be_an_instance_of(MatrixSub)
+ (m*1).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/new_spec.rb b/spec/ruby/library/matrix/new_spec.rb
new file mode 100644
index 0000000000..82d2bd88a7
--- /dev/null
+++ b/spec/ruby/library/matrix/new_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix.new" do
+ it "is private" do
+ Matrix.should have_private_method(:new)
+ end
+end
diff --git a/spec/ruby/library/matrix/normal_spec.rb b/spec/ruby/library/matrix/normal_spec.rb
new file mode 100644
index 0000000000..140909dcc2
--- /dev/null
+++ b/spec/ruby/library/matrix/normal_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix.normal?" do
+ # it "returns false for non normal matrices" do
+ # Matrix[[0, 1], [1, 2]].normal?.should == false
+ # end
+
+ it "returns true for normal matrices" do
+ Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].normal?.should == true
+ Matrix[[0, Complex(0, 2)], [Complex(0, -2), 0]].normal?.should == true
+ end
+
+ it "raises an error for rectangular matrices" do
+ [
+ Matrix[[0], [0]],
+ Matrix[[0, 0]],
+ Matrix.empty(0, 2),
+ Matrix.empty(2, 0),
+ ].each do |rectangual_matrix|
+ lambda {
+ rectangual_matrix.normal?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/orthogonal_spec.rb b/spec/ruby/library/matrix/orthogonal_spec.rb
new file mode 100644
index 0000000000..2e76b5924c
--- /dev/null
+++ b/spec/ruby/library/matrix/orthogonal_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix.orthogonal?" do
+ it "returns false for non orthogonal matrices" do
+ Matrix[[0, 1], [1, 2]].orthogonal?.should == false
+ Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].orthogonal?.should == false
+ end
+
+ it "returns true for orthogonal matrices" do
+ Matrix[[0, 1], [1, 0]].orthogonal?.should == true
+ end
+
+ it "raises an error for rectangular matrices" do
+ [
+ Matrix[[0], [0]],
+ Matrix[[0, 0]],
+ Matrix.empty(0, 2),
+ Matrix.empty(2, 0),
+ ].each do |rectangual_matrix|
+ lambda {
+ rectangual_matrix.orthogonal?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/permutation_spec.rb b/spec/ruby/library/matrix/permutation_spec.rb
new file mode 100644
index 0000000000..7098c46015
--- /dev/null
+++ b/spec/ruby/library/matrix/permutation_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#permutation?" do
+ it "returns true for a permutation Matrix" do
+ Matrix[[0, 1, 0], [0, 0, 1], [1, 0, 0]].permutation?.should be_true
+ end
+
+ it "returns false for a non permutation square Matrix" do
+ Matrix[[0, 1], [0, 0]].permutation?.should be_false
+ Matrix[[-1, 0], [0, -1]].permutation?.should be_false
+ Matrix[[1, 0], [1, 0]].permutation?.should be_false
+ Matrix[[1, 0], [1, 1]].permutation?.should be_false
+ end
+
+ it "returns true for an empty 0x0 matrix" do
+ Matrix.empty(0,0).permutation?.should be_true
+ end
+
+ it "raises an error for rectangular matrices" do
+ [
+ Matrix[[0], [0]],
+ Matrix[[0, 0]],
+ Matrix.empty(0, 2),
+ Matrix.empty(2, 0),
+ ].each do |rectangual_matrix|
+ lambda {
+ rectangual_matrix.permutation?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/plus_spec.rb b/spec/ruby/library/matrix/plus_spec.rb
new file mode 100644
index 0000000000..59addfdf62
--- /dev/null
+++ b/spec/ruby/library/matrix/plus_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#+" do
+ before :each do
+ @a = Matrix[ [1,2], [3,4] ]
+ @b = Matrix[ [4,5], [6,7] ]
+ end
+
+ it "returns the result of adding the corresponding elements of self and other" do
+ (@a + @b).should == Matrix[ [5,7], [9,11] ]
+ end
+
+ it "returns an instance of Matrix" do
+ (@a + @b).should be_kind_of(Matrix)
+ end
+
+ it "raises a Matrix::ErrDimensionMismatch if the matrices are different sizes" do
+ lambda { @a + Matrix[ [1] ] }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+ it "raises a ExceptionForMatrix::ErrOperationNotDefined if other is a Numeric Type" do
+ lambda { @a + 2 }.should raise_error(ExceptionForMatrix::ErrOperationNotDefined)
+ lambda { @a + 1.2 }.should raise_error(ExceptionForMatrix::ErrOperationNotDefined)
+ lambda { @a + bignum_value }.should raise_error(ExceptionForMatrix::ErrOperationNotDefined)
+ end
+
+ it "raises a TypeError if other is of wrong type" do
+ lambda { @a + nil }.should raise_error(TypeError)
+ lambda { @a + "a" }.should raise_error(TypeError)
+ lambda { @a + [ [1, 2] ] }.should raise_error(TypeError)
+ lambda { @a + Object.new }.should raise_error(TypeError)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ m = MatrixSub.ins
+ (m+m).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/rank_spec.rb b/spec/ruby/library/matrix/rank_spec.rb
new file mode 100644
index 0000000000..42b6de1ab8
--- /dev/null
+++ b/spec/ruby/library/matrix/rank_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#rank" do
+ it "returns the rank of the Matrix" do
+ Matrix[ [7,6], [3,9] ].rank.should == 2
+ end
+
+ it "doesn't loop forever" do
+ Matrix[ [1,2,3], [4,5,6], [7,8,9] ].rank.should == 2
+ Matrix[ [1, 2, 0, 3], [1, -2, 3, 0], [0, 0, 4, 8], [2, 4, 0, 6] ].rank.
+ should == 3
+ end
+
+ it "works for some easy rectangular matrices" do
+ Matrix[[0,0],[0,0],[1,0]].rank.should == 1
+ Matrix[[0,1],[0,0],[1,0]].rank.should == 2
+ end
+end
diff --git a/spec/ruby/library/matrix/real_spec.rb b/spec/ruby/library/matrix/real_spec.rb
new file mode 100644
index 0000000000..98da7f8a7c
--- /dev/null
+++ b/spec/ruby/library/matrix/real_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#real?" do
+ it "returns true for matrices with all real entries" do
+ Matrix[ [1, 2], [3, 4] ].real?.should be_true
+ Matrix[ [1.9, 2], [3, 4] ].real?.should be_true
+ end
+
+ it "returns true for empty matrices" do
+ Matrix.empty.real?.should be_true
+ end
+
+ it "returns false if one element is a Complex" do
+ Matrix[ [Complex(1,1), 2], [3, 4] ].real?.should be_false
+ end
+
+ conflicts_with :CMath do
+ it "returns false if one element is a Complex whose imaginary part is 0" do
+ Matrix[ [Complex(1,0), 2], [3, 4] ].real?.should be_false
+ end
+ end
+end
+
+describe "Matrix#real" do
+ it "returns a matrix with the real part of the elements of the receiver" do
+ Matrix[ [1, 2], [3, 4] ].real.should == Matrix[ [1, 2], [3, 4] ]
+ Matrix[ [1.9, Complex(1,1)], [Complex(-0.42, 0), 4] ].real.should == Matrix[ [1.9, 1], [-0.42, 4] ]
+ end
+
+ it "returns empty matrices on the same size if empty" do
+ Matrix.empty(0, 3).real.should == Matrix.empty(0, 3)
+ Matrix.empty(3, 0).real.should == Matrix.empty(3, 0)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.ins.real.should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/rect_spec.rb b/spec/ruby/library/matrix/rect_spec.rb
new file mode 100644
index 0000000000..d0a3b2705b
--- /dev/null
+++ b/spec/ruby/library/matrix/rect_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/rectangular', __FILE__)
+
+describe "Matrix#rect" do
+ it_behaves_like(:matrix_rectangular, :rect)
+end
diff --git a/spec/ruby/library/matrix/rectangular_spec.rb b/spec/ruby/library/matrix/rectangular_spec.rb
new file mode 100644
index 0000000000..7af446cb18
--- /dev/null
+++ b/spec/ruby/library/matrix/rectangular_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/rectangular', __FILE__)
+
+describe "Matrix#rectangular" do
+ it_behaves_like(:matrix_rectangular, :rectangular)
+end
diff --git a/spec/ruby/library/matrix/regular_spec.rb b/spec/ruby/library/matrix/regular_spec.rb
new file mode 100644
index 0000000000..2f0af99c1e
--- /dev/null
+++ b/spec/ruby/library/matrix/regular_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#regular?" do
+
+ it "returns false for singular matrices" do
+ m = Matrix[ [1,2,3], [3,4,3], [0,0,0] ]
+ m.regular?.should be_false
+
+ m = Matrix[ [1,2,9], [3,4,9], [1,2,9] ]
+ m.regular?.should be_false
+ end
+
+ it "returns true if the Matrix is regular" do
+ Matrix[ [0,1], [1,0] ].regular?.should be_true
+ end
+
+ it "returns true for an empty 0x0 matrix" do
+ Matrix.empty(0,0).regular?.should be_true
+ end
+
+ it "raises an error for rectangular matrices" do
+ lambda {
+ Matrix[[1], [2], [3]].regular?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+
+ lambda {
+ Matrix.empty(3,0).regular?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+end
diff --git a/spec/ruby/library/matrix/round_spec.rb b/spec/ruby/library/matrix/round_spec.rb
new file mode 100644
index 0000000000..f502a35c68
--- /dev/null
+++ b/spec/ruby/library/matrix/round_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix#round" do
+ it "returns a matrix with all entries rounded" do
+ Matrix[ [1, 2.34], [5.67, 8] ].round.should == Matrix[ [1, 2], [6, 8] ]
+ Matrix[ [1, 2.34], [5.67, 8] ].round(1).should == Matrix[ [1, 2.3], [5.7, 8] ]
+ end
+
+ it "returns empty matrices on the same size if empty" do
+ Matrix.empty(0, 3).round.should == Matrix.empty(0, 3)
+ Matrix.empty(3, 0).round(42).should == Matrix.empty(3, 0)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.ins.round.should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/row_size_spec.rb b/spec/ruby/library/matrix/row_size_spec.rb
new file mode 100644
index 0000000000..ee685ba5fb
--- /dev/null
+++ b/spec/ruby/library/matrix/row_size_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#row_size" do
+ it "returns the number rows" do
+ Matrix[ [1,2], [3, 4], [5, 6] ].row_size.should == 3
+ end
+
+ it "returns the number rows even for some empty matrices" do
+ Matrix[ [], [], [] ].row_size.should == 3
+ end
+
+end
diff --git a/spec/ruby/library/matrix/row_spec.rb b/spec/ruby/library/matrix/row_spec.rb
new file mode 100644
index 0000000000..e165e48f5f
--- /dev/null
+++ b/spec/ruby/library/matrix/row_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#row" do
+ before :all do
+ @m = Matrix[ [1, 2], [2, 3], [3, 4] ]
+ end
+
+ it "returns a Vector when called without a block" do
+ @m.row(0).should == Vector[1,2]
+ end
+
+ it "yields the elements of the row when called with a block" do
+ a = []
+ @m.row(0) {|x| a << x}
+ a.should == [1,2]
+ end
+
+ it "counts backwards for negative argument" do
+ @m.row(-1).should == Vector[3, 4]
+ end
+
+ it "returns self when called with a block" do
+ @m.row(0) { |x| x }.should equal(@m)
+ end
+
+ it "returns nil when out of bounds" do
+ @m.row(3).should == nil
+ @m.row(-4).should == nil
+ end
+
+ it "never yields when out of bounds" do
+ lambda { @m.row(3){ raise } }.should_not raise_error
+ lambda { @m.row(-4){ raise } }.should_not raise_error
+ end
+end
diff --git a/spec/ruby/library/matrix/row_vector_spec.rb b/spec/ruby/library/matrix/row_vector_spec.rb
new file mode 100644
index 0000000000..60907e9247
--- /dev/null
+++ b/spec/ruby/library/matrix/row_vector_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix.row_vector" do
+
+ it "returns a Matrix" do
+ Matrix.row_vector([]).should be_an_instance_of(Matrix)
+ end
+
+ it "returns a single-row Matrix with the specified values" do
+ Matrix.row_vector([1,2]).should == Matrix[ [1,2] ]
+ end
+
+ it "returns a 1x0 matrix when called with an empty Array" do
+ Matrix.row_vector([]).should == Matrix[ [] ]
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.row_vector([1]).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/row_vectors_spec.rb b/spec/ruby/library/matrix/row_vectors_spec.rb
new file mode 100644
index 0000000000..46f97bb748
--- /dev/null
+++ b/spec/ruby/library/matrix/row_vectors_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#row_vectors" do
+
+ before :each do
+ @vectors = Matrix[ [1,2], [3,4] ].row_vectors
+ end
+
+ it "returns an Array" do
+ Matrix[ [1,2], [3,4] ].row_vectors.should be_an_instance_of(Array)
+ end
+
+ it "returns an Array of Vectors" do
+ @vectors.all? {|v| v.should be_an_instance_of(Vector)}
+ end
+
+ it "returns each row as a Vector" do
+ @vectors.should == [Vector[1,2], Vector[3,4]]
+ end
+
+ it "returns an empty Array for empty matrices" do
+ Matrix[].row_vectors.should == []
+ Matrix[ [] ].row_vectors.should == [ Vector[] ]
+ end
+end
diff --git a/spec/ruby/library/matrix/rows_spec.rb b/spec/ruby/library/matrix/rows_spec.rb
new file mode 100644
index 0000000000..d583a07b30
--- /dev/null
+++ b/spec/ruby/library/matrix/rows_spec.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix.rows" do
+ before :each do
+ @a = [1, 2]
+ @b = [3, 4]
+ @m = Matrix.rows([@a, @b])
+ end
+
+ it "returns a Matrix" do
+ @m.should be_kind_of(Matrix)
+ end
+
+ it "creates a matrix from argument rows" do
+ @m.row(0).to_a.should == @a
+ @m.row(1).to_a.should == @b
+ end
+
+ it "copies the original rows by default" do
+ @a << 3
+ @b << 6
+ @m.row(0).should_not equal(@a)
+ @m.row(1).should_not equal(@b)
+ end
+
+ it "references the original rows if copy is false" do
+ @m_ref = Matrix.rows([@a, @b], false)
+ @a << 3
+ @b << 6
+ @m_ref.row(0).to_a.should == @a
+ @m_ref.row(1).to_a.should == @b
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.rows([[0, 1], [0, 1]]).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/scalar/Fail_spec.rb b/spec/ruby/library/matrix/scalar/Fail_spec.rb
new file mode 100644
index 0000000000..fbd0f3013a
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar/Fail_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::Scalar#Fail" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/scalar/Raise_spec.rb b/spec/ruby/library/matrix/scalar/Raise_spec.rb
new file mode 100644
index 0000000000..3e98fcb22a
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar/Raise_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::Scalar#Raise" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/scalar/divide_spec.rb b/spec/ruby/library/matrix/scalar/divide_spec.rb
new file mode 100644
index 0000000000..6b8e0b6bcc
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar/divide_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::Scalar#/" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/scalar/exponent_spec.rb b/spec/ruby/library/matrix/scalar/exponent_spec.rb
new file mode 100644
index 0000000000..55997793eb
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar/exponent_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::Scalar#**" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/scalar/included_spec.rb b/spec/ruby/library/matrix/scalar/included_spec.rb
new file mode 100644
index 0000000000..58ee233eb3
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar/included_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::Scalar.included" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/scalar/initialize_spec.rb b/spec/ruby/library/matrix/scalar/initialize_spec.rb
new file mode 100644
index 0000000000..fd6ef00211
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar/initialize_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::Scalar#initialize" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/scalar/minus_spec.rb b/spec/ruby/library/matrix/scalar/minus_spec.rb
new file mode 100644
index 0000000000..19a7b4f1a1
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar/minus_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::Scalar#-" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/scalar/multiply_spec.rb b/spec/ruby/library/matrix/scalar/multiply_spec.rb
new file mode 100644
index 0000000000..247cc1447c
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar/multiply_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::Scalar#*" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/scalar/plus_spec.rb b/spec/ruby/library/matrix/scalar/plus_spec.rb
new file mode 100644
index 0000000000..7cdaa1c7f3
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar/plus_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix::Scalar#+" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/scalar_spec.rb b/spec/ruby/library/matrix/scalar_spec.rb
new file mode 100644
index 0000000000..3da8771471
--- /dev/null
+++ b/spec/ruby/library/matrix/scalar_spec.rb
@@ -0,0 +1,67 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix.scalar" do
+
+ before :each do
+ @side = 3
+ @value = 8
+ @a = Matrix.scalar(@side, @value)
+ end
+
+ it "returns a Matrix" do
+ @a.should be_kind_of(Matrix)
+ end
+
+ it "returns a n x n matrix" do
+ @a.row_size.should == @side
+ @a.column_size.should == @side
+ end
+
+ it "initializes diagonal to value" do
+ (0...@a.row_size).each do |i|
+ @a[i, i].should == @value
+ end
+ end
+
+ it "initializes all non-diagonal values to 0" do
+ (0...@a.row_size).each do |i|
+ (0...@a.column_size).each do |j|
+ if i != j
+ @a[i, j].should == 0
+ end
+ end
+ end
+ end
+
+ before :each do
+ @side = 3
+ @value = 8
+ @a = Matrix.scalar(@side, @value)
+ end
+
+ it "returns a Matrix" do
+ @a.should be_kind_of(Matrix)
+ end
+
+ it "returns a square matrix, where the first argument specifies the side of the square" do
+ @a.row_size.should == @side
+ @a.column_size.should == @side
+ end
+
+ it "puts the second argument in all diagonal values" do
+ (0...@a.row_size).each do |i|
+ @a[i, i].should == @value
+ end
+ end
+
+ it "fills all values not on the main diagonal with 0" do
+ (0...@a.row_size).each do |i|
+ (0...@a.column_size).each do |j|
+ if i != j
+ @a[i, j].should == 0
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/shared/collect.rb b/spec/ruby/library/matrix/shared/collect.rb
new file mode 100644
index 0000000000..256cd6a190
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/collect.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe :collect, shared: true do
+ before :all do
+ @m = Matrix[ [1, 2], [1, 2] ]
+ end
+
+ it "returns an instance of Matrix" do
+ @m.send(@method){|n| n * 2 }.should be_kind_of(Matrix)
+ end
+
+ it "returns a Matrix where each element is the result of the block" do
+ @m.send(@method) { |n| n * 2 }.should == Matrix[ [2, 4], [2, 4] ]
+ end
+
+ it "returns an enumerator if no block is given" do
+ @m.send(@method).should be_an_instance_of(Enumerator)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.ins.send(@method){1}.should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/shared/conjugate.rb b/spec/ruby/library/matrix/shared/conjugate.rb
new file mode 100644
index 0000000000..180ff4fa98
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/conjugate.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe :matrix_conjugate, shared: true do
+ it "returns a matrix with all entries 'conjugated'" do
+ Matrix[ [1, 2], [3, 4] ].send(@method).should == Matrix[ [1, 2], [3, 4] ]
+ Matrix[ [1.9, Complex(1,1)], [3, 4] ].send(@method).should == Matrix[ [1.9, Complex(1,-1)], [3, 4] ]
+ end
+
+ it "returns empty matrices on the same size if empty" do
+ Matrix.empty(0, 3).send(@method).should == Matrix.empty(0, 3)
+ Matrix.empty(3, 0).send(@method).should == Matrix.empty(3, 0)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.ins.send(@method).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/shared/determinant.rb b/spec/ruby/library/matrix/shared/determinant.rb
new file mode 100644
index 0000000000..47a58c62a6
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/determinant.rb
@@ -0,0 +1,38 @@
+require 'matrix'
+
+describe :determinant, shared: true do
+ it "returns the determinant of a square Matrix" do
+ m = Matrix[ [7,6], [3,9] ]
+ m.send(@method).should == 45
+
+ m = Matrix[ [9, 8], [6,5] ]
+ m.send(@method).should == -3
+
+ m = Matrix[ [9,8,3], [4,20,5], [1,1,1] ]
+ m.send(@method).should == 95
+ end
+
+ it "returns the determinant of a single-element Matrix" do
+ m = Matrix[ [2] ]
+ m.send(@method).should == 2
+ end
+
+ it "returns 1 for an empty Matrix" do
+ m = Matrix[ ]
+ m.send(@method).should == 1
+ end
+
+ it "returns the determinant even for Matrices containing 0 as first entry" do
+ Matrix[[0,1],[1,0]].send(@method).should == -1
+ end
+
+ it "raises an error for rectangular matrices" do
+ lambda {
+ Matrix[[1], [2], [3]].send(@method)
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+
+ lambda {
+ Matrix.empty(3,0).send(@method)
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+end
diff --git a/spec/ruby/library/matrix/shared/equal_value.rb b/spec/ruby/library/matrix/shared/equal_value.rb
new file mode 100644
index 0000000000..e2102e823a
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/equal_value.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe :equal, shared: true do
+ before do
+ @matrix = Matrix[ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6] ]
+ end
+
+ it "returns true for self" do
+ @matrix.send(@method, @matrix).should be_true
+ end
+
+ it "returns true for equal matrices" do
+ @matrix.send(@method, Matrix[ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6] ]).should be_true
+ end
+
+ it "returns false for different matrices" do
+ @matrix.send(@method, Matrix[ [42, 2, 3, 4, 5], [2, 3, 4, 5, 6] ]).should be_false
+ @matrix.send(@method, Matrix[ [1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6, 7] ]).should be_false
+ @matrix.send(@method, Matrix[ [1, 2, 3], [2, 3, 4] ]).should be_false
+ end
+
+ it "returns false for different empty matrices" do
+ Matrix.empty(42, 0).send(@method, Matrix.empty(6, 0)).should be_false
+ Matrix.empty(0, 42).send(@method, Matrix.empty(0, 6)).should be_false
+ Matrix.empty(0, 0).send(@method, Matrix.empty(6, 0)).should be_false
+ Matrix.empty(0, 0).send(@method, Matrix.empty(0, 6)).should be_false
+ end
+
+ it "doesn't distinguish on subclasses" do
+ MatrixSub.ins.send(@method, Matrix.I(2)).should be_true
+ end
+end
diff --git a/spec/ruby/library/matrix/shared/identity.rb b/spec/ruby/library/matrix/shared/identity.rb
new file mode 100644
index 0000000000..20b35ae8e3
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/identity.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe :matrix_identity, shared: true do
+ it "returns a Matrix" do
+ Matrix.send(@method, 2).should be_kind_of(Matrix)
+ end
+
+ it "returns a n x n identity matrix" do
+ Matrix.send(@method, 3).should == Matrix.scalar(3, 1)
+ Matrix.send(@method, 100).should == Matrix.scalar(100, 1)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.send(@method, 2).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/shared/imaginary.rb b/spec/ruby/library/matrix/shared/imaginary.rb
new file mode 100644
index 0000000000..61a65a62ec
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/imaginary.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe :matrix_imaginary, shared: true do
+ it "returns a matrix with the imaginary part of the elements of the receiver" do
+ Matrix[ [1, 2], [3, 4] ].send(@method).should == Matrix[ [0, 0], [0, 0] ]
+ Matrix[ [1.9, Complex(1,1)], [Complex(-2,0.42), 4] ].send(@method).should == Matrix[ [0, 1], [0.42, 0] ]
+ end
+
+ it "returns empty matrices on the same size if empty" do
+ Matrix.empty(0, 3).send(@method).should == Matrix.empty(0, 3)
+ Matrix.empty(3, 0).send(@method).should == Matrix.empty(3, 0)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.ins.send(@method).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/shared/inverse.rb b/spec/ruby/library/matrix/shared/inverse.rb
new file mode 100644
index 0000000000..c6996df4a3
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/inverse.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe :inverse, shared: true do
+
+ it "returns a Matrix" do
+ Matrix[ [1,2], [2,1] ].send(@method).should be_an_instance_of(Matrix)
+ end
+
+ it "returns the inverse of the Matrix" do
+ Matrix[
+ [1, 3, 3], [1, 4, 3], [1, 3, 4]
+ ].send(@method).should ==
+ Matrix[
+ [7, -3, -3], [-1, 1, 0], [-1, 0, 1]
+ ]
+ end
+
+ it "returns the inverse of the Matrix (other case)" do
+ Matrix[
+ [1, 2, 3], [0, 1, 4], [5, 6, 0]
+ ].send(@method).should be_close_to_matrix([
+ [-24, 18, 5], [20, -15, -4], [-5, 4, 1]
+ ])
+ end
+
+ it "raises a ErrDimensionMismatch if the Matrix is not square" do
+ lambda{
+ Matrix[ [1,2,3], [1,2,3] ].send(@method)
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.ins.send(@method).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/shared/rectangular.rb b/spec/ruby/library/matrix/shared/rectangular.rb
new file mode 100644
index 0000000000..4206311586
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/rectangular.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe :matrix_rectangular, shared: true do
+ it "returns [receiver.real, receiver.imag]" do
+ m = Matrix[ [1.2, Complex(1,2)], [Complex(-2,0.42), 4] ]
+ m.send(@method).should == [m.real, m.imag]
+
+ m = Matrix.empty(3, 0)
+ m.send(@method).should == [m.real, m.imag]
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns instances of that subclass" do
+ MatrixSub.ins.send(@method).each{|m| m.should be_an_instance_of(MatrixSub) }
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/shared/trace.rb b/spec/ruby/library/matrix/shared/trace.rb
new file mode 100644
index 0000000000..2a42839f5d
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/trace.rb
@@ -0,0 +1,12 @@
+require 'matrix'
+
+describe :trace, shared: true do
+ it "returns the sum of diagonal elements in a square Matrix" do
+ Matrix[[7,6], [3,9]].trace.should == 16
+ end
+
+ it "returns the sum of diagonal elements in a rectangular Matrix" do
+ lambda{ Matrix[[1,2,3], [4,5,6]].trace}.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+end
diff --git a/spec/ruby/library/matrix/shared/transpose.rb b/spec/ruby/library/matrix/shared/transpose.rb
new file mode 100644
index 0000000000..dba6c71041
--- /dev/null
+++ b/spec/ruby/library/matrix/shared/transpose.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe :matrix_transpose, shared: true do
+ it "returns a transposed matrix" do
+ Matrix[[1, 2], [3, 4], [5, 6]].send(@method).should == Matrix[[1, 3, 5], [2, 4, 6]]
+ end
+
+ it "can transpose empty matrices" do
+ m = Matrix[[], [], []]
+ m.send(@method).send(@method).should == m
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.ins.send(@method).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/singular_spec.rb b/spec/ruby/library/matrix/singular_spec.rb
new file mode 100644
index 0000000000..83914befbe
--- /dev/null
+++ b/spec/ruby/library/matrix/singular_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#singular?" do
+ it "returns true for singular matrices" do
+ m = Matrix[ [1,2,3], [3,4,3], [0,0,0] ]
+ m.singular?.should be_true
+
+ m = Matrix[ [1,2,9], [3,4,9], [1,2,9] ]
+ m.singular?.should be_true
+ end
+
+ it "returns false if the Matrix is regular" do
+ Matrix[ [0,1], [1,0] ].singular?.should be_false
+ end
+
+ it "returns false for an empty 0x0 matrix" do
+ Matrix.empty(0,0).singular?.should be_false
+ end
+
+ it "raises an error for rectangular matrices" do
+ lambda {
+ Matrix[[1], [2], [3]].singular?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+
+ lambda {
+ Matrix.empty(3,0).singular?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+
+end
diff --git a/spec/ruby/library/matrix/spec_helper.rb b/spec/ruby/library/matrix/spec_helper.rb
new file mode 100644
index 0000000000..d44612981a
--- /dev/null
+++ b/spec/ruby/library/matrix/spec_helper.rb
@@ -0,0 +1,35 @@
+class BeCloseToMatrixMatcher
+ def initialize(expected, tolerance = TOLERANCE)
+ SpecExpectation.matcher! rescue "Used with the balance_should_and_match branch of mspec"
+ @expected = Matrix[*expected]
+ @tolerance = tolerance
+ end
+
+ def matches?(actual)
+ @actual = actual
+ return false unless @actual.is_a? Matrix
+ return false unless @actual.row_size == @expected.row_size
+ @actual.row_size.times do |i|
+ a, e = @actual.row(i), @expected.row(i)
+ return false unless a.size == e.size
+ a.size.times do |j|
+ return false unless (a[j] - e[j]).abs < @tolerance
+ end
+ end
+ true
+ end
+
+ def failure_message
+ ["Expected #{@expected}", "to be within +/- #{@tolerance} of #{@actual}"]
+ end
+
+ def negative_failure_message
+ ["Expected #{@expected}", "not to be within +/- #{@tolerance} of #{@actual}"]
+ end
+end
+
+class Object
+ def be_close_to_matrix(expected, tolerance = TOLERANCE)
+ BeCloseToMatrixMatcher.new(expected, tolerance)
+ end
+end
diff --git a/spec/ruby/library/matrix/square_spec.rb b/spec/ruby/library/matrix/square_spec.rb
new file mode 100644
index 0000000000..a117916a4c
--- /dev/null
+++ b/spec/ruby/library/matrix/square_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#square?" do
+
+ it "returns true when the Matrix is square" do
+ Matrix[ [1,2], [2,4] ].square?.should be_true
+ Matrix[ [100,3,5], [9.5, 4.9, 8], [2,0,77] ].square?.should be_true
+ end
+
+ it "returns true when the Matrix has only one element" do
+ Matrix[ [9] ].square?.should be_true
+ end
+
+ it "returns false when the Matrix is rectangular" do
+ Matrix[ [1, 2] ].square?.should be_false
+ end
+
+ it "returns false when the Matrix is rectangular" do
+ Matrix[ [1], [2] ].square?.should be_false
+ end
+
+ it "returns handles empty matrices" do
+ Matrix[].square?.should be_true
+ Matrix[[]].square?.should be_false
+ Matrix.columns([[]]).square?.should be_false
+ end
+end
diff --git a/spec/ruby/library/matrix/symmetric_spec.rb b/spec/ruby/library/matrix/symmetric_spec.rb
new file mode 100644
index 0000000000..53f962c0e2
--- /dev/null
+++ b/spec/ruby/library/matrix/symmetric_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix.symmetric?" do
+ it "returns true for a symmetric Matrix" do
+ Matrix[[1, 2, Complex(0, 3)], [2, 4, 5], [Complex(0, 3), 5, 6]].symmetric?.should be_true
+ end
+
+ it "returns true for a 0x0 empty matrix" do
+ Matrix.empty.symmetric?.should be_true
+ end
+
+ it "returns false for an assymetric Matrix" do
+ Matrix[[1, 2],[-2, 1]].symmetric?.should be_false
+ end
+
+ it "raises an error for rectangular matrices" do
+ [
+ Matrix[[0], [0]],
+ Matrix[[0, 0]],
+ Matrix.empty(0, 2),
+ Matrix.empty(2, 0),
+ ].each do |rectangual_matrix|
+ lambda {
+ rectangual_matrix.symmetric?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/t_spec.rb b/spec/ruby/library/matrix/t_spec.rb
new file mode 100644
index 0000000000..1c57c25de3
--- /dev/null
+++ b/spec/ruby/library/matrix/t_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/transpose', __FILE__)
+
+describe "Matrix#transpose" do
+ it_behaves_like(:matrix_transpose, :t)
+end
diff --git a/spec/ruby/library/matrix/to_a_spec.rb b/spec/ruby/library/matrix/to_a_spec.rb
new file mode 100644
index 0000000000..70db580312
--- /dev/null
+++ b/spec/ruby/library/matrix/to_a_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#to_a" do
+ it "returns the array of arrays that describe the rows of the matrix" do
+ Matrix[].to_a.should == []
+ Matrix[[]].to_a.should == [[]]
+ Matrix[[1]].to_a.should == [[1]]
+ Matrix[[1, 2], [3, 4]].to_a.should == [[1, 2],[3, 4]]
+ end
+end
diff --git a/spec/ruby/library/matrix/to_s_spec.rb b/spec/ruby/library/matrix/to_s_spec.rb
new file mode 100644
index 0000000000..eb175d486b
--- /dev/null
+++ b/spec/ruby/library/matrix/to_s_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix#to_s" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/matrix/tr_spec.rb b/spec/ruby/library/matrix/tr_spec.rb
new file mode 100644
index 0000000000..4b07a70203
--- /dev/null
+++ b/spec/ruby/library/matrix/tr_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/trace', __FILE__)
+require 'matrix'
+
+describe "Matrix#tr" do
+ it_behaves_like(:trace, :tr)
+end
diff --git a/spec/ruby/library/matrix/trace_spec.rb b/spec/ruby/library/matrix/trace_spec.rb
new file mode 100644
index 0000000000..08adb256c0
--- /dev/null
+++ b/spec/ruby/library/matrix/trace_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/trace', __FILE__)
+require 'matrix'
+
+describe "Matrix#trace" do
+ it_behaves_like(:trace, :trace)
+end
diff --git a/spec/ruby/library/matrix/transpose_spec.rb b/spec/ruby/library/matrix/transpose_spec.rb
new file mode 100644
index 0000000000..2a30a80efc
--- /dev/null
+++ b/spec/ruby/library/matrix/transpose_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/transpose', __FILE__)
+
+describe "Matrix#transpose" do
+ it_behaves_like(:matrix_transpose, :transpose)
+end
diff --git a/spec/ruby/library/matrix/unit_spec.rb b/spec/ruby/library/matrix/unit_spec.rb
new file mode 100644
index 0000000000..058d719043
--- /dev/null
+++ b/spec/ruby/library/matrix/unit_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/identity', __FILE__)
+
+describe "Matrix.unit" do
+ it_behaves_like(:matrix_identity, :unit)
+end
diff --git a/spec/ruby/library/matrix/unitary_spec.rb b/spec/ruby/library/matrix/unitary_spec.rb
new file mode 100644
index 0000000000..e322a5a3ce
--- /dev/null
+++ b/spec/ruby/library/matrix/unitary_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix.unitary?" do
+ it "returns false for non unitary matrices" do
+ Matrix[[0, 1], [1, 2]].unitary?.should == false
+ Matrix[[0, Complex(0, 2)], [Complex(0, 2), 0]].unitary?.should == false
+ Matrix[[0, Complex(0, 1)], [Complex(0, -1), 0]].unitary?.should == false
+ Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].unitary?.should == false
+ end
+
+ it "returns true for unitary matrices" do
+ Matrix[[0, Complex(0, 1)], [Complex(0, 1), 0]].unitary?.should == true
+ end
+
+ it "raises an error for rectangular matrices" do
+ [
+ Matrix[[0], [0]],
+ Matrix[[0, 0]],
+ Matrix.empty(0, 2),
+ Matrix.empty(2, 0),
+ ].each do |rectangual_matrix|
+ lambda {
+ rectangual_matrix.unitary?
+ }.should raise_error(Matrix::ErrDimensionMismatch)
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/upper_triangular_spec.rb b/spec/ruby/library/matrix/upper_triangular_spec.rb
new file mode 100644
index 0000000000..be88150b85
--- /dev/null
+++ b/spec/ruby/library/matrix/upper_triangular_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Matrix.upper_triangular?" do
+ it "returns true for an upper triangular Matrix" do
+ Matrix[[1, 2, 3], [0, 2, 3], [0, 0, 3]].upper_triangular?.should be_true
+ Matrix.diagonal([1, 2, 3]).upper_triangular?.should be_true
+ Matrix[[1, 2], [0, 2], [0, 0], [0, 0]].upper_triangular?.should be_true
+ Matrix[[1, 2, 3, 4], [0, 2, 3, 4]].upper_triangular?.should be_true
+ end
+
+ it "returns false for a non upper triangular square Matrix" do
+ Matrix[[0, 0], [1, 0]].upper_triangular?.should be_false
+ Matrix[[1, 2, 3], [1, 2, 3], [1, 2, 3]].upper_triangular?.should be_false
+ Matrix[[0, 0], [0, 0], [0, 0], [0, 1]].upper_triangular?.should be_false
+ Matrix[[0, 0, 0, 0], [1, 0, 0, 0]].upper_triangular?.should be_false
+ end
+
+ it "returns true for an empty matrix" do
+ Matrix.empty(3,0).upper_triangular?.should be_true
+ Matrix.empty(0,3).upper_triangular?.should be_true
+ Matrix.empty(0,0).upper_triangular?.should be_true
+ end
+end
diff --git a/spec/ruby/library/matrix/vector/cross_product_spec.rb b/spec/ruby/library/matrix/vector/cross_product_spec.rb
new file mode 100644
index 0000000000..f26cf585da
--- /dev/null
+++ b/spec/ruby/library/matrix/vector/cross_product_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Vector#cross_product" do
+ it "returns the cross product of a vector" do
+ Vector[1, 2, 3].cross_product(Vector[0, -4, 5]).should == Vector[22, -5, -4]
+ end
+
+ it "raises an error unless both vectors have dimension 3" do
+ lambda {
+ Vector[1, 2, 3].cross_product(Vector[0, -4])
+ }.should raise_error(Vector::ErrDimensionMismatch)
+ end
+end
diff --git a/spec/ruby/library/matrix/vector/each2_spec.rb b/spec/ruby/library/matrix/vector/each2_spec.rb
new file mode 100644
index 0000000000..e9d89e21c4
--- /dev/null
+++ b/spec/ruby/library/matrix/vector/each2_spec.rb
@@ -0,0 +1,49 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Vector.each2" do
+ before :all do
+ @v = Vector[1, 2, 3]
+ @v2 = Vector[4, 5, 6]
+ end
+
+ it "requires one argument" do
+ lambda { @v.each2(@v2, @v2){} }.should raise_error(ArgumentError)
+ lambda { @v.each2(){} }.should raise_error(ArgumentError)
+ end
+
+ describe "given one argument" do
+ it "accepts an Array argument" do
+ a = []
+ @v.each2([7, 8, 9]){|x, y| a << x << y}
+ a.should == [1, 7, 2, 8, 3, 9]
+ end
+
+ it "raises a DimensionMismatch error if the Vector size is different" do
+ lambda { @v.each2(Vector[1,2]){} }.should raise_error(Vector::ErrDimensionMismatch)
+ lambda { @v.each2(Vector[1,2,3,4]){} }.should raise_error(Vector::ErrDimensionMismatch)
+ end
+
+ it "yields arguments in sequence" do
+ a = []
+ @v.each2(@v2){|first, second| a << [first, second]}
+ a.should == [[1, 4], [2, 5], [3, 6]]
+ end
+
+ it "yield arguments in pairs" do
+ a = []
+ @v.each2(@v2){|*pair| a << pair}
+ a.should == [[1, 4], [2, 5], [3, 6]]
+ end
+
+ it "returns self when given a block" do
+ @v.each2(@v2){}.should equal(@v)
+ end
+
+ it "returns an enumerator if no block given" do
+ enum = @v.each2(@v2)
+ enum.should be_an_instance_of(Enumerator)
+ enum.to_a.should == [[1, 4], [2, 5], [3, 6]]
+ end
+ end
+end
diff --git a/spec/ruby/library/matrix/vector/eql_spec.rb b/spec/ruby/library/matrix/vector/eql_spec.rb
new file mode 100644
index 0000000000..6cc69bbf7d
--- /dev/null
+++ b/spec/ruby/library/matrix/vector/eql_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Vector#eql?" do
+ before do
+ @vector = Vector[1, 2, 3, 4, 5]
+ end
+
+ it "returns true for self" do
+ @vector.eql?(@vector).should be_true
+ end
+
+ it "returns false when there are a pair corresponding elements which are not equal in the sense of Kernel#eql?" do
+ @vector.eql?(Vector[1, 2, 3, 4, 5.0]).should be_false
+ end
+end
diff --git a/spec/ruby/library/matrix/vector/inner_product_spec.rb b/spec/ruby/library/matrix/vector/inner_product_spec.rb
new file mode 100644
index 0000000000..a953598b51
--- /dev/null
+++ b/spec/ruby/library/matrix/vector/inner_product_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Vector#inner_product" do
+ it "returns the inner product of a vector" do
+ Vector[1, 2, 3].inner_product(Vector[0, -4, 5]).should == 7
+ end
+
+ it "returns 0 for empty vectors" do
+ Vector[].inner_product(Vector[]).should == 0
+ end
+
+ it "raises an error for mismatched vectors" do
+ lambda {
+ Vector[1, 2, 3].inner_product(Vector[0, -4])
+ }.should raise_error(Vector::ErrDimensionMismatch)
+ end
+
+ it "uses the conjugate of its argument" do
+ Vector[Complex(1,2)].inner_product(Vector[Complex(3,4)]).should == Complex(11, 2)
+ end
+end
diff --git a/spec/ruby/library/matrix/vector/normalize_spec.rb b/spec/ruby/library/matrix/vector/normalize_spec.rb
new file mode 100644
index 0000000000..14aac1f5e3
--- /dev/null
+++ b/spec/ruby/library/matrix/vector/normalize_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'matrix'
+
+describe "Vector#normalize" do
+ it "returns a normalized copy of the vector" do
+ x = 0.2672612419124244
+ Vector[1, 2, 3].normalize.should == Vector[x, x * 2, x * 3]
+ end
+
+ it "raises an error for zero vectors" do
+ lambda {
+ Vector[].normalize
+ }.should raise_error(Vector::ZeroVectorError)
+ lambda {
+ Vector[0, 0, 0].normalize
+ }.should raise_error(Vector::ZeroVectorError)
+ end
+end
diff --git a/spec/ruby/library/matrix/zero_spec.rb b/spec/ruby/library/matrix/zero_spec.rb
new file mode 100644
index 0000000000..f83d29e837
--- /dev/null
+++ b/spec/ruby/library/matrix/zero_spec.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require 'matrix'
+
+describe "Matrix.zero" do
+ it "returns an object of type Matrix" do
+ Matrix.zero(3).should be_kind_of(Matrix)
+ end
+
+ it "creates a n x n matrix" do
+ m3 = Matrix.zero(3)
+ m3.row_size.should == 3
+ m3.column_size.should == 3
+
+ m8 = Matrix.zero(8)
+ m8.row_size.should == 8
+ m8.column_size.should == 8
+ end
+
+ it "initializes all cells to 0" do
+ size = 10
+ m = Matrix.zero(size)
+
+ (0...size).each do |i|
+ (0...size).each do |j|
+ m[i, j].should == 0
+ end
+ end
+ end
+
+ describe "for a subclass of Matrix" do
+ it "returns an instance of that subclass" do
+ MatrixSub.zero(3).should be_an_instance_of(MatrixSub)
+ end
+ end
+end
+
+describe "Matrix.zero?" do
+ it "returns true for empty matrices" do
+ Matrix.empty.zero?.should == true
+ Matrix.empty(3,0).zero?.should == true
+ Matrix.empty(0,3).zero?.should == true
+ end
+
+ it "returns true for matrices with zero entries" do
+ Matrix.zero(2,3).zero?.should == true
+ end
+
+ it "returns false for matrices with non zero entries" do
+ Matrix[[1]].zero?.should == false
+ end
+end
diff --git a/spec/ruby/library/net/FTPError_spec.rb b/spec/ruby/library/net/FTPError_spec.rb
new file mode 100644
index 0000000000..7cc06f681a
--- /dev/null
+++ b/spec/ruby/library/net/FTPError_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'net/ftp'
+
+describe "Net::FTPError" do
+ it "is an Exception" do
+ Net::FTPError.should < Exception
+ end
+end
diff --git a/spec/ruby/library/net/FTPPermError_spec.rb b/spec/ruby/library/net/FTPPermError_spec.rb
new file mode 100644
index 0000000000..d9a7189468
--- /dev/null
+++ b/spec/ruby/library/net/FTPPermError_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'net/ftp'
+
+describe "Net::FTPPermError" do
+ it "is an Exception" do
+ Net::FTPPermError.should < Exception
+ end
+
+ it "is a subclass of Net::FTPError" do
+ Net::FTPPermError.should < Net::FTPError
+ end
+end
diff --git a/spec/ruby/library/net/FTPProtoError_spec.rb b/spec/ruby/library/net/FTPProtoError_spec.rb
new file mode 100644
index 0000000000..445ba1cd2f
--- /dev/null
+++ b/spec/ruby/library/net/FTPProtoError_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'net/ftp'
+
+describe "Net::FTPProtoError" do
+ it "is an Exception" do
+ Net::FTPProtoError.should < Exception
+ end
+
+ it "is a subclass of Net::FTPError" do
+ Net::FTPPermError.should < Net::FTPError
+ end
+end
diff --git a/spec/ruby/library/net/FTPReplyError_spec.rb b/spec/ruby/library/net/FTPReplyError_spec.rb
new file mode 100644
index 0000000000..b697f0b95a
--- /dev/null
+++ b/spec/ruby/library/net/FTPReplyError_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'net/ftp'
+
+describe "Net::FTPReplyError" do
+ it "is an Exception" do
+ Net::FTPReplyError.should < Exception
+ end
+
+ it "is a subclass of Net::FTPError" do
+ Net::FTPPermError.should < Net::FTPError
+ end
+end
diff --git a/spec/ruby/library/net/FTPTempError_spec.rb b/spec/ruby/library/net/FTPTempError_spec.rb
new file mode 100644
index 0000000000..8d74d371da
--- /dev/null
+++ b/spec/ruby/library/net/FTPTempError_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'net/ftp'
+
+describe "Net::FTPTempError" do
+ it "is an Exception" do
+ Net::FTPTempError.should < Exception
+ end
+
+ it "is a subclass of Net::FTPError" do
+ Net::FTPPermError.should < Net::FTPError
+ end
+end
diff --git a/spec/ruby/library/net/ftp/abort_spec.rb b/spec/ruby/library/net/ftp/abort_spec.rb
new file mode 100644
index 0000000000..ea47eaf9bf
--- /dev/null
+++ b/spec/ruby/library/net/ftp/abort_spec.rb
@@ -0,0 +1,62 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#abort" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the ABOR command to the server" do
+ lambda { @ftp.abort }.should_not raise_error
+ end
+
+ it "ignores the response" do
+ @ftp.abort
+ @ftp.last_response.should == "220 Dummy FTP Server ready!\n"
+ end
+
+ it "returns the full response" do
+ @ftp.abort.should == "226 Closing data connection. (ABOR)\n"
+ end
+
+ it "does not raise any error when the response code is 225" do
+ @server.should_receive(:abor).and_respond("225 Data connection open; no transfer in progress.")
+ lambda { @ftp.abort }.should_not raise_error
+ end
+
+ it "does not raise any error when the response code is 226" do
+ @server.should_receive(:abor).and_respond("226 Closing data connection.")
+ lambda { @ftp.abort }.should_not raise_error
+ end
+
+ it "raises a Net::FTPProtoError when the response code is 500" do
+ @server.should_receive(:abor).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.abort }.should raise_error(Net::FTPProtoError)
+ end
+
+ it "raises a Net::FTPProtoError when the response code is 501" do
+ @server.should_receive(:abor).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.abort }.should raise_error(Net::FTPProtoError)
+ end
+
+ it "raises a Net::FTPProtoError when the response code is 502" do
+ @server.should_receive(:abor).and_respond("502 Command not implemented.")
+ lambda { @ftp.abort }.should raise_error(Net::FTPProtoError)
+ end
+
+ it "raises a Net::FTPProtoError when the response code is 421" do
+ @server.should_receive(:abor).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.abort }.should raise_error(Net::FTPProtoError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/acct_spec.rb b/spec/ruby/library/net/ftp/acct_spec.rb
new file mode 100644
index 0000000000..e60c6b3088
--- /dev/null
+++ b/spec/ruby/library/net/ftp/acct_spec.rb
@@ -0,0 +1,58 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#acct" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "writes the ACCT command to the server" do
+ @ftp.acct("my_account")
+ @ftp.last_response.should == "230 User 'my_account' logged in, proceed. (ACCT)\n"
+ end
+
+ it "returns nil" do
+ @ftp.acct("my_account").should == nil
+ end
+
+ it "does not raise any error when the response code is 230" do
+ @server.should_receive(:acct).and_respond("230 User logged in, proceed.")
+ lambda { @ftp.acct("my_account") }.should_not raise_error
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:acct).and_respond("530 Not logged in.")
+ lambda { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:acct).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:acct).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 503" do
+ @server.should_receive(:acct).and_respond("503 Bad sequence of commands.")
+ lambda { @ftp.acct("my_account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:acct).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.acct("my_account") }.should raise_error(Net::FTPTempError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/binary_spec.rb b/spec/ruby/library/net/ftp/binary_spec.rb
new file mode 100644
index 0000000000..6f1a1ab8ba
--- /dev/null
+++ b/spec/ruby/library/net/ftp/binary_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP#binary" do
+ it "returns true when self is in binary mode" do
+ ftp = Net::FTP.new
+ ftp.binary.should be_true
+
+ ftp.binary = false
+ ftp.binary.should be_false
+ end
+end
+
+describe "Net::FTP#binary=" do
+ it "sets self to binary mode when passed true" do
+ ftp = Net::FTP.new
+
+ ftp.binary = true
+ ftp.binary.should be_true
+
+ ftp.binary = false
+ ftp.binary.should be_false
+ end
+end
diff --git a/spec/ruby/library/net/ftp/chdir_spec.rb b/spec/ruby/library/net/ftp/chdir_spec.rb
new file mode 100644
index 0000000000..f6cfac5b66
--- /dev/null
+++ b/spec/ruby/library/net/ftp/chdir_spec.rb
@@ -0,0 +1,99 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#chdir" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ describe "when switching to the parent directory" do
+ it "sends the 'CDUP' command to the server" do
+ @ftp.chdir("..")
+ @ftp.last_response.should == "200 Command okay. (CDUP)\n"
+ end
+
+ it "returns nil" do
+ @ftp.chdir("..").should be_nil
+ end
+
+ it "does not raise a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:cdup).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.chdir("..") }.should_not raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:cdup).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.chdir("..") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:cdup).and_respond("502 Command not implemented.")
+ lambda { @ftp.chdir("..") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:cdup).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.chdir("..") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:cdup).and_respond("530 Not logged in.")
+ lambda { @ftp.chdir("..") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:cdup).and_respond("550 Requested action not taken.")
+ lambda { @ftp.chdir("..") }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ it "writes the 'CWD' command with the passed directory to the socket" do
+ @ftp.chdir("test")
+ @ftp.last_response.should == "200 Command okay. (CWD test)\n"
+ end
+
+ it "returns nil" do
+ @ftp.chdir("test").should be_nil
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:cwd).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.chdir("test") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:cwd).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.chdir("test") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:cwd).and_respond("502 Command not implemented.")
+ lambda { @ftp.chdir("test") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:cwd).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.chdir("test") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:cwd).and_respond("530 Not logged in.")
+ lambda { @ftp.chdir("test") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:cwd).and_respond("550 Requested action not taken.")
+ lambda { @ftp.chdir("test") }.should raise_error(Net::FTPPermError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/close_spec.rb b/spec/ruby/library/net/ftp/close_spec.rb
new file mode 100644
index 0000000000..0f6866221f
--- /dev/null
+++ b/spec/ruby/library/net/ftp/close_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP#close" do
+ before :each do
+ @socket = mock("Socket")
+ @socket.stub!(:closed?).and_return(false)
+ @socket.stub!(:read_timeout).and_return(60)
+ @socket.stub!(:read_timeout=).and_return(3)
+
+ @ftp = Net::FTP.new
+ @ftp.instance_variable_set(:@sock, @socket)
+ end
+
+ it "closes the socket" do
+ @socket.should_receive(:close)
+ @ftp.close.should be_nil
+ end
+
+ it "does not try to close the socket if it has already been closed" do
+ @socket.should_receive(:closed?).and_return(true)
+ @socket.should_not_receive(:close)
+ @ftp.close.should be_nil
+ end
+
+ it "does not try to close the socket if it is nil" do
+ @ftp.instance_variable_set(:@sock, nil)
+ @ftp.close.should be_nil
+ end
+end
diff --git a/spec/ruby/library/net/ftp/closed_spec.rb b/spec/ruby/library/net/ftp/closed_spec.rb
new file mode 100644
index 0000000000..7b31717c00
--- /dev/null
+++ b/spec/ruby/library/net/ftp/closed_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP#closed?" do
+ before :each do
+ @socket = mock("Socket")
+
+ @ftp = Net::FTP.new
+ @ftp.instance_variable_set(:@sock, @socket)
+ end
+
+ it "returns true when the socket is closed" do
+ @socket.should_receive(:closed?).and_return(true)
+ @ftp.closed?.should be_true
+ end
+
+ it "returns true when the socket is nil" do
+ @ftp.instance_variable_set(:@sock, nil)
+ @ftp.closed?.should be_true
+ end
+end
diff --git a/spec/ruby/library/net/ftp/connect_spec.rb b/spec/ruby/library/net/ftp/connect_spec.rb
new file mode 100644
index 0000000000..f3c1565fc2
--- /dev/null
+++ b/spec/ruby/library/net/ftp/connect_spec.rb
@@ -0,0 +1,49 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+# TODO: Add specs for using the SOCKSSocket
+describe "Net::FTP#connect" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ end
+
+ after :each do
+ @server.connect_message = nil
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "tries to connect to the FTP Server on the given host and port" do
+ lambda { @ftp.connect(@server.hostname, @server.server_port) }.should_not raise_error
+ end
+
+ it "returns nil" do
+ @ftp.connect(@server.hostname, @server.server_port).should be_nil
+ end
+
+ it "prints a small debug line when in debug mode" do
+ @ftp.debug_mode = true
+ lambda { @ftp.connect(@server.hostname, @server.server_port) }.should output(/#{"connect: "}#{@server.hostname}#{", "}#{@server.server_port}#{"\\nget: 220 Dummy FTP Server ready!"}/)
+ @ftp.debug_mode = false
+ end
+
+ it "does not raise any error when the response code is 220" do
+ @server.connect_message = "220 Dummy FTP Server ready!"
+ lambda { @ftp.connect(@server.hostname, @server.server_port) }.should_not raise_error
+ end
+
+ it "raises a Net::FTPReplyError when the response code is 120" do
+ @server.connect_message = "120 Service ready in nnn minutes."
+ lambda { @ftp.connect(@server.hostname, @server.server_port) }.should raise_error(Net::FTPReplyError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.connect_message = "421 Service not available, closing control connection."
+ lambda { @ftp.connect(@server.hostname, @server.server_port) }.should raise_error(Net::FTPTempError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/debug_mode_spec.rb b/spec/ruby/library/net/ftp/debug_mode_spec.rb
new file mode 100644
index 0000000000..c4aa5eee3c
--- /dev/null
+++ b/spec/ruby/library/net/ftp/debug_mode_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP#debug_mode" do
+ it "returns true when self is in debug mode" do
+ ftp = Net::FTP.new
+ ftp.debug_mode.should be_false
+
+ ftp.debug_mode = true
+ ftp.debug_mode.should be_true
+ end
+end
+
+describe "Net::FTP#debug_mode=" do
+ it "sets self into debug mode when passed true" do
+ ftp = Net::FTP.new
+ ftp.debug_mode = true
+ ftp.debug_mode.should be_true
+
+ ftp.debug_mode = false
+ ftp.debug_mode.should be_false
+ end
+end
diff --git a/spec/ruby/library/net/ftp/default_passive_spec.rb b/spec/ruby/library/net/ftp/default_passive_spec.rb
new file mode 100644
index 0000000000..f526373b82
--- /dev/null
+++ b/spec/ruby/library/net/ftp/default_passive_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+ruby_version_is "2.3" do
+ describe "Net::FTP#default_passive" do
+ it "is true by default" do
+ ruby_exe(fixture(__FILE__, "default_passive.rb")).should == "true\ntrue\n"
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/delete_spec.rb b/spec/ruby/library/net/ftp/delete_spec.rb
new file mode 100644
index 0000000000..b20ef32651
--- /dev/null
+++ b/spec/ruby/library/net/ftp/delete_spec.rb
@@ -0,0 +1,59 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#delete" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the DELE command with the passed filename to the server" do
+ @ftp.delete("test.file")
+ @ftp.last_response.should == "250 Requested file action okay, completed. (DELE test.file)\n"
+ end
+
+ it "raises a Net::FTPTempError when the response code is 450" do
+ @server.should_receive(:dele).and_respond("450 Requested file action not taken.")
+ lambda { @ftp.delete("test.file") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:dele).and_respond("550 Requested action not taken.")
+ lambda { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:dele).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:dele).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:dele).and_respond("502 Command not implemented.")
+ lambda { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:dele).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.delete("test.file") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:dele).and_respond("530 Not logged in.")
+ lambda { @ftp.delete("test.file") }.should raise_error(Net::FTPPermError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/dir_spec.rb b/spec/ruby/library/net/ftp/dir_spec.rb
new file mode 100644
index 0000000000..6a2b766ca2
--- /dev/null
+++ b/spec/ruby/library/net/ftp/dir_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+require File.expand_path('../shared/list', __FILE__)
+
+describe "Net::FTP#dir" do
+ it_behaves_like :net_ftp_list, :dir
+end
diff --git a/spec/ruby/library/net/ftp/fixtures/default_passive.rb b/spec/ruby/library/net/ftp/fixtures/default_passive.rb
new file mode 100644
index 0000000000..b6995d6f34
--- /dev/null
+++ b/spec/ruby/library/net/ftp/fixtures/default_passive.rb
@@ -0,0 +1,3 @@
+require "net/ftp"
+puts Net::FTP.default_passive
+puts Net::FTP.new.passive
diff --git a/spec/ruby/library/net/ftp/fixtures/passive.rb b/spec/ruby/library/net/ftp/fixtures/passive.rb
new file mode 100644
index 0000000000..6b5cde82df
--- /dev/null
+++ b/spec/ruby/library/net/ftp/fixtures/passive.rb
@@ -0,0 +1,2 @@
+require "net/ftp"
+print Net::FTP.new.passive
diff --git a/spec/ruby/library/net/ftp/fixtures/putbinaryfile b/spec/ruby/library/net/ftp/fixtures/putbinaryfile
new file mode 100644
index 0000000000..f3130c6e43
--- /dev/null
+++ b/spec/ruby/library/net/ftp/fixtures/putbinaryfile
@@ -0,0 +1,3 @@
+This is an example file
+which is going to be transmitted
+using #putbinaryfile.
diff --git a/spec/ruby/library/net/ftp/fixtures/puttextfile b/spec/ruby/library/net/ftp/fixtures/puttextfile
new file mode 100644
index 0000000000..b4f3b2b62d
--- /dev/null
+++ b/spec/ruby/library/net/ftp/fixtures/puttextfile
@@ -0,0 +1,3 @@
+This is an example file
+which is going to be transmitted
+using #puttextfile.
diff --git a/spec/ruby/library/net/ftp/fixtures/server.rb b/spec/ruby/library/net/ftp/fixtures/server.rb
new file mode 100644
index 0000000000..a6741820ff
--- /dev/null
+++ b/spec/ruby/library/net/ftp/fixtures/server.rb
@@ -0,0 +1,273 @@
+module NetFTPSpecs
+ class DummyFTP
+ attr_accessor :connect_message
+ attr_reader :login_user, :login_pass, :login_acct
+
+ # hostname or IP address
+ attr_reader :hostname
+ # port number
+ attr_reader :server_port
+
+ def initialize
+ @hostname = "localhost"
+ @server = TCPServer.new(@hostname, 0)
+ @server_port = @server.addr[1]
+
+ @handlers = {}
+ @commands = []
+ @connect_message = nil
+ end
+
+ def serve_once
+ @thread = Thread.new do
+ @socket = @server.accept
+ @socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 1)
+ begin
+ handle_request
+ ensure
+ @socket.close
+ end
+ end
+ end
+
+ def handle_request
+ # Send out the welcome message.
+ response @connect_message || "220 Dummy FTP Server ready!"
+
+ begin
+ while command = @socket.recv(1024)
+ command, argument = command.chomp.split(" ", 2)
+
+ if command == "QUIT"
+ self.response("221 OK, bye")
+ break
+ elsif proc_handler = @handlers[command.downcase.to_sym]
+ if argument.nil?
+ proc_handler.call(self)
+ else
+ proc_handler.call(self, argument)
+ end
+ else
+ if argument.nil?
+ self.send(command.downcase.to_sym)
+ else
+ self.send(command.downcase.to_sym, argument)
+ end
+ end
+ end
+ rescue => e
+ self.error_response("Exception: #{e} #{e.backtrace.inspect}")
+ end
+ end
+
+ def error_response(text)
+ self.response("451 #{text}")
+ end
+
+ def response(text)
+ @socket.puts(text) unless @socket.closed?
+ end
+
+ def stop
+ @datasocket.close unless @datasocket.nil? || @datasocket.closed?
+ @server.close
+ @thread.join
+ end
+
+
+ ##
+ def handle(sym, &block)
+ @handlers[sym] = block
+ end
+
+ def should_receive(method)
+ @handler_for = method
+ self
+ end
+
+ def and_respond(text)
+ @handlers[@handler_for] = lambda { |s, *args| s.response(text) }
+ end
+
+ ##
+ # FTP methods
+ ##
+
+ def abor
+ self.response("226 Closing data connection. (ABOR)")
+ end
+
+ def acct(account)
+ @login_acct = account
+ self.response("230 User '#{account}' logged in, proceed. (ACCT)")
+ end
+
+ def cdup
+ self.response("200 Command okay. (CDUP)")
+ end
+
+ def cwd(dir)
+ self.response("200 Command okay. (CWD #{dir})")
+ end
+
+ def dele(file)
+ self.response("250 Requested file action okay, completed. (DELE #{file})")
+ end
+
+ def eprt(arg)
+ _, _, host, port = arg.split("|")
+
+ @datasocket = TCPSocket.new(host, port)
+ self.response("200 port opened")
+ end
+
+ def help(param = :default)
+ if param == :default
+ self.response("211 System status, or system help reply. (HELP)")
+ else
+ self.response("211 System status, or system help reply. (HELP #{param})")
+ end
+ end
+
+ def list(folder)
+ self.response("150 opening ASCII connection for file list")
+ @datasocket.puts("-rw-r--r-- 1 spec staff 507 17 Jul 18:41 last_response_code.rb")
+ @datasocket.puts("-rw-r--r-- 1 spec staff 50 17 Jul 18:41 list.rb")
+ @datasocket.puts("-rw-r--r-- 1 spec staff 48 17 Jul 18:41 pwd.rb")
+ @datasocket.close()
+ self.response("226 transfer complete (LIST #{folder})")
+ end
+
+ def mdtm(filename)
+ self.response("213 19980705132316")
+ end
+
+ def mkd(foldername)
+ self.response(%Q{257 "#{foldername.gsub('"', '""')}" created.})
+ end
+
+ def nlst(folder = nil)
+ self.response("150 opening ASCII connection for file list")
+ @datasocket.puts("last_response_code.rb")
+ @datasocket.puts("list.rb")
+ @datasocket.puts("pwd.rb")
+ @datasocket.close()
+ self.response("226 transfer complete (NLST#{folder ? " #{folder}" : ""})")
+ end
+
+ def noop
+ self.response("200 Command okay. (NOOP)")
+ end
+
+ def pass(password)
+ @login_pass = password
+ self.response("230 User logged in, proceed. (PASS #{password})")
+ end
+
+ def port(arg)
+ nums = arg.split(",")
+
+ if nums[0] == "::1"
+ # IPv6
+ port = nums[1].to_i * 256 + nums[2].to_i
+ host = nums[0]
+ else
+ # IPv4
+ port = nums[4].to_i * 256 + nums[5].to_i
+ host = nums[0..3].join(".")
+ end
+
+ @datasocket = TCPSocket.new(host, port)
+ self.response("200 port opened")
+ end
+
+ def pwd
+ self.response('257 "/some/dir/" - current directory')
+ end
+
+ def retr(file)
+ self.response("125 Data transfer starting")
+ if @restart_at && @restart_at == 20
+ @datasocket.puts("of the file named '#{file}'.")
+ @restart_at = nil
+ else
+ @datasocket.puts("This is the content")
+ @datasocket.puts("of the file named '#{file}'.")
+ end
+ @datasocket.close()
+ self.response("226 Closing data connection. (RETR #{file})")
+ end
+
+ def rest(at_bytes)
+ @restart_at = at_bytes.to_i
+ self.response("350 Requested file action pending further information. (REST)")
+ end
+
+ def rmd(folder)
+ self.response("250 Requested file action okay, completed. (RMD #{folder})")
+ end
+
+ def rnfr(from)
+ @rename_from = from
+ self.response("350 Requested file action pending further information.")
+ end
+
+ def rnto(to)
+ self.response("250 Requested file action okay, completed. (Renamed #{@rename_from} to #{to})")
+ @rename_from = nil
+ end
+
+ def site(param)
+ self.response("200 Command okay. (SITE #{param})")
+ end
+
+ def size(filename)
+ if filename == "binary"
+ self.response("213 24")
+ else
+ self.response("213 1024")
+ end
+ end
+
+ def stat
+ self.response("211 System status, or system help reply. (STAT)")
+ end
+
+ def stor(file)
+ tmp_file = tmp("#{file}file", false)
+
+ self.response("125 Data transfer starting.")
+
+ mode = @restart_at ? "a" : "w"
+
+ File.open(tmp_file, mode + "b") do |f|
+ loop do
+ data = @datasocket.recv(1024)
+ break if !data || data.empty?
+ f << data
+ end
+ end
+
+ #@datasocket.close()
+ self.response("200 OK, Data received. (STOR #{file})")
+ end
+
+ def appe(file)
+ @restart_at = true
+ stor(file)
+ end
+
+ def syst
+ self.response("215 FTP Dummy Server (SYST)")
+ end
+
+ def type(type)
+ self.response("200 TYPE switched to #{type}")
+ end
+
+ def user(name)
+ @login_user = name
+ self.response("230 User logged in, proceed. (USER #{name})")
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/get_spec.rb b/spec/ruby/library/net/ftp/get_spec.rb
new file mode 100644
index 0000000000..59fc45d010
--- /dev/null
+++ b/spec/ruby/library/net/ftp/get_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+require File.expand_path('../shared/gettextfile', __FILE__)
+require File.expand_path('../shared/getbinaryfile', __FILE__)
+
+describe "Net::FTP#get (binary mode)" do
+ before :each do
+ @binary_mode = true
+ end
+
+ it_behaves_like :net_ftp_getbinaryfile, :get
+end
+
+describe "Net::FTP#get (text mode)" do
+ before :each do
+ @binary_mode = false
+ end
+
+ it_behaves_like :net_ftp_gettextfile, :get
+end
diff --git a/spec/ruby/library/net/ftp/getbinaryfile_spec.rb b/spec/ruby/library/net/ftp/getbinaryfile_spec.rb
new file mode 100644
index 0000000000..0f921c8b1d
--- /dev/null
+++ b/spec/ruby/library/net/ftp/getbinaryfile_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+require File.expand_path('../shared/getbinaryfile', __FILE__)
+
+describe "Net::FTP#getbinaryfile" do
+ it_behaves_like :net_ftp_getbinaryfile, :getbinaryfile
+end
diff --git a/spec/ruby/library/net/ftp/getdir_spec.rb b/spec/ruby/library/net/ftp/getdir_spec.rb
new file mode 100644
index 0000000000..19ace4dff9
--- /dev/null
+++ b/spec/ruby/library/net/ftp/getdir_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../shared/pwd', __FILE__)
+
+describe "Net::FTP#getdir" do
+ it_behaves_like :net_ftp_pwd, :getdir
+end
diff --git a/spec/ruby/library/net/ftp/gettextfile_spec.rb b/spec/ruby/library/net/ftp/gettextfile_spec.rb
new file mode 100644
index 0000000000..29077df253
--- /dev/null
+++ b/spec/ruby/library/net/ftp/gettextfile_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+require File.expand_path('../shared/gettextfile', __FILE__)
+
+describe "Net::FTP#gettextfile" do
+ it_behaves_like :net_ftp_gettextfile, :gettextfile
+end
diff --git a/spec/ruby/library/net/ftp/help_spec.rb b/spec/ruby/library/net/ftp/help_spec.rb
new file mode 100644
index 0000000000..6f5f901024
--- /dev/null
+++ b/spec/ruby/library/net/ftp/help_spec.rb
@@ -0,0 +1,66 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#help" do
+ def with_connection
+ yield
+ end
+
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "writes the HELP command to the server" do
+ @ftp.help
+ @ftp.last_response.should == "211 System status, or system help reply. (HELP)\n"
+ end
+
+ it "returns the server's response" do
+ @ftp.help.should == "211 System status, or system help reply. (HELP)\n"
+ end
+
+ it "writes the HELP command with an optional parameter to the socket" do
+ @ftp.help("some parameter").should == "211 System status, or system help reply. (HELP some parameter)\n"
+ end
+
+ it "does not raise any error when the response code is 211" do
+ @server.should_receive(:help).and_respond("211 System status, or system help reply.")
+ lambda { @ftp.help }.should_not raise_error
+ end
+
+ it "does not raise any error when the response code is 214" do
+ @server.should_receive(:help).and_respond("214 Help message.")
+ lambda { @ftp.help }.should_not raise_error
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:help).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.help }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:help).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.help }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:help).and_respond("502 Command not implemented.")
+ lambda { @ftp.help }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:help).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.help }.should raise_error(Net::FTPTempError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/initialize_spec.rb b/spec/ruby/library/net/ftp/initialize_spec.rb
new file mode 100644
index 0000000000..767bbecedb
--- /dev/null
+++ b/spec/ruby/library/net/ftp/initialize_spec.rb
@@ -0,0 +1,87 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP#initialize" do
+ before :each do
+ @ftp = Net::FTP.allocate
+ @ftp.stub!(:connect)
+ end
+
+ it "is private" do
+ Net::FTP.should have_private_instance_method(:initialize)
+ end
+
+ it "sets self into binary mode" do
+ @ftp.binary.should be_nil
+ @ftp.send(:initialize)
+ @ftp.binary.should be_true
+ end
+
+ it "sets self into active mode" do
+ @ftp.passive.should be_nil
+ @ftp.send(:initialize)
+ @ftp.passive.should be_false
+ end
+
+ it "sets self into non-debug mode" do
+ @ftp.debug_mode.should be_nil
+ @ftp.send(:initialize)
+ @ftp.debug_mode.should be_false
+ end
+
+ it "sets self to not resume file uploads/downloads" do
+ @ftp.resume.should be_nil
+ @ftp.send(:initialize)
+ @ftp.resume.should be_false
+ end
+
+ describe "when passed no arguments" do
+ it "does not try to connect" do
+ @ftp.should_not_receive(:connect)
+ @ftp.send(:initialize)
+ end
+ end
+
+ describe "when passed host" do
+ it "tries to connect to the passed host" do
+ @ftp.should_receive(:connect).with("localhost")
+ @ftp.send(:initialize, "localhost")
+ end
+ end
+
+ describe "when passed host, user" do
+ it "tries to connect to the passed host" do
+ @ftp.should_receive(:connect).with("localhost")
+ @ftp.send(:initialize, "localhost")
+ end
+
+ it "tries to login with the passed username" do
+ @ftp.should_receive(:login).with("rubyspec", nil, nil)
+ @ftp.send(:initialize, "localhost", "rubyspec")
+ end
+ end
+
+ describe "when passed host, user, password" do
+ it "tries to connect to the passed host" do
+ @ftp.should_receive(:connect).with("localhost")
+ @ftp.send(:initialize, "localhost")
+ end
+
+ it "tries to login with the passed username and password" do
+ @ftp.should_receive(:login).with("rubyspec", "rocks", nil)
+ @ftp.send(:initialize, "localhost", "rubyspec", "rocks")
+ end
+ end
+
+ describe "when passed host, user" do
+ it "tries to connect to the passed host" do
+ @ftp.should_receive(:connect).with("localhost")
+ @ftp.send(:initialize, "localhost")
+ end
+
+ it "tries to login with the passed username, password and account" do
+ @ftp.should_receive(:login).with("rubyspec", "rocks", "account")
+ @ftp.send(:initialize, "localhost", "rubyspec", "rocks", "account")
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/last_response_code_spec.rb b/spec/ruby/library/net/ftp/last_response_code_spec.rb
new file mode 100644
index 0000000000..77651a9be4
--- /dev/null
+++ b/spec/ruby/library/net/ftp/last_response_code_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../shared/last_response_code', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#last_response_code" do
+ it_behaves_like :net_ftp_last_response_code, :last_response_code
+end
diff --git a/spec/ruby/library/net/ftp/last_response_spec.rb b/spec/ruby/library/net/ftp/last_response_spec.rb
new file mode 100644
index 0000000000..eb53f92774
--- /dev/null
+++ b/spec/ruby/library/net/ftp/last_response_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#last_response" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "returns the last response" do
+ @ftp.last_response.should == "220 Dummy FTP Server ready!\n"
+ @ftp.help
+ @ftp.last_response.should == "211 System status, or system help reply. (HELP)\n"
+ end
+end
diff --git a/spec/ruby/library/net/ftp/lastresp_spec.rb b/spec/ruby/library/net/ftp/lastresp_spec.rb
new file mode 100644
index 0000000000..d2c6f44e48
--- /dev/null
+++ b/spec/ruby/library/net/ftp/lastresp_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../shared/last_response_code', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#lastresp" do
+ it_behaves_like :net_ftp_last_response_code, :lastresp
+end
diff --git a/spec/ruby/library/net/ftp/list_spec.rb b/spec/ruby/library/net/ftp/list_spec.rb
new file mode 100644
index 0000000000..41c55c42ac
--- /dev/null
+++ b/spec/ruby/library/net/ftp/list_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+require File.expand_path('../shared/list', __FILE__)
+
+describe "Net::FTP#list" do
+ it_behaves_like :net_ftp_list, :list
+end
diff --git a/spec/ruby/library/net/ftp/login_spec.rb b/spec/ruby/library/net/ftp/login_spec.rb
new file mode 100644
index 0000000000..9768d9cf33
--- /dev/null
+++ b/spec/ruby/library/net/ftp/login_spec.rb
@@ -0,0 +1,195 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#login" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ describe "when passed no arguments" do
+ it "sends the USER command with 'anonymous' as name to the server" do
+ @ftp.login
+ @server.login_user.should == "anonymous"
+ end
+
+ it "sends 'anonymous@' as a password when required" do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ @ftp.login
+ @server.login_pass.should == "anonymous@"
+ end
+
+ it "raises a Net::FTPReplyError when the server requests an account" do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ @server.should_receive(:pass).and_respond("332 Need account for login.")
+ lambda { @ftp.login }.should raise_error(Net::FTPReplyError)
+ end
+ end
+
+ describe "when passed name" do
+ it "sends the USER command with the passed name to the server" do
+ @ftp.login("rubyspec")
+ @server.login_user.should == "rubyspec"
+ end
+
+ it "raises a Net::FTPReplyError when the server requests a password, but none was given" do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ lambda { @ftp.login("rubyspec") }.should raise_error(Net::FTPReplyError)
+ end
+
+ it "raises a Net::FTPReplyError when the server requests an account, but none was given" do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ @server.should_receive(:pass).and_respond("332 Need account for login.")
+ lambda { @ftp.login("rubyspec") }.should raise_error(Net::FTPReplyError)
+ end
+ end
+
+ describe "when passed name, password" do
+ it "sends the USER command with the passed name to the server" do
+ @ftp.login("rubyspec", "rocks")
+ @server.login_user.should == "rubyspec"
+ end
+
+ it "sends the passed password when required" do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ @ftp.login("rubyspec", "rocks")
+ @server.login_pass.should == "rocks"
+ end
+
+ it "raises a Net::FTPReplyError when the server requests an account" do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ @server.should_receive(:pass).and_respond("332 Need account for login.")
+ lambda { @ftp.login("rubyspec", "rocks") }.should raise_error(Net::FTPReplyError)
+ end
+ end
+
+ describe "when passed name, password, account" do
+ it "sends the USER command with the passed name to the server" do
+ @ftp.login("rubyspec", "rocks", "account")
+ @server.login_user.should == "rubyspec"
+ end
+
+ it "sends the passed password when required" do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ @ftp.login("rubyspec", "rocks", "account")
+ @server.login_pass.should == "rocks"
+ end
+
+ it "sends the passed account when required" do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ @server.should_receive(:pass).and_respond("332 Need account for login.")
+ @ftp.login("rubyspec", "rocks", "account")
+ @server.login_acct.should == "account"
+ end
+ end
+
+ describe "when the USER command fails" do
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:user).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:user).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:user).and_respond("502 Command not implemented.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:user).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:user).and_respond("530 Not logged in.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ describe "when the PASS command fails" do
+ before :each do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ end
+
+ it "does not raise an Error when the response code is 202" do
+ @server.should_receive(:pass).and_respond("202 Command not implemented, superfluous at this site.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should_not raise_error
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:pass).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:pass).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:pass).and_respond("502 Command not implemented.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:pass).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:pass).and_respond("530 Not logged in.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ describe "when the ACCT command fails" do
+ before :each do
+ @server.should_receive(:user).and_respond("331 User name okay, need password.")
+ @server.should_receive(:pass).and_respond("332 Need account for login.")
+ end
+
+ it "does not raise an Error when the response code is 202" do
+ @server.should_receive(:acct).and_respond("202 Command not implemented, superfluous at this site.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should_not raise_error
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:acct).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:acct).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:acct).and_respond("502 Command not implemented.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:acct).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:acct).and_respond("530 Not logged in.")
+ lambda { @ftp.login("rubyspec", "rocks", "account") }.should raise_error(Net::FTPPermError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/ls_spec.rb b/spec/ruby/library/net/ftp/ls_spec.rb
new file mode 100644
index 0000000000..f713fb46aa
--- /dev/null
+++ b/spec/ruby/library/net/ftp/ls_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+require File.expand_path('../shared/list', __FILE__)
+
+describe "Net::FTP#ls" do
+ it_behaves_like :net_ftp_list, :ls
+end
diff --git a/spec/ruby/library/net/ftp/mdtm_spec.rb b/spec/ruby/library/net/ftp/mdtm_spec.rb
new file mode 100644
index 0000000000..bbd28d10b1
--- /dev/null
+++ b/spec/ruby/library/net/ftp/mdtm_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#mdtm" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the MDTM with the passed filename command to the server" do
+ @ftp.mdtm("test.file")
+ @ftp.last_response.should == "213 19980705132316\n"
+ end
+
+ it "returns the last modification time of the passed file" do
+ @ftp.mdtm("test.file").should == "19980705132316"
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:mdtm).and_respond("550 Requested action not taken.")
+ lambda { @ftp.mdtm("test.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:mdtm).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.mdtm("test.file") }.should raise_error(Net::FTPTempError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/mkdir_spec.rb b/spec/ruby/library/net/ftp/mkdir_spec.rb
new file mode 100644
index 0000000000..2a7088e5d9
--- /dev/null
+++ b/spec/ruby/library/net/ftp/mkdir_spec.rb
@@ -0,0 +1,61 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#mkdir" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the MKD command with the passed pathname to the server" do
+ @ftp.mkdir("test.folder")
+ @ftp.last_response.should == %{257 "test.folder" created.\n}
+ end
+
+ it "returns the path to the newly created directory" do
+ @ftp.mkdir("test.folder").should == "test.folder"
+ @ftp.mkdir("/absolute/path/to/test.folder").should == "/absolute/path/to/test.folder"
+ @ftp.mkdir("relative/path/to/test.folder").should == "relative/path/to/test.folder"
+ @ftp.mkdir('/usr/dm/foo"bar').should == '/usr/dm/foo"bar'
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:mkd).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:mkd).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:mkd).and_respond("502 Command not implemented.")
+ lambda { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:mkd).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:mkd).and_respond("530 Not logged in.")
+ lambda { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:mkd).and_respond("550 Requested action not taken.")
+ lambda { @ftp.mkdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/mtime_spec.rb b/spec/ruby/library/net/ftp/mtime_spec.rb
new file mode 100644
index 0000000000..0e76aa079b
--- /dev/null
+++ b/spec/ruby/library/net/ftp/mtime_spec.rb
@@ -0,0 +1,50 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#mtime" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the MDTM with the passed filename command to the server" do
+ @ftp.mtime("test.file")
+ @ftp.last_response.should == "213 19980705132316\n"
+ end
+
+ describe "when passed filename" do
+ it "returns the last modification time of the passed file as a Time object in the local time" do
+ @ftp.mtime("test.file").should == Time.gm("1998", "07", "05", "13", "23", "16")
+ end
+ end
+
+ describe "when passed filename, local_time" do
+ it "returns the last modification time as a Time object in UTC when local_time is true" do
+ @ftp.mtime("test.file", true).should == Time.local("1998", "07", "05", "13", "23", "16")
+ end
+
+ it "returns the last modification time as a Time object in the local time when local_time is false" do
+ @ftp.mtime("test.file", false).should == Time.gm("1998", "07", "05", "13", "23", "16")
+ end
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:mdtm).and_respond("550 Requested action not taken.")
+ lambda { @ftp.mtime("test.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:mdtm).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.mtime("test.file") }.should raise_error(Net::FTPTempError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/nlst_spec.rb b/spec/ruby/library/net/ftp/nlst_spec.rb
new file mode 100644
index 0000000000..4723e9f6c6
--- /dev/null
+++ b/spec/ruby/library/net/ftp/nlst_spec.rb
@@ -0,0 +1,92 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#nlst" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.passive = false
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ describe "when passed no arguments" do
+ it "returns an Array containing a list of files in the current dir" do
+ @ftp.nlst.should == ["last_response_code.rb", "list.rb", "pwd.rb"]
+ @ftp.last_response.should == "226 transfer complete (NLST)\n"
+ end
+ end
+
+ describe "when passed dir" do
+ it "returns an Array containing a list of files in the passed dir" do
+ @ftp.nlst("test.folder").should == ["last_response_code.rb", "list.rb", "pwd.rb"]
+ @ftp.last_response.should == "226 transfer complete (NLST test.folder)\n"
+ end
+ end
+
+ describe "when the NLST command fails" do
+ it "raises a Net::FTPTempError when the response code is 450" do
+ @server.should_receive(:nlst).and_respond("450 Requested file action not taken..")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:nlst).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:nlst).and_respond("501 Syntax error, command unrecognized.")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:nlst).and_respond("502 Command not implemented.")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:nlst).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:nlst).and_respond("530 Not logged in.")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ describe "when opening the data port fails" do
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:eprt).and_respond("500 Syntax error, command unrecognized.")
+ @server.should_receive(:port).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:eprt).and_respond("501 Syntax error in parameters or arguments.")
+ @server.should_receive(:port).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:eprt).and_respond("421 Service not available, closing control connection.")
+ @server.should_receive(:port).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:eprt).and_respond("530 Not logged in.")
+ @server.should_receive(:port).and_respond("530 Not logged in.")
+ lambda { @ftp.nlst }.should raise_error(Net::FTPPermError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/noop_spec.rb b/spec/ruby/library/net/ftp/noop_spec.rb
new file mode 100644
index 0000000000..1bc6ccd913
--- /dev/null
+++ b/spec/ruby/library/net/ftp/noop_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#noop" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the NOOP command to the server" do
+ @ftp.noop
+ @ftp.last_response.should == "200 Command okay. (NOOP)\n"
+ end
+
+ it "returns nil" do
+ @ftp.noop.should be_nil
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:noop).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.noop }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:noop).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.noop }.should raise_error(Net::FTPTempError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/open_spec.rb b/spec/ruby/library/net/ftp/open_spec.rb
new file mode 100644
index 0000000000..b422e64c87
--- /dev/null
+++ b/spec/ruby/library/net/ftp/open_spec.rb
@@ -0,0 +1,55 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP.open" do
+ before :each do
+ @ftp = mock("Net::FTP instance")
+ Net::FTP.stub!(:new).and_return(@ftp)
+ end
+
+ describe "when passed no block" do
+ it "returns a new Net::FTP instance" do
+ Net::FTP.open("localhost").should equal(@ftp)
+ end
+
+ it "passes the passed arguments down to Net::FTP.new" do
+ Net::FTP.should_receive(:new).with("localhost", "user", "password", "account")
+ Net::FTP.open("localhost", "user", "password", "account")
+ end
+ end
+
+ describe "when passed a block" do
+ before :each do
+ @ftp.stub!(:close)
+ end
+
+ it "yields a new Net::FTP instance to the passed block" do
+ yielded = false
+ Net::FTP.open("localhost") do |ftp|
+ yielded = true
+ ftp.should equal(@ftp)
+ end
+ yielded.should be_true
+ end
+
+ it "closes the Net::FTP instance after yielding" do
+ Net::FTP.open("localhost") do |ftp|
+ ftp.should_receive(:close)
+ end
+ end
+
+ it "closes the Net::FTP instance even if an exception is raised while yielding" do
+ begin
+ Net::FTP.open("localhost") do |ftp|
+ ftp.should_receive(:close)
+ raise ArgumentError, "some exception"
+ end
+ rescue ArgumentError
+ end
+ end
+
+ it "returns the block's return value" do
+ Net::FTP.open("localhost") { :test }.should == :test
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/passive_spec.rb b/spec/ruby/library/net/ftp/passive_spec.rb
new file mode 100644
index 0000000000..fd9a0dffe3
--- /dev/null
+++ b/spec/ruby/library/net/ftp/passive_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP#passive" do
+ it "returns true when self is in passive mode" do
+ ftp = Net::FTP.new
+ ftp.passive.should be_false
+
+ ftp.passive = true
+ ftp.passive.should be_true
+ end
+
+ ruby_version_is ""..."2.3" do
+ it "is false by default" do
+ ruby_exe(fixture(__FILE__, "passive.rb")).should == "false"
+ end
+ end
+
+ ruby_version_is "2.3" do
+ it "is the value of Net::FTP.default_value by default" do
+ ruby_exe(fixture(__FILE__, "passive.rb")).should == "true"
+ end
+ end
+end
+
+describe "Net::FTP#passive=" do
+ it "sets self to passive mode when passed true" do
+ ftp = Net::FTP.new
+
+ ftp.passive = true
+ ftp.passive.should be_true
+
+ ftp.passive = false
+ ftp.passive.should be_false
+ end
+end
diff --git a/spec/ruby/library/net/ftp/put_spec.rb b/spec/ruby/library/net/ftp/put_spec.rb
new file mode 100644
index 0000000000..61a8d00543
--- /dev/null
+++ b/spec/ruby/library/net/ftp/put_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+require File.expand_path('../shared/puttextfile', __FILE__)
+require File.expand_path('../shared/putbinaryfile', __FILE__)
+
+describe "Net::FTP#put (binary mode)" do
+ before :each do
+ @binary_mode = true
+ end
+
+ it_behaves_like :net_ftp_putbinaryfile, :put
+end
+
+describe "Net::FTP#put (text mode)" do
+ before :each do
+ @binary_mode = false
+ end
+
+ it_behaves_like :net_ftp_puttextfile, :put
+end
diff --git a/spec/ruby/library/net/ftp/putbinaryfile_spec.rb b/spec/ruby/library/net/ftp/putbinaryfile_spec.rb
new file mode 100644
index 0000000000..18955409b6
--- /dev/null
+++ b/spec/ruby/library/net/ftp/putbinaryfile_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+require File.expand_path('../shared/putbinaryfile', __FILE__)
+
+describe "Net::FTP#putbinaryfile" do
+ it_behaves_like :net_ftp_putbinaryfile, :putbinaryfile
+end
diff --git a/spec/ruby/library/net/ftp/puttextfile_spec.rb b/spec/ruby/library/net/ftp/puttextfile_spec.rb
new file mode 100644
index 0000000000..2ca6e98c92
--- /dev/null
+++ b/spec/ruby/library/net/ftp/puttextfile_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+require File.expand_path('../shared/puttextfile', __FILE__)
+
+describe "Net::FTP#puttextfile" do
+ it_behaves_like :net_ftp_puttextfile, :puttextfile
+end
diff --git a/spec/ruby/library/net/ftp/pwd_spec.rb b/spec/ruby/library/net/ftp/pwd_spec.rb
new file mode 100644
index 0000000000..d5438d8e56
--- /dev/null
+++ b/spec/ruby/library/net/ftp/pwd_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#pwd" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the PWD command to the server" do
+ @ftp.pwd
+ @ftp.last_response.should == "257 \"/some/dir/\" - current directory\n"
+ end
+
+ it "returns the current directory" do
+ @ftp.pwd.should == "/some/dir/"
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:pwd).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.pwd }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:pwd).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.pwd }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:pwd).and_respond("502 Command not implemented.")
+ lambda { @ftp.pwd }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:pwd).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.pwd }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:pwd).and_respond("550 Requested action not taken.")
+ lambda { @ftp.pwd }.should raise_error(Net::FTPPermError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/quit_spec.rb b/spec/ruby/library/net/ftp/quit_spec.rb
new file mode 100644
index 0000000000..c053641939
--- /dev/null
+++ b/spec/ruby/library/net/ftp/quit_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#quit" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the QUIT command to the server" do
+ @ftp.quit
+ @ftp.last_response.should == "221 OK, bye\n"
+ end
+
+ it "does not close the socket automagically" do
+ @ftp.quit
+ @ftp.closed?.should be_false
+ end
+
+ it "returns nil" do
+ @ftp.quit.should be_nil
+ end
+end
diff --git a/spec/ruby/library/net/ftp/rename_spec.rb b/spec/ruby/library/net/ftp/rename_spec.rb
new file mode 100644
index 0000000000..0216d2059a
--- /dev/null
+++ b/spec/ruby/library/net/ftp/rename_spec.rb
@@ -0,0 +1,94 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#rename" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ describe "when passed from_name, to_name" do
+ it "sends the RNFR command with the passed from_name and the RNTO command with the passed to_name to the server" do
+ @ftp.rename("from.file", "to.file")
+ @ftp.last_response.should == "250 Requested file action okay, completed. (Renamed from.file to to.file)\n"
+ end
+
+ it "returns something" do
+ @ftp.rename("from.file", "to.file").should be_nil
+ end
+ end
+
+ describe "when the RNFR command fails" do
+ it "raises a Net::FTPTempError when the response code is 450" do
+ @server.should_receive(:rnfr).and_respond("450 Requested file action not taken.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:rnfr).and_respond("550 Requested action not taken.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:rnfr).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:rnfr).and_respond("502 Command not implemented.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:rnfr).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:rnfr).and_respond("530 Not logged in.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ describe "when the RNTO command fails" do
+ it "raises a Net::FTPPermError when the response code is 532" do
+ @server.should_receive(:rnfr).and_respond("532 Need account for storing files.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 553" do
+ @server.should_receive(:rnto).and_respond("553 Requested action not taken.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:rnto).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:rnto).and_respond("502 Command not implemented.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:rnto).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:rnto).and_respond("530 Not logged in.")
+ lambda { @ftp.rename("from.file", "to.file") }.should raise_error(Net::FTPPermError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/resume_spec.rb b/spec/ruby/library/net/ftp/resume_spec.rb
new file mode 100644
index 0000000000..9ec4a921aa
--- /dev/null
+++ b/spec/ruby/library/net/ftp/resume_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP#resume" do
+ it "returns true when self is set to resume uploads/downloads" do
+ ftp = Net::FTP.new
+ ftp.resume.should be_false
+
+ ftp.resume = true
+ ftp.resume.should be_true
+ end
+end
+
+describe "Net::FTP#resume=" do
+ it "sets self to resume uploads/downloads when set to true" do
+ ftp = Net::FTP.new
+ ftp.resume = true
+ ftp.resume.should be_true
+
+ ftp.resume = false
+ ftp.resume.should be_false
+ end
+end
diff --git a/spec/ruby/library/net/ftp/retrbinary_spec.rb b/spec/ruby/library/net/ftp/retrbinary_spec.rb
new file mode 100644
index 0000000000..fd7af0b62a
--- /dev/null
+++ b/spec/ruby/library/net/ftp/retrbinary_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#retrbinary" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the passed command to the server" do
+ @ftp.retrbinary("RETR test", 4096) {}
+ @ftp.last_response.should == "226 Closing data connection. (RETR test)\n"
+ end
+
+ it "yields the received content as binary blocks of the passed size" do
+ res = []
+ @ftp.retrbinary("RETR test", 10) { |bin| res << bin }
+ res.should == [ "This is th", "e content\n", "of the fil", "e named 't", "est'.\n" ]
+ end
+end
diff --git a/spec/ruby/library/net/ftp/retrlines_spec.rb b/spec/ruby/library/net/ftp/retrlines_spec.rb
new file mode 100644
index 0000000000..cb8d48ecf7
--- /dev/null
+++ b/spec/ruby/library/net/ftp/retrlines_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#retrlines" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the passed command over the socket" do
+ @ftp.retrlines("LIST test.dir") {}
+ @ftp.last_response.should == "226 transfer complete (LIST test.dir)\n"
+ end
+
+ it "yields each received line to the passed block" do
+ res = []
+ @ftp.retrlines("LIST test.dir") { |x| res << x }
+ res.should == [
+ "-rw-r--r-- 1 spec staff 507 17 Jul 18:41 last_response_code.rb",
+ "-rw-r--r-- 1 spec staff 50 17 Jul 18:41 list.rb",
+ "-rw-r--r-- 1 spec staff 48 17 Jul 18:41 pwd.rb"
+ ]
+ end
+end
diff --git a/spec/ruby/library/net/ftp/return_code_spec.rb b/spec/ruby/library/net/ftp/return_code_spec.rb
new file mode 100644
index 0000000000..b6090aeb61
--- /dev/null
+++ b/spec/ruby/library/net/ftp/return_code_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP#return_code" do
+ before :each do
+ @ftp = Net::FTP.new
+ end
+
+ it "outputs a warning and returns a newline" do
+ lambda do
+ @ftp.return_code.should == "\n"
+ end.should complain("warning: Net::FTP#return_code is obsolete and do nothing\n")
+ end
+end
+
+describe "Net::FTP#return_code=" do
+ before :each do
+ @ftp = Net::FTP.new
+ end
+
+ it "outputs a warning" do
+ lambda { @ftp.return_code = 123 }.should complain("warning: Net::FTP#return_code= is obsolete and do nothing\n")
+ end
+end
diff --git a/spec/ruby/library/net/ftp/rmdir_spec.rb b/spec/ruby/library/net/ftp/rmdir_spec.rb
new file mode 100644
index 0000000000..453c7823c4
--- /dev/null
+++ b/spec/ruby/library/net/ftp/rmdir_spec.rb
@@ -0,0 +1,58 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#rmdir" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the RMD command with the passed pathname to the server" do
+ @ftp.rmdir("test.folder")
+ @ftp.last_response.should == "250 Requested file action okay, completed. (RMD test.folder)\n"
+ end
+
+ it "returns nil" do
+ @ftp.rmdir("test.folder").should be_nil
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:rmd).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:rmd).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:rmd).and_respond("502 Command not implemented.")
+ lambda { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:rmd).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:rmd).and_respond("530 Not logged in.")
+ lambda { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:rmd).and_respond("550 Requested action not taken.")
+ lambda { @ftp.rmdir("test.folder") }.should raise_error(Net::FTPPermError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/sendcmd_spec.rb b/spec/ruby/library/net/ftp/sendcmd_spec.rb
new file mode 100644
index 0000000000..9bdca621bc
--- /dev/null
+++ b/spec/ruby/library/net/ftp/sendcmd_spec.rb
@@ -0,0 +1,54 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#sendcmd" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the passed command to the server" do
+ @ftp.sendcmd("HELP")
+ @ftp.last_response.should == "211 System status, or system help reply. (HELP)\n"
+ end
+
+ it "returns the server's response" do
+ @ftp.sendcmd("HELP").should == "211 System status, or system help reply. (HELP)\n"
+ end
+
+ it "raises no error when the response code is 1xx, 2xx or 3xx" do
+ @server.should_receive(:help).and_respond("120 Service ready in nnn minutes.")
+ lambda { @ftp.sendcmd("HELP") }.should_not raise_error
+
+ @server.should_receive(:help).and_respond("200 Command okay.")
+ lambda { @ftp.sendcmd("HELP") }.should_not raise_error
+
+ @server.should_receive(:help).and_respond("350 Requested file action pending further information.")
+ lambda { @ftp.sendcmd("HELP") }.should_not raise_error
+ end
+
+ it "raises a Net::FTPTempError when the response code is 4xx" do
+ @server.should_receive(:help).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.sendcmd("HELP") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 5xx" do
+ @server.should_receive(:help).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.sendcmd("HELP") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPProtoError when the response code is not between 1xx-5xx" do
+ @server.should_receive(:help).and_respond("999 Invalid response.")
+ lambda { @ftp.sendcmd("HELP") }.should raise_error(Net::FTPProtoError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/set_socket_spec.rb b/spec/ruby/library/net/ftp/set_socket_spec.rb
new file mode 100644
index 0000000000..1553445219
--- /dev/null
+++ b/spec/ruby/library/net/ftp/set_socket_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "Net::FTP#set_socket" do
+ # TODO: I won't spec this method, as it is not used
+ # anywhere and it should be private anyway.
+ #it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/net/ftp/shared/getbinaryfile.rb b/spec/ruby/library/net/ftp/shared/getbinaryfile.rb
new file mode 100644
index 0000000000..2252935b2d
--- /dev/null
+++ b/spec/ruby/library/net/ftp/shared/getbinaryfile.rb
@@ -0,0 +1,150 @@
+describe :net_ftp_getbinaryfile, shared: :true do
+ before :each do
+ @fixture_file = File.dirname(__FILE__) + "/../fixtures/getbinaryfile"
+ @tmp_file = tmp("getbinaryfile")
+
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ @ftp.binary = @binary_mode
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+
+ rm_r @tmp_file
+ end
+
+ it "sends the RETR command to the server" do
+ @ftp.send(@method, "test", @tmp_file)
+ @ftp.last_response.should == "226 Closing data connection. (RETR test)\n"
+ end
+
+ it "returns nil" do
+ @ftp.send(@method, "test", @tmp_file).should be_nil
+ end
+
+ it "saves the contents of the passed remote file to the passed local file" do
+ @ftp.send(@method, "test", @tmp_file)
+ File.read(@tmp_file).should == "This is the content\nof the file named 'test'.\n"
+ end
+
+ describe "when passed a block" do
+ it "yields the received content as binary blocks of the passed size" do
+ res = []
+ @ftp.send(@method, "test", @tmp_file, 10) { |bin| res << bin }
+ res.should == [ "This is th", "e content\n", "of the fil", "e named 't", "est'.\n" ]
+ end
+ end
+
+ describe "when resuming an existing file" do
+ before :each do
+ @tmp_file = tmp("getbinaryfile_resume")
+
+ File.open(@tmp_file, "wb") do |f|
+ f << "This is the content\n"
+ end
+
+ @ftp.resume = true
+ end
+
+ it "saves the remaining content of the passed remote file to the passed local file" do
+ @ftp.send(@method, "test", @tmp_file)
+ File.read(@tmp_file).should == "This is the content\nof the file named 'test'.\n"
+ end
+
+ describe "and the REST command fails" do
+ it "raises a Net::FTPProtoError when the response code is 550" do
+ @server.should_receive(:rest).and_respond("Requested action not taken.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPProtoError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:rest).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:rest).and_respond("501 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:rest).and_respond("502 Command not implemented.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:rest).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:rest).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+ end
+ end
+
+ describe "when the RETR command fails" do
+ it "raises a Net::FTPTempError when the response code is 450" do
+ @server.should_receive(:retr).and_respond("450 Requested file action not taken.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPProtoError when the response code is 550" do
+ @server.should_receive(:retr).and_respond("Requested action not taken.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPProtoError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:retr).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:retr).and_respond("501 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:retr).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:retr).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ describe "when opening the data port fails" do
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:eprt).and_respond("500 Syntax error, command unrecognized.")
+ @server.should_receive(:port).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:eprt).and_respond("501 Syntax error in parameters or arguments.")
+ @server.should_receive(:port).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:eprt).and_respond("421 Service not available, closing control connection.")
+ @server.should_receive(:port).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:eprt).and_respond("530 Not logged in.")
+ @server.should_receive(:port).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/shared/gettextfile.rb b/spec/ruby/library/net/ftp/shared/gettextfile.rb
new file mode 100644
index 0000000000..6219581d12
--- /dev/null
+++ b/spec/ruby/library/net/ftp/shared/gettextfile.rb
@@ -0,0 +1,100 @@
+describe :net_ftp_gettextfile, shared: :true do
+ before :each do
+ @tmp_file = tmp("gettextfile")
+
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ @ftp.binary = @binary_mode
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+
+ rm_r @tmp_file
+ end
+
+ it "sends the RETR command to the server" do
+ @ftp.send(@method, "test", @tmp_file)
+ @ftp.last_response.should == "226 Closing data connection. (RETR test)\n"
+ end
+
+ it "returns nil" do
+ @ftp.send(@method, "test", @tmp_file).should be_nil
+ end
+
+ it "saves the contents of the passed remote file to the passed local file" do
+ @ftp.send(@method, "test", @tmp_file)
+ File.read(@tmp_file).should == "This is the content\nof the file named 'test'.\n"
+ end
+
+ describe "when passed a block" do
+ it "yields each line of the retrieved file to the passed block" do
+ res = []
+ @ftp.send(@method, "test", @tmp_file) { |line| res << line }
+ res.should == [ "This is the content", "of the file named 'test'."]
+ end
+ end
+
+ describe "when the RETR command fails" do
+ it "raises a Net::FTPTempError when the response code is 450" do
+ @server.should_receive(:retr).and_respond("450 Requested file action not taken.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPProtoError when the response code is 550" do
+ @server.should_receive(:retr).and_respond("Requested action not taken.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPProtoError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:retr).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:retr).and_respond("501 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:retr).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:retr).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ describe "when opening the data port fails" do
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:eprt).and_respond("500 Syntax error, command unrecognized.")
+ @server.should_receive(:port).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:eprt).and_respond("501 Syntax error in parameters or arguments.")
+ @server.should_receive(:port).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:eprt).and_respond("421 Service not available, closing control connection.")
+ @server.should_receive(:port).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:eprt).and_respond("530 Not logged in.")
+ @server.should_receive(:port).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, "test", @tmp_file) }.should raise_error(Net::FTPPermError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/shared/last_response_code.rb b/spec/ruby/library/net/ftp/shared/last_response_code.rb
new file mode 100644
index 0000000000..4fe53677db
--- /dev/null
+++ b/spec/ruby/library/net/ftp/shared/last_response_code.rb
@@ -0,0 +1,25 @@
+describe :net_ftp_last_response_code, shared: true do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "returns the response code for the last response" do
+ @server.should_receive(:help).and_respond("200 Command okay.")
+ @ftp.help
+ @ftp.send(@method).should == "200"
+
+ @server.should_receive(:help).and_respond("212 Directory status.")
+ @ftp.help
+ @ftp.send(@method).should == "212"
+ end
+end
diff --git a/spec/ruby/library/net/ftp/shared/list.rb b/spec/ruby/library/net/ftp/shared/list.rb
new file mode 100644
index 0000000000..50ca8ad119
--- /dev/null
+++ b/spec/ruby/library/net/ftp/shared/list.rb
@@ -0,0 +1,104 @@
+describe :net_ftp_list, shared: true do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.passive = false
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ describe "when passed a block" do
+ it "yields each file in the list of files in the passed dir" do
+ expected = [
+ "-rw-r--r-- 1 spec staff 507 17 Jul 18:41 last_response_code.rb",
+ "-rw-r--r-- 1 spec staff 50 17 Jul 18:41 list.rb",
+ "-rw-r--r-- 1 spec staff 48 17 Jul 18:41 pwd.rb"
+ ]
+
+ res = []
+ @ftp.send(@method, "test.folder") { |line| res << line}
+ res.should == expected
+
+ @ftp.last_response.should == "226 transfer complete (LIST test.folder)\n"
+ end
+ end
+
+ describe "when passed no block" do
+ it "returns an Array containing a list of files in the passed dir" do
+ expected = [
+ "-rw-r--r-- 1 spec staff 507 17 Jul 18:41 last_response_code.rb",
+ "-rw-r--r-- 1 spec staff 50 17 Jul 18:41 list.rb",
+ "-rw-r--r-- 1 spec staff 48 17 Jul 18:41 pwd.rb"
+ ]
+
+ @ftp.send(@method, "test.folder").should == expected
+
+ @ftp.last_response.should == "226 transfer complete (LIST test.folder)\n"
+ end
+ end
+
+ describe "when the LIST command fails" do
+ it "raises a Net::FTPTempError when the response code is 450" do
+ @server.should_receive(:list).and_respond("450 Requested file action not taken..")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:list).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:list).and_respond("501 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:list).and_respond("502 Command not implemented.")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:list).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:list).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ describe "when opening the data port fails" do
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:eprt).and_respond("500 Syntax error, command unrecognized.")
+ @server.should_receive(:port).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:eprt).and_respond("501 Syntax error in parameters or arguments.")
+ @server.should_receive(:port).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:eprt).and_respond("421 Service not available, closing control connection.")
+ @server.should_receive(:port).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:eprt).and_respond("530 Not logged in.")
+ @server.should_receive(:port).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method) }.should raise_error(Net::FTPPermError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/shared/putbinaryfile.rb b/spec/ruby/library/net/ftp/shared/putbinaryfile.rb
new file mode 100644
index 0000000000..74eaf320ae
--- /dev/null
+++ b/spec/ruby/library/net/ftp/shared/putbinaryfile.rb
@@ -0,0 +1,167 @@
+describe :net_ftp_putbinaryfile, shared: :true do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @local_fixture_file = File.dirname(__FILE__) + "/../fixtures/putbinaryfile"
+ @remote_tmp_file = tmp("binaryfile", false)
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ @ftp.binary = @binary_mode
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+
+ rm_r @remote_tmp_file
+ end
+
+ it "sends the STOR command to the server" do
+ @ftp.send(@method, @local_fixture_file, "binary")
+ @ftp.last_response.should == "200 OK, Data received. (STOR binary)\n"
+ end
+
+ it "sends the contents of the passed local_file, without modifications" do
+ @ftp.send(@method, @local_fixture_file, "binary")
+
+ remote_lines = File.readlines(@remote_tmp_file)
+ local_lines = File.readlines(@local_fixture_file)
+
+ remote_lines.should == local_lines
+ end
+
+ it "returns nil" do
+ @ftp.send(@method, @local_fixture_file, "binary").should be_nil
+ end
+
+ describe "when passed a block" do
+ it "yields the transmitted content as binary blocks of the passed size" do
+ res = []
+ @ftp.send(@method, @local_fixture_file, "binary", 10) { |x| res << x }
+ res.should == [
+ "This is an", " example f",
+ "ile\nwhich ", "is going t",
+ "o be trans", "mitted\nusi",
+ "ng #putbin", "aryfile.\n"
+ ]
+ end
+ end
+
+ describe "when resuming an existing file" do
+ before :each do
+ File.open(@remote_tmp_file, "w") do |f|
+ f << "This is an example file\n"
+ end
+
+ @ftp.resume = true
+ end
+
+ it "sends the remaining content of the passed local_file to the passed remote_file" do
+ @ftp.send(@method, @local_fixture_file, "binary")
+ File.read(@remote_tmp_file).should == File.read(@local_fixture_file)
+ end
+
+ describe "and the APPE command fails" do
+ it "raises a Net::FTPProtoError when the response code is 550" do
+ @server.should_receive(:appe).and_respond("Requested action not taken.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPProtoError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:appe).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:appe).and_respond("501 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:appe).and_respond("502 Command not implemented.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:appe).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:appe).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+ end
+ end
+
+ describe "when the STOR command fails" do
+ it "raises a Net::FTPPermError when the response code is 532" do
+ @server.should_receive(:stor).and_respond("532 Need account for storing files.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 450" do
+ @server.should_receive(:stor).and_respond("450 Requested file action not taken.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 452" do
+ @server.should_receive(:stor).and_respond("452 Requested action not taken.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 553" do
+ @server.should_receive(:stor).and_respond("553 Requested action not taken.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:stor).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:stor).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:stor).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:stor).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ describe "when opening the data port fails" do
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:eprt).and_respond("500 Syntax error, command unrecognized.")
+ @server.should_receive(:port).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:eprt).and_respond("501 Syntax error in parameters or arguments.")
+ @server.should_receive(:port).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:eprt).and_respond("421 Service not available, closing control connection.")
+ @server.should_receive(:port).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:eprt).and_respond("530 Not logged in.")
+ @server.should_receive(:port).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, @local_fixture_file, "binary") }.should raise_error(Net::FTPPermError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/shared/puttextfile.rb b/spec/ruby/library/net/ftp/shared/puttextfile.rb
new file mode 100644
index 0000000000..9bfdc7c41e
--- /dev/null
+++ b/spec/ruby/library/net/ftp/shared/puttextfile.rb
@@ -0,0 +1,120 @@
+describe :net_ftp_puttextfile, shared: true do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @local_fixture_file = File.dirname(__FILE__) + "/../fixtures/puttextfile"
+ @remote_tmp_file = tmp("textfile", false)
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ @ftp.binary = @binary_mode
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+
+ rm_r @remote_tmp_file
+ end
+
+ it "sends the STOR command to the server" do
+ @ftp.send(@method, @local_fixture_file, "text")
+ @ftp.last_response.should == "200 OK, Data received. (STOR text)\n"
+ end
+
+ it "sends the contents of the passed local_file, using \\r\\n as the newline separator" do
+ @ftp.send(@method, @local_fixture_file, "text")
+
+ remote_lines = open(@remote_tmp_file, "rb") {|f| f.read }
+ local_lines = open(@local_fixture_file, "rb") {|f| f.read }
+
+ remote_lines.should_not == local_lines
+ remote_lines.should == local_lines.gsub("\n", "\r\n")
+ end
+
+ it "returns nil" do
+ @ftp.send(@method, @local_fixture_file, "text").should be_nil
+ end
+
+ describe "when passed a block" do
+ it "yields each transmitted line" do
+ res = []
+ @ftp.send(@method, @local_fixture_file, "text") { |x| res << x }
+ res.should == [
+ "This is an example file\r\n",
+ "which is going to be transmitted\r\n",
+ "using #puttextfile.\r\n"
+ ]
+ end
+ end
+
+ describe "when the STOR command fails" do
+ it "raises a Net::FTPPermError when the response code is 532" do
+ @server.should_receive(:stor).and_respond("532 Need account for storing files.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 450" do
+ @server.should_receive(:stor).and_respond("450 Requested file action not taken.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 452" do
+ @server.should_receive(:stor).and_respond("452 Requested action not taken.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 553" do
+ @server.should_receive(:stor).and_respond("553 Requested action not taken.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:stor).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:stor).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:stor).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:stor).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPPermError)
+ end
+ end
+
+ describe "when opening the data port fails" do
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:eprt).and_respond("500 Syntax error, command unrecognized.")
+ @server.should_receive(:port).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:eprt).and_respond("501 Syntax error in parameters or arguments.")
+ @server.should_receive(:port).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:eprt).and_respond("421 Service not available, closing control connection.")
+ @server.should_receive(:port).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:eprt).and_respond("530 Not logged in.")
+ @server.should_receive(:port).and_respond("530 Not logged in.")
+ lambda { @ftp.send(@method, @local_fixture_file, "text") }.should raise_error(Net::FTPPermError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/shared/pwd.rb b/spec/ruby/library/net/ftp/shared/pwd.rb
new file mode 100644
index 0000000000..951d020f2d
--- /dev/null
+++ b/spec/ruby/library/net/ftp/shared/pwd.rb
@@ -0,0 +1,3 @@
+describe :net_ftp_pwd, shared: true do
+
+end
diff --git a/spec/ruby/library/net/ftp/site_spec.rb b/spec/ruby/library/net/ftp/site_spec.rb
new file mode 100644
index 0000000000..d02b94e899
--- /dev/null
+++ b/spec/ruby/library/net/ftp/site_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#site" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the SITE command with the passed argument to the server" do
+ @ftp.site("param")
+ @ftp.last_response.should == "200 Command okay. (SITE param)\n"
+ end
+
+ it "returns nil" do
+ @ftp.site("param").should be_nil
+ end
+
+ it "does not raise an error when the response code is 202" do
+ @server.should_receive(:site).and_respond("202 Command not implemented, superfluous at this site.")
+ lambda { @ftp.site("param") }.should_not raise_error
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:site).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.site("param") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:site).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.site("param") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:site).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.site("param") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:site).and_respond("530 Requested action not taken.")
+ lambda { @ftp.site("param") }.should raise_error(Net::FTPPermError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/size_spec.rb b/spec/ruby/library/net/ftp/size_spec.rb
new file mode 100644
index 0000000000..a3d5db50b4
--- /dev/null
+++ b/spec/ruby/library/net/ftp/size_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#size" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the SIZE command to the server" do
+ @ftp.size("test.file")
+ @ftp.last_response.should == "213 1024\n"
+ end
+
+ it "returns the size of the passed file as Integer" do
+ @ftp.size("test.file").should eql(1024)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:size).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.size("test.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:size).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.size("test.file") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:size).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.size("test.file") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 550" do
+ @server.should_receive(:size).and_respond("550 Requested action not taken.")
+ lambda { @ftp.size("test.file") }.should raise_error(Net::FTPPermError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/spec_helper.rb b/spec/ruby/library/net/ftp/spec_helper.rb
new file mode 100644
index 0000000000..c87d16218b
--- /dev/null
+++ b/spec/ruby/library/net/ftp/spec_helper.rb
@@ -0,0 +1,5 @@
+require "net/ftp"
+
+if defined?(Net::FTP.default_passive)
+ Net::FTP.default_passive = false
+end
diff --git a/spec/ruby/library/net/ftp/status_spec.rb b/spec/ruby/library/net/ftp/status_spec.rb
new file mode 100644
index 0000000000..7e9927c3c8
--- /dev/null
+++ b/spec/ruby/library/net/ftp/status_spec.rb
@@ -0,0 +1,63 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#status" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the STAT command to the server" do
+ @ftp.status
+ @ftp.last_response.should == "211 System status, or system help reply. (STAT)\n"
+ end
+
+ it "returns the received information" do
+ @ftp.status.should == "211 System status, or system help reply. (STAT)\n"
+ end
+
+ it "does not raise an error when the response code is 212" do
+ @server.should_receive(:stat).and_respond("212 Directory status.")
+ lambda { @ftp.status }.should_not raise_error
+ end
+
+ it "does not raise an error when the response code is 213" do
+ @server.should_receive(:stat).and_respond("213 File status.")
+ lambda { @ftp.status }.should_not raise_error
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:stat).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.status }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:stat).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.status }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:stat).and_respond("502 Command not implemented.")
+ lambda { @ftp.status }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:stat).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.status }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 530" do
+ @server.should_receive(:stat).and_respond("530 Requested action not taken.")
+ lambda { @ftp.status }.should raise_error(Net::FTPPermError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/storbinary_spec.rb b/spec/ruby/library/net/ftp/storbinary_spec.rb
new file mode 100644
index 0000000000..fc7561b5a9
--- /dev/null
+++ b/spec/ruby/library/net/ftp/storbinary_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#storbinary" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @local_fixture_file = File.dirname(__FILE__) + "/fixtures/putbinaryfile"
+ @tmp_file = tmp("binaryfile", false)
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+
+ rm_r @tmp_file
+ end
+
+ it "sends the passed command and the passed File object's content to the server" do
+ File.open(@local_fixture_file) do |f|
+ f.binmode
+
+ @ftp.storbinary("STOR binary", f, 4096) {}
+ @ftp.last_response.should == "200 OK, Data received. (STOR binary)\n"
+ end
+ end
+
+ it "yields the transmitted content as binary blocks of the passed size" do
+ File.open(@local_fixture_file) do |f|
+ f.binmode
+
+ res = []
+ @ftp.storbinary("STOR binary", f, 10) { |x| res << x }
+ res.should == [
+ "This is an", " example f",
+ "ile\nwhich ", "is going t",
+ "o be trans", "mitted\nusi",
+ "ng #putbin", "aryfile.\n"
+ ]
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/storlines_spec.rb b/spec/ruby/library/net/ftp/storlines_spec.rb
new file mode 100644
index 0000000000..9ea4b83603
--- /dev/null
+++ b/spec/ruby/library/net/ftp/storlines_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#storlines" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @local_fixture_file = File.dirname(__FILE__) + "/fixtures/puttextfile"
+ @tmp_file = tmp("textfile", false)
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+
+ rm_r @tmp_file
+ end
+
+ it "sends the passed command and the passed File object's content to the server" do
+ File.open(@local_fixture_file) do |f|
+ @ftp.storlines("STOR text", f) {}
+ @ftp.last_response.should == "200 OK, Data received. (STOR text)\n"
+ end
+ end
+
+ it "yields each line of the transmitted content" do
+ File.open(@local_fixture_file) do |f|
+ res = []
+ @ftp.storlines("STOR text", f) { |x| res << x }
+ res.should == [
+ "This is an example file\r\n",
+ "which is going to be transmitted\r\n",
+ "using #puttextfile.\r\n"
+ ]
+ end
+ end
+end
diff --git a/spec/ruby/library/net/ftp/system_spec.rb b/spec/ruby/library/net/ftp/system_spec.rb
new file mode 100644
index 0000000000..603dd09152
--- /dev/null
+++ b/spec/ruby/library/net/ftp/system_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#system" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the SYST command to the server" do
+ @ftp.system
+ @ftp.last_response.should =~ /\A215 FTP Dummy Server \(SYST\)\Z/
+ end
+
+ it "returns the received information" do
+ @ftp.system.should =~ /\AFTP Dummy Server \(SYST\)\Z/
+ end
+
+ it "raises a Net::FTPPermError when the response code is 500" do
+ @server.should_receive(:syst).and_respond("500 Syntax error, command unrecognized.")
+ lambda { @ftp.system }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 501" do
+ @server.should_receive(:syst).and_respond("501 Syntax error in parameters or arguments.")
+ lambda { @ftp.system }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 502" do
+ @server.should_receive(:syst).and_respond("502 Command not implemented.")
+ lambda { @ftp.system }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 421" do
+ @server.should_receive(:syst).and_respond("421 Service not available, closing control connection.")
+ lambda { @ftp.system }.should raise_error(Net::FTPTempError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/voidcmd_spec.rb b/spec/ruby/library/net/ftp/voidcmd_spec.rb
new file mode 100644
index 0000000000..8b3e0c17c9
--- /dev/null
+++ b/spec/ruby/library/net/ftp/voidcmd_spec.rb
@@ -0,0 +1,54 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#voidcmd" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "sends the passed command to the server" do
+ @server.should_receive(:help).and_respond("2xx Does not raise.")
+ lambda { @ftp.voidcmd("HELP") }.should_not raise_error
+ end
+
+ it "returns nil" do
+ @server.should_receive(:help).and_respond("2xx Does not raise.")
+ @ftp.voidcmd("HELP").should be_nil
+ end
+
+ it "raises a Net::FTPReplyError when the response code is 1xx" do
+ @server.should_receive(:help).and_respond("1xx Does raise a Net::FTPReplyError.")
+ lambda { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPReplyError)
+ end
+
+ it "raises a Net::FTPReplyError when the response code is 3xx" do
+ @server.should_receive(:help).and_respond("3xx Does raise a Net::FTPReplyError.")
+ lambda { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPReplyError)
+ end
+
+ it "raises a Net::FTPTempError when the response code is 4xx" do
+ @server.should_receive(:help).and_respond("4xx Does raise a Net::FTPTempError.")
+ lambda { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPTempError)
+ end
+
+ it "raises a Net::FTPPermError when the response code is 5xx" do
+ @server.should_receive(:help).and_respond("5xx Does raise a Net::FTPPermError.")
+ lambda { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPPermError)
+ end
+
+ it "raises a Net::FTPProtoError when the response code is not valid" do
+ @server.should_receive(:help).and_respond("999 Does raise a Net::FTPProtoError.")
+ lambda { @ftp.voidcmd("HELP") }.should raise_error(Net::FTPProtoError)
+ end
+end
diff --git a/spec/ruby/library/net/ftp/welcome_spec.rb b/spec/ruby/library/net/ftp/welcome_spec.rb
new file mode 100644
index 0000000000..5505623ce3
--- /dev/null
+++ b/spec/ruby/library/net/ftp/welcome_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../spec_helper', __FILE__)
+require File.expand_path('../fixtures/server', __FILE__)
+
+describe "Net::FTP#welcome" do
+ before :each do
+ @server = NetFTPSpecs::DummyFTP.new
+ @server.serve_once
+
+ @ftp = Net::FTP.new
+ @ftp.connect(@server.hostname, @server.server_port)
+ end
+
+ after :each do
+ @ftp.quit rescue nil
+ @ftp.close
+ @server.stop
+ end
+
+ it "returns the server's welcome message" do
+ @ftp.welcome.should be_nil
+ @ftp.login
+ @ftp.welcome.should == "230 User logged in, proceed. (USER anonymous)\n"
+ end
+end
diff --git a/spec/ruby/library/net/http/HTTPBadResponse_spec.rb b/spec/ruby/library/net/http/HTTPBadResponse_spec.rb
new file mode 100644
index 0000000000..78bb0c8420
--- /dev/null
+++ b/spec/ruby/library/net/http/HTTPBadResponse_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPBadResponse" do
+ it "is a subclass of StandardError" do
+ Net::HTTPBadResponse.should < StandardError
+ end
+end
diff --git a/spec/ruby/library/net/http/HTTPError_spec.rb b/spec/ruby/library/net/http/HTTPError_spec.rb
new file mode 100644
index 0000000000..5fa87f140b
--- /dev/null
+++ b/spec/ruby/library/net/http/HTTPError_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPError" do
+ it "is a subclass of Net::ProtocolError" do
+ Net::HTTPError.should < Net::ProtocolError
+ end
+
+ it "includes the Net::HTTPExceptions module" do
+ Net::HTTPError.should < Net::HTTPExceptions
+ end
+end
diff --git a/spec/ruby/library/net/http/HTTPFatalError_spec.rb b/spec/ruby/library/net/http/HTTPFatalError_spec.rb
new file mode 100644
index 0000000000..72468faf8d
--- /dev/null
+++ b/spec/ruby/library/net/http/HTTPFatalError_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPFatalError" do
+ it "is a subclass of Net::ProtoFatalError" do
+ Net::HTTPFatalError.should < Net::ProtoFatalError
+ end
+
+ it "includes the Net::HTTPExceptions module" do
+ Net::HTTPFatalError.should < Net::HTTPExceptions
+ end
+end
diff --git a/spec/ruby/library/net/http/HTTPHeaderSyntaxError_spec.rb b/spec/ruby/library/net/http/HTTPHeaderSyntaxError_spec.rb
new file mode 100644
index 0000000000..3e7ee24365
--- /dev/null
+++ b/spec/ruby/library/net/http/HTTPHeaderSyntaxError_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPHeaderSyntaxError" do
+ it "is a subclass of StandardError" do
+ Net::HTTPHeaderSyntaxError.should < StandardError
+ end
+end
diff --git a/spec/ruby/library/net/http/HTTPRetriableError_spec.rb b/spec/ruby/library/net/http/HTTPRetriableError_spec.rb
new file mode 100644
index 0000000000..71f6bdb196
--- /dev/null
+++ b/spec/ruby/library/net/http/HTTPRetriableError_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPRetriableError" do
+ it "is a subclass of Net::ProtoRetriableError" do
+ Net::HTTPRetriableError.should < Net::ProtoRetriableError
+ end
+
+ it "includes the Net::HTTPExceptions module" do
+ Net::HTTPRetriableError.should < Net::HTTPExceptions
+ end
+end
diff --git a/spec/ruby/library/net/http/HTTPServerException_spec.rb b/spec/ruby/library/net/http/HTTPServerException_spec.rb
new file mode 100644
index 0000000000..35566ab0c5
--- /dev/null
+++ b/spec/ruby/library/net/http/HTTPServerException_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPServerException" do
+ it "is a subclass of Net::ProtoServerError" do
+ Net::HTTPServerException.should < Net::ProtoServerError
+ end
+
+ it "includes the Net::HTTPExceptions module" do
+ Net::HTTPServerException.should < Net::HTTPExceptions
+ end
+end
diff --git a/spec/ruby/library/net/http/http/Proxy_spec.rb b/spec/ruby/library/net/http/http/Proxy_spec.rb
new file mode 100644
index 0000000000..2de3fb2d75
--- /dev/null
+++ b/spec/ruby/library/net/http/http/Proxy_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.Proxy" do
+ it "returns a new subclass of Net::HTTP" do
+ Net::HTTP.Proxy("localhost").should < Net::HTTP
+ end
+
+ it "returns Net::HTTP when the passed address is nil" do
+ Net::HTTP.Proxy(nil).should == Net::HTTP
+ end
+
+ it "sets the returned subclasses' proxy options based on the passed arguments" do
+ http_with_proxy = Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks")
+ http_with_proxy.proxy_address.should == "localhost"
+ http_with_proxy.proxy_port.should eql(1234)
+ http_with_proxy.proxy_user.should == "rspec"
+ http_with_proxy.proxy_pass.should == "rocks"
+ end
+end
+
+describe "Net::HTTP#proxy?" do
+ describe "when self is no proxy class instance" do
+ it "returns false" do
+ Net::HTTP.new("localhost", 3333).proxy?.should be_false
+ end
+ end
+
+ describe "when self is a proxy class instance" do
+ it "returns false" do
+ http_with_proxy = Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks")
+ http_with_proxy.new("localhost", 3333).proxy?.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/active_spec.rb b/spec/ruby/library/net/http/http/active_spec.rb
new file mode 100644
index 0000000000..28f1872fa9
--- /dev/null
+++ b/spec/ruby/library/net/http/http/active_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/started', __FILE__)
+
+describe "Net::HTTP#active?" do
+ it_behaves_like :net_http_started_p, :active?
+end
diff --git a/spec/ruby/library/net/http/http/address_spec.rb b/spec/ruby/library/net/http/http/address_spec.rb
new file mode 100644
index 0000000000..a0fe28fb9e
--- /dev/null
+++ b/spec/ruby/library/net/http/http/address_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP#address" do
+ it "returns the current host name" do
+ net = Net::HTTP.new("localhost")
+ net.address.should == "localhost"
+ end
+end
diff --git a/spec/ruby/library/net/http/http/close_on_empty_response_spec.rb b/spec/ruby/library/net/http/http/close_on_empty_response_spec.rb
new file mode 100644
index 0000000000..52bede524e
--- /dev/null
+++ b/spec/ruby/library/net/http/http/close_on_empty_response_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP#close_on_empty_response" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "Net::HTTP#close_on_empty_response=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/net/http/http/copy_spec.rb b/spec/ruby/library/net/http/http/copy_spec.rb
new file mode 100644
index 0000000000..c3c5e784b1
--- /dev/null
+++ b/spec/ruby/library/net/http/http/copy_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#copy" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends a COPY request to the passed path and returns the response" do
+ response = @http.copy("/request")
+ response.should be_kind_of(Net::HTTPResponse)
+ response.body.should == "Request type: COPY"
+ end
+end
diff --git a/spec/ruby/library/net/http/http/default_port_spec.rb b/spec/ruby/library/net/http/http/default_port_spec.rb
new file mode 100644
index 0000000000..8d9b3ac64a
--- /dev/null
+++ b/spec/ruby/library/net/http/http/default_port_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.default_port" do
+ it "returns 80" do
+ Net::HTTP.http_default_port.should eql(80)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/delete_spec.rb b/spec/ruby/library/net/http/http/delete_spec.rb
new file mode 100644
index 0000000000..856d3b3af3
--- /dev/null
+++ b/spec/ruby/library/net/http/http/delete_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#delete" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends a DELETE request to the passed path and returns the response" do
+ response = @http.delete("/request")
+ response.should be_kind_of(Net::HTTPResponse)
+ response.body.should == "Request type: DELETE"
+ end
+end
diff --git a/spec/ruby/library/net/http/http/finish_spec.rb b/spec/ruby/library/net/http/http/finish_spec.rb
new file mode 100644
index 0000000000..ccc6878961
--- /dev/null
+++ b/spec/ruby/library/net/http/http/finish_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#finish" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.new("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when self has been started" do
+ it "closes the tcp connection" do
+ @http.start
+ @http.finish
+ @http.started?.should be_false
+ end
+ end
+
+ describe "when self has not been started yet" do
+ it "raises an IOError" do
+ lambda { @http.finish }.should raise_error(IOError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/fixtures/http_server.rb b/spec/ruby/library/net/http/http/fixtures/http_server.rb
new file mode 100644
index 0000000000..c2ae2360d3
--- /dev/null
+++ b/spec/ruby/library/net/http/http/fixtures/http_server.rb
@@ -0,0 +1,93 @@
+require 'webrick'
+require 'webrick/httpservlet/abstract'
+
+module NetHTTPSpecs
+ class NullWriter
+ def <<(s) end
+ def puts(*args) end
+ def print(*args) end
+ def printf(*args) end
+ end
+
+ class SpecServlet < WEBrick::HTTPServlet::AbstractServlet
+ def handle(req, res)
+ reply(req, res)
+ end
+
+ %w{ do_GET do_HEAD do_POST do_PUT do_PROPPATCH do_LOCK do_UNLOCK
+ do_OPTIONS do_PROPFIND do_DELETE do_MOVE do_COPY
+ do_MKCOL do_TRACE }.each do |method|
+ alias_method method.to_sym, :handle
+ end
+ end
+
+ class RequestServlet < SpecServlet
+ def reply(req, res)
+ res.content_type = "text/plain"
+ res.body = "Request type: #{req.request_method}"
+ end
+ end
+
+ class RequestBodyServlet < SpecServlet
+ def reply(req, res)
+ res.content_type = "text/plain"
+ res.body = req.body
+ end
+ end
+
+ class RequestHeaderServlet < SpecServlet
+ def reply(req, res)
+ res.content_type = "text/plain"
+ res.body = req.header.inspect
+ end
+ end
+
+ class << self
+ @server = nil
+ @server_thread = nil
+
+ def port
+ raise "server not started" unless @server
+ @server.config[:Port]
+ end
+
+ def start_server
+ server_config = {
+ BindAddress: "localhost",
+ Port: 0,
+ Logger: WEBrick::Log.new(NullWriter.new),
+ AccessLog: [],
+ ServerType: Thread
+ }
+
+ @server = WEBrick::HTTPServer.new(server_config)
+
+ @server.mount_proc('/') do |req, res|
+ res.content_type = "text/plain"
+ res.body = "This is the index page."
+ end
+ @server.mount('/request', RequestServlet)
+ @server.mount("/request/body", RequestBodyServlet)
+ @server.mount("/request/header", RequestHeaderServlet)
+
+ @server_thread = @server.start
+ end
+
+ def stop_server
+ if @server
+ begin
+ @server.shutdown
+ rescue Errno::EPIPE
+ # Because WEBrick is not thread-safe and only catches IOError
+ end
+ @server = nil
+ end
+ if @server_thread
+ @server_thread.join
+ @server_thread = nil
+ end
+ timeout = WEBrick::Utils::TimeoutHandler
+ timeout.terminate if timeout.respond_to?(:terminate)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/get2_spec.rb b/spec/ruby/library/net/http/http/get2_spec.rb
new file mode 100644
index 0000000000..2173156adf
--- /dev/null
+++ b/spec/ruby/library/net/http/http/get2_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/request_get', __FILE__)
+
+describe "Net::HTTP#get2" do
+ it_behaves_like :net_ftp_request_get, :get2
+end
diff --git a/spec/ruby/library/net/http/http/get_print_spec.rb b/spec/ruby/library/net/http/http/get_print_spec.rb
new file mode 100644
index 0000000000..d91a584aaa
--- /dev/null
+++ b/spec/ruby/library/net/http/http/get_print_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP.get_print" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @port = NetHTTPSpecs.port
+ end
+
+ after :each do
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when passed URI" do
+ it "it prints the body of the specified uri to $stdout" do
+ lambda do
+ Net::HTTP.get_print URI.parse("http://localhost:#{@port}/")
+ end.should output(/This is the index page\./)
+ end
+ end
+
+ describe "when passed host, path, port" do
+ it "it prints the body of the specified uri to $stdout" do
+ lambda do
+ Net::HTTP.get_print 'localhost', "/", @port
+ end.should output(/This is the index page\./)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/get_response_spec.rb b/spec/ruby/library/net/http/http/get_response_spec.rb
new file mode 100644
index 0000000000..fdc1ae1f66
--- /dev/null
+++ b/spec/ruby/library/net/http/http/get_response_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP.get_response" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @port = NetHTTPSpecs.port
+ end
+
+ after :each do
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when passed URI" do
+ it "returns the response for the specified uri" do
+ res = Net::HTTP.get_response(URI.parse("http://localhost:#{@port}/"))
+ res.content_type.should == "text/plain"
+ res.body.should == "This is the index page."
+ end
+ end
+
+ describe "when passed host, path, port" do
+ it "returns the response for the specified host-path-combination" do
+ res = Net::HTTP.get_response('localhost', "/", @port)
+ res.content_type.should == "text/plain"
+ res.body.should == "This is the index page."
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/get_spec.rb b/spec/ruby/library/net/http/http/get_spec.rb
new file mode 100644
index 0000000000..d434191d2d
--- /dev/null
+++ b/spec/ruby/library/net/http/http/get_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP.get when passed URI" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @port = NetHTTPSpecs.port
+ end
+
+ after :each do
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when passed URI" do
+ it "returns the body of the specified uri" do
+ Net::HTTP.get(URI.parse("http://localhost:#{@port}/")).should == "This is the index page."
+ end
+ end
+
+ describe "when passed host, path, port" do
+ it "returns the body of the specified host-path-combination" do
+ Net::HTTP.get('localhost', "/", @port).should == "This is the index page."
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/head2_spec.rb b/spec/ruby/library/net/http/http/head2_spec.rb
new file mode 100644
index 0000000000..66d533c84d
--- /dev/null
+++ b/spec/ruby/library/net/http/http/head2_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/request_head', __FILE__)
+
+describe "Net::HTTP#head2" do
+ it_behaves_like :net_ftp_request_head, :head2
+end
+
diff --git a/spec/ruby/library/net/http/http/head_spec.rb b/spec/ruby/library/net/http/http/head_spec.rb
new file mode 100644
index 0000000000..d0d13a6451
--- /dev/null
+++ b/spec/ruby/library/net/http/http/head_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#head" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends a HEAD request to the passed path and returns the response" do
+ response = @http.head("/request")
+ # HEAD requests have no responses
+ response.body.should be_nil
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.head("/request").should be_kind_of(Net::HTTPResponse)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/http_default_port_spec.rb b/spec/ruby/library/net/http/http/http_default_port_spec.rb
new file mode 100644
index 0000000000..6b840bbf30
--- /dev/null
+++ b/spec/ruby/library/net/http/http/http_default_port_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.http_default_port" do
+ it "returns 80" do
+ Net::HTTP.http_default_port.should eql(80)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/https_default_port_spec.rb b/spec/ruby/library/net/http/http/https_default_port_spec.rb
new file mode 100644
index 0000000000..bd213f2325
--- /dev/null
+++ b/spec/ruby/library/net/http/http/https_default_port_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.https_default_port" do
+ it "returns 443" do
+ Net::HTTP.https_default_port.should eql(443)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/initialize_spec.rb b/spec/ruby/library/net/http/http/initialize_spec.rb
new file mode 100644
index 0000000000..0cd59f493d
--- /dev/null
+++ b/spec/ruby/library/net/http/http/initialize_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP#initialize" do
+ it "is private" do
+ Net::HTTP.should have_private_instance_method(:initialize)
+ end
+
+ describe "when passed address" do
+ before :each do
+ @net = Net::HTTP.allocate
+ @net.send(:initialize, "localhost")
+ end
+
+ it "sets the new Net::HTTP instance's address to the passed address" do
+ @net.address.should == "localhost"
+ end
+
+ it "sets the new Net::HTTP instance's port to the default HTTP port" do
+ @net.port.should eql(Net::HTTP.default_port)
+ end
+
+ it "does not start the new Net::HTTP instance" do
+ @net.started?.should be_false
+ end
+ end
+
+ describe "when passed address, port" do
+ before :each do
+ @net = Net::HTTP.allocate
+ @net.send(:initialize, "localhost", 3333)
+ end
+
+ it "sets the new Net::HTTP instance's address to the passed address" do
+ @net.address.should == "localhost"
+ end
+
+ it "sets the new Net::HTTP instance's port to the passed port" do
+ @net.port.should eql(3333)
+ end
+
+ it "does not start the new Net::HTTP instance" do
+ @net.started?.should be_false
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/inspect_spec.rb b/spec/ruby/library/net/http/http/inspect_spec.rb
new file mode 100644
index 0000000000..7c5d9bf0eb
--- /dev/null
+++ b/spec/ruby/library/net/http/http/inspect_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#inspect" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @port = NetHTTPSpecs.port
+ @http = Net::HTTP.new("localhost", @port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "returns a String representation of self" do
+ @http.inspect.should be_kind_of(String)
+ @http.inspect.should == "#<Net::HTTP localhost:#{@port} open=false>"
+
+ @http.start
+ @http.inspect.should == "#<Net::HTTP localhost:#{@port} open=true>"
+ end
+end
diff --git a/spec/ruby/library/net/http/http/is_version_1_1_spec.rb b/spec/ruby/library/net/http/http/is_version_1_1_spec.rb
new file mode 100644
index 0000000000..8fa5da6be7
--- /dev/null
+++ b/spec/ruby/library/net/http/http/is_version_1_1_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../shared/version_1_1', __FILE__)
+
+describe "Net::HTTP.is_version_1_1?" do
+ it_behaves_like :net_http_version_1_1_p, :is_version_1_1?
+end
diff --git a/spec/ruby/library/net/http/http/is_version_1_2_spec.rb b/spec/ruby/library/net/http/http/is_version_1_2_spec.rb
new file mode 100644
index 0000000000..344ac7f7c0
--- /dev/null
+++ b/spec/ruby/library/net/http/http/is_version_1_2_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../shared/version_1_2', __FILE__)
+
+describe "Net::HTTP.is_version_1_2?" do
+ it_behaves_like :net_http_version_1_2_p, :is_version_1_2?
+end
diff --git a/spec/ruby/library/net/http/http/lock_spec.rb b/spec/ruby/library/net/http/http/lock_spec.rb
new file mode 100644
index 0000000000..e44099f9e5
--- /dev/null
+++ b/spec/ruby/library/net/http/http/lock_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#lock" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends a LOCK request to the passed path and returns the response" do
+ response = @http.lock("/request", "test=test")
+ response.should be_kind_of(Net::HTTPResponse)
+ response.body.should == "Request type: LOCK"
+ end
+end
diff --git a/spec/ruby/library/net/http/http/mkcol_spec.rb b/spec/ruby/library/net/http/http/mkcol_spec.rb
new file mode 100644
index 0000000000..51b0a5b9c0
--- /dev/null
+++ b/spec/ruby/library/net/http/http/mkcol_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#mkcol" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends a MKCOL request to the passed path and returns the response" do
+ response = @http.mkcol("/request")
+ response.should be_kind_of(Net::HTTPResponse)
+ response.body.should == "Request type: MKCOL"
+ end
+end
diff --git a/spec/ruby/library/net/http/http/move_spec.rb b/spec/ruby/library/net/http/http/move_spec.rb
new file mode 100644
index 0000000000..0aa00195f8
--- /dev/null
+++ b/spec/ruby/library/net/http/http/move_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#head" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends a MOVE request to the passed path and returns the response" do
+ response = @http.move("/request")
+ # HEAD requests have no responses
+ response.body.should == "Request type: MOVE"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.move("/request").should be_kind_of(Net::HTTPResponse)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/new_spec.rb b/spec/ruby/library/net/http/http/new_spec.rb
new file mode 100644
index 0000000000..b741eb0a4c
--- /dev/null
+++ b/spec/ruby/library/net/http/http/new_spec.rb
@@ -0,0 +1,86 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.new" do
+ describe "when passed address" do
+ before :each do
+ @http = Net::HTTP.new("localhost")
+ end
+
+ it "returns a Net::HTTP instance" do
+ @http.proxy?.should be_false
+ @http.instance_of?(Net::HTTP).should be_true
+ end
+
+ it "sets the new Net::HTTP instance's address to the passed address" do
+ @http.address.should == "localhost"
+ end
+
+ it "sets the new Net::HTTP instance's port to the default HTTP port" do
+ @http.port.should eql(Net::HTTP.default_port)
+ end
+
+ it "does not start the new Net::HTTP instance" do
+ @http.started?.should be_false
+ end
+ end
+
+ describe "when passed address, port" do
+ before :each do
+ @http = Net::HTTP.new("localhost", 3333)
+ end
+
+ it "returns a Net::HTTP instance" do
+ @http.proxy?.should be_false
+ @http.instance_of?(Net::HTTP).should be_true
+ end
+
+ it "sets the new Net::HTTP instance's address to the passed address" do
+ @http.address.should == "localhost"
+ end
+
+ it "sets the new Net::HTTP instance's port to the passed port" do
+ @http.port.should eql(3333)
+ end
+
+ it "does not start the new Net::HTTP instance" do
+ @http.started?.should be_false
+ end
+ end
+
+ describe "when passed address, port, *proxy_options" do
+ it "returns a Net::HTTP instance" do
+ http = Net::HTTP.new("localhost", 3333, "localhost")
+ http.proxy?.should be_true
+ http.instance_of?(Net::HTTP).should be_true
+ http.should be_kind_of(Net::HTTP)
+ end
+
+ it "correctly sets the passed Proxy options" do
+ http = Net::HTTP.new("localhost", 3333, "localhost")
+ http.proxy_address.should == "localhost"
+ http.proxy_port.should eql(80)
+ http.proxy_user.should be_nil
+ http.proxy_pass.should be_nil
+
+ http = Net::HTTP.new("localhost", 3333, "localhost", 1234)
+ http.proxy_address.should == "localhost"
+ http.proxy_port.should eql(1234)
+ http.proxy_user.should be_nil
+ http.proxy_pass.should be_nil
+
+ http = Net::HTTP.new("localhost", 3333, "localhost", 1234, "rubyspec")
+ http.proxy_address.should == "localhost"
+ http.proxy_port.should eql(1234)
+ http.proxy_user.should == "rubyspec"
+ http.proxy_pass.should be_nil
+
+ http = Net::HTTP.new("localhost", 3333, "localhost", 1234, "rubyspec", "rocks")
+ http.proxy_address.should == "localhost"
+ http.proxy_port.should eql(1234)
+ http.proxy_user.should == "rubyspec"
+ http.proxy_pass.should == "rocks"
+ end
+ end
+
+end
diff --git a/spec/ruby/library/net/http/http/newobj_spec.rb b/spec/ruby/library/net/http/http/newobj_spec.rb
new file mode 100644
index 0000000000..88d5881725
--- /dev/null
+++ b/spec/ruby/library/net/http/http/newobj_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.newobj" do
+ before :each do
+ @net = Net::HTTP.newobj("localhost")
+ end
+
+ describe "when passed address" do
+ it "returns a new Net::HTTP instance" do
+ @net.should be_kind_of(Net::HTTP)
+ end
+
+ it "sets the new Net::HTTP instance's address to the passed address" do
+ @net.address.should == "localhost"
+ end
+
+ it "sets the new Net::HTTP instance's port to the default HTTP port" do
+ @net.port.should eql(Net::HTTP.default_port)
+ end
+
+ it "does not start the new Net::HTTP instance" do
+ @net.started?.should be_false
+ end
+ end
+
+ describe "when passed address, port" do
+ before :each do
+ @net = Net::HTTP.newobj("localhost", 3333)
+ end
+
+ it "returns a new Net::HTTP instance" do
+ @net.should be_kind_of(Net::HTTP)
+ end
+
+ it "sets the new Net::HTTP instance's address to the passed address" do
+ @net.address.should == "localhost"
+ end
+
+ it "sets the new Net::HTTP instance's port to the passed port" do
+ @net.port.should eql(3333)
+ end
+
+ it "does not start the new Net::HTTP instance" do
+ @net.started?.should be_false
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/open_timeout_spec.rb b/spec/ruby/library/net/http/http/open_timeout_spec.rb
new file mode 100644
index 0000000000..0142ae6c06
--- /dev/null
+++ b/spec/ruby/library/net/http/http/open_timeout_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP#open_timeout" do
+ ruby_version_is ""..."2.3" do
+ it "returns the seconds to wait till the connection is open" do
+ net = Net::HTTP.new("localhost")
+ net.open_timeout.should be_nil
+ net.open_timeout = 10
+ net.open_timeout.should eql(10)
+ end
+ end
+
+ ruby_version_is "2.3" do
+ it "returns the seconds to wait till the connection is open" do
+ net = Net::HTTP.new("localhost")
+ net.open_timeout.should eql(60)
+ net.open_timeout = 10
+ net.open_timeout.should eql(10)
+ end
+ end
+end
+
+describe "Net::HTTP#open_timeout=" do
+ it "sets the seconds to wait till the connection is open" do
+ net = Net::HTTP.new("localhost")
+ net.open_timeout = 10
+ net.open_timeout.should eql(10)
+ end
+
+ it "returns the newly set value" do
+ net = Net::HTTP.new("localhost")
+ (net.open_timeout = 10).should eql(10)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/options_spec.rb b/spec/ruby/library/net/http/http/options_spec.rb
new file mode 100644
index 0000000000..9c5e810105
--- /dev/null
+++ b/spec/ruby/library/net/http/http/options_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#options" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends an options request to the passed path and returns the response" do
+ response = @http.options("/request")
+
+ response.body.should == "Request type: OPTIONS"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.options("/request").should be_kind_of(Net::HTTPResponse)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/port_spec.rb b/spec/ruby/library/net/http/http/port_spec.rb
new file mode 100644
index 0000000000..a916f722bf
--- /dev/null
+++ b/spec/ruby/library/net/http/http/port_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP#port" do
+ it "returns the current port number" do
+ net = Net::HTTP.new("localhost", 3333)
+ net.port.should eql(3333)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/post2_spec.rb b/spec/ruby/library/net/http/http/post2_spec.rb
new file mode 100644
index 0000000000..298b2277bc
--- /dev/null
+++ b/spec/ruby/library/net/http/http/post2_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/request_post', __FILE__)
+
+describe "Net::HTTP#post2" do
+ it_behaves_like :net_ftp_request_post, :post2
+end
diff --git a/spec/ruby/library/net/http/http/post_form_spec.rb b/spec/ruby/library/net/http/http/post_form_spec.rb
new file mode 100644
index 0000000000..4a5d7ec731
--- /dev/null
+++ b/spec/ruby/library/net/http/http/post_form_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP.post_form when passed URI" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @port = NetHTTPSpecs.port
+ end
+
+ after :each do
+ NetHTTPSpecs.stop_server
+ end
+
+ it "POSTs the passed form data to the given uri" do
+ uri = URI.parse("http://localhost:#{@port}/request/body")
+ data = { test: :data }
+
+ res = Net::HTTP.post_form(uri, data)
+ res.body.should == "test=data"
+ end
+end
diff --git a/spec/ruby/library/net/http/http/post_spec.rb b/spec/ruby/library/net/http/http/post_spec.rb
new file mode 100644
index 0000000000..a50663a01d
--- /dev/null
+++ b/spec/ruby/library/net/http/http/post_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#post" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends an post request to the passed path and returns the response" do
+ response = @http.post("/request", "test=test")
+ response.body.should == "Request type: POST"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.post("/request", "test=test").should be_kind_of(Net::HTTPResponse)
+ end
+
+ describe "when passed a block" do
+ it "yields fragments of the response body to the passed block" do
+ str = ""
+ @http.post("/request", "test=test") do |res|
+ str << res
+ end
+ str.should == "Request type: POST"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.post("/request", "test=test") {}.should be_kind_of(Net::HTTPResponse)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/propfind_spec.rb b/spec/ruby/library/net/http/http/propfind_spec.rb
new file mode 100644
index 0000000000..c242eeec68
--- /dev/null
+++ b/spec/ruby/library/net/http/http/propfind_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#propfind" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends an propfind request to the passed path and returns the response" do
+ response = @http.propfind("/request", "test=test")
+ response.body.should == "Request type: PROPFIND"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.propfind("/request", "test=test").should be_kind_of(Net::HTTPResponse)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/proppatch_spec.rb b/spec/ruby/library/net/http/http/proppatch_spec.rb
new file mode 100644
index 0000000000..8567f60719
--- /dev/null
+++ b/spec/ruby/library/net/http/http/proppatch_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#proppatch" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends an proppatch request to the passed path and returns the response" do
+ response = @http.proppatch("/request", "test=test")
+ response.body.should == "Request type: PROPPATCH"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.proppatch("/request", "test=test").should be_kind_of(Net::HTTPResponse)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/proxy_address_spec.rb b/spec/ruby/library/net/http/http/proxy_address_spec.rb
new file mode 100644
index 0000000000..85f8dfedb4
--- /dev/null
+++ b/spec/ruby/library/net/http/http/proxy_address_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.proxy_address" do
+ describe "when self is no proxy class" do
+ it "returns nil" do
+ Net::HTTP.proxy_address.should be_nil
+ end
+ end
+
+ describe "when self is a proxy class" do
+ it "returns the address for self's proxy connection" do
+ Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks").proxy_address.should == "localhost"
+ end
+ end
+end
+
+describe "Net::HTTP#proxy_address" do
+ describe "when self is no proxy class instance" do
+ it "returns nil" do
+ Net::HTTP.new("localhost", 3333).proxy_address.should be_nil
+ end
+ end
+
+ describe "when self is a proxy class instance" do
+ it "returns the password for self's proxy connection" do
+ http_with_proxy = Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks")
+ http_with_proxy.new("localhost", 3333).proxy_address.should == "localhost"
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/proxy_class_spec.rb b/spec/ruby/library/net/http/http/proxy_class_spec.rb
new file mode 100644
index 0000000000..30d38a93e7
--- /dev/null
+++ b/spec/ruby/library/net/http/http/proxy_class_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.proxy_class?" do
+ it "returns true if sels is a class created with Net::HTTP.Proxy" do
+ Net::HTTP.proxy_class?.should be_false
+ Net::HTTP.Proxy("localhost").proxy_class?.should be_true
+ end
+end
diff --git a/spec/ruby/library/net/http/http/proxy_pass_spec.rb b/spec/ruby/library/net/http/http/proxy_pass_spec.rb
new file mode 100644
index 0000000000..09db6f2877
--- /dev/null
+++ b/spec/ruby/library/net/http/http/proxy_pass_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.proxy_pass" do
+ describe "when self is no proxy class" do
+ it "returns nil" do
+ Net::HTTP.proxy_pass.should be_nil
+ end
+ end
+
+ describe "when self is a proxy class" do
+ it "returns nil if no password was set for self's proxy connection" do
+ Net::HTTP.Proxy("localhost").proxy_pass.should be_nil
+ end
+
+ it "returns the password for self's proxy connection" do
+ Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks").proxy_pass.should == "rocks"
+ end
+ end
+end
+
+describe "Net::HTTP#proxy_pass" do
+ describe "when self is no proxy class instance" do
+ it "returns nil" do
+ Net::HTTP.new("localhost", 3333).proxy_pass.should be_nil
+ end
+ end
+
+ describe "when self is a proxy class instance" do
+ it "returns nil if no password was set for self's proxy connection" do
+ Net::HTTP.Proxy("localhost").new("localhost", 3333).proxy_pass.should be_nil
+ end
+
+ it "returns the password for self's proxy connection" do
+ http_with_proxy = Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks")
+ http_with_proxy.new("localhost", 3333).proxy_pass.should == "rocks"
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/proxy_port_spec.rb b/spec/ruby/library/net/http/http/proxy_port_spec.rb
new file mode 100644
index 0000000000..0655232c6b
--- /dev/null
+++ b/spec/ruby/library/net/http/http/proxy_port_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.proxy_port" do
+ describe "when self is no proxy class" do
+ it "returns nil" do
+ Net::HTTP.proxy_port.should be_nil
+ end
+ end
+
+ describe "when self is a proxy class" do
+ it "returns 80 if no port was set for self's proxy connection" do
+ Net::HTTP.Proxy("localhost").proxy_port.should eql(80)
+ end
+
+ it "returns the port for self's proxy connection" do
+ Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks").proxy_port.should eql(1234)
+ end
+ end
+end
+
+describe "Net::HTTP#proxy_port" do
+ describe "when self is no proxy class instance" do
+ it "returns nil" do
+ Net::HTTP.new("localhost", 3333).proxy_port.should be_nil
+ end
+ end
+
+ describe "when self is a proxy class instance" do
+ it "returns 80 if no port was set for self's proxy connection" do
+ Net::HTTP.Proxy("localhost").new("localhost", 3333).proxy_port.should eql(80)
+ end
+
+ it "returns the port for self's proxy connection" do
+ http_with_proxy = Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks")
+ http_with_proxy.new("localhost", 3333).proxy_port.should eql(1234)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/proxy_user_spec.rb b/spec/ruby/library/net/http/http/proxy_user_spec.rb
new file mode 100644
index 0000000000..1beacca642
--- /dev/null
+++ b/spec/ruby/library/net/http/http/proxy_user_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.proxy_user" do
+ describe "when self is no proxy class" do
+ it "returns nil" do
+ Net::HTTP.proxy_user.should be_nil
+ end
+ end
+
+ describe "when self is a proxy class" do
+ it "returns nil if no username was set for self's proxy connection" do
+ Net::HTTP.Proxy("localhost").proxy_user.should be_nil
+ end
+
+ it "returns the username for self's proxy connection" do
+ Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks").proxy_user.should == "rspec"
+ end
+ end
+end
+
+describe "Net::HTTP#proxy_user" do
+ describe "when self is no proxy class instance" do
+ it "returns nil" do
+ Net::HTTP.new("localhost", 3333).proxy_user.should be_nil
+ end
+ end
+
+ describe "when self is a proxy class instance" do
+ it "returns nil if no username was set for self's proxy connection" do
+ Net::HTTP.Proxy("localhost").new("localhost", 3333).proxy_user.should be_nil
+ end
+
+ it "returns the username for self's proxy connection" do
+ http_with_proxy = Net::HTTP.Proxy("localhost", 1234, "rspec", "rocks")
+ http_with_proxy.new("localhost", 3333).proxy_user.should == "rspec"
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/put2_spec.rb b/spec/ruby/library/net/http/http/put2_spec.rb
new file mode 100644
index 0000000000..a0e832d170
--- /dev/null
+++ b/spec/ruby/library/net/http/http/put2_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/request_put', __FILE__)
+
+describe "Net::HTTP#put2" do
+ it_behaves_like :net_ftp_request_put, :put2
+end
diff --git a/spec/ruby/library/net/http/http/put_spec.rb b/spec/ruby/library/net/http/http/put_spec.rb
new file mode 100644
index 0000000000..ab7e794db0
--- /dev/null
+++ b/spec/ruby/library/net/http/http/put_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#put" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends an put request to the passed path and returns the response" do
+ response = @http.put("/request", "test=test")
+ response.body.should == "Request type: PUT"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.put("/request", "test=test").should be_kind_of(Net::HTTPResponse)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/read_timeout_spec.rb b/spec/ruby/library/net/http/http/read_timeout_spec.rb
new file mode 100644
index 0000000000..86f2e0246d
--- /dev/null
+++ b/spec/ruby/library/net/http/http/read_timeout_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP#read_timeout" do
+ it "returns the seconds to wait until reading one block" do
+ net = Net::HTTP.new("localhost")
+ net.read_timeout.should eql(60)
+ net.read_timeout = 10
+ net.read_timeout.should eql(10)
+ end
+end
+
+describe "Net::HTTP#read_timeout=" do
+ it "sets the seconds to wait till the connection is open" do
+ net = Net::HTTP.new("localhost")
+ net.read_timeout = 10
+ net.read_timeout.should eql(10)
+ end
+
+ it "returns the newly set value" do
+ net = Net::HTTP.new("localhost")
+ (net.read_timeout = 10).should eql(10)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/request_get_spec.rb b/spec/ruby/library/net/http/http/request_get_spec.rb
new file mode 100644
index 0000000000..33b040c622
--- /dev/null
+++ b/spec/ruby/library/net/http/http/request_get_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/request_get', __FILE__)
+
+describe "Net::HTTP#request_get" do
+ it_behaves_like :net_ftp_request_get, :get2
+end
diff --git a/spec/ruby/library/net/http/http/request_head_spec.rb b/spec/ruby/library/net/http/http/request_head_spec.rb
new file mode 100644
index 0000000000..85ff56dcb5
--- /dev/null
+++ b/spec/ruby/library/net/http/http/request_head_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/request_head', __FILE__)
+
+describe "Net::HTTP#request_head" do
+ it_behaves_like :net_ftp_request_head, :request_head
+end
diff --git a/spec/ruby/library/net/http/http/request_post_spec.rb b/spec/ruby/library/net/http/http/request_post_spec.rb
new file mode 100644
index 0000000000..937b4d5d59
--- /dev/null
+++ b/spec/ruby/library/net/http/http/request_post_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/request_post', __FILE__)
+
+describe "Net::HTTP#request_post" do
+ it_behaves_like :net_ftp_request_post, :request_post
+end
diff --git a/spec/ruby/library/net/http/http/request_put_spec.rb b/spec/ruby/library/net/http/http/request_put_spec.rb
new file mode 100644
index 0000000000..c3a4b6d538
--- /dev/null
+++ b/spec/ruby/library/net/http/http/request_put_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/request_put', __FILE__)
+
+describe "Net::HTTP#request_put" do
+ it_behaves_like :net_ftp_request_put, :request_put
+end
diff --git a/spec/ruby/library/net/http/http/request_spec.rb b/spec/ruby/library/net/http/http/request_spec.rb
new file mode 100644
index 0000000000..d1c754df8c
--- /dev/null
+++ b/spec/ruby/library/net/http/http/request_spec.rb
@@ -0,0 +1,109 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#request" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when passed request_object" do
+ it "makes a HTTP Request based on the passed request_object" do
+ response = @http.request(Net::HTTP::Get.new("/request"), "test=test")
+ response.body.should == "Request type: GET"
+
+ response = @http.request(Net::HTTP::Head.new("/request"), "test=test")
+ response.body.should be_nil
+
+ response = @http.request(Net::HTTP::Post.new("/request"), "test=test")
+ response.body.should == "Request type: POST"
+
+ response = @http.request(Net::HTTP::Put.new("/request"), "test=test")
+ response.body.should == "Request type: PUT"
+
+ response = @http.request(Net::HTTP::Proppatch.new("/request"), "test=test")
+ response.body.should == "Request type: PROPPATCH"
+
+ response = @http.request(Net::HTTP::Lock.new("/request"), "test=test")
+ response.body.should == "Request type: LOCK"
+
+ response = @http.request(Net::HTTP::Unlock.new("/request"), "test=test")
+ response.body.should == "Request type: UNLOCK"
+
+ # TODO: Does not work?
+ #response = @http.request(Net::HTTP::Options.new("/request"), "test=test")
+ #response.body.should be_nil
+
+ response = @http.request(Net::HTTP::Propfind.new("/request"), "test=test")
+ response.body.should == "Request type: PROPFIND"
+
+ response = @http.request(Net::HTTP::Delete.new("/request"), "test=test")
+ response.body.should == "Request type: DELETE"
+
+ response = @http.request(Net::HTTP::Move.new("/request"), "test=test")
+ response.body.should == "Request type: MOVE"
+
+ response = @http.request(Net::HTTP::Copy.new("/request"), "test=test")
+ response.body.should == "Request type: COPY"
+
+ response = @http.request(Net::HTTP::Mkcol.new("/request"), "test=test")
+ response.body.should == "Request type: MKCOL"
+
+ response = @http.request(Net::HTTP::Trace.new("/request"), "test=test")
+ response.body.should == "Request type: TRACE"
+ end
+ end
+
+ describe "when passed request_object and request_body" do
+ it "sends the passed request_body when making the HTTP Request" do
+ response = @http.request(Net::HTTP::Get.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Head.new("/request/body"), "test=test")
+ response.body.should be_nil
+
+ response = @http.request(Net::HTTP::Post.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Put.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Proppatch.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Lock.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Unlock.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ # TODO: Does not work?
+ #response = @http.request(Net::HTTP::Options.new("/request/body"), "test=test")
+ #response.body.should be_nil
+
+ response = @http.request(Net::HTTP::Propfind.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Delete.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Move.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Copy.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Mkcol.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+
+ response = @http.request(Net::HTTP::Trace.new("/request/body"), "test=test")
+ response.body.should == "test=test"
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/request_types_spec.rb b/spec/ruby/library/net/http/http/request_types_spec.rb
new file mode 100644
index 0000000000..8855a7db66
--- /dev/null
+++ b/spec/ruby/library/net/http/http/request_types_spec.rb
@@ -0,0 +1,254 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP::Get" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Get.should < Net::HTTPRequest
+ end
+
+ it "represents the 'GET'-Request-Method" do
+ Net::HTTP::Get::METHOD.should == "GET"
+ end
+
+ it "has no Request Body" do
+ Net::HTTP::Get::REQUEST_HAS_BODY.should be_false
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Get::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Head" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Head.should < Net::HTTPRequest
+ end
+
+ it "represents the 'HEAD'-Request-Method" do
+ Net::HTTP::Head::METHOD.should == "HEAD"
+ end
+
+ it "has no Request Body" do
+ Net::HTTP::Head::REQUEST_HAS_BODY.should be_false
+ end
+
+ it "has no Respone Body" do
+ Net::HTTP::Head::RESPONSE_HAS_BODY.should be_false
+ end
+end
+
+describe "Net::HTTP::Post" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Post.should < Net::HTTPRequest
+ end
+
+ it "represents the 'POST'-Request-Method" do
+ Net::HTTP::Post::METHOD.should == "POST"
+ end
+
+ it "has a Request Body" do
+ Net::HTTP::Post::REQUEST_HAS_BODY.should be_true
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Post::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Put" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Put.should < Net::HTTPRequest
+ end
+
+ it "represents the 'PUT'-Request-Method" do
+ Net::HTTP::Put::METHOD.should == "PUT"
+ end
+
+ it "has a Request Body" do
+ Net::HTTP::Put::REQUEST_HAS_BODY.should be_true
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Put::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Delete" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Delete.should < Net::HTTPRequest
+ end
+
+ it "represents the 'DELETE'-Request-Method" do
+ Net::HTTP::Delete::METHOD.should == "DELETE"
+ end
+
+ it "has no Request Body" do
+ Net::HTTP::Delete::REQUEST_HAS_BODY.should be_false
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Delete::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Options" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Options.should < Net::HTTPRequest
+ end
+
+ it "represents the 'OPTIONS'-Request-Method" do
+ Net::HTTP::Options::METHOD.should == "OPTIONS"
+ end
+
+ it "has no Request Body" do
+ Net::HTTP::Options::REQUEST_HAS_BODY.should be_false
+ end
+
+ it "has no Respone Body" do
+ Net::HTTP::Options::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Trace" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Trace.should < Net::HTTPRequest
+ end
+
+ it "represents the 'TRACE'-Request-Method" do
+ Net::HTTP::Trace::METHOD.should == "TRACE"
+ end
+
+ it "has no Request Body" do
+ Net::HTTP::Trace::REQUEST_HAS_BODY.should be_false
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Trace::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Propfind" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Propfind.should < Net::HTTPRequest
+ end
+
+ it "represents the 'PROPFIND'-Request-Method" do
+ Net::HTTP::Propfind::METHOD.should == "PROPFIND"
+ end
+
+ it "has a Request Body" do
+ Net::HTTP::Propfind::REQUEST_HAS_BODY.should be_true
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Propfind::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Proppatch" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Proppatch.should < Net::HTTPRequest
+ end
+
+ it "represents the 'PROPPATCH'-Request-Method" do
+ Net::HTTP::Proppatch::METHOD.should == "PROPPATCH"
+ end
+
+ it "has a Request Body" do
+ Net::HTTP::Proppatch::REQUEST_HAS_BODY.should be_true
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Proppatch::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Mkcol" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Mkcol.should < Net::HTTPRequest
+ end
+
+ it "represents the 'MKCOL'-Request-Method" do
+ Net::HTTP::Mkcol::METHOD.should == "MKCOL"
+ end
+
+ it "has a Request Body" do
+ Net::HTTP::Mkcol::REQUEST_HAS_BODY.should be_true
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Mkcol::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Copy" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Copy.should < Net::HTTPRequest
+ end
+
+ it "represents the 'COPY'-Request-Method" do
+ Net::HTTP::Copy::METHOD.should == "COPY"
+ end
+
+ it "has no Request Body" do
+ Net::HTTP::Copy::REQUEST_HAS_BODY.should be_false
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Copy::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Move" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Move.should < Net::HTTPRequest
+ end
+
+ it "represents the 'MOVE'-Request-Method" do
+ Net::HTTP::Move::METHOD.should == "MOVE"
+ end
+
+ it "has no Request Body" do
+ Net::HTTP::Move::REQUEST_HAS_BODY.should be_false
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Move::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Lock" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Lock.should < Net::HTTPRequest
+ end
+
+ it "represents the 'LOCK'-Request-Method" do
+ Net::HTTP::Lock::METHOD.should == "LOCK"
+ end
+
+ it "has a Request Body" do
+ Net::HTTP::Lock::REQUEST_HAS_BODY.should be_true
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Lock::RESPONSE_HAS_BODY.should be_true
+ end
+end
+
+describe "Net::HTTP::Unlock" do
+ it "is a subclass of Net::HTTPRequest" do
+ Net::HTTP::Unlock.should < Net::HTTPRequest
+ end
+
+ it "represents the 'UNLOCK'-Request-Method" do
+ Net::HTTP::Unlock::METHOD.should == "UNLOCK"
+ end
+
+ it "has a Request Body" do
+ Net::HTTP::Unlock::REQUEST_HAS_BODY.should be_true
+ end
+
+ it "has a Respone Body" do
+ Net::HTTP::Unlock::RESPONSE_HAS_BODY.should be_true
+ end
+end
diff --git a/spec/ruby/library/net/http/http/send_request_spec.rb b/spec/ruby/library/net/http/http/send_request_spec.rb
new file mode 100644
index 0000000000..5a704496ec
--- /dev/null
+++ b/spec/ruby/library/net/http/http/send_request_spec.rb
@@ -0,0 +1,61 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#send_request" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+
+ # HEAD is special so handled separately
+ @methods = %w[
+ GET POST PUT DELETE
+ OPTIONS
+ PROPFIND PROPPATCH LOCK UNLOCK
+ ]
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ # TODO: Does only work with GET and POST requests
+ describe "when passed type, path" do
+ it "sends a HTTP Request of the passed type to the passed path" do
+ response = @http.send_request("HEAD", "/request")
+ response.body.should be_nil
+
+ @methods.each do |method|
+ response = @http.send_request(method, "/request")
+ response.body.should == "Request type: #{method}"
+ end
+ end
+ end
+
+ describe "when passed type, path, body" do
+ it "sends a HTTP Request with the passed body" do
+ response = @http.send_request("HEAD", "/request/body", "test=test")
+ response.body.should be_nil
+
+ @methods.each do |method|
+ response = @http.send_request(method, "/request/body", "test=test")
+ response.body.should == "test=test"
+ end
+ end
+ end
+
+ describe "when passed type, path, body, headers" do
+ it "sends a HTTP Request with the passed headers" do
+ referer = 'https://www.ruby-lang.org/'.freeze
+
+ response = @http.send_request("HEAD", "/request/header", "test=test", "referer" => referer)
+ response.body.should be_nil
+
+ @methods.each do |method|
+ response = @http.send_request(method, "/request/header", "test=test", "referer" => referer)
+ response.body.should include('"referer"=>["' + referer + '"]')
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/set_debug_output_spec.rb b/spec/ruby/library/net/http/http/set_debug_output_spec.rb
new file mode 100644
index 0000000000..806f468a84
--- /dev/null
+++ b/spec/ruby/library/net/http/http/set_debug_output_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require "stringio"
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#set_debug_output when passed io" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.new("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sets the passed io as output stream for debugging" do
+ io = StringIO.new
+
+ @http.set_debug_output(io)
+ @http.start
+ io.string.should_not be_empty
+ size = io.string.size
+
+ @http.get("/")
+ io.string.size.should > size
+ end
+
+ it "outputs a warning when the connection has already been started" do
+ @http.start
+ lambda { @http.set_debug_output(StringIO.new) }.should complain("Net::HTTP#set_debug_output called after HTTP started\n")
+ end
+end
diff --git a/spec/ruby/library/net/http/http/shared/request_get.rb b/spec/ruby/library/net/http/http/shared/request_get.rb
new file mode 100644
index 0000000000..b0eca665d6
--- /dev/null
+++ b/spec/ruby/library/net/http/http/shared/request_get.rb
@@ -0,0 +1,41 @@
+describe :net_ftp_request_get, shared: true do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when passed no block" do
+ it "sends a GET request to the passed path and returns the response" do
+ response = @http.send(@method, "/request")
+ response.body.should == "Request type: GET"
+ end
+
+ it "returns a Net::HTTPResponse object" do
+ response = @http.send(@method, "/request")
+ response.should be_kind_of(Net::HTTPResponse)
+ end
+ end
+
+ describe "when passed a block" do
+ it "sends a GET request to the passed path and returns the response" do
+ response = @http.send(@method, "/request") {}
+ response.body.should == "Request type: GET"
+ end
+
+ it "yields the response to the passed block" do
+ @http.send(@method, "/request") do |response|
+ response.body.should == "Request type: GET"
+ end
+ end
+
+ it "returns a Net::HTTPResponse object" do
+ response = @http.send(@method, "/request") {}
+ response.should be_kind_of(Net::HTTPResponse)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/shared/request_head.rb b/spec/ruby/library/net/http/http/shared/request_head.rb
new file mode 100644
index 0000000000..0e669de9ac
--- /dev/null
+++ b/spec/ruby/library/net/http/http/shared/request_head.rb
@@ -0,0 +1,41 @@
+describe :net_ftp_request_head, shared: true do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when passed no block" do
+ it "sends a head request to the passed path and returns the response" do
+ response = @http.send(@method, "/request")
+ response.body.should be_nil
+ end
+
+ it "returns a Net::HTTPResponse object" do
+ response = @http.send(@method, "/request")
+ response.should be_kind_of(Net::HTTPResponse)
+ end
+ end
+
+ describe "when passed a block" do
+ it "sends a head request to the passed path and returns the response" do
+ response = @http.send(@method, "/request") {}
+ response.body.should be_nil
+ end
+
+ it "yields the response to the passed block" do
+ @http.send(@method, "/request") do |response|
+ response.body.should be_nil
+ end
+ end
+
+ it "returns a Net::HTTPResponse object" do
+ response = @http.send(@method, "/request") {}
+ response.should be_kind_of(Net::HTTPResponse)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/shared/request_post.rb b/spec/ruby/library/net/http/http/shared/request_post.rb
new file mode 100644
index 0000000000..06c5e139f9
--- /dev/null
+++ b/spec/ruby/library/net/http/http/shared/request_post.rb
@@ -0,0 +1,41 @@
+describe :net_ftp_request_post, shared: true do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when passed no block" do
+ it "sends a post request to the passed path and returns the response" do
+ response = @http.send(@method, "/request", "test=test")
+ response.body.should == "Request type: POST"
+ end
+
+ it "returns a Net::HTTPResponse object" do
+ response = @http.send(@method, "/request", "test=test")
+ response.should be_kind_of(Net::HTTPResponse)
+ end
+ end
+
+ describe "when passed a block" do
+ it "sends a post request to the passed path and returns the response" do
+ response = @http.send(@method, "/request", "test=test") {}
+ response.body.should == "Request type: POST"
+ end
+
+ it "yields the response to the passed block" do
+ @http.send(@method, "/request", "test=test") do |response|
+ response.body.should == "Request type: POST"
+ end
+ end
+
+ it "returns a Net::HTTPResponse object" do
+ response = @http.send(@method, "/request", "test=test") {}
+ response.should be_kind_of(Net::HTTPResponse)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/shared/request_put.rb b/spec/ruby/library/net/http/http/shared/request_put.rb
new file mode 100644
index 0000000000..6ae791d7e7
--- /dev/null
+++ b/spec/ruby/library/net/http/http/shared/request_put.rb
@@ -0,0 +1,41 @@
+describe :net_ftp_request_put, shared: true do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when passed no block" do
+ it "sends a put request to the passed path and returns the response" do
+ response = @http.send(@method, "/request", "test=test")
+ response.body.should == "Request type: PUT"
+ end
+
+ it "returns a Net::HTTPResponse object" do
+ response = @http.send(@method, "/request", "test=test")
+ response.should be_kind_of(Net::HTTPResponse)
+ end
+ end
+
+ describe "when passed a block" do
+ it "sends a put request to the passed path and returns the response" do
+ response = @http.send(@method, "/request", "test=test") {}
+ response.body.should == "Request type: PUT"
+ end
+
+ it "yields the response to the passed block" do
+ @http.send(@method, "/request", "test=test") do |response|
+ response.body.should == "Request type: PUT"
+ end
+ end
+
+ it "returns a Net::HTTPResponse object" do
+ response = @http.send(@method, "/request", "test=test") {}
+ response.should be_kind_of(Net::HTTPResponse)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/shared/started.rb b/spec/ruby/library/net/http/http/shared/started.rb
new file mode 100644
index 0000000000..9ff6272c31
--- /dev/null
+++ b/spec/ruby/library/net/http/http/shared/started.rb
@@ -0,0 +1,26 @@
+describe :net_http_started_p, shared: true do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.new("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "returns true when self has been started" do
+ @http.start
+ @http.send(@method).should be_true
+ end
+
+ it "returns false when self has not been started yet" do
+ @http.send(@method).should be_false
+ end
+
+ it "returns false when self has been stopped again" do
+ @http.start
+ @http.finish
+ @http.send(@method).should be_false
+ end
+end
diff --git a/spec/ruby/library/net/http/http/shared/version_1_1.rb b/spec/ruby/library/net/http/http/shared/version_1_1.rb
new file mode 100644
index 0000000000..db3d6a986d
--- /dev/null
+++ b/spec/ruby/library/net/http/http/shared/version_1_1.rb
@@ -0,0 +1,6 @@
+describe :net_http_version_1_1_p, shared: true do
+ it "returns the state of net/http 1.1 features" do
+ Net::HTTP.version_1_2
+ Net::HTTP.send(@method).should be_false
+ end
+end
diff --git a/spec/ruby/library/net/http/http/shared/version_1_2.rb b/spec/ruby/library/net/http/http/shared/version_1_2.rb
new file mode 100644
index 0000000000..b044182c60
--- /dev/null
+++ b/spec/ruby/library/net/http/http/shared/version_1_2.rb
@@ -0,0 +1,6 @@
+describe :net_http_version_1_2_p, shared: true do
+ it "returns the state of net/http 1.2 features" do
+ Net::HTTP.version_1_2
+ Net::HTTP.send(@method).should be_true
+ end
+end
diff --git a/spec/ruby/library/net/http/http/socket_type_spec.rb b/spec/ruby/library/net/http/http/socket_type_spec.rb
new file mode 100644
index 0000000000..4ec9b68571
--- /dev/null
+++ b/spec/ruby/library/net/http/http/socket_type_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP.socket_type" do
+ it "returns BufferedIO" do
+ Net::HTTP.socket_type.should == Net::BufferedIO
+ end
+end
diff --git a/spec/ruby/library/net/http/http/start_spec.rb b/spec/ruby/library/net/http/http/start_spec.rb
new file mode 100644
index 0000000000..407d57e494
--- /dev/null
+++ b/spec/ruby/library/net/http/http/start_spec.rb
@@ -0,0 +1,111 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP.start" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @port = NetHTTPSpecs.port
+ end
+
+ after :each do
+ NetHTTPSpecs.stop_server
+ end
+
+ describe "when not passed a block" do
+ before :each do
+ @http = Net::HTTP.start("localhost", @port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ end
+
+ it "returns a new Net::HTTP object for the passed address and port" do
+ @http.should be_kind_of(Net::HTTP)
+ @http.address.should == "localhost"
+ @http.port.should == @port
+ end
+
+ it "opens the tcp connection" do
+ @http.started?.should be_true
+ end
+ end
+
+ describe "when passed a block" do
+ it "returns the blocks return value" do
+ Net::HTTP.start("localhost", @port) { :test }.should == :test
+ end
+
+ it "yields the new Net::HTTP object to the block" do
+ yielded = false
+ Net::HTTP.start("localhost", @port) do |net|
+ yielded = true
+ net.should be_kind_of(Net::HTTP)
+ end
+ yielded.should be_true
+ end
+
+ it "opens the tcp connection before yielding" do
+ Net::HTTP.start("localhost", @port) { |http| http.started?.should be_true }
+ end
+
+ it "closes the tcp connection after yielding" do
+ net = nil
+ Net::HTTP.start("localhost", @port) { |x| net = x }
+ net.started?.should be_false
+ end
+ end
+end
+
+describe "Net::HTTP#start" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.new("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "returns self" do
+ @http.start.should equal(@http)
+ end
+
+ it "opens the tcp connection" do
+ @http.start
+ @http.started?.should be_true
+ end
+
+ describe "when self has already been started" do
+ it "raises an IOError" do
+ @http.start
+ lambda { @http.start }.should raise_error(IOError)
+ end
+ end
+
+ describe "when passed a block" do
+ it "returns the blocks return value" do
+ @http.start { :test }.should == :test
+ end
+
+ it "yields the new Net::HTTP object to the block" do
+ yielded = false
+ @http.start do |http|
+ yielded = true
+ http.should equal(@http)
+ end
+ yielded.should be_true
+ end
+
+ it "opens the tcp connection before yielding" do
+ @http.start { |http| http.started?.should be_true }
+ end
+
+ it "closes the tcp connection after yielding" do
+ @http.start { }
+ @http.started?.should be_false
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/http/started_spec.rb b/spec/ruby/library/net/http/http/started_spec.rb
new file mode 100644
index 0000000000..01c17c93c1
--- /dev/null
+++ b/spec/ruby/library/net/http/http/started_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+require File.expand_path('../shared/started', __FILE__)
+
+describe "Net::HTTP#started?" do
+ it_behaves_like :net_http_started_p, :started?
+end
diff --git a/spec/ruby/library/net/http/http/trace_spec.rb b/spec/ruby/library/net/http/http/trace_spec.rb
new file mode 100644
index 0000000000..6cce15fc09
--- /dev/null
+++ b/spec/ruby/library/net/http/http/trace_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#trace" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends a TRACE request to the passed path and returns the response" do
+ response = @http.trace("/request")
+ response.body.should == "Request type: TRACE"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.trace("/request").should be_kind_of(Net::HTTPResponse)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/unlock_spec.rb b/spec/ruby/library/net/http/http/unlock_spec.rb
new file mode 100644
index 0000000000..12df417e1a
--- /dev/null
+++ b/spec/ruby/library/net/http/http/unlock_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/http_server', __FILE__)
+
+describe "Net::HTTP#unlock" do
+ before :each do
+ NetHTTPSpecs.start_server
+ @http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
+ end
+
+ after :each do
+ @http.finish if @http.started?
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends an UNLOCK request to the passed path and returns the response" do
+ response = @http.unlock("/request", "test=test")
+ response.body.should == "Request type: UNLOCK"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ @http.unlock("/request", "test=test").should be_kind_of(Net::HTTPResponse)
+ end
+end
diff --git a/spec/ruby/library/net/http/http/use_ssl_spec.rb b/spec/ruby/library/net/http/http/use_ssl_spec.rb
new file mode 100644
index 0000000000..19d065ed8e
--- /dev/null
+++ b/spec/ruby/library/net/http/http/use_ssl_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTP#use_ssl?" do
+ it "returns false" do
+ http = Net::HTTP.new("localhost")
+ http.use_ssl?.should be_false
+ end
+end
diff --git a/spec/ruby/library/net/http/http/version_1_1_spec.rb b/spec/ruby/library/net/http/http/version_1_1_spec.rb
new file mode 100644
index 0000000000..f13ec9b7f1
--- /dev/null
+++ b/spec/ruby/library/net/http/http/version_1_1_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../shared/version_1_1', __FILE__)
+
+describe "Net::HTTP.version_1_1?" do
+ it_behaves_like :net_http_version_1_1_p, :version_1_1?
+end
diff --git a/spec/ruby/library/net/http/http/version_1_2_spec.rb b/spec/ruby/library/net/http/http/version_1_2_spec.rb
new file mode 100644
index 0000000000..63c2112422
--- /dev/null
+++ b/spec/ruby/library/net/http/http/version_1_2_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../shared/version_1_2', __FILE__)
+
+describe "Net::HTTP.version_1_2" do
+ it "turns on net/http 1.2 features" do
+ Net::HTTP.version_1_2
+
+ Net::HTTP.version_1_2?.should be_true
+ Net::HTTP.version_1_1?.should be_false
+ end
+
+ it "returns true" do
+ Net::HTTP.version_1_2.should be_true
+ end
+end
+
+describe "Net::HTTP.version_1_2?" do
+ it_behaves_like :net_http_version_1_2_p, :version_1_2?
+end
diff --git a/spec/ruby/library/net/http/httpexceptions/fixtures/classes.rb b/spec/ruby/library/net/http/httpexceptions/fixtures/classes.rb
new file mode 100644
index 0000000000..abe8855eff
--- /dev/null
+++ b/spec/ruby/library/net/http/httpexceptions/fixtures/classes.rb
@@ -0,0 +1,5 @@
+module NetHTTPExceptionsSpecs
+ class Simple < StandardError
+ include Net::HTTPExceptions
+ end
+end
diff --git a/spec/ruby/library/net/http/httpexceptions/initialize_spec.rb b/spec/ruby/library/net/http/httpexceptions/initialize_spec.rb
new file mode 100644
index 0000000000..8c0c4934f7
--- /dev/null
+++ b/spec/ruby/library/net/http/httpexceptions/initialize_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPExceptions#initialize when passed message, response" do
+ before :each do
+ @exception = NetHTTPExceptionsSpecs::Simple.new("error message", "a http response")
+ end
+
+ it "calls super with the passed message" do
+ @exception.message.should == "error message"
+ end
+
+ it "sets self's response to the passed response" do
+ @exception.response.should == "a http response"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpexceptions/response_spec.rb b/spec/ruby/library/net/http/httpexceptions/response_spec.rb
new file mode 100644
index 0000000000..becf74bddf
--- /dev/null
+++ b/spec/ruby/library/net/http/httpexceptions/response_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPExceptions#response" do
+ it "returns self's response" do
+ exception = NetHTTPExceptionsSpecs::Simple.new("error message", "a http response")
+ exception.response.should == "a http response"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/body_exist_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/body_exist_spec.rb
new file mode 100644
index 0000000000..cb3565b899
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/body_exist_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPGenericRequest#body_exist?" do
+ it "returns true when the response is expected to have a body" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.body_exist?.should be_true
+
+ request = Net::HTTPGenericRequest.new("POST", true, false, "/some/path")
+ request.body_exist?.should be_false
+ end
+
+ describe "when $VERBOSE is true" do
+ it "emits a warning" do
+ request = Net::HTTPGenericRequest.new("POST", true, false, "/some/path")
+ lambda {
+ $VERBOSE = true
+ request.body_exist?
+ }.should complain(/body_exist\? is obsolete/)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/body_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/body_spec.rb
new file mode 100644
index 0000000000..4aa4fff2bc
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/body_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require "stringio"
+
+describe "Net::HTTPGenericRequest#body" do
+ it "returns self's request body" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.body.should be_nil
+
+ request.body = "Some Content"
+ request.body.should == "Some Content"
+ end
+end
+
+describe "Net::HTTPGenericRequest#body=" do
+ before :each do
+ @request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ end
+
+ it "sets self's body content to the passed String" do
+ @request.body = "Some Content"
+ @request.body.should == "Some Content"
+ end
+
+ it "sets self's body stream to nil" do
+ @request.body_stream = StringIO.new("")
+ @request.body = "Some Content"
+ @request.body_stream.should be_nil
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/body_stream_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/body_stream_spec.rb
new file mode 100644
index 0000000000..df6e02a8c1
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/body_stream_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require "stringio"
+
+describe "Net::HTTPGenericRequest#body_stream" do
+ it "returns self's body stream Object" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.body_stream.should be_nil
+
+ stream = StringIO.new("test")
+ request.body_stream = stream
+ request.body_stream.should equal(stream)
+ end
+end
+
+describe "Net::HTTPGenericRequest#body_stream=" do
+ before :each do
+ @request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ @stream = StringIO.new("test")
+ end
+
+ it "sets self's body stream to the passed Object" do
+ @request.body_stream = @stream
+ @request.body_stream.should equal(@stream)
+ end
+
+ it "sets self's body to nil" do
+ @request.body = "Some Content"
+ @request.body_stream = @stream
+ @request.body.should be_nil
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/exec_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/exec_spec.rb
new file mode 100644
index 0000000000..b3850d6c74
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/exec_spec.rb
@@ -0,0 +1,131 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require "stringio"
+
+describe "Net::HTTPGenericRequest#exec when passed socket, version, path" do
+ before :each do
+ @socket = StringIO.new("")
+ @buffered_socket = Net::BufferedIO.new(@socket)
+ end
+
+ it "executes the request over the socket to the path using the HTTP version" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+
+ request.exec(@buffered_socket, "1.1", "/some/path")
+ str = @socket.string
+
+ str.should =~ %r[POST /some/path HTTP/1.1\r\n]
+ str.should =~ %r[Accept: \*/\*\r\n]
+ str[-4..-1].should == "\r\n\r\n"
+
+ request = Net::HTTPGenericRequest.new("GET", true, true, "/some/path",
+ "Content-Type" => "text/html")
+
+ request.exec(@buffered_socket, "1.0", "/some/other/path")
+ str = @socket.string
+
+ str.should =~ %r[GET /some/other/path HTTP/1.0\r\n]
+ str.should =~ %r[Accept: \*/\*\r\n]
+ str.should =~ %r[Content-Type: text/html\r\n]
+ str[-4..-1].should == "\r\n\r\n"
+ end
+
+ describe "when a request body is set" do
+ it "sets the 'Content-Type' header to 'application/x-www-form-urlencoded' unless the 'Content-Type' header is supplied" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.body = "Some Content"
+
+ request.exec(@buffered_socket, "1.1", "/some/other/path")
+ str = @socket.string
+
+ str.should =~ %r[POST /some/other/path HTTP/1.1\r\n]
+ str.should =~ %r[Accept: \*/\*\r\n]
+ str.should =~ %r[Content-Type: application/x-www-form-urlencoded\r\n]
+ str.should =~ %r[Content-Length: 12\r\n]
+ str[-16..-1].should == "\r\n\r\nSome Content"
+ end
+
+ it "correctly sets the 'Content-Length' header and includes the body" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path",
+ "Content-Type" => "text/html")
+ request.body = "Some Content"
+
+ request.exec(@buffered_socket, "1.1", "/some/other/path")
+ str = @socket.string
+
+ str.should =~ %r[POST /some/other/path HTTP/1.1\r\n]
+ str.should =~ %r[Accept: \*/\*\r\n]
+ str.should =~ %r[Content-Type: text/html\r\n]
+ str.should =~ %r[Content-Length: 12\r\n]
+ str[-16..-1].should == "\r\n\r\nSome Content"
+ end
+ end
+
+ describe "when a body stream is set" do
+ it "sets the 'Content-Type' header to 'application/x-www-form-urlencoded' unless the 'Content-Type' header is supplied" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path",
+ "Content-Length" => "10")
+ request.body_stream = StringIO.new("a" * 20)
+
+ request.exec(@buffered_socket, "1.1", "/some/other/path")
+ str = @socket.string
+
+ str.should =~ %r[POST /some/other/path HTTP/1.1\r\n]
+ str.should =~ %r[Accept: \*/\*\r\n]
+ str.should =~ %r[Content-Type: application/x-www-form-urlencoded\r\n]
+ str.should =~ %r[Content-Length: 10\r\n]
+ str[-24..-1].should == "\r\n\r\naaaaaaaaaaaaaaaaaaaa"
+ end
+
+ it "sends the whole stream, regardless of the 'Content-Length' header" do
+ request = Net::HTTPGenericRequest.new("POST", true, true,"/some/path",
+ "Content-Type" => "text/html",
+ "Content-Length" => "10")
+ request.body_stream = StringIO.new("a" * 20)
+
+ request.exec(@buffered_socket, "1.1", "/some/other/path")
+ str = @socket.string
+
+ str.should =~ %r[POST /some/other/path HTTP/1.1\r\n]
+ str.should =~ %r[Accept: \*/\*\r\n]
+ str.should =~ %r[Content-Type: text/html\r\n]
+ str.should =~ %r[Content-Length: 10\r\n]
+ str[-24..-1].should == "\r\n\r\naaaaaaaaaaaaaaaaaaaa"
+ end
+
+ it "sends the request in chunks when 'Transfer-Encoding' is set to 'chunked'" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path",
+ "Content-Type" => "text/html",
+ "Transfer-Encoding" => "chunked")
+ datasize = 1024 * 10
+ request.body_stream = StringIO.new("a" * datasize)
+
+ request.exec(@buffered_socket, "1.1", "/some/other/path")
+ str = @socket.string
+
+ str.should =~ %r[POST /some/other/path HTTP/1.1\r\n]
+ str.should =~ %r[Accept: \*/\*\r\n]
+ str.should =~ %r[Content-Type: text/html\r\n]
+ str.should =~ %r[Transfer-Encoding: chunked\r\n]
+ str =~ %r[\r\n\r\n]
+ str = $'
+ while datasize > 0
+ chunk_size_line, str = str.split(/\r\n/, 2)
+ chunk_size = chunk_size_line[/\A[0-9A-Fa-f]+/].to_i(16)
+ str.slice!(0, chunk_size).should == 'a' * chunk_size
+ datasize -= chunk_size
+ str.slice!(0, 2).should == "\r\n"
+ end
+ datasize.should == 0
+ str.should == %"0\r\n\r\n"
+ end
+
+ it "raises an ArgumentError when the 'Content-Length' is not set or 'Transfer-Encoding' is not set to 'chunked'" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path",
+ "Content-Type" => "text/html")
+ request.body_stream = StringIO.new("Some Content")
+
+ lambda { request.exec(@buffered_socket, "1.1", "/some/other/path") }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/inspect_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/inspect_spec.rb
new file mode 100644
index 0000000000..269ce4fe52
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/inspect_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPGenericRequest#inspect" do
+ it "returns a String representation of self" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.inspect.should == "#<Net::HTTPGenericRequest POST>"
+
+ request = Net::HTTPGenericRequest.new("GET", false, true, "/some/path")
+ request.inspect.should == "#<Net::HTTPGenericRequest GET>"
+
+ request = Net::HTTPGenericRequest.new("BLA", true, true, "/some/path")
+ request.inspect.should == "#<Net::HTTPGenericRequest BLA>"
+
+ # Subclasses
+ request = Net::HTTP::Get.new("/some/path")
+ request.inspect.should == "#<Net::HTTP::Get GET>"
+
+ request = Net::HTTP::Post.new("/some/path")
+ request.inspect.should == "#<Net::HTTP::Post POST>"
+
+ request = Net::HTTP::Trace.new("/some/path")
+ request.inspect.should == "#<Net::HTTP::Trace TRACE>"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/method_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/method_spec.rb
new file mode 100644
index 0000000000..eef87ff3a7
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/method_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPGenericRequest#method" do
+ it "returns self's request method" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.method.should == "POST"
+
+ request = Net::HTTPGenericRequest.new("GET", false, true, "/some/path")
+ request.method.should == "GET"
+
+ request = Net::HTTPGenericRequest.new("BLA", true, true, "/some/path")
+ request.method.should == "BLA"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/path_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/path_spec.rb
new file mode 100644
index 0000000000..e48d37b0e9
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/path_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPGenericRequest#path" do
+ it "returns self's request path" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.path.should == "/some/path"
+
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/other/path")
+ request.path.should == "/some/other/path"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/request_body_permitted_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/request_body_permitted_spec.rb
new file mode 100644
index 0000000000..1e0b3ab028
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/request_body_permitted_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPGenericRequest#request_body_permitted?" do
+ it "returns true when the request is expected to have a body" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.request_body_permitted?.should be_true
+
+ request = Net::HTTPGenericRequest.new("POST", false, true, "/some/path")
+ request.request_body_permitted?.should be_false
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/response_body_permitted_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/response_body_permitted_spec.rb
new file mode 100644
index 0000000000..ee5a43e637
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/response_body_permitted_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPGenericRequest#response_body_permitted?" do
+ it "returns true when the response is expected to have a body" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.response_body_permitted?.should be_true
+
+ request = Net::HTTPGenericRequest.new("POST", true, false, "/some/path")
+ request.response_body_permitted?.should be_false
+ end
+end
diff --git a/spec/ruby/library/net/http/httpgenericrequest/set_body_internal_spec.rb b/spec/ruby/library/net/http/httpgenericrequest/set_body_internal_spec.rb
new file mode 100644
index 0000000000..bff8646d5a
--- /dev/null
+++ b/spec/ruby/library/net/http/httpgenericrequest/set_body_internal_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPGenericRequest#set_body_internal when passed string" do
+ before :each do
+ @request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ end
+
+ it "sets self's body to the passed string" do
+ @request.set_body_internal("Some Content")
+ @request.body.should == "Some Content"
+ end
+
+ it "raises an ArgumentError when the body or body_stream of self have already been set" do
+ @request.body = "Some Content"
+ lambda { @request.set_body_internal("Some other Content") }.should raise_error(ArgumentError)
+
+ @request.body_stream = "Some Content"
+ lambda { @request.set_body_internal("Some other Content") }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/add_field_spec.rb b/spec/ruby/library/net/http/httpheader/add_field_spec.rb
new file mode 100644
index 0000000000..b736a92694
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/add_field_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#add_field when passed key, value" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "adds the passed value to the header entry with the passed key" do
+ @headers.add_field("My-Header", "a")
+ @headers.get_fields("My-Header").should == ["a"]
+
+ @headers.add_field("My-Header", "b")
+ @headers.get_fields("My-Header").should == ["a", "b"]
+
+ @headers.add_field("My-Header", "c")
+ @headers.get_fields("My-Header").should == ["a", "b", "c"]
+ end
+
+ it "is case-insensitive" do
+ @headers.add_field("My-Header", "a")
+ @headers.get_fields("My-Header").should == ["a"]
+
+ @headers.add_field("my-header", "b")
+ @headers.get_fields("My-Header").should == ["a", "b"]
+
+ @headers.add_field("MY-HEADER", "c")
+ @headers.get_fields("My-Header").should == ["a", "b", "c"]
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/basic_auth_spec.rb b/spec/ruby/library/net/http/httpheader/basic_auth_spec.rb
new file mode 100644
index 0000000000..b9ed792d46
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/basic_auth_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#basic_auth when passed account, password" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "sets the 'Authorization' Header entry for basic authorization" do
+ @headers.basic_auth("rubyspec", "rocks")
+ @headers["Authorization"].should == "Basic cnVieXNwZWM6cm9ja3M="
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/canonical_each_spec.rb b/spec/ruby/library/net/http/httpheader/canonical_each_spec.rb
new file mode 100644
index 0000000000..a891c12d80
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/canonical_each_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/each_capitalized', __FILE__)
+
+describe "Net::HTTPHeader#canonical_each" do
+ it_behaves_like :net_httpheader_each_capitalized, :canonical_each
+end
diff --git a/spec/ruby/library/net/http/httpheader/chunked_spec.rb b/spec/ruby/library/net/http/httpheader/chunked_spec.rb
new file mode 100644
index 0000000000..2b08baf34c
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/chunked_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#chunked?" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns true if the 'Transfer-Encoding' header entry is set to chunked" do
+ @headers.chunked?.should be_false
+
+ @headers["Transfer-Encoding"] = "bla"
+ @headers.chunked?.should be_false
+
+ @headers["Transfer-Encoding"] = "blachunkedbla"
+ @headers.chunked?.should be_false
+
+ @headers["Transfer-Encoding"] = "chunked"
+ @headers.chunked?.should be_true
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/content_length_spec.rb b/spec/ruby/library/net/http/httpheader/content_length_spec.rb
new file mode 100644
index 0000000000..009eafde85
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/content_length_spec.rb
@@ -0,0 +1,54 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#content_length" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns nil if no 'Content-Length' header entry is set" do
+ @headers.content_length.should be_nil
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when the 'Content-Length' header entry has an invalid format" do
+ @headers["Content-Length"] = "invalid"
+ lambda { @headers.content_length }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+
+ it "returns the value of the 'Content-Length' header entry as an Integer" do
+ @headers["Content-Length"] = "123"
+ @headers.content_length.should eql(123)
+
+ @headers["Content-Length"] = "123valid"
+ @headers.content_length.should eql(123)
+
+ @headers["Content-Length"] = "valid123"
+ @headers.content_length.should eql(123)
+ end
+end
+
+describe "Net::HTTPHeader#content_length=" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "removes the 'Content-Length' entry if passed false or nil" do
+ @headers["Content-Length"] = "123"
+ @headers.content_length = nil
+ @headers["Content-Lenght"].should be_nil
+ end
+
+ it "sets the 'Content-Length' entry to the passed value" do
+ @headers.content_length = "123"
+ @headers["Content-Length"].should == "123"
+
+ @headers.content_length = "123valid"
+ @headers["Content-Length"].should == "123"
+ end
+
+ it "sets the 'Content-Length' entry to 0 if the passed value is not valid" do
+ @headers.content_length = "invalid123"
+ @headers["Content-Length"].should == "0"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/content_range_spec.rb b/spec/ruby/library/net/http/httpheader/content_range_spec.rb
new file mode 100644
index 0000000000..dc601fb365
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/content_range_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#content_range" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns a Range object that represents the 'Content-Range' header entry" do
+ @headers["Content-Range"] = "bytes 0-499/1234"
+ @headers.content_range.should == (0..499)
+
+ @headers["Content-Range"] = "bytes 500-1233/1234"
+ @headers.content_range.should == (500..1233)
+ end
+
+ it "returns nil when there is no 'Content-Range' header entry" do
+ @headers.content_range.should be_nil
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when the 'Content-Range' has an invalid format" do
+ @headers["Content-Range"] = "invalid"
+ lambda { @headers.content_range }.should raise_error(Net::HTTPHeaderSyntaxError)
+
+ @headers["Content-Range"] = "bytes 123-abc"
+ lambda { @headers.content_range }.should raise_error(Net::HTTPHeaderSyntaxError)
+
+ @headers["Content-Range"] = "bytes abc-123"
+ lambda { @headers.content_range }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/content_type_spec.rb b/spec/ruby/library/net/http/httpheader/content_type_spec.rb
new file mode 100644
index 0000000000..7c3dfba7e7
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/content_type_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/set_content_type', __FILE__)
+
+describe "Net::HTTPHeader#content_type" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns the content type string, as per 'Content-Type' header entry" do
+ @headers["Content-Type"] = "text/html"
+ @headers.content_type.should == "text/html"
+
+ @headers["Content-Type"] = "text/html;charset=utf-8"
+ @headers.content_type.should == "text/html"
+ end
+
+ it "returns nil if the 'Content-Type' header entry does not exist" do
+ @headers.content_type.should be_nil
+ end
+end
+
+describe "Net::HTTPHeader#content_type=" do
+ it_behaves_like :net_httpheader_set_content_type, :content_type=
+end
diff --git a/spec/ruby/library/net/http/httpheader/delete_spec.rb b/spec/ruby/library/net/http/httpheader/delete_spec.rb
new file mode 100644
index 0000000000..9adbfd7813
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/delete_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#delete when passed key" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "removes the header entry with the passed key" do
+ @headers["My-Header"] = "test"
+ @headers.delete("My-Header")
+
+ @headers["My-Header"].should be_nil
+ @headers.size.should eql(0)
+ end
+
+ it "returns the removed values" do
+ @headers["My-Header"] = "test"
+ @headers.delete("My-Header").should == ["test"]
+ end
+
+ it "is case-insensitive" do
+ @headers["My-Header"] = "test"
+ @headers.delete("my-header")
+
+ @headers["My-Header"].should be_nil
+ @headers.size.should eql(0)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/each_capitalized_name_spec.rb b/spec/ruby/library/net/http/httpheader/each_capitalized_name_spec.rb
new file mode 100644
index 0000000000..7adba9dec5
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/each_capitalized_name_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#each_capitalized_name" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ @headers["My-Header"] = "test"
+ @headers.add_field("My-Other-Header", "a")
+ @headers.add_field("My-Other-Header", "b")
+ end
+
+ describe "when passed a block" do
+ it "yields each header key to the passed block (keys capitalized)" do
+ res = []
+ @headers.each_capitalized_name do |key|
+ res << key
+ end
+ res.sort.should == ["My-Header", "My-Other-Header"]
+ end
+ end
+
+ describe "when passed no block" do
+ it "returns an Enumerator" do
+ enumerator = @headers.each_capitalized_name
+ enumerator.should be_an_instance_of(Enumerator)
+
+ res = []
+ enumerator.each do |key|
+ res << key
+ end
+ res.sort.should == ["My-Header", "My-Other-Header"]
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/each_capitalized_spec.rb b/spec/ruby/library/net/http/httpheader/each_capitalized_spec.rb
new file mode 100644
index 0000000000..1dcf18a9d1
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/each_capitalized_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/each_capitalized', __FILE__)
+
+describe "Net::HTTPHeader#each_capitalized" do
+ it_behaves_like :net_httpheader_each_capitalized, :each_capitalized
+end
+
diff --git a/spec/ruby/library/net/http/httpheader/each_header_spec.rb b/spec/ruby/library/net/http/httpheader/each_header_spec.rb
new file mode 100644
index 0000000000..00d5894282
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/each_header_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/each_header', __FILE__)
+
+describe "Net::HTTPHeader#each_header" do
+ it_behaves_like :net_httpheader_each_header, :each_header
+end
diff --git a/spec/ruby/library/net/http/httpheader/each_key_spec.rb b/spec/ruby/library/net/http/httpheader/each_key_spec.rb
new file mode 100644
index 0000000000..5c81830be6
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/each_key_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/each_name', __FILE__)
+
+describe "Net::HTTPHeader#each_key" do
+ it_behaves_like :net_httpheader_each_name, :each_key
+end
diff --git a/spec/ruby/library/net/http/httpheader/each_name_spec.rb b/spec/ruby/library/net/http/httpheader/each_name_spec.rb
new file mode 100644
index 0000000000..e785ae249a
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/each_name_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/each_name', __FILE__)
+
+describe "Net::HTTPHeader#each_name" do
+ it_behaves_like :net_httpheader_each_name, :each_name
+end
diff --git a/spec/ruby/library/net/http/httpheader/each_spec.rb b/spec/ruby/library/net/http/httpheader/each_spec.rb
new file mode 100644
index 0000000000..e8fb6713c3
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/each_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/each_header', __FILE__)
+
+describe "Net::HTTPHeader#each" do
+ it_behaves_like :net_httpheader_each_header, :each
+end
diff --git a/spec/ruby/library/net/http/httpheader/each_value_spec.rb b/spec/ruby/library/net/http/httpheader/each_value_spec.rb
new file mode 100644
index 0000000000..1adb723a53
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/each_value_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#each_value" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ @headers["My-Header"] = "test"
+ @headers.add_field("My-Other-Header", "a")
+ @headers.add_field("My-Other-Header", "b")
+ end
+
+ describe "when passed a block" do
+ it "yields each header entry's joined values" do
+ res = []
+ @headers.each_value do |value|
+ res << value
+ end
+ res.sort.should == ["a, b", "test"]
+ end
+ end
+
+ describe "when passed no block" do
+ it "returns an Enumerator" do
+ enumerator = @headers.each_value
+ enumerator.should be_an_instance_of(Enumerator)
+
+ res = []
+ enumerator.each do |key|
+ res << key
+ end
+ res.sort.should == ["a, b", "test"]
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/element_reference_spec.rb b/spec/ruby/library/net/http/httpheader/element_reference_spec.rb
new file mode 100644
index 0000000000..bfe6b48ad4
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/element_reference_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#[] when passed key" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns the value of the header entry with the passed key" do
+ @headers["My-Header"] = "test"
+ @headers["My-Header"].should == "test"
+ @headers["My-Other-Header"] = "another test"
+ @headers["My-Other-Header"].should == "another test"
+ end
+
+ it "is case-insensitive" do
+ @headers["My-Header"] = "test"
+
+ @headers['My-Header'].should == "test"
+ @headers['my-Header'].should == "test"
+ @headers['My-header'].should == "test"
+ @headers['my-header'].should == "test"
+ @headers['MY-HEADER'].should == "test"
+ end
+
+ it "returns multi-element values joined together" do
+ @headers["My-Header"] = "test"
+ @headers.add_field("My-Header", "another test")
+ @headers.add_field("My-Header", "and one more")
+
+ @headers["My-Header"].should == "test, another test, and one more"
+ end
+
+ it "returns nil for non-existing entries" do
+ @headers["My-Header"].should be_nil
+ @headers["My-Other-Header"].should be_nil
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/element_set_spec.rb b/spec/ruby/library/net/http/httpheader/element_set_spec.rb
new file mode 100644
index 0000000000..a5a2900e94
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/element_set_spec.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#[]= when passed key, value" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "sets the header entry with the passed key to the passed value" do
+ @headers["My-Header"] = "test"
+ @headers["My-Header"].should == "test"
+
+ @headers["My-Header"] = "overwritten"
+ @headers["My-Header"].should == "overwritten"
+
+ @headers["My-Other-Header"] = "another test"
+ @headers["My-Other-Header"].should == "another test"
+ end
+
+ it "is case-insensitive" do
+ @headers['My-Header'] = "test"
+ @headers['my-Header'] = "another test"
+ @headers['My-header'] = "and one more test"
+ @headers['my-header'] = "and another one"
+ @headers['MY-HEADER'] = "last one"
+
+ @headers["My-Header"].should == "last one"
+ @headers.size.should eql(1)
+ end
+
+ it "removes the header entry with the passed key when the value is false or nil" do
+ @headers['My-Header'] = "test"
+ @headers['My-Header'] = nil
+ @headers['My-Header'].should be_nil
+
+ @headers['My-Header'] = "test"
+ @headers['My-Header'] = false
+ @headers['My-Header'].should be_nil
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/fetch_spec.rb b/spec/ruby/library/net/http/httpheader/fetch_spec.rb
new file mode 100644
index 0000000000..7182c4396e
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/fetch_spec.rb
@@ -0,0 +1,68 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#fetch" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ describe "when passed key" do
+ it "returns the header entry for the passed key" do
+ @headers["My-Header"] = "test"
+ @headers.fetch("My-Header").should == "test"
+
+ @headers.add_field("My-Other-Header", "a")
+ @headers.add_field("My-Other-Header", "b")
+ @headers.add_field("My-Other-Header", "c")
+ @headers.fetch("My-Other-Header").should == "a, b, c"
+ end
+
+ it "is case-insensitive" do
+ @headers["My-Header"] = "test"
+ @headers.fetch("my-header").should == "test"
+ @headers.fetch("MY-HEADER").should == "test"
+ end
+
+ it "returns nil when there is no entry for the passed key" do
+ lambda { @headers.fetch("my-header") }.should raise_error(IndexError)
+ end
+ end
+
+ describe "when passed key, default" do
+ it "returns the header entry for the passed key" do
+ @headers["My-Header"] = "test"
+ @headers.fetch("My-Header", "bla").should == "test"
+
+ @headers.add_field("My-Other-Header", "a")
+ @headers.add_field("My-Other-Header", "b")
+ @headers.add_field("My-Other-Header", "c")
+ @headers.fetch("My-Other-Header", "bla").should == "a, b, c"
+ end
+
+ # TODO: This raises a NoMethodError: undefined method `join' for "bla":String
+ it "returns the default value when there is no entry for the passed key" do
+ @headers.fetch("My-Header", "bla").should == "bla"
+ end
+ end
+
+ describe "when passed key and block" do
+ it "returns the header entry for the passed key" do
+ @headers["My-Header"] = "test"
+ @headers.fetch("My-Header") {}.should == "test"
+
+ @headers.add_field("My-Other-Header", "a")
+ @headers.add_field("My-Other-Header", "b")
+ @headers.add_field("My-Other-Header", "c")
+ -> {
+ @result = @headers.fetch("My-Other-Header", "bla") {}
+ }.should complain(/block supersedes default value argument/)
+ @result.should == "a, b, c"
+ end
+
+ # TODO: This raises a NoMethodError: undefined method `join' for "redaeh-ym":String
+ it "yieldsand returns the block's return value when there is no entry for the passed key" do
+ @headers.fetch("My-Header") { |key| key.reverse }.should == "redaeh-ym"
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/fixtures/classes.rb b/spec/ruby/library/net/http/httpheader/fixtures/classes.rb
new file mode 100644
index 0000000000..b5ec6abd75
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/fixtures/classes.rb
@@ -0,0 +1,11 @@
+module NetHTTPHeaderSpecs
+ class Example
+ include Net::HTTPHeader
+
+ attr_accessor :body
+
+ def initialize
+ initialize_http_header({})
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/form_data_spec.rb b/spec/ruby/library/net/http/httpheader/form_data_spec.rb
new file mode 100644
index 0000000000..7781990824
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/form_data_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/set_form_data', __FILE__)
+
+describe "Net::HTTPHeader#form_data=" do
+ it_behaves_like :net_httpheader_set_form_data, :form_data=
+end
diff --git a/spec/ruby/library/net/http/httpheader/get_fields_spec.rb b/spec/ruby/library/net/http/httpheader/get_fields_spec.rb
new file mode 100644
index 0000000000..f7828f752c
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/get_fields_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#get_fields when passed key" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns an Array containing the values of the header entry with the passed key" do
+ @headers["My-Header"] = "a"
+ @headers.get_fields("My-Header").should == ["a"]
+
+ @headers.add_field("My-Header", "b")
+ @headers.get_fields("My-Header").should == ["a", "b"]
+ end
+
+ it "returns a copy of the header entry values" do
+ @headers["My-Header"] = "a"
+
+ @headers.get_fields("My-Header").clear
+ @headers.get_fields("My-Header").should == ["a"]
+
+ @headers.get_fields("My-Header") << "b"
+ @headers.get_fields("My-Header").should == ["a"]
+ end
+
+ it "returns nil for non-existing header entries" do
+ @headers.get_fields("My-Header").should be_nil
+ @headers.get_fields("My-Other-header").should be_nil
+ end
+
+ it "is case-insensitive" do
+ @headers["My-Header"] = "test"
+ @headers.get_fields("My-Header").should == ["test"]
+ @headers.get_fields("my-header").should == ["test"]
+ @headers.get_fields("MY-HEADER").should == ["test"]
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/initialize_http_header_spec.rb b/spec/ruby/library/net/http/httpheader/initialize_http_header_spec.rb
new file mode 100644
index 0000000000..ffb56642d4
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/initialize_http_header_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#initialize_http_header when passed Hash" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.allocate
+ end
+
+ it "initializes the HTTP Header using the passed Hash" do
+ @headers.initialize_http_header("My-Header" => "test", "My-Other-Header" => "another test")
+ @headers["My-Header"].should == "test"
+ @headers["My-Other-Header"].should == "another test"
+ end
+
+ it "complains about duplicate keys when in verbose mode" do
+ lambda do
+ $VERBOSE = true
+ @headers.initialize_http_header("My-Header" => "test", "my-header" => "another test")
+ end.should complain(/duplicated HTTP header/)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/key_spec.rb b/spec/ruby/library/net/http/httpheader/key_spec.rb
new file mode 100644
index 0000000000..0cb5f711dc
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/key_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#key? when passed key" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns true if the header entry with the passed key exists" do
+ @headers.key?("My-Header").should be_false
+ @headers["My-Header"] = "test"
+ @headers.key?("My-Header").should be_true
+ end
+
+ it "is case-insensitive" do
+ @headers["My-Header"] = "test"
+ @headers.key?("my-header").should be_true
+ @headers.key?("MY-HEADER").should be_true
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/length_spec.rb b/spec/ruby/library/net/http/httpheader/length_spec.rb
new file mode 100644
index 0000000000..50cb1c1f7f
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/length_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/size', __FILE__)
+
+describe "Net::HTTPHeader#length" do
+ it_behaves_like :net_httpheader_size, :length
+end
diff --git a/spec/ruby/library/net/http/httpheader/main_type_spec.rb b/spec/ruby/library/net/http/httpheader/main_type_spec.rb
new file mode 100644
index 0000000000..34e2ddbc65
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/main_type_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#main_type" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns the 'main-content-type', as per 'Content-Type' header entry" do
+ @headers["Content-Type"] = "text/html"
+ @headers.main_type.should == "text"
+
+ @headers["Content-Type"] = "application/pdf"
+ @headers.main_type.should == "application"
+
+ @headers["Content-Type"] = "text/html;charset=utf-8"
+ @headers.main_type.should == "text"
+ end
+
+ it "returns nil if the 'Content-Type' header entry does not exist" do
+ @headers.main_type.should be_nil
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/proxy_basic_auth_spec.rb b/spec/ruby/library/net/http/httpheader/proxy_basic_auth_spec.rb
new file mode 100644
index 0000000000..5e7d87af36
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/proxy_basic_auth_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#proxy_basic_auth when passed account, password" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "sets the 'Proxy-Authorization' Header entry for basic authorization" do
+ @headers.proxy_basic_auth("rubyspec", "rocks")
+ @headers["Proxy-Authorization"].should == "Basic cnVieXNwZWM6cm9ja3M="
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/range_length_spec.rb b/spec/ruby/library/net/http/httpheader/range_length_spec.rb
new file mode 100644
index 0000000000..ec3b00d805
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/range_length_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#range_length" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns the length of the Range represented by the 'Content-Range' header entry" do
+ @headers["Content-Range"] = "bytes 0-499/1234"
+ @headers.range_length.should eql(500)
+
+ @headers["Content-Range"] = "bytes 500-1233/1234"
+ @headers.range_length.should eql(734)
+ end
+
+ it "returns nil when there is no 'Content-Range' header entry" do
+ @headers.range_length.should be_nil
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when the 'Content-Range' has an invalid format" do
+ @headers["Content-Range"] = "invalid"
+ lambda { @headers.range_length }.should raise_error(Net::HTTPHeaderSyntaxError)
+
+ @headers["Content-Range"] = "bytes 123-abc"
+ lambda { @headers.range_length }.should raise_error(Net::HTTPHeaderSyntaxError)
+
+ @headers["Content-Range"] = "bytes abc-123"
+ lambda { @headers.range_length }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/range_spec.rb b/spec/ruby/library/net/http/httpheader/range_spec.rb
new file mode 100644
index 0000000000..d71d2ed598
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/range_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/set_range', __FILE__)
+
+describe "Net::HTTPHeader#range" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns a Range object that represents the 'Range' header entry" do
+ @headers["Range"] = "bytes=0-499"
+ @headers.range.should == [0..499]
+
+ @headers["Range"] = "bytes=500-1233"
+ @headers.range.should == [500..1233]
+
+ @headers["Range"] = "bytes=10-"
+ @headers.range.should == [10..-1]
+
+ @headers["Range"] = "bytes=-10"
+ @headers.range.should == [-10..-1]
+ end
+
+ it "returns nil when there is no 'Range' header entry" do
+ @headers.range.should be_nil
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when the 'Range' has an invalid format" do
+ @headers["Range"] = "invalid"
+ lambda { @headers.range }.should raise_error(Net::HTTPHeaderSyntaxError)
+
+ @headers["Range"] = "bytes 123-abc"
+ lambda { @headers.range }.should raise_error(Net::HTTPHeaderSyntaxError)
+
+ @headers["Range"] = "bytes abc-123"
+ lambda { @headers.range }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when the 'Range' was not specified" do
+ @headers["Range"] = "bytes=-"
+ lambda { @headers.range }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+end
+
+describe "Net::HTTPHeader#range=" do
+ it_behaves_like :net_httpheader_set_range, :range=
+end
diff --git a/spec/ruby/library/net/http/httpheader/set_content_type_spec.rb b/spec/ruby/library/net/http/httpheader/set_content_type_spec.rb
new file mode 100644
index 0000000000..b9a62154ad
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/set_content_type_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/set_content_type', __FILE__)
+
+describe "Net::HTTPHeader#set_content_type" do
+ it_behaves_like :net_httpheader_set_content_type, :set_content_type
+end
diff --git a/spec/ruby/library/net/http/httpheader/set_form_data_spec.rb b/spec/ruby/library/net/http/httpheader/set_form_data_spec.rb
new file mode 100644
index 0000000000..e675437ba4
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/set_form_data_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/set_form_data', __FILE__)
+
+describe "Net::HTTPHeader#set_form_data" do
+ it_behaves_like :net_httpheader_set_form_data, :set_form_data
+end
diff --git a/spec/ruby/library/net/http/httpheader/set_range_spec.rb b/spec/ruby/library/net/http/httpheader/set_range_spec.rb
new file mode 100644
index 0000000000..af3f00f99c
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/set_range_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/set_range', __FILE__)
+
+describe "Net::HTTPHeader#set_range" do
+ it_behaves_like :net_httpheader_set_range, :set_range
+end
diff --git a/spec/ruby/library/net/http/httpheader/shared/each_capitalized.rb b/spec/ruby/library/net/http/httpheader/shared/each_capitalized.rb
new file mode 100644
index 0000000000..3bac409876
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/shared/each_capitalized.rb
@@ -0,0 +1,31 @@
+describe :net_httpheader_each_capitalized, shared: true do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ @headers["my-header"] = "test"
+ @headers.add_field("my-Other-Header", "a")
+ @headers.add_field("My-Other-header", "b")
+ end
+
+ describe "when passed a block" do
+ it "yields each header entry to the passed block (capitalized keys, values joined)" do
+ res = []
+ @headers.send(@method) do |key, value|
+ res << [key, value]
+ end
+ res.sort.should == [["My-Header", "test"], ["My-Other-Header", "a, b"]]
+ end
+ end
+
+ describe "when passed no block" do
+ it "returns an Enumerator" do
+ enumerator = @headers.send(@method)
+ enumerator.should be_an_instance_of(Enumerator)
+
+ res = []
+ enumerator.each do |*key|
+ res << key
+ end
+ res.sort.should == [["My-Header", "test"], ["My-Other-Header", "a, b"]]
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/shared/each_header.rb b/spec/ruby/library/net/http/httpheader/shared/each_header.rb
new file mode 100644
index 0000000000..6bf3a6ddfe
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/shared/each_header.rb
@@ -0,0 +1,31 @@
+describe :net_httpheader_each_header, shared: true do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ @headers["My-Header"] = "test"
+ @headers.add_field("My-Other-Header", "a")
+ @headers.add_field("My-Other-Header", "b")
+ end
+
+ describe "when passed a block" do
+ it "yields each header entry to the passed block (keys in lower case, values joined)" do
+ res = []
+ @headers.send(@method) do |key, value|
+ res << [key, value]
+ end
+ res.sort.should == [["my-header", "test"], ["my-other-header", "a, b"]]
+ end
+ end
+
+ describe "when passed no block" do
+ it "returns an Enumerator" do
+ enumerator = @headers.send(@method)
+ enumerator.should be_an_instance_of(Enumerator)
+
+ res = []
+ enumerator.each do |*key|
+ res << key
+ end
+ res.sort.should == [["my-header", "test"], ["my-other-header", "a, b"]]
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/shared/each_name.rb b/spec/ruby/library/net/http/httpheader/shared/each_name.rb
new file mode 100644
index 0000000000..efc6a09dfd
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/shared/each_name.rb
@@ -0,0 +1,31 @@
+describe :net_httpheader_each_name, shared: true do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ @headers["My-Header"] = "test"
+ @headers.add_field("My-Other-Header", "a")
+ @headers.add_field("My-Other-Header", "b")
+ end
+
+ describe "when passed a block" do
+ it "yields each header key to the passed block (keys in lower case)" do
+ res = []
+ @headers.send(@method) do |key|
+ res << key
+ end
+ res.sort.should == ["my-header", "my-other-header"]
+ end
+ end
+
+ describe "when passed no block" do
+ it "returns an Enumerator" do
+ enumerator = @headers.send(@method)
+ enumerator.should be_an_instance_of(Enumerator)
+
+ res = []
+ enumerator.each do |key|
+ res << key
+ end
+ res.sort.should == ["my-header", "my-other-header"]
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/shared/set_content_type.rb b/spec/ruby/library/net/http/httpheader/shared/set_content_type.rb
new file mode 100644
index 0000000000..b7359bdca6
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/shared/set_content_type.rb
@@ -0,0 +1,18 @@
+describe :net_httpheader_set_content_type, shared: true do
+ describe "when passed type, params" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "sets the 'Content-Type' header entry based on the passed type and params" do
+ @headers.send(@method, "text/html")
+ @headers["Content-Type"].should == "text/html"
+
+ @headers.send(@method, "text/html", "charset" => "utf-8")
+ @headers["Content-Type"].should == "text/html; charset=utf-8"
+
+ @headers.send(@method, "text/html", "charset" => "utf-8", "rubyspec" => "rocks")
+ @headers["Content-Type"].split(/; /).sort.should == %w[charset=utf-8 rubyspec=rocks text/html]
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/shared/set_form_data.rb b/spec/ruby/library/net/http/httpheader/shared/set_form_data.rb
new file mode 100644
index 0000000000..db20b18803
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/shared/set_form_data.rb
@@ -0,0 +1,27 @@
+describe :net_httpheader_set_form_data, shared: true do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ describe "when passed params" do
+ it "automatically set the 'Content-Type' to 'application/x-www-form-urlencoded'" do
+ @headers.send(@method, "cmd" => "search", "q" => "ruby", "max" => "50")
+ @headers["Content-Type"].should == "application/x-www-form-urlencoded"
+ end
+
+ it "sets self's body based on the passed form parameters" do
+ @headers.send(@method, "cmd" => "search", "q" => "ruby", "max" => "50")
+ @headers.body.split("&").sort.should == ["cmd=search", "max=50", "q=ruby"]
+ end
+ end
+
+ describe "when passed params, separator" do
+ it "sets self's body based on the passed form parameters and the passed separator" do
+ @headers.send(@method, {"cmd" => "search", "q" => "ruby", "max" => "50"}, "&")
+ @headers.body.split("&").sort.should == ["cmd=search", "max=50", "q=ruby"]
+
+ @headers.send(@method, {"cmd" => "search", "q" => "ruby", "max" => "50"}, ";")
+ @headers.body.split(";").sort.should == ["cmd=search", "max=50", "q=ruby"]
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/shared/set_range.rb b/spec/ruby/library/net/http/httpheader/shared/set_range.rb
new file mode 100644
index 0000000000..6a98edbe10
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/shared/set_range.rb
@@ -0,0 +1,89 @@
+describe :net_httpheader_set_range, shared: true do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ describe "when passed nil" do
+ it "returns nil" do
+ @headers.send(@method, nil).should be_nil
+ end
+
+ it "deletes the 'Range' header entry" do
+ @headers["Range"] = "bytes 0-499/1234"
+ @headers.send(@method, nil)
+ @headers["Range"].should be_nil
+ end
+ end
+
+ describe "when passed Numeric" do
+ it "sets the 'Range' header entry based on the passed Numeric" do
+ @headers.send(@method, 10)
+ @headers["Range"].should == "bytes=0-9"
+
+ @headers.send(@method, -10)
+ @headers["Range"].should == "bytes=-10"
+
+ @headers.send(@method, 10.9)
+ @headers["Range"].should == "bytes=0-9"
+ end
+ end
+
+ describe "when passed Range" do
+ it "sets the 'Range' header entry based on the passed Range" do
+ @headers.send(@method, 10..200)
+ @headers["Range"].should == "bytes=10-200"
+
+ @headers.send(@method, 1..5)
+ @headers["Range"].should == "bytes=1-5"
+
+ @headers.send(@method, 1...5)
+ @headers["Range"].should == "bytes=1-4"
+
+ @headers.send(@method, 234..567)
+ @headers["Range"].should == "bytes=234-567"
+
+ @headers.send(@method, -5..-1)
+ @headers["Range"].should == "bytes=-5"
+
+ @headers.send(@method, 1..-1)
+ @headers["Range"].should == "bytes=1-"
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when the first Range element is negative" do
+ lambda { @headers.send(@method, -10..5) }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when the last Range element is negative" do
+ lambda { @headers.send(@method, 10..-5) }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when the last Range element is smaller than the first" do
+ lambda { @headers.send(@method, 10..5) }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+ end
+
+ describe "when passed start, end" do
+ it "sets the 'Range' header entry based on the passed start and length values" do
+ @headers.send(@method, 10, 200)
+ @headers["Range"].should == "bytes=10-209"
+
+ @headers.send(@method, 1, 5)
+ @headers["Range"].should == "bytes=1-5"
+
+ @headers.send(@method, 234, 567)
+ @headers["Range"].should == "bytes=234-800"
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when start is negative" do
+ lambda { @headers.send(@method, -10, 5) }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when start + length is negative" do
+ lambda { @headers.send(@method, 10, -15) }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+
+ it "raises a Net::HTTPHeaderSyntaxError when length is negative" do
+ lambda { @headers.send(@method, 10, -4) }.should raise_error(Net::HTTPHeaderSyntaxError)
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/shared/size.rb b/spec/ruby/library/net/http/httpheader/shared/size.rb
new file mode 100644
index 0000000000..e2b1e4c22b
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/shared/size.rb
@@ -0,0 +1,18 @@
+describe :net_httpheader_size, shared: true do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns the number of header entries in self" do
+ @headers.send(@method).should eql(0)
+
+ @headers["a"] = "b"
+ @headers.send(@method).should eql(1)
+
+ @headers["b"] = "b"
+ @headers.send(@method).should eql(2)
+
+ @headers["c"] = "c"
+ @headers.send(@method).should eql(3)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/size_spec.rb b/spec/ruby/library/net/http/httpheader/size_spec.rb
new file mode 100644
index 0000000000..3ea3969046
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/size_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/size', __FILE__)
+
+describe "Net::HTTPHeader#size" do
+ it_behaves_like :net_httpheader_size, :size
+end
diff --git a/spec/ruby/library/net/http/httpheader/sub_type_spec.rb b/spec/ruby/library/net/http/httpheader/sub_type_spec.rb
new file mode 100644
index 0000000000..65cae5a3f3
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/sub_type_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#sub_type" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns the 'sub-content-type', as per 'Content-Type' header entry" do
+ @headers["Content-Type"] = "text/html"
+ @headers.sub_type.should == "html"
+
+ @headers["Content-Type"] = "application/pdf"
+ @headers.sub_type.should == "pdf"
+
+ @headers["Content-Type"] = "text/html;charset=utf-8"
+ @headers.sub_type.should == "html"
+ end
+
+ it "returns nil if no 'sub-content-type' is set" do
+ @headers["Content-Type"] = "text"
+ @headers.sub_type.should be_nil
+
+ @headers["Content-Type"] = "text;charset=utf-8"
+ @headers.sub_type.should be_nil
+ end
+
+ it "returns nil if the 'Content-Type' header entry does not exist" do
+ @headers.sub_type.should be_nil
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/to_hash_spec.rb b/spec/ruby/library/net/http/httpheader/to_hash_spec.rb
new file mode 100644
index 0000000000..4b59c78c90
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/to_hash_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#to_hash" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns a Hash representing all Header entries (keys in lower case, values as arrays)" do
+ @headers.to_hash.should == {}
+
+ @headers["My-Header"] = "test"
+ @headers.to_hash.should == { "my-header" => ["test"] }
+
+ @headers.add_field("My-Header", "another test")
+ @headers.to_hash.should == { "my-header" => ["test", "another test"] }
+ end
+
+ it "does not allow modifying the headers from the returned hash" do
+ @headers.to_hash["my-header"] = ["test"]
+ @headers.to_hash.should == {}
+ @headers.key?("my-header").should be_false
+ end
+end
diff --git a/spec/ruby/library/net/http/httpheader/type_params_spec.rb b/spec/ruby/library/net/http/httpheader/type_params_spec.rb
new file mode 100644
index 0000000000..f4cd54f101
--- /dev/null
+++ b/spec/ruby/library/net/http/httpheader/type_params_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Net::HTTPHeader#type_params" do
+ before :each do
+ @headers = NetHTTPHeaderSpecs::Example.new
+ end
+
+ it "returns additional 'Content-Type' information as a Hash" do
+ @headers["Content-Type"] = "text/html;charset=utf-8"
+ @headers.type_params.should == {"charset" => "utf-8"}
+
+ @headers["Content-Type"] = "text/html; charset=utf-8; rubyspec=rocks"
+ @headers.type_params.should == {"charset" => "utf-8", "rubyspec" => "rocks"}
+ end
+
+ it "returns an empty Hash when no additional 'Content-Type' information is set" do
+ @headers.type_params.should == {}
+
+ @headers["Content-Type"] = "text/html"
+ @headers.type_params.should == {}
+ end
+end
diff --git a/spec/ruby/library/net/http/httprequest/initialize_spec.rb b/spec/ruby/library/net/http/httprequest/initialize_spec.rb
new file mode 100644
index 0000000000..8abbf13c93
--- /dev/null
+++ b/spec/ruby/library/net/http/httprequest/initialize_spec.rb
@@ -0,0 +1,45 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+module NetHTTPRequestSpecs
+ class TestRequest < Net::HTTPRequest
+ METHOD = "TEST"
+ REQUEST_HAS_BODY = false
+ RESPONSE_HAS_BODY = true
+ end
+end
+
+describe "Net::HTTPRequest#initialize" do
+ before :each do
+ @req = NetHTTPRequestSpecs::TestRequest.allocate
+ end
+
+ it "uses the METHOD constants to set the request method" do
+ @req.send(:initialize, "/some/path")
+ @req.method.should == "TEST"
+ end
+
+ it "uses the REQUEST_HAS_BODY to set whether the Request has a body or not" do
+ @req.send(:initialize, "/some/path")
+ @req.request_body_permitted?.should be_false
+ end
+
+ it "uses the RESPONSE_HAS_BODY to set whether the Response can have a body or not" do
+ @req.send(:initialize, "/some/path")
+ @req.response_body_permitted?.should be_true
+ end
+
+ describe "when passed path" do
+ it "sets self's path to the passed path" do
+ @req.send(:initialize, "/some/path")
+ @req.path.should == "/some/path"
+ end
+ end
+
+ describe "when passed path, headers" do
+ it "uses the passed headers Hash to initialize self's header entries" do
+ @req.send(:initialize, "/some/path", "Content-Type" => "text/html")
+ @req["Content-Type"].should == "text/html"
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb b/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb
new file mode 100644
index 0000000000..9688b0759e
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse.body_permitted?" do
+ it "returns true if this response type can have a response body" do
+ Net::HTTPUnknownResponse.body_permitted?.should == true
+ Net::HTTPInformation.body_permitted?.should == false
+ Net::HTTPSuccess.body_permitted?.should == true
+ Net::HTTPRedirection.body_permitted?.should == true
+ Net::HTTPClientError.body_permitted?.should == true
+ Net::HTTPServerError.body_permitted?.should == true
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/body_spec.rb b/spec/ruby/library/net/http/httpresponse/body_spec.rb
new file mode 100644
index 0000000000..169a6687a2
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/body_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../shared/body', __FILE__)
+
+describe "Net::HTTPResponse#body" do
+ it_behaves_like :net_httpresponse_body, :body
+end
diff --git a/spec/ruby/library/net/http/httpresponse/code_spec.rb b/spec/ruby/library/net/http/httpresponse/code_spec.rb
new file mode 100644
index 0000000000..9430af3100
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/code_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#code" do
+ it "returns the result code string" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.code.should == "???"
+
+ res = Net::HTTPInformation.new("1.0", "1xx", "test response")
+ res.code.should == "1xx"
+
+ res = Net::HTTPSuccess.new("1.0", "2xx", "test response")
+ res.code.should == "2xx"
+
+ res = Net::HTTPRedirection.new("1.0", "3xx", "test response")
+ res.code.should == "3xx"
+
+ res = Net::HTTPClientError.new("1.0", "4xx", "test response")
+ res.code.should == "4xx"
+
+ res = Net::HTTPServerError.new("1.0", "5xx", "test response")
+ res.code.should == "5xx"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/code_type_spec.rb b/spec/ruby/library/net/http/httpresponse/code_type_spec.rb
new file mode 100644
index 0000000000..899c2ed9bf
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/code_type_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#code_type" do
+ it "returns self's class" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.code_type.should == Net::HTTPUnknownResponse
+
+ res = Net::HTTPInformation.new("1.0", "1xx", "test response")
+ res.code_type.should == Net::HTTPInformation
+
+ res = Net::HTTPSuccess.new("1.0", "2xx", "test response")
+ res.code_type.should == Net::HTTPSuccess
+
+ res = Net::HTTPRedirection.new("1.0", "3xx", "test response")
+ res.code_type.should == Net::HTTPRedirection
+
+ res = Net::HTTPClientError.new("1.0", "4xx", "test response")
+ res.code_type.should == Net::HTTPClientError
+
+ res = Net::HTTPServerError.new("1.0", "5xx", "test response")
+ res.code_type.should == Net::HTTPServerError
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/entity_spec.rb b/spec/ruby/library/net/http/httpresponse/entity_spec.rb
new file mode 100644
index 0000000000..3b6be5eb00
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/entity_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require File.expand_path('../shared/body', __FILE__)
+
+describe "Net::HTTPResponse#entity" do
+ it_behaves_like :net_httpresponse_body, :entity
+end
diff --git a/spec/ruby/library/net/http/httpresponse/error_spec.rb b/spec/ruby/library/net/http/httpresponse/error_spec.rb
new file mode 100644
index 0000000000..7b0f61e520
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/error_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#error!" do
+ it "raises self's class 'EXCEPTION_TYPE' Exception" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ lambda { res.error! }.should raise_error(Net::HTTPError)
+
+ res = Net::HTTPInformation.new("1.0", "1xx", "test response")
+ lambda { res.error! }.should raise_error(Net::HTTPError)
+
+ res = Net::HTTPSuccess.new("1.0", "2xx", "test response")
+ lambda { res.error! }.should raise_error(Net::HTTPError)
+
+ res = Net::HTTPRedirection.new("1.0", "3xx", "test response")
+ lambda { res.error! }.should raise_error(Net::HTTPRetriableError)
+
+ res = Net::HTTPClientError.new("1.0", "4xx", "test response")
+ lambda { res.error! }.should raise_error(Net::HTTPServerException)
+
+ res = Net::HTTPServerError.new("1.0", "5xx", "test response")
+ lambda { res.error! }.should raise_error(Net::HTTPFatalError)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/error_type_spec.rb b/spec/ruby/library/net/http/httpresponse/error_type_spec.rb
new file mode 100644
index 0000000000..a6b0155998
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/error_type_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#error_type" do
+ it "returns self's class 'EXCEPTION_TYPE' constant" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.error_type.should == Net::HTTPError
+
+ res = Net::HTTPInformation.new("1.0", "1xx", "test response")
+ res.error_type.should == Net::HTTPError
+
+ res = Net::HTTPSuccess.new("1.0", "2xx", "test response")
+ res.error_type.should == Net::HTTPError
+
+ res = Net::HTTPRedirection.new("1.0", "3xx", "test response")
+ res.error_type.should == Net::HTTPRetriableError
+
+ res = Net::HTTPClientError.new("1.0", "4xx", "test response")
+ res.error_type.should == Net::HTTPServerException
+
+ res = Net::HTTPServerError.new("1.0", "5xx", "test response")
+ res.error_type.should == Net::HTTPFatalError
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/exception_type_spec.rb b/spec/ruby/library/net/http/httpresponse/exception_type_spec.rb
new file mode 100644
index 0000000000..e1a48e0c12
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/exception_type_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse.exception_type" do
+ it "returns self's 'EXCEPTION_TYPE' constant" do
+ Net::HTTPUnknownResponse.exception_type.should == Net::HTTPError
+ Net::HTTPInformation.exception_type.should == Net::HTTPError
+ Net::HTTPSuccess.exception_type.should == Net::HTTPError
+ Net::HTTPRedirection.exception_type.should == Net::HTTPRetriableError
+ Net::HTTPClientError.exception_type.should == Net::HTTPServerException
+ Net::HTTPServerError.exception_type.should == Net::HTTPFatalError
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/header_spec.rb b/spec/ruby/library/net/http/httpresponse/header_spec.rb
new file mode 100644
index 0000000000..21e3dec418
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/header_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#header" do
+ it "returns self" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.response.should equal(res)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/http_version_spec.rb b/spec/ruby/library/net/http/httpresponse/http_version_spec.rb
new file mode 100644
index 0000000000..a1192c1cbe
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/http_version_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#http_version" do
+ it "returns self's http version" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.http_version.should == "1.0"
+
+ res = Net::HTTPUnknownResponse.new("1.1", "???", "test response")
+ res.http_version.should == "1.1"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/initialize_spec.rb b/spec/ruby/library/net/http/httpresponse/initialize_spec.rb
new file mode 100644
index 0000000000..dcb6da3afe
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/initialize_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#initialize when passed http_version, response_code, response_message" do
+ it "sets self http_version, response_code and response_message to the passed values" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.http_version.should == "1.0"
+ res.code.should == "???"
+ res.message.should == "test response"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/inspect_spec.rb b/spec/ruby/library/net/http/httpresponse/inspect_spec.rb
new file mode 100644
index 0000000000..f5463afa96
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/inspect_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require "stringio"
+
+describe "Net::HTTPResponse#inspect" do
+ it "returns a String representation of self" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.inspect.should == "#<Net::HTTPUnknownResponse ??? test response readbody=false>"
+
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ socket = Net::BufferedIO.new(StringIO.new("test body"))
+ res.reading_body(socket, true) {}
+ res.inspect.should == "#<Net::HTTPUnknownResponse ??? test response readbody=true>"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/message_spec.rb b/spec/ruby/library/net/http/httpresponse/message_spec.rb
new file mode 100644
index 0000000000..57a927aff0
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/message_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#message" do
+ it "returns self's response message" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.message.should == "test response"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/msg_spec.rb b/spec/ruby/library/net/http/httpresponse/msg_spec.rb
new file mode 100644
index 0000000000..9b19d34234
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/msg_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#msg" do
+ it "returns self's response message" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.message.should == "test response"
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/read_body_spec.rb b/spec/ruby/library/net/http/httpresponse/read_body_spec.rb
new file mode 100644
index 0000000000..d71b4144f4
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/read_body_spec.rb
@@ -0,0 +1,86 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#read_body" do
+ before :each do
+ @res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ @socket = Net::BufferedIO.new(StringIO.new("test body"))
+ end
+
+ describe "when passed no arguments" do
+ it "returns the read body" do
+ @res.reading_body(@socket, true) do
+ @res.read_body.should == "test body"
+ end
+ end
+
+ it "returns the previously read body if called a second time" do
+ @res.reading_body(@socket, true) do
+ @res.read_body.should equal(@res.read_body)
+ end
+ end
+ end
+
+ describe "when passed a buffer" do
+ it "reads the body to the passed buffer" do
+ @res.reading_body(@socket, true) do
+ buffer = ""
+ @res.read_body(buffer)
+ buffer.should == "test body"
+ end
+ end
+
+ it "returns the passed buffer" do
+ @res.reading_body(@socket, true) do
+ buffer = ""
+ @res.read_body(buffer).should equal(buffer)
+ end
+ end
+
+ it "raises an IOError if called a second time" do
+ @res.reading_body(@socket, true) do
+ @res.read_body("")
+ lambda { @res.read_body("") }.should raise_error(IOError)
+ end
+ end
+ end
+
+ describe "when passed a block" do
+ it "reads the body and yields it to the passed block (in chunks)" do
+ @res.reading_body(@socket, true) do
+ yielded = false
+
+ buffer = ""
+ @res.read_body do |body|
+ yielded = true
+ buffer << body
+ end
+
+ yielded.should be_true
+ buffer.should == "test body"
+ end
+ end
+
+ it "returns the ReadAdapter" do
+ @res.reading_body(@socket, true) do
+ @res.read_body { nil }.should be_kind_of(Net::ReadAdapter)
+ end
+ end
+
+ it "raises an IOError if called a second time" do
+ @res.reading_body(@socket, true) do
+ @res.read_body {}
+ lambda { @res.read_body {} }.should raise_error(IOError)
+ end
+ end
+ end
+
+ describe "when passed buffer and block" do
+ it "rauses an ArgumentError" do
+ @res.reading_body(@socket, true) do
+ lambda { @res.read_body("") {} }.should raise_error(ArgumentError)
+ end
+ end
+ end
+end
+
diff --git a/spec/ruby/library/net/http/httpresponse/read_header_spec.rb b/spec/ruby/library/net/http/httpresponse/read_header_spec.rb
new file mode 100644
index 0000000000..6bbabdfe10
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/read_header_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#read_header" do
+ it "returns self" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.response.should equal(res)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/read_new_spec.rb b/spec/ruby/library/net/http/httpresponse/read_new_spec.rb
new file mode 100644
index 0000000000..e2fb0f1a05
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/read_new_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse.read_new" do
+ it "creates a HTTPResponse object based on the response read from the passed socket" do
+ socket = Net::BufferedIO.new(StringIO.new(<<EOS))
+HTTP/1.1 200 OK
+Content-Type: text/html; charset=utf-8
+
+test-body
+EOS
+ response = Net::HTTPResponse.read_new(socket)
+
+ response.should be_kind_of(Net::HTTPOK)
+ response.code.should == "200"
+ response["Content-Type"].should == "text/html; charset=utf-8"
+
+ response.reading_body(socket, true) do
+ response.body.should == "test-body\n"
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/reading_body_spec.rb b/spec/ruby/library/net/http/httpresponse/reading_body_spec.rb
new file mode 100644
index 0000000000..5e53e00adc
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/reading_body_spec.rb
@@ -0,0 +1,58 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+require "stringio"
+
+describe "Net::HTTPResponse#reading_body" do
+ before :each do
+ @res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ @socket = Net::BufferedIO.new(StringIO.new("test body"))
+ end
+
+ describe "when body_allowed is true" do
+ it "reads and returns the response body for self from the passed socket" do
+ @res.reading_body(@socket, true) {}.should == "test body"
+ @res.body.should == "test body"
+ end
+
+ it "yields the passed block before reading the body" do
+ yielded = false
+
+ @res.reading_body(@socket, true) do
+ @res.inspect.should == "#<Net::HTTPUnknownResponse ??? test response readbody=false>"
+ yielded = true
+ end
+
+ yielded.should be_true
+ end
+
+ describe "but the response type is not allowed to have a body" do
+ before :each do
+ @res = Net::HTTPInformation.new("1.0", "???", "test response")
+ end
+
+ it "returns nil" do
+ @res.reading_body(@socket, false) {}.should be_nil
+ @res.body.should be_nil
+ end
+
+ it "yields the passed block" do
+ yielded = false
+ @res.reading_body(@socket, true) { yielded = true }
+ yielded.should be_true
+ end
+ end
+ end
+
+ describe "when body_allowed is false" do
+ it "returns nil" do
+ @res.reading_body(@socket, false) {}.should be_nil
+ @res.body.should be_nil
+ end
+
+ it "yields the passed block" do
+ yielded = false
+ @res.reading_body(@socket, true) { yielded = true }
+ yielded.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/response_spec.rb b/spec/ruby/library/net/http/httpresponse/response_spec.rb
new file mode 100644
index 0000000000..826320be9e
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/response_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#response" do
+ it "returns self" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ res.response.should equal(res)
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/shared/body.rb b/spec/ruby/library/net/http/httpresponse/shared/body.rb
new file mode 100644
index 0000000000..91d5fe6375
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/shared/body.rb
@@ -0,0 +1,18 @@
+describe :net_httpresponse_body, shared: true do
+ before :each do
+ @res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ @socket = Net::BufferedIO.new(StringIO.new("test body"))
+ end
+
+ it "returns the read body" do
+ @res.reading_body(@socket, true) do
+ @res.send(@method).should == "test body"
+ end
+ end
+
+ it "returns the previously read body if called a second time" do
+ @res.reading_body(@socket, true) do
+ @res.send(@method).should equal(@res.send(@method))
+ end
+ end
+end
diff --git a/spec/ruby/library/net/http/httpresponse/value_spec.rb b/spec/ruby/library/net/http/httpresponse/value_spec.rb
new file mode 100644
index 0000000000..7e4f7863eb
--- /dev/null
+++ b/spec/ruby/library/net/http/httpresponse/value_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'net/http'
+
+describe "Net::HTTPResponse#value" do
+ it "raises an HTTP error for non 2xx HTTP Responses" do
+ res = Net::HTTPUnknownResponse.new("1.0", "???", "test response")
+ lambda { res.value }.should raise_error(Net::HTTPError)
+
+ res = Net::HTTPInformation.new("1.0", "1xx", "test response")
+ lambda { res.value }.should raise_error(Net::HTTPError)
+
+ res = Net::HTTPSuccess.new("1.0", "2xx", "test response")
+ lambda { res.value }.should_not raise_error(Net::HTTPError)
+
+ res = Net::HTTPRedirection.new("1.0", "3xx", "test response")
+ lambda { res.value }.should raise_error(Net::HTTPRetriableError)
+
+ res = Net::HTTPClientError.new("1.0", "4xx", "test response")
+ lambda { res.value }.should raise_error(Net::HTTPServerException)
+
+ res = Net::HTTPServerError.new("1.0", "5xx", "test response")
+ lambda { res.value }.should raise_error(Net::HTTPFatalError)
+ end
+end
diff --git a/spec/ruby/library/observer/add_observer_spec.rb b/spec/ruby/library/observer/add_observer_spec.rb
new file mode 100644
index 0000000000..7a2d349c85
--- /dev/null
+++ b/spec/ruby/library/observer/add_observer_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Observer#add_observer" do
+
+ before :each do
+ @observable = ObservableSpecs.new
+ @observer = ObserverCallbackSpecs.new
+ end
+
+ it "adds the observer" do
+ @observer.value.should == nil
+ @observable.changed
+ @observable.notify_observers("test")
+ @observer.value.should == nil
+
+ @observable.add_observer(@observer)
+ @observable.changed
+ @observable.notify_observers("test2")
+ @observer.value.should == "test2"
+ end
+
+end
diff --git a/spec/ruby/library/observer/count_observers_spec.rb b/spec/ruby/library/observer/count_observers_spec.rb
new file mode 100644
index 0000000000..68eaccfaaa
--- /dev/null
+++ b/spec/ruby/library/observer/count_observers_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Observer#count_observers" do
+ before :each do
+ @observable = ObservableSpecs.new
+ @observer = ObserverCallbackSpecs.new
+ @observer2 = ObserverCallbackSpecs.new
+ end
+
+ it "returns the number of observers" do
+ @observable.count_observers.should == 0
+ @observable.add_observer(@observer)
+ @observable.count_observers.should == 1
+ @observable.add_observer(@observer2)
+ @observable.count_observers.should == 2
+ end
+
+ it "returns the number of unique observers" do
+ 2.times { @observable.add_observer(@observer) }
+ @observable.count_observers.should == 1
+ end
+end
diff --git a/spec/ruby/library/observer/delete_observer_spec.rb b/spec/ruby/library/observer/delete_observer_spec.rb
new file mode 100644
index 0000000000..b9dc95167c
--- /dev/null
+++ b/spec/ruby/library/observer/delete_observer_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Observer#delete_observer" do
+ before :each do
+ @observable = ObservableSpecs.new
+ @observer = ObserverCallbackSpecs.new
+ end
+
+ it "deletes the observer" do
+ @observable.add_observer(@observer)
+ @observable.delete_observer(@observer)
+
+ @observable.changed
+ @observable.notify_observers("test")
+ @observer.value.should == nil
+ end
+
+end
diff --git a/spec/ruby/library/observer/delete_observers_spec.rb b/spec/ruby/library/observer/delete_observers_spec.rb
new file mode 100644
index 0000000000..58b10418dd
--- /dev/null
+++ b/spec/ruby/library/observer/delete_observers_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Observer#delete_observers" do
+ before :each do
+ @observable = ObservableSpecs.new
+ @observer = ObserverCallbackSpecs.new
+ end
+
+ it "deletes the observers" do
+ @observable.add_observer(@observer)
+ @observable.delete_observers
+
+ @observable.changed
+ @observable.notify_observers("test")
+ @observer.value.should == nil
+ end
+
+end
diff --git a/spec/ruby/library/observer/fixtures/classes.rb b/spec/ruby/library/observer/fixtures/classes.rb
new file mode 100644
index 0000000000..70cd1b1be2
--- /dev/null
+++ b/spec/ruby/library/observer/fixtures/classes.rb
@@ -0,0 +1,17 @@
+require 'observer'
+
+class ObserverCallbackSpecs
+ attr_reader :value
+
+ def initialize
+ @value = nil
+ end
+
+ def update(value)
+ @value = value
+ end
+end
+
+class ObservableSpecs
+ include Observable
+end
diff --git a/spec/ruby/library/observer/notify_observers_spec.rb b/spec/ruby/library/observer/notify_observers_spec.rb
new file mode 100644
index 0000000000..cafbdd56e6
--- /dev/null
+++ b/spec/ruby/library/observer/notify_observers_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Observer#notify_observers" do
+
+ before :each do
+ @observable = ObservableSpecs.new
+ @observer = ObserverCallbackSpecs.new
+ @observable.add_observer(@observer)
+ end
+
+ it "must call changed before notifying observers" do
+ @observer.value.should == nil
+ @observable.notify_observers("test")
+ @observer.value.should == nil
+ end
+
+ it "verifies observer responds to update" do
+ lambda {
+ @observable.add_observer(@observable)
+ }.should raise_error(NoMethodError)
+ end
+
+ it "receives the callback" do
+ @observer.value.should == nil
+ @observable.changed
+ @observable.notify_observers("test")
+ @observer.value.should == "test"
+ end
+
+end
diff --git a/spec/ruby/library/open3/capture2_spec.rb b/spec/ruby/library/open3/capture2_spec.rb
new file mode 100644
index 0000000000..e5bcc67ae0
--- /dev/null
+++ b/spec/ruby/library/open3/capture2_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.capture2" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/capture2e_spec.rb b/spec/ruby/library/open3/capture2e_spec.rb
new file mode 100644
index 0000000000..6254914222
--- /dev/null
+++ b/spec/ruby/library/open3/capture2e_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.capture2e" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/capture3_spec.rb b/spec/ruby/library/open3/capture3_spec.rb
new file mode 100644
index 0000000000..cbfa023eb5
--- /dev/null
+++ b/spec/ruby/library/open3/capture3_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.capture3" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/pipeline_r_spec.rb b/spec/ruby/library/open3/pipeline_r_spec.rb
new file mode 100644
index 0000000000..c5c2f02087
--- /dev/null
+++ b/spec/ruby/library/open3/pipeline_r_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.pipeline_r" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/pipeline_rw_spec.rb b/spec/ruby/library/open3/pipeline_rw_spec.rb
new file mode 100644
index 0000000000..6f9830270b
--- /dev/null
+++ b/spec/ruby/library/open3/pipeline_rw_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.pipeline_rw" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/pipeline_spec.rb b/spec/ruby/library/open3/pipeline_spec.rb
new file mode 100644
index 0000000000..f8ace3d2da
--- /dev/null
+++ b/spec/ruby/library/open3/pipeline_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.pipeline" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/pipeline_start_spec.rb b/spec/ruby/library/open3/pipeline_start_spec.rb
new file mode 100644
index 0000000000..76af0b88e5
--- /dev/null
+++ b/spec/ruby/library/open3/pipeline_start_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.pipeline_start" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/pipeline_w_spec.rb b/spec/ruby/library/open3/pipeline_w_spec.rb
new file mode 100644
index 0000000000..e3336b7fe1
--- /dev/null
+++ b/spec/ruby/library/open3/pipeline_w_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.pipeline_w" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/popen2_spec.rb b/spec/ruby/library/open3/popen2_spec.rb
new file mode 100644
index 0000000000..49bab91bef
--- /dev/null
+++ b/spec/ruby/library/open3/popen2_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.popen2" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/popen2e_spec.rb b/spec/ruby/library/open3/popen2e_spec.rb
new file mode 100644
index 0000000000..2361543afa
--- /dev/null
+++ b/spec/ruby/library/open3/popen2e_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.popen2e" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/open3/popen3_spec.rb b/spec/ruby/library/open3/popen3_spec.rb
new file mode 100644
index 0000000000..9733ab15cd
--- /dev/null
+++ b/spec/ruby/library/open3/popen3_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'open3'
+
+describe "Open3.popen3" do
+ it "returns in, out, err and a thread waiting the process" do
+ stdin, out, err, waiter = Open3.popen3(ruby_cmd("print :foo"))
+ begin
+ stdin.should be_kind_of IO
+ out.should be_kind_of IO
+ err.should be_kind_of IO
+ waiter.should be_kind_of Thread
+
+ out.read.should == "foo"
+ ensure
+ stdin.close
+ out.close
+ err.close
+ waiter.join
+ end
+ end
+
+ it "executes a process with a pipe to read stdout" do
+ Open3.popen3(ruby_cmd("print :foo")) do |stdin, out, err|
+ out.read.should == "foo"
+ end
+ end
+
+ it "executes a process with a pipe to read stderr" do
+ Open3.popen3(ruby_cmd("STDERR.print :foo")) do |stdin, out, err|
+ err.read.should == "foo"
+ end
+ end
+
+ it "executes a process with a pipe to write stdin" do
+ Open3.popen3(ruby_cmd("print STDIN.read")) do |stdin, out, err|
+ stdin.write("foo")
+ stdin.close
+ out.read.should == "foo"
+ end
+ end
+
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/openssl/cipher_spec.rb b/spec/ruby/library/openssl/cipher_spec.rb
new file mode 100644
index 0000000000..c3eb1280a2
--- /dev/null
+++ b/spec/ruby/library/openssl/cipher_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/constants', __FILE__)
+require 'openssl'
+
+describe "OpenSSL::Cipher's CipherError" do
+ it "exists under OpenSSL::Cipher namespace" do
+ OpenSSL::Cipher.should have_constant :CipherError
+ end
+end
diff --git a/spec/ruby/library/openssl/config/freeze_spec.rb b/spec/ruby/library/openssl/config/freeze_spec.rb
new file mode 100644
index 0000000000..2ed48ae629
--- /dev/null
+++ b/spec/ruby/library/openssl/config/freeze_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../shared/constants', __FILE__)
+
+require 'openssl'
+
+describe "OpenSSL::Config#freeze" do
+ it "needs to be reviewed for completeness"
+
+ it "freezes" do
+ c = OpenSSL::Config.new
+ lambda{c['foo'] = [ ['key', 'value'] ]}.should_not raise_error
+ c.freeze
+ c.frozen?.should be_true
+ lambda{c['foo'] = [ ['key', 'value'] ]}.should raise_error
+ end
+end
diff --git a/spec/ruby/library/openssl/hmac/digest_spec.rb b/spec/ruby/library/openssl/hmac/digest_spec.rb
new file mode 100644
index 0000000000..36edee87bd
--- /dev/null
+++ b/spec/ruby/library/openssl/hmac/digest_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../shared/constants', __FILE__)
+require 'openssl'
+
+describe "OpenSSL::HMAC.digest" do
+ it "returns an SHA1 digest" do
+ cur_digest = OpenSSL::Digest::SHA1.new
+ cur_digest.digest.should == HMACConstants::BlankSHA1Digest
+ digest = OpenSSL::HMAC.digest(cur_digest,
+ HMACConstants::Key,
+ HMACConstants::Contents)
+ digest.should == HMACConstants::SHA1Digest
+ end
+end
+
+# Should add in similar specs for MD5, RIPEMD160, and SHA256
diff --git a/spec/ruby/library/openssl/hmac/hexdigest_spec.rb b/spec/ruby/library/openssl/hmac/hexdigest_spec.rb
new file mode 100644
index 0000000000..b61bcf6a8f
--- /dev/null
+++ b/spec/ruby/library/openssl/hmac/hexdigest_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../shared/constants', __FILE__)
+require 'openssl'
+
+describe "OpenSSL::HMAC.hexdigest" do
+ it "returns an SHA1 hex digest" do
+ cur_digest = OpenSSL::Digest::SHA1.new
+ cur_digest.hexdigest.should == HMACConstants::BlankSHA1HexDigest
+ hexdigest = OpenSSL::HMAC.hexdigest(cur_digest,
+ HMACConstants::Key,
+ HMACConstants::Contents)
+ hexdigest.should == HMACConstants::SHA1Hexdigest
+ end
+end
+
+# Should add in similar specs for MD5, RIPEMD160, and SHA256
diff --git a/spec/ruby/library/openssl/random/pseudo_bytes_spec.rb b/spec/ruby/library/openssl/random/pseudo_bytes_spec.rb
new file mode 100644
index 0000000000..83c8cc13c8
--- /dev/null
+++ b/spec/ruby/library/openssl/random/pseudo_bytes_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/random_bytes.rb', __FILE__)
+
+if defined?(OpenSSL::Random.pseudo_bytes)
+ describe "OpenSSL::Random.pseudo_bytes" do
+ it_behaves_like :openssl_random_bytes, :pseudo_bytes
+ end
+end
diff --git a/spec/ruby/library/openssl/random/random_bytes_spec.rb b/spec/ruby/library/openssl/random/random_bytes_spec.rb
new file mode 100644
index 0000000000..b8bd209eb0
--- /dev/null
+++ b/spec/ruby/library/openssl/random/random_bytes_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/random_bytes.rb', __FILE__)
+
+describe "OpenSSL::Random.random_bytes" do
+ it_behaves_like :openssl_random_bytes, :random_bytes
+end
diff --git a/spec/ruby/library/openssl/random/shared/random_bytes.rb b/spec/ruby/library/openssl/random/shared/random_bytes.rb
new file mode 100644
index 0000000000..399e40de39
--- /dev/null
+++ b/spec/ruby/library/openssl/random/shared/random_bytes.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'openssl'
+
+describe :openssl_random_bytes, shared: true do |cmd|
+ it "generates a random binary string of specified length" do
+ (1..64).each do |idx|
+ bytes = OpenSSL::Random.send(@method, idx)
+ bytes.should be_kind_of(String)
+ bytes.length.should == idx
+ end
+ end
+
+ it "generates different binary strings with subsequent invocations" do
+ # quick and dirty check, but good enough
+ values = []
+ 256.times do
+ val = OpenSSL::Random.send(@method, 16)
+ # make sure the random bytes are not repeating
+ values.include?(val).should == false
+ values << val
+ end
+ end
+
+ it "raises ArgumentError on negative arguments" do
+ lambda {
+ OpenSSL::Random.send(@method, -1)
+ }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/openssl/shared/constants.rb b/spec/ruby/library/openssl/shared/constants.rb
new file mode 100644
index 0000000000..0bed4156a1
--- /dev/null
+++ b/spec/ruby/library/openssl/shared/constants.rb
@@ -0,0 +1,11 @@
+# -*- encoding: binary -*-
+module HMACConstants
+
+ Contents = "Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. \nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. \nIt was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
+ Key = 'sekrit'
+
+ BlankSHA1Digest = "\3329\243\356^kK\r2U\277\357\225`\030\220\257\330\a\t"
+ SHA1Digest = "\236\022\323\341\037\236\262n\344\t\372:\004J\242\330\257\270\363\264"
+ BlankSHA1HexDigest = "da39a3ee5e6b4b0d3255bfef95601890afd80709"
+ SHA1Hexdigest = "9e12d3e11f9eb26ee409fa3a044aa2d8afb8f3b4"
+end
diff --git a/spec/ruby/library/openssl/x509/name/parse_spec.rb b/spec/ruby/library/openssl/x509/name/parse_spec.rb
new file mode 100644
index 0000000000..c42760fdb7
--- /dev/null
+++ b/spec/ruby/library/openssl/x509/name/parse_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'openssl'
+
+describe "OpenSSL::X509::Name.parse" do
+ it "parses a /-delimited string of key-value pairs into a Name" do
+ dn = "/DC=org/DC=ruby-lang/CN=www.ruby-lang.org"
+ name = OpenSSL::X509::Name.parse(dn)
+
+ name.to_s.should == dn
+
+ ary = name.to_a
+
+ ary[0][0].should == "DC"
+ ary[1][0].should == "DC"
+ ary[2][0].should == "CN"
+ ary[0][1].should == "org"
+ ary[1][1].should == "ruby-lang"
+ ary[2][1].should == "www.ruby-lang.org"
+ ary[0][2].should == OpenSSL::ASN1::IA5STRING
+ ary[1][2].should == OpenSSL::ASN1::IA5STRING
+ ary[2][2].should == OpenSSL::ASN1::UTF8STRING
+ end
+
+ it "parses a comma-delimited string of key-value pairs into a name" do
+ dn = "DC=org, DC=ruby-lang, CN=www.ruby-lang.org"
+ name = OpenSSL::X509::Name.parse(dn)
+
+ name.to_s.should == "/DC=org/DC=ruby-lang/CN=www.ruby-lang.org"
+
+ ary = name.to_a
+
+ ary[0][1].should == "org"
+ ary[1][1].should == "ruby-lang"
+ ary[2][1].should == "www.ruby-lang.org"
+ end
+
+ it "raises TypeError if the given string contains no key/value pairs" do
+ lambda do
+ OpenSSL::X509::Name.parse("hello")
+ end.should raise_error(TypeError)
+ end
+
+ it "raises OpenSSL::X509::NameError if the given string contains invalid keys" do
+ lambda do
+ OpenSSL::X509::Name.parse("hello=goodbye")
+ end.should raise_error(OpenSSL::X509::NameError)
+ end
+end
diff --git a/spec/ruby/library/openstruct/delete_field_spec.rb b/spec/ruby/library/openstruct/delete_field_spec.rb
new file mode 100644
index 0000000000..a565f61b92
--- /dev/null
+++ b/spec/ruby/library/openstruct/delete_field_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ostruct'
+
+describe "OpenStruct#delete_field" do
+ before :each do
+ @os = OpenStruct.new(name: "John Smith", age: 70, pension: 300)
+ end
+
+ it "removes the named field from self's method/value table" do
+ @os.delete_field(:name)
+ @os[:name].should be_nil
+ end
+
+ it "does remove the accessor methods" do
+ @os.delete_field(:name)
+ @os.respond_to?(:name).should be_false
+ @os.respond_to?(:name=).should be_false
+ end
+end
diff --git a/spec/ruby/library/openstruct/element_reference_spec.rb b/spec/ruby/library/openstruct/element_reference_spec.rb
new file mode 100644
index 0000000000..431843547d
--- /dev/null
+++ b/spec/ruby/library/openstruct/element_reference_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "ostruct"
+
+describe "OpenStruct#[]" do
+ before :each do
+ @os = OpenStruct.new
+ end
+
+ it "returns the associated value" do
+ @os.foo = 42
+ @os[:foo].should == 42
+ end
+end
diff --git a/spec/ruby/library/openstruct/element_set_spec.rb b/spec/ruby/library/openstruct/element_set_spec.rb
new file mode 100644
index 0000000000..afa65247e4
--- /dev/null
+++ b/spec/ruby/library/openstruct/element_set_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "ostruct"
+
+describe "OpenStruct#[]=" do
+ before :each do
+ @os = OpenStruct.new
+ end
+
+ it "sets the associated value" do
+ @os[:foo] = 42
+ @os.foo.should == 42
+ end
+end
diff --git a/spec/ruby/library/openstruct/equal_value_spec.rb b/spec/ruby/library/openstruct/equal_value_spec.rb
new file mode 100644
index 0000000000..0d2d1d881e
--- /dev/null
+++ b/spec/ruby/library/openstruct/equal_value_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "ostruct"
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "OpenStruct#==" do
+ before :each do
+ @os = OpenStruct.new(name: "John")
+ end
+
+ it "returns false when the passed argument is no OpenStruct" do
+ (@os == Object.new).should be_false
+ (@os == "Test").should be_false
+ (@os == 10).should be_false
+ (@os == :sym).should be_false
+ end
+
+ it "returns true when self and other are equal method/value wise" do
+ (@os == @os).should be_true
+ (@os == OpenStruct.new(name: "John")).should be_true
+ (@os == OpenStructSpecs::OpenStructSub.new(name: "John")).should be_true
+
+ (@os == OpenStruct.new(name: "Jonny")).should be_false
+ (@os == OpenStructSpecs::OpenStructSub.new(name: "Jonny")).should be_false
+
+ (@os == OpenStruct.new(name: "John", age: 20)).should be_false
+ (@os == OpenStructSpecs::OpenStructSub.new(name: "John", age: 20)).should be_false
+ end
+end
diff --git a/spec/ruby/library/openstruct/fixtures/classes.rb b/spec/ruby/library/openstruct/fixtures/classes.rb
new file mode 100644
index 0000000000..da42e8511d
--- /dev/null
+++ b/spec/ruby/library/openstruct/fixtures/classes.rb
@@ -0,0 +1,4 @@
+module OpenStructSpecs
+ class OpenStructSub < OpenStruct
+ end
+end
diff --git a/spec/ruby/library/openstruct/frozen_spec.rb b/spec/ruby/library/openstruct/frozen_spec.rb
new file mode 100644
index 0000000000..26dd556e97
--- /dev/null
+++ b/spec/ruby/library/openstruct/frozen_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ostruct'
+
+describe "OpenStruct.new when frozen" do
+ before :each do
+ @os = OpenStruct.new(name: "John Smith", age: 70, pension: 300).freeze
+ end
+ #
+ # method_missing case handled in method_missing_spec.rb
+ #
+ it "is still readable" do
+ @os.age.should eql(70)
+ @os.pension.should eql(300)
+ @os.name.should == "John Smith"
+ end
+
+ it "is not writeable" do
+ lambda{ @os.age = 42 }.should raise_error( RuntimeError )
+ end
+
+ it "cannot create new fields" do
+ lambda{ @os.state = :new }.should raise_error( RuntimeError )
+ end
+
+ it "creates a frozen clone" do
+ f = @os.clone
+ f.age.should == 70
+ lambda{ f.age = 0 }.should raise_error( RuntimeError )
+ lambda{ f.state = :newer }.should raise_error( RuntimeError )
+ end
+
+ it "creates an unfrozen dup" do
+ d = @os.dup
+ d.age.should == 70
+ d.age = 42
+ d.age.should == 42
+ end
+end
diff --git a/spec/ruby/library/openstruct/initialize_spec.rb b/spec/ruby/library/openstruct/initialize_spec.rb
new file mode 100644
index 0000000000..b5edde7618
--- /dev/null
+++ b/spec/ruby/library/openstruct/initialize_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ostruct'
+
+describe "OpenStruct#initialize" do
+ it "is private" do
+ OpenStruct.should have_private_instance_method(:initialize)
+ end
+end
diff --git a/spec/ruby/library/openstruct/inspect_spec.rb b/spec/ruby/library/openstruct/inspect_spec.rb
new file mode 100644
index 0000000000..826437b3c1
--- /dev/null
+++ b/spec/ruby/library/openstruct/inspect_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ostruct'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/inspect', __FILE__)
+
+describe "OpenStruct#inspect" do
+ it_behaves_like :ostruct_inspect, :inspect
+end
diff --git a/spec/ruby/library/openstruct/marshal_dump_spec.rb b/spec/ruby/library/openstruct/marshal_dump_spec.rb
new file mode 100644
index 0000000000..cdc1564699
--- /dev/null
+++ b/spec/ruby/library/openstruct/marshal_dump_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "ostruct"
+
+describe "OpenStruct#marshal_dump" do
+ it "returns the method/value table" do
+ os = OpenStruct.new("age" => 20, "name" => "John")
+ os.marshal_dump.should == { age: 20, name: "John" }
+ end
+end
diff --git a/spec/ruby/library/openstruct/marshal_load_spec.rb b/spec/ruby/library/openstruct/marshal_load_spec.rb
new file mode 100644
index 0000000000..9c89697d8f
--- /dev/null
+++ b/spec/ruby/library/openstruct/marshal_load_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "ostruct"
+
+describe "OpenStruct#marshal_load when passed [Hash]" do
+ it "defines methods based on the passed Hash" do
+ os = OpenStruct.new
+ os.marshal_load(age: 20, name: "John")
+
+ os.age.should eql(20)
+ os.name.should == "John"
+ end
+end
diff --git a/spec/ruby/library/openstruct/method_missing_spec.rb b/spec/ruby/library/openstruct/method_missing_spec.rb
new file mode 100644
index 0000000000..6051fd48d8
--- /dev/null
+++ b/spec/ruby/library/openstruct/method_missing_spec.rb
@@ -0,0 +1,47 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "ostruct"
+
+describe "OpenStruct#method_missing when called with a method name ending in '='" do
+ before :each do
+ @os = OpenStruct.new
+ end
+
+ it "raises an ArgumentError when not passed any additional arguments" do
+ lambda { @os.method_missing(:test=) }.should raise_error(ArgumentError)
+ end
+
+ it "raises a TypeError when self is frozen" do
+ @os.freeze
+ lambda { @os.method_missing(:test=, "test") }.should raise_error(RuntimeError)
+ end
+
+ it "creates accessor methods" do
+ @os.method_missing(:test=, "test")
+ @os.respond_to?(:test=).should be_true
+ @os.respond_to?(:test).should be_true
+
+ @os.test.should == "test"
+ @os.test = "changed"
+ @os.test.should == "changed"
+ end
+
+ it "updates the method/value table with the passed method/value" do
+ @os.method_missing(:test=, "test")
+ @os.send(:table)[:test].should == "test"
+ end
+end
+
+describe "OpenStruct#method_missing when passed additional arguments" do
+ it "raises a NoMethodError" do
+ os = OpenStruct.new
+ lambda { os.method_missing(:test, 1, 2, 3) }.should raise_error(NoMethodError)
+ end
+end
+
+describe "OpenStruct#method_missing when not passed any additional arguments" do
+ it "returns the value for the passed method from the method/value table" do
+ os = OpenStruct.new(age: 20)
+ os.method_missing(:age).should eql(20)
+ os.method_missing(:name).should be_nil
+ end
+end
diff --git a/spec/ruby/library/openstruct/new_spec.rb b/spec/ruby/library/openstruct/new_spec.rb
new file mode 100644
index 0000000000..ce33634e08
--- /dev/null
+++ b/spec/ruby/library/openstruct/new_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ostruct'
+
+describe "OpenStruct.new when passed [Hash]" do
+ before :each do
+ @os = OpenStruct.new(name: "John Smith", age: 70, pension: 300)
+ end
+
+ it "creates an attribute for each key of the passed Hash" do
+ @os.age.should eql(70)
+ @os.pension.should eql(300)
+ @os.name.should == "John Smith"
+ end
+end
+
+describe "OpenStruct.new when passed no arguments" do
+ it "returns a new OpenStruct Object without any attributes" do
+ OpenStruct.new.to_s.should == "#<OpenStruct>"
+ end
+end
diff --git a/spec/ruby/library/openstruct/shared/inspect.rb b/spec/ruby/library/openstruct/shared/inspect.rb
new file mode 100644
index 0000000000..ffcd690e1f
--- /dev/null
+++ b/spec/ruby/library/openstruct/shared/inspect.rb
@@ -0,0 +1,20 @@
+describe :ostruct_inspect, shared: true do
+ it "returns a String representation of self" do
+ os = OpenStruct.new(name: "John Smith")
+ os.send(@method).should == "#<OpenStruct name=\"John Smith\">"
+
+ os = OpenStruct.new(age: 20, name: "John Smith")
+ os.send(@method).should be_kind_of(String)
+ end
+
+ it "correctly handles self-referential OpenStructs" do
+ os = OpenStruct.new
+ os.self = os
+ os.send(@method).should == "#<OpenStruct self=#<OpenStruct ...>>"
+ end
+
+ it "correctly handles OpenStruct subclasses" do
+ os = OpenStructSpecs::OpenStructSub.new(name: "John Smith")
+ os.send(@method).should == "#<OpenStructSpecs::OpenStructSub name=\"John Smith\">"
+ end
+end
diff --git a/spec/ruby/library/openstruct/to_h_spec.rb b/spec/ruby/library/openstruct/to_h_spec.rb
new file mode 100644
index 0000000000..f1bffd6fa6
--- /dev/null
+++ b/spec/ruby/library/openstruct/to_h_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ostruct'
+
+describe "OpenStruct#to_h" do
+ before :each do
+ @h = {name: "John Smith", age: 70, pension: 300}
+ @os = OpenStruct.new(@h)
+ @to_h = @os.to_h
+ end
+
+ it "returns a Hash with members as keys" do
+ @to_h.should == @h
+ end
+
+ it "returns a Hash with keys as symbols" do
+ os = OpenStruct.new("name" => "John Smith", "age" => 70)
+ os.pension = 300
+ os.to_h.should == @h
+ end
+
+ it "does not return the hash used as initializer" do
+ @to_h.should_not equal(@h)
+ end
+
+ it "returns a Hash that is independent from the struct" do
+ @to_h[:age] = 71
+ @os.age.should == 70
+ end
+end
diff --git a/spec/ruby/library/openstruct/to_s_spec.rb b/spec/ruby/library/openstruct/to_s_spec.rb
new file mode 100644
index 0000000000..8efa3f5aaf
--- /dev/null
+++ b/spec/ruby/library/openstruct/to_s_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'ostruct'
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/inspect', __FILE__)
+
+describe "OpenStruct#to_s" do
+ it_behaves_like :ostruct_inspect, :to_s
+end
diff --git a/spec/ruby/library/pathname/absolute_spec.rb b/spec/ruby/library/pathname/absolute_spec.rb
new file mode 100644
index 0000000000..af0639493a
--- /dev/null
+++ b/spec/ruby/library/pathname/absolute_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#absolute?" do
+
+ it "returns true for the root directory" do
+ Pathname.new('/').absolute?.should == true
+ end
+
+ it "returns true for a dir starting with a slash" do
+ Pathname.new('/usr/local/bin').absolute?.should == true
+ end
+
+ it "returns false for a dir not starting with a slash" do
+ Pathname.new('fish').absolute?.should == false
+ end
+
+ it "returns false for a dir not starting with a slash" do
+ Pathname.new('fish/dog/cow').absolute?.should == false
+ end
+
+end
+
diff --git a/spec/ruby/library/pathname/equal_value_spec.rb b/spec/ruby/library/pathname/equal_value_spec.rb
new file mode 100644
index 0000000000..afcdb08de8
--- /dev/null
+++ b/spec/ruby/library/pathname/equal_value_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#==" do
+
+ it "returns true when identical paths are used" do
+ (Pathname.new('') == Pathname.new('')).should == true
+ end
+
+ it "returns true when identical paths are used" do
+ (Pathname.new('') == Pathname.new('/usr/local/bin')).should == false
+ end
+
+end
+
diff --git a/spec/ruby/library/pathname/hash_spec.rb b/spec/ruby/library/pathname/hash_spec.rb
new file mode 100644
index 0000000000..f3201e2f4f
--- /dev/null
+++ b/spec/ruby/library/pathname/hash_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#hash" do
+
+ it "is equal to the hash of the pathname" do
+ Pathname.new('/usr/local/bin/').hash.should == '/usr/local/bin/'.hash
+ end
+
+ it "is not equal the hash of a different pathname" do
+ Pathname.new('/usr/local/bin/').hash.should_not == '/usr/bin/'.hash
+ end
+
+end
+
diff --git a/spec/ruby/library/pathname/join_spec.rb b/spec/ruby/library/pathname/join_spec.rb
new file mode 100644
index 0000000000..8c77bb1f59
--- /dev/null
+++ b/spec/ruby/library/pathname/join_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#join" do
+ it "without separators" do
+ Pathname.new('/usr').join(Pathname.new('foo')).should == Pathname.new('/usr/foo')
+ end
+
+ it "with separators" do
+ Pathname.new('/usr').join(Pathname.new('/foo')).should == Pathname.new('/foo')
+ end
+
+ it "with a string" do
+ Pathname.new('/usr').join('foo').should == Pathname.new('/usr/foo')
+ end
+
+ it "with root" do
+ Pathname.new('/usr').join(Pathname.new('/')).should == Pathname.new('/')
+ end
+
+ it "with a relative path" do
+ Pathname.new('/usr').join(Pathname.new('../foo')).should == Pathname.new('/foo')
+ end
+
+ it "a relative path with current" do
+ Pathname.new('.').join(Pathname.new('foo')).should == Pathname.new('foo')
+ end
+
+ it "an absolute path with current" do
+ Pathname.new('.').join(Pathname.new('/foo')).should == Pathname.new('/foo')
+ end
+
+ it "a prefixed relative path with current" do
+ Pathname.new('.').join(Pathname.new('./foo')).should == Pathname.new('foo')
+ end
+
+ it "multiple paths" do
+ Pathname.new('.').join(Pathname.new('./foo'), 'bar').should == Pathname.new('foo/bar')
+ end
+end
diff --git a/spec/ruby/library/pathname/new_spec.rb b/spec/ruby/library/pathname/new_spec.rb
new file mode 100644
index 0000000000..a888e98736
--- /dev/null
+++ b/spec/ruby/library/pathname/new_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname.new" do
+ it "returns a new Pathname Object with 1 argument" do
+ Pathname.new('').should be_kind_of(Pathname)
+ end
+
+ it "raises an ArgumentError when called with \0" do
+ lambda { Pathname.new("\0")}.should raise_error(ArgumentError)
+ end
+
+ it "is tainted if path is tainted" do
+ path = '/usr/local/bin'.taint
+ Pathname.new(path).tainted?.should == true
+ end
+
+ it "raises a TypeError if not passed a String type" do
+ lambda { Pathname.new(nil) }.should raise_error(TypeError)
+ lambda { Pathname.new(0) }.should raise_error(TypeError)
+ lambda { Pathname.new(true) }.should raise_error(TypeError)
+ lambda { Pathname.new(false) }.should raise_error(TypeError)
+ end
+
+ it "initializes with an object with to_path" do
+ Pathname.new(mock_to_path('foo')).should == Pathname.new('foo')
+ end
+end
diff --git a/spec/ruby/library/pathname/parent_spec.rb b/spec/ruby/library/pathname/parent_spec.rb
new file mode 100644
index 0000000000..53d3f1e50e
--- /dev/null
+++ b/spec/ruby/library/pathname/parent_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#parent" do
+
+ it "has parent of root as root" do
+ Pathname.new('/').parent.to_s.should == '/'
+ end
+
+ it "has parent of /usr/ as root" do
+ Pathname.new('/usr/').parent.to_s.should == '/'
+ end
+
+ it "has parent of /usr/local as root" do
+ Pathname.new('/usr/local').parent.to_s.should == '/usr'
+ end
+
+end
+
diff --git a/spec/ruby/library/pathname/realdirpath_spec.rb b/spec/ruby/library/pathname/realdirpath_spec.rb
new file mode 100644
index 0000000000..f76e37602c
--- /dev/null
+++ b/spec/ruby/library/pathname/realdirpath_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#realdirpath" do
+
+ it "returns a Pathname" do
+ Pathname.pwd.realdirpath.should be_an_instance_of(Pathname)
+ end
+
+end
diff --git a/spec/ruby/library/pathname/realpath_spec.rb b/spec/ruby/library/pathname/realpath_spec.rb
new file mode 100644
index 0000000000..e1c9eb34ea
--- /dev/null
+++ b/spec/ruby/library/pathname/realpath_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#realpath" do
+
+ it "returns a Pathname" do
+ Pathname.pwd.realpath.should be_an_instance_of(Pathname)
+ end
+
+end
diff --git a/spec/ruby/library/pathname/relative_path_from_spec.rb b/spec/ruby/library/pathname/relative_path_from_spec.rb
new file mode 100644
index 0000000000..b3bc85e307
--- /dev/null
+++ b/spec/ruby/library/pathname/relative_path_from_spec.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#relative_path_from" do
+ def relative_path_str(dest, base)
+ Pathname.new(dest).relative_path_from(Pathname.new(base)).to_s
+ end
+
+ it "raises an error when the two paths do not share a common prefix" do
+ lambda { relative_path_str('/usr', 'foo') }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error when the base directory has .." do
+ lambda { relative_path_str('a', '..') }.should raise_error(ArgumentError)
+ end
+
+ it "retuns a path relative from root" do
+ relative_path_str('/usr', '/').should == 'usr'
+ end
+
+ it 'returns 1 level up when both paths are relative' do
+ relative_path_str('a', 'b').should == '../a'
+ relative_path_str('a', 'b/').should == '../a'
+ end
+
+ it 'returns a relative path when both are absolute' do
+ relative_path_str('/a', '/b').should == '../a'
+ end
+
+ it "returns a path relative to the current directory" do
+ relative_path_str('/usr/bin/ls', '/usr').should == 'bin/ls'
+ end
+
+ it 'returns a . when base and dest are the same' do
+ relative_path_str('/usr', '/usr').should == '.'
+ end
+
+ it 'returns the same directory with a non clean base that matches the current dir' do
+ relative_path_str('/usr', '/stuff/..').should == 'usr'
+ end
+
+ it 'returns a relative path with a non clean base that matches a different dir' do
+ relative_path_str('/usr', '/stuff/../foo').should == '../usr'
+ end
+
+ it 'returns current and pattern when only those patterns are used' do
+ relative_path_str('.', '.').should == '.'
+ relative_path_str('..', '..').should == '.'
+ relative_path_str('..', '.').should == '..'
+ end
+end
diff --git a/spec/ruby/library/pathname/relative_spec.rb b/spec/ruby/library/pathname/relative_spec.rb
new file mode 100644
index 0000000000..a44d8c5a66
--- /dev/null
+++ b/spec/ruby/library/pathname/relative_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#relative?" do
+
+ it "returns false for the root directory" do
+ Pathname.new('/').relative?.should == false
+ end
+
+ it "returns false for a dir starting with a slash" do
+ Pathname.new('/usr/local/bin').relative?.should == false
+ end
+
+ it "returns true for a dir not starting with a slash" do
+ Pathname.new('fish').relative?.should == true
+ end
+
+ it "returns true for a dir not starting with a slash" do
+ Pathname.new('fish/dog/cow').relative?.should == true
+ end
+
+end
+
diff --git a/spec/ruby/library/pathname/root_spec.rb b/spec/ruby/library/pathname/root_spec.rb
new file mode 100644
index 0000000000..a5efcf69b4
--- /dev/null
+++ b/spec/ruby/library/pathname/root_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#root?" do
+
+ it "returns true for root directories" do
+ Pathname.new('/').root?.should == true
+ end
+
+ it "returns false for empty string" do
+ Pathname.new('').root?.should == false
+ end
+
+ it "returns false for a top level directory" do
+ Pathname.new('/usr').root?.should == false
+ end
+
+ it "returns false for a top level with .. appended directory" do
+ Pathname.new('/usr/..').root?.should == false
+ end
+
+ it "returns false for a directory below top level" do
+ Pathname.new('/usr/local/bin/').root?.should == false
+ end
+
+end
+
diff --git a/spec/ruby/library/pathname/sub_spec.rb b/spec/ruby/library/pathname/sub_spec.rb
new file mode 100644
index 0000000000..36b6ebb247
--- /dev/null
+++ b/spec/ruby/library/pathname/sub_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pathname'
+
+describe "Pathname#sub" do
+
+ it "replaces the pattern with rest" do
+ Pathname.new('/usr/local/bin/').sub(/local/, 'fish').to_s.should == '/usr/fish/bin/'
+ end
+
+ it "returns a new object" do
+ p = Pathname.new('/usr/local/bin/')
+ p.sub(/local/, 'fish').should_not == p
+ end
+
+end
+
diff --git a/spec/ruby/library/pp/pp_spec.rb b/spec/ruby/library/pp/pp_spec.rb
new file mode 100644
index 0000000000..3a0135270a
--- /dev/null
+++ b/spec/ruby/library/pp/pp_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'pp'
+
+describe "PP.pp" do
+ it 'works with default arguments' do
+ array = [1, 2, 3]
+
+ lambda {
+ PP.pp array
+ }.should output "[1, 2, 3]\n"
+ end
+
+ it 'allows specifying out explicitly' do
+ array = [1, 2, 3]
+ other_out = IOStub.new
+
+ lambda {
+ PP.pp array, other_out
+ }.should output "" # no output on stdout
+
+ other_out.to_s.should == "[1, 2, 3]\n"
+ end
+
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/prime/each_spec.rb b/spec/ruby/library/prime/each_spec.rb
new file mode 100644
index 0000000000..bccccfdcdc
--- /dev/null
+++ b/spec/ruby/library/prime/each_spec.rb
@@ -0,0 +1,167 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'prime'
+
+describe :prime_each, shared: true do
+ before :each do
+ ScratchPad.record []
+ end
+
+ it "enumerates primes" do
+ primes = Prime.instance
+ result = []
+
+ primes.each { |p|
+ result << p
+ break if p > 10
+ }
+
+ result.should == [2, 3, 5, 7, 11]
+ end
+
+ it "yields ascending primes to the block" do
+ previous = 1
+ @object.each do |prime|
+ break if prime > 1000
+ ScratchPad << prime
+ prime.should > previous
+ previous = prime
+ end
+
+ all_prime = true
+ ScratchPad.recorded.all? do |prime|
+ all_prime &&= (2..Math.sqrt(prime)).all? { |d| prime % d != 0 }
+ end
+
+ all_prime.should be_true
+ end
+
+ it "returns the last evaluated expression in the passed block" do
+ @object.each { break :value }.should equal(:value)
+ end
+
+ describe "when not passed a block" do
+ before :each do
+ @prime_enum = @object.each
+ end
+
+ it "returns an object that is Enumerable" do
+ @prime_enum.each.should be_kind_of(Enumerable)
+ end
+
+ it "returns an object that responds to #with_index" do
+ @prime_enum.should respond_to(:with_index)
+ end
+
+ it "returns an object that responds to #with_object" do
+ @prime_enum.should respond_to(:with_object)
+ end
+
+ it "returns an object that responds to #next" do
+ @prime_enum.should respond_to(:next)
+ end
+
+ it "returns an object that responds to #rewind" do
+ @prime_enum.should respond_to(:rewind)
+ end
+
+ it "yields primes starting at 2 independent of prior enumerators" do
+ @prime_enum.next.should == 2
+ @prime_enum.next.should == 3
+
+ @object.each { |prime| break prime }.should == 2
+ end
+
+ it "returns an enumerator that yields previous primes when #rewind is called" do
+ @prime_enum.next.should == 2
+ @prime_enum.next.should == 3
+ @prime_enum.rewind
+ @prime_enum.next.should == 2
+ end
+
+ it "returns independent enumerators" do
+ enum = @object.each
+ enum.next.should == 2
+ enum.next.should == 3
+
+ @prime_enum.next.should == 2
+
+ enum.next.should == 5
+ end
+ end
+end
+
+describe :prime_each_with_arguments, shared: true do
+ before :each do
+ ScratchPad.record []
+ end
+
+ it "yields ascending primes less than or equal to the argument" do
+ bound = 1000
+ previous = 1
+ @object.each(bound) do |prime|
+ ScratchPad << prime
+ prime.should > previous
+ previous = prime
+ end
+
+ ScratchPad.recorded.all? do |prime|
+ (2..Math.sqrt(prime)).all? { |d| prime % d != 0 }
+ end.should be_true
+
+ ScratchPad.recorded.all? { |prime| prime <= bound }.should be_true
+ end
+
+ it "returns nil when no prime is generated" do
+ @object.each(1) { :value }.should be_nil
+ end
+
+ it "yields primes starting at 2 independent of prior enumeration" do
+ @object.each(10) { |prime| prime }.should == 7
+ @object.each(10) { |prime| break prime }.should == 2
+ end
+
+ it "accepts a pseudo-prime generator as the second argument" do
+ generator = mock('very bad pseudo-prime generator')
+ generator.should_receive(:upper_bound=).with(100)
+ generator.should_receive(:each).and_yield(2).and_yield(3).and_yield(4)
+
+ @object.each(100, generator) { |prime| ScratchPad << prime }
+ ScratchPad.recorded.should == [2, 3, 4]
+ end
+
+ describe "when not passed a block" do
+ it "returns an object that returns primes less than or equal to the bound" do
+ bound = 100
+ @object.each(bound).all? { |prime| prime <= bound }.should be_true
+ end
+ end
+end
+
+describe "Prime.each" do
+ it_behaves_like :prime_each, :each, Prime
+end
+
+describe "Prime.each" do
+ it_behaves_like :prime_each_with_arguments, :each, Prime
+end
+
+describe "Prime#each with Prime.instance" do
+ it_behaves_like :prime_each, :each, Prime.instance
+end
+
+describe "Prime#each with Prime.instance" do
+ it_behaves_like :prime_each_with_arguments, :each, Prime.instance
+end
+
+describe "Prime#each with Prime.instance" do
+ before :each do
+ @object = Prime.instance
+ end
+
+ it_behaves_like :prime_each, :each
+
+ it "resets the enumerator with each call" do
+ @object.each { |prime| break if prime > 10 }
+ @object.each { |prime| break prime }.should == 2
+ end
+end
diff --git a/spec/ruby/library/prime/instance_spec.rb b/spec/ruby/library/prime/instance_spec.rb
new file mode 100644
index 0000000000..64497c1b7c
--- /dev/null
+++ b/spec/ruby/library/prime/instance_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'prime'
+
+describe "Prime.instance" do
+ it "returns a object representing the set of prime numbers" do
+ Prime.instance.should be_kind_of(Prime)
+ end
+
+ it "returns a object with no obsolete features" do
+ Prime.instance.should_not respond_to(:succ)
+ Prime.instance.should_not respond_to(:next)
+ end
+
+ it "does not complain anything" do
+ lambda { Prime.instance }.should_not complain
+ end
+
+ it "raises a ArgumentError when is called with some arguments" do
+ lambda { Prime.instance(1) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/prime/int_from_prime_division_spec.rb b/spec/ruby/library/prime/int_from_prime_division_spec.rb
new file mode 100644
index 0000000000..df98976f5f
--- /dev/null
+++ b/spec/ruby/library/prime/int_from_prime_division_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'prime'
+
+describe "Prime.int_from_prime_division" do
+ it "returns the product of the given factorization" do
+ Prime.int_from_prime_division([[2,3], [3,3], [5,3], [7,3], [11,3], [13,3], [17,3]]).
+ should == 2**3 * 3**3 * 5**3 * 7**3 * 11**3 * 13**3 * 17**3
+ end
+
+ it "returns 1 for an empty factorization" do
+ Prime.int_from_prime_division([]).should == 1
+ end
+end
diff --git a/spec/ruby/library/prime/integer/each_prime_spec.rb b/spec/ruby/library/prime/integer/each_prime_spec.rb
new file mode 100644
index 0000000000..e1b0092762
--- /dev/null
+++ b/spec/ruby/library/prime/integer/each_prime_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'prime'
+
+describe "Integer.each_prime" do
+ it "is transferred to Prime.each" do
+ Prime.should_receive(:each).with(100).and_yield(2).and_yield(3).and_yield(5)
+ yielded = []
+ Integer.each_prime(100) do |prime|
+ yielded << prime
+ end
+ yielded.should == [2,3,5]
+ end
+end
diff --git a/spec/ruby/library/prime/integer/from_prime_division_spec.rb b/spec/ruby/library/prime/integer/from_prime_division_spec.rb
new file mode 100644
index 0000000000..6ef98a2ecf
--- /dev/null
+++ b/spec/ruby/library/prime/integer/from_prime_division_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'prime'
+
+describe "Integer.from_prime_division" do
+ it "returns the product of the given factorization" do
+ Integer.from_prime_division([[2,3], [3,3], [5,3], [7,3], [11,3], [13,3], [17,3]]).
+ should == 2**3 * 3**3 * 5**3 * 7**3 * 11**3 * 13**3 * 17**3
+ end
+
+ it "returns 1 for an empty factorization" do
+ Integer.from_prime_division([]).should == 1
+ end
+end
diff --git a/spec/ruby/library/prime/integer/prime_division_spec.rb b/spec/ruby/library/prime/integer/prime_division_spec.rb
new file mode 100644
index 0000000000..db137778ea
--- /dev/null
+++ b/spec/ruby/library/prime/integer/prime_division_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'prime'
+
+describe "Integer#prime_division" do
+ it "returns an array of a prime factor and a corresponding exponent" do
+ (2*3*5*7*11*13*17).prime_division.should ==
+ [[2,1], [3,1], [5,1], [7,1], [11,1], [13,1], [17,1]]
+ end
+
+ it "returns an empty array for 1" do
+ 1.prime_division.should == []
+ end
+ it "returns an empty array for -1" do
+ -1.prime_division.should == [[-1, 1]]
+ end
+ it "raises ZeroDivisionError for 0" do
+ lambda { 0.prime_division }.should raise_error(ZeroDivisionError)
+ end
+end
diff --git a/spec/ruby/library/prime/integer/prime_spec.rb b/spec/ruby/library/prime/integer/prime_spec.rb
new file mode 100644
index 0000000000..ba869ba60e
--- /dev/null
+++ b/spec/ruby/library/prime/integer/prime_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'prime'
+
+describe "Integer#prime?" do
+ it "returns a true value for prime numbers" do
+ 2.prime?.should be_true
+ 3.prime?.should be_true
+ (2**31-1).prime?.should be_true # 8th Mersenne prime (M8)
+ end
+
+ it "returns a false value for composite numbers" do
+ 4.prime?.should be_false
+ 15.prime?.should be_false
+ (2**32-1).prime?.should be_false
+ ( (2**17-1)*(2**19-1) ).prime?.should be_false # M6*M7
+ end
+end
diff --git a/spec/ruby/library/prime/next_spec.rb b/spec/ruby/library/prime/next_spec.rb
new file mode 100644
index 0000000000..afff353d6e
--- /dev/null
+++ b/spec/ruby/library/prime/next_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/next', __FILE__)
+require 'prime'
+
+describe "Prime#next" do
+ it_behaves_like :prime_next, :next
+end
diff --git a/spec/ruby/library/prime/prime_division_spec.rb b/spec/ruby/library/prime/prime_division_spec.rb
new file mode 100644
index 0000000000..faca8bda02
--- /dev/null
+++ b/spec/ruby/library/prime/prime_division_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'prime'
+
+describe "Prime.prime_division" do
+ it "returns an array of a prime factor and a corresponding exponent" do
+ Prime.prime_division(2*3*5*7*11*13*17).should ==
+ [[2,1], [3,1], [5,1], [7,1], [11,1], [13,1], [17,1]]
+ end
+
+ it "returns an empty array for 1" do
+ Prime.prime_division(1).should == []
+ end
+
+ it "returns [[-1, 1]] for -1" do
+ Prime.prime_division(-1).should == [[-1, 1]]
+ end
+
+ it "includes [[-1, 1]] in the divisors of a negative number" do
+ Prime.prime_division(-10).should include([-1, 1])
+ end
+
+ it "raises ZeroDivisionError for 0" do
+ lambda { Prime.prime_division(0) }.should raise_error(ZeroDivisionError)
+ end
+end
diff --git a/spec/ruby/library/prime/prime_spec.rb b/spec/ruby/library/prime/prime_spec.rb
new file mode 100644
index 0000000000..7a41496f7f
--- /dev/null
+++ b/spec/ruby/library/prime/prime_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'prime'
+
+describe "Prime#prime?" do
+ it "returns a true value for prime numbers" do
+ Prime.prime?(2).should be_true
+ Prime.prime?(3).should be_true
+ Prime.prime?(2**31-1).should be_true # 8th Mersenne prime (M8)
+ end
+
+ it "returns a false value for composite numbers" do
+ Prime.prime?(4).should be_false
+ Prime.prime?(15).should be_false
+ Prime.prime?(2**32-1).should be_false
+ Prime.prime?( (2**17-1)*(2**19-1) ).should be_false # M6*M7
+ end
+end
diff --git a/spec/ruby/library/prime/shared/next.rb b/spec/ruby/library/prime/shared/next.rb
new file mode 100644
index 0000000000..f79b2c051e
--- /dev/null
+++ b/spec/ruby/library/prime/shared/next.rb
@@ -0,0 +1,8 @@
+describe :prime_next, shared: true do
+ it "returns the element at the current position and moves forward" do
+ p = Prime.instance.each
+ p.next.should == 2
+ p.next.should == 3
+ p.next.next.should == 6
+ end
+end
diff --git a/spec/ruby/library/prime/succ_spec.rb b/spec/ruby/library/prime/succ_spec.rb
new file mode 100644
index 0000000000..85d22ee654
--- /dev/null
+++ b/spec/ruby/library/prime/succ_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/next', __FILE__)
+require 'prime'
+
+describe "Prime#succ" do
+ it_behaves_like :prime_next, :succ
+end
diff --git a/spec/ruby/library/readline/basic_quote_characters_spec.rb b/spec/ruby/library/readline/basic_quote_characters_spec.rb
new file mode 100644
index 0000000000..7d25df2047
--- /dev/null
+++ b/spec/ruby/library/readline/basic_quote_characters_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+platform_is_not :darwin do
+ with_feature :readline do
+ describe "Readline.basic_quote_characters" do
+ it "returns not nil" do
+ Readline.basic_quote_characters.should_not be_nil
+ end
+ end
+
+ describe "Readline.basic_quote_characters=" do
+ it "returns the passed string" do
+ Readline.basic_quote_characters = "test"
+ Readline.basic_quote_characters.should == "test"
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/basic_word_break_characters_spec.rb b/spec/ruby/library/readline/basic_word_break_characters_spec.rb
new file mode 100644
index 0000000000..c2ec6cede7
--- /dev/null
+++ b/spec/ruby/library/readline/basic_word_break_characters_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline.basic_word_break_characters" do
+ it "returns not nil" do
+ Readline.basic_word_break_characters.should_not be_nil
+ end
+ end
+
+ describe "Readline.basic_word_break_characters=" do
+ it "returns the passed string" do
+ Readline.basic_word_break_characters = "test"
+ Readline.basic_word_break_characters.should == "test"
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/completer_quote_characters_spec.rb b/spec/ruby/library/readline/completer_quote_characters_spec.rb
new file mode 100644
index 0000000000..a836a0591e
--- /dev/null
+++ b/spec/ruby/library/readline/completer_quote_characters_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline.completer_quote_characters" do
+ it "returns nil" do
+ Readline.completer_quote_characters.should be_nil
+ end
+ end
+
+ describe "Readline.completer_quote_characters=" do
+ it "returns the passed string" do
+ Readline.completer_quote_characters = "test"
+ Readline.completer_quote_characters.should == "test"
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/completer_word_break_characters_spec.rb b/spec/ruby/library/readline/completer_word_break_characters_spec.rb
new file mode 100644
index 0000000000..2e0cc277a6
--- /dev/null
+++ b/spec/ruby/library/readline/completer_word_break_characters_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline.completer_word_break_characters" do
+ it "returns nil" do
+ Readline.completer_word_break_characters.should be_nil
+ end
+ end
+
+ describe "Readline.completer_word_break_characters=" do
+ it "returns the passed string" do
+ Readline.completer_word_break_characters = "test"
+ Readline.completer_word_break_characters.should == "test"
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/completion_append_character_spec.rb b/spec/ruby/library/readline/completion_append_character_spec.rb
new file mode 100644
index 0000000000..ee41abea05
--- /dev/null
+++ b/spec/ruby/library/readline/completion_append_character_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline.completion_append_character" do
+ it "returns not nil" do
+ Readline.completion_append_character.should_not be_nil
+ end
+ end
+
+ describe "Readline.completion_append_character=" do
+ it "returns the first character of the passed string" do
+ Readline.completion_append_character = "test"
+ Readline.completion_append_character.should == "t"
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/completion_case_fold_spec.rb b/spec/ruby/library/readline/completion_case_fold_spec.rb
new file mode 100644
index 0000000000..604460869e
--- /dev/null
+++ b/spec/ruby/library/readline/completion_case_fold_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline.completion_case_fold" do
+ it "returns nil" do
+ Readline.completion_case_fold.should be_nil
+ end
+ end
+
+ describe "Readline.completion_case_fold=" do
+ it "returns the passed boolean" do
+ Readline.completion_case_fold = true
+ Readline.completion_case_fold.should == true
+ Readline.completion_case_fold = false
+ Readline.completion_case_fold.should == false
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/completion_proc_spec.rb b/spec/ruby/library/readline/completion_proc_spec.rb
new file mode 100644
index 0000000000..e525fbd191
--- /dev/null
+++ b/spec/ruby/library/readline/completion_proc_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline.completion_proc" do
+ it "returns nil" do
+ Readline.completion_proc.should be_nil
+ end
+ end
+
+ describe "Readline.completion_proc=" do
+ it "returns the passed Proc" do
+ proc = Proc.new do |e|
+ end
+ Readline.completion_proc = proc
+ Readline.completion_proc.should == proc
+ end
+
+ it "returns an ArgumentError if not given an Proc or #call" do
+ lambda { Readline.completion_proc = "test" }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/constants_spec.rb b/spec/ruby/library/readline/constants_spec.rb
new file mode 100644
index 0000000000..226a3509b9
--- /dev/null
+++ b/spec/ruby/library/readline/constants_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+with_feature :readline do
+ # Note: additional specs for HISTORY are in 'history' subdir.
+ describe "Readline::HISTORY" do
+ it "is defined" do
+ Readline.const_defined?(:HISTORY).should == true
+ end
+ end
+
+ describe "Readline::VERSION" do
+ it "is defined and is a non-empty String" do
+ Readline.const_defined?(:VERSION).should == true
+ Readline::VERSION.should be_kind_of(String)
+ Readline::VERSION.should_not be_empty
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/emacs_editing_mode_spec.rb b/spec/ruby/library/readline/emacs_editing_mode_spec.rb
new file mode 100644
index 0000000000..6c2e84b08f
--- /dev/null
+++ b/spec/ruby/library/readline/emacs_editing_mode_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+platform_is_not :darwin do
+ with_feature :readline do
+ describe "Readline.emacs_editing_mode" do
+ it "returns nil" do
+ Readline.emacs_editing_mode.should be_nil
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/filename_quote_characters_spec.rb b/spec/ruby/library/readline/filename_quote_characters_spec.rb
new file mode 100644
index 0000000000..abee5e9700
--- /dev/null
+++ b/spec/ruby/library/readline/filename_quote_characters_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+platform_is_not :darwin do
+ with_feature :readline do
+ describe "Readline.filename_quote_characters" do
+ it "returns nil" do
+ Readline.filename_quote_characters.should be_nil
+ end
+ end
+
+ describe "Readline.filename_quote_characters=" do
+ it "returns the passed string" do
+ Readline.filename_quote_characters = "test"
+ Readline.filename_quote_characters.should == "test"
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/append_spec.rb b/spec/ruby/library/readline/history/append_spec.rb
new file mode 100644
index 0000000000..3ea0bbf57f
--- /dev/null
+++ b/spec/ruby/library/readline/history/append_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.<<" do
+ it "appends the given Object to the history" do
+ Readline::HISTORY << "1"
+ Readline::HISTORY.size.should == 1
+
+ Readline::HISTORY << "2"
+ Readline::HISTORY.size.should == 2
+
+ Readline::HISTORY.pop.should == "2"
+ Readline::HISTORY.pop.should == "1"
+ end
+
+ it "tries to convert the passed Object to a String using #to_str" do
+ obj = mock("Converted to String")
+ obj.should_receive(:to_str).and_return("converted")
+
+ Readline::HISTORY << obj
+ Readline::HISTORY.pop.should == "converted"
+ end
+
+ it "raises a TypeError when the passed Object can't be converted to a String" do
+ lambda { Readline::HISTORY << mock("Object") }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/delete_at_spec.rb b/spec/ruby/library/readline/history/delete_at_spec.rb
new file mode 100644
index 0000000000..38f180ca08
--- /dev/null
+++ b/spec/ruby/library/readline/history/delete_at_spec.rb
@@ -0,0 +1,45 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.delete_at" do
+ it "deletes and returns the history entry at the specified index" do
+ Readline::HISTORY.push("1", "2", "3")
+
+ Readline::HISTORY.delete_at(1).should == "2"
+ Readline::HISTORY.size.should == 2
+
+ Readline::HISTORY.delete_at(1).should == "3"
+ Readline::HISTORY.size.should == 1
+
+ Readline::HISTORY.delete_at(0).should == "1"
+ Readline::HISTORY.size.should == 0
+
+
+ Readline::HISTORY.push("1", "2", "3", "4")
+
+ Readline::HISTORY.delete_at(-2).should == "3"
+ Readline::HISTORY.size.should == 3
+
+ Readline::HISTORY.delete_at(-2).should == "2"
+ Readline::HISTORY.size.should == 2
+
+ Readline::HISTORY.delete_at(0).should == "1"
+ Readline::HISTORY.size.should == 1
+
+ Readline::HISTORY.delete_at(0).should == "4"
+ Readline::HISTORY.size.should == 0
+ end
+
+ it "raises an IndexError when the given index is greater than the history size" do
+ lambda { Readline::HISTORY.delete_at(10) }.should raise_error(IndexError)
+ lambda { Readline::HISTORY.delete_at(-10) }.should raise_error(IndexError)
+ end
+
+ it "taints the returned strings" do
+ Readline::HISTORY.push("1", "2", "3")
+ Readline::HISTORY.delete_at(0).tainted?.should be_true
+ Readline::HISTORY.delete_at(0).tainted?.should be_true
+ Readline::HISTORY.delete_at(0).tainted?.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/each_spec.rb b/spec/ruby/library/readline/history/each_spec.rb
new file mode 100644
index 0000000000..5057e04970
--- /dev/null
+++ b/spec/ruby/library/readline/history/each_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.each" do
+ before :each do
+ Readline::HISTORY.push("1", "2", "3")
+ end
+
+ after :each do
+ Readline::HISTORY.pop
+ Readline::HISTORY.pop
+ Readline::HISTORY.pop
+ end
+
+ it "yields each item in the history" do
+ result = []
+ Readline::HISTORY.each do |x|
+ result << x
+ end
+ result.should == ["1", "2", "3"]
+ end
+
+ it "yields tainted Objects" do
+ Readline::HISTORY.each do |x|
+ x.tainted?.should be_true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/element_reference_spec.rb b/spec/ruby/library/readline/history/element_reference_spec.rb
new file mode 100644
index 0000000000..c656179ddd
--- /dev/null
+++ b/spec/ruby/library/readline/history/element_reference_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.[]" do
+ before :each do
+ Readline::HISTORY.push("1", "2", "3")
+ end
+
+ after :each do
+ Readline::HISTORY.pop
+ Readline::HISTORY.pop
+ Readline::HISTORY.pop
+ end
+
+ it "returns tainted objects" do
+ Readline::HISTORY[0].tainted?.should be_true
+ Readline::HISTORY[1].tainted?.should be_true
+ end
+
+ it "returns the history item at the passed index" do
+ Readline::HISTORY[0].should == "1"
+ Readline::HISTORY[1].should == "2"
+ Readline::HISTORY[2].should == "3"
+
+ Readline::HISTORY[-1].should == "3"
+ Readline::HISTORY[-2].should == "2"
+ Readline::HISTORY[-3].should == "1"
+ end
+
+ it "raises an IndexError when there is no item at the passed index" do
+ lambda { Readline::HISTORY[-10] }.should raise_error(IndexError)
+ lambda { Readline::HISTORY[-9] }.should raise_error(IndexError)
+ lambda { Readline::HISTORY[-8] }.should raise_error(IndexError)
+
+ lambda { Readline::HISTORY[8] }.should raise_error(IndexError)
+ lambda { Readline::HISTORY[9] }.should raise_error(IndexError)
+ lambda { Readline::HISTORY[10] }.should raise_error(IndexError)
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/element_set_spec.rb b/spec/ruby/library/readline/history/element_set_spec.rb
new file mode 100644
index 0000000000..8d6fe196ef
--- /dev/null
+++ b/spec/ruby/library/readline/history/element_set_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.[]=" do
+ before :each do
+ Readline::HISTORY.push("1", "2", "3")
+ end
+
+ after :each do
+ Readline::HISTORY.pop
+ Readline::HISTORY.pop
+ Readline::HISTORY.pop
+ end
+
+ it "returns the new value for the passed index" do
+ (Readline::HISTORY[1] = "second test").should == "second test"
+ end
+
+ it "raises an IndexError when there is no item at the passed positive index" do
+ lambda { Readline::HISTORY[10] = "test" }.should raise_error(IndexError)
+ end
+
+ it "sets the item at the given index" do
+ Readline::HISTORY[0] = "test"
+ Readline::HISTORY[0].should == "test"
+
+ Readline::HISTORY[1] = "second test"
+ Readline::HISTORY[1].should == "second test"
+ end
+
+ it "raises an IndexError when there is no item at the passed negative index" do
+ lambda { Readline::HISTORY[10] = "test" }.should raise_error(IndexError)
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/empty_spec.rb b/spec/ruby/library/readline/history/empty_spec.rb
new file mode 100644
index 0000000000..92a4fcd063
--- /dev/null
+++ b/spec/ruby/library/readline/history/empty_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.empty?" do
+ it "returns true when the history is empty" do
+ Readline::HISTORY.should be_empty
+ Readline::HISTORY.push("test")
+ Readline::HISTORY.should_not be_empty
+ Readline::HISTORY.pop
+ Readline::HISTORY.should be_empty
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/history_spec.rb b/spec/ruby/library/readline/history/history_spec.rb
new file mode 100644
index 0000000000..dfa6544036
--- /dev/null
+++ b/spec/ruby/library/readline/history/history_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY" do
+ it "is extended with the Enumerable module" do
+ Readline::HISTORY.should be_kind_of(Enumerable)
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/length_spec.rb b/spec/ruby/library/readline/history/length_spec.rb
new file mode 100644
index 0000000000..6700d4f234
--- /dev/null
+++ b/spec/ruby/library/readline/history/length_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ require File.expand_path('../shared/size', __FILE__)
+
+ describe "Readline::HISTORY.length" do
+ it_behaves_like :readline_history_size, :length
+ end
+end
diff --git a/spec/ruby/library/readline/history/pop_spec.rb b/spec/ruby/library/readline/history/pop_spec.rb
new file mode 100644
index 0000000000..34562dff3b
--- /dev/null
+++ b/spec/ruby/library/readline/history/pop_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.pop" do
+ it "returns nil when the history is empty" do
+ Readline::HISTORY.pop.should be_nil
+ end
+
+ it "returns and removes the last item from the history" do
+ Readline::HISTORY.push("1", "2", "3")
+ Readline::HISTORY.size.should == 3
+
+ Readline::HISTORY.pop.should == "3"
+ Readline::HISTORY.size.should == 2
+
+ Readline::HISTORY.pop.should == "2"
+ Readline::HISTORY.size.should == 1
+
+ Readline::HISTORY.pop.should == "1"
+ Readline::HISTORY.size.should == 0
+ end
+
+ it "taints the returned strings" do
+ Readline::HISTORY.push("1", "2", "3")
+ Readline::HISTORY.pop.tainted?.should be_true
+ Readline::HISTORY.pop.tainted?.should be_true
+ Readline::HISTORY.pop.tainted?.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/push_spec.rb b/spec/ruby/library/readline/history/push_spec.rb
new file mode 100644
index 0000000000..b59b17ed03
--- /dev/null
+++ b/spec/ruby/library/readline/history/push_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.push" do
+ it "pushes all passed Objects into the history" do
+ Readline::HISTORY.push("1", "2", "3")
+ Readline::HISTORY.size.should == 3
+
+ Readline::HISTORY.pop.should == "3"
+ Readline::HISTORY.pop.should == "2"
+ Readline::HISTORY.pop.should == "1"
+ end
+
+ it "tries to convert the passed Object to a String using #to_str" do
+ obj = mock("Converted to String")
+ obj.should_receive(:to_str).and_return("converted")
+
+ Readline::HISTORY.push(obj)
+ Readline::HISTORY.pop.should == "converted"
+ end
+
+ it "raises a TypeError when the passed Object can't be converted to a String" do
+ lambda { Readline::HISTORY.push(mock("Object")) }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/shared/size.rb b/spec/ruby/library/readline/history/shared/size.rb
new file mode 100644
index 0000000000..1d6df86f78
--- /dev/null
+++ b/spec/ruby/library/readline/history/shared/size.rb
@@ -0,0 +1,14 @@
+describe :readline_history_size, shared: true do
+ it "returns the size of the history" do
+ Readline::HISTORY.send(@method).should == 0
+ Readline::HISTORY.push("1", "2", "")
+ Readline::HISTORY.send(@method).should == 3
+
+ Readline::HISTORY.pop
+ Readline::HISTORY.send(@method).should == 2
+
+ Readline::HISTORY.pop
+ Readline::HISTORY.pop
+ Readline::HISTORY.send(@method).should == 0
+ end
+end
diff --git a/spec/ruby/library/readline/history/shift_spec.rb b/spec/ruby/library/readline/history/shift_spec.rb
new file mode 100644
index 0000000000..3d4782998d
--- /dev/null
+++ b/spec/ruby/library/readline/history/shift_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.shift" do
+ it "returns nil when the history is empty" do
+ Readline::HISTORY.shift.should be_nil
+ end
+
+ it "returns and removes the first item from the history" do
+ Readline::HISTORY.push("1", "2", "3")
+ Readline::HISTORY.size.should == 3
+
+ Readline::HISTORY.shift.should == "1"
+ Readline::HISTORY.size.should == 2
+
+ Readline::HISTORY.shift.should == "2"
+ Readline::HISTORY.size.should == 1
+
+ Readline::HISTORY.shift.should == "3"
+ Readline::HISTORY.size.should == 0
+ end
+
+ it "taints the returned strings" do
+ Readline::HISTORY.push("1", "2", "3")
+ Readline::HISTORY.shift.tainted?.should be_true
+ Readline::HISTORY.shift.tainted?.should be_true
+ Readline::HISTORY.shift.tainted?.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/history/size_spec.rb b/spec/ruby/library/readline/history/size_spec.rb
new file mode 100644
index 0000000000..815c68de27
--- /dev/null
+++ b/spec/ruby/library/readline/history/size_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ require File.expand_path('../shared/size', __FILE__)
+
+ describe "Readline::HISTORY.size" do
+ it_behaves_like :readline_history_size, :size
+ end
+end
diff --git a/spec/ruby/library/readline/history/to_s_spec.rb b/spec/ruby/library/readline/history/to_s_spec.rb
new file mode 100644
index 0000000000..30ba5a1249
--- /dev/null
+++ b/spec/ruby/library/readline/history/to_s_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline::HISTORY.to_s" do
+ it "returns 'HISTORY'" do
+ Readline::HISTORY.to_s.should == "HISTORY"
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/readline_spec.rb b/spec/ruby/library/readline/readline_spec.rb
new file mode 100644
index 0000000000..599f84dffd
--- /dev/null
+++ b/spec/ruby/library/readline/readline_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+with_feature :readline do
+ describe "Readline.readline" do
+ before :each do
+ @file = tmp('readline')
+ @out = tmp('out.txt')
+ touch(@file) { |f|
+ f.puts "test"
+ }
+ @options = { options: "-rreadline", args: [@out, "< #{@file}"] }
+ end
+
+ after :each do
+ rm_r @file, @out
+ end
+
+ # Somehow those specs block on Windows
+ platform_is_not :windows do
+ it "returns the input string" do
+ ruby_exe('File.write ARGV[0], Readline.readline', @options)
+ File.read(@out).should == "test"
+ end
+
+ it "taints the returned strings" do
+ ruby_exe('File.write ARGV[0], Readline.readline.tainted?', @options)
+ File.read(@out).should == "true"
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/readline/spec_helper.rb b/spec/ruby/library/readline/spec_helper.rb
new file mode 100644
index 0000000000..04ab0f755f
--- /dev/null
+++ b/spec/ruby/library/readline/spec_helper.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+begin
+ require 'readline'
+rescue LoadError
+else
+ # rb-readline behaves quite differently
+ unless defined?(RbReadline)
+ MSpec.enable_feature :readline
+ end
+end
diff --git a/spec/ruby/library/readline/vi_editing_mode_spec.rb b/spec/ruby/library/readline/vi_editing_mode_spec.rb
new file mode 100644
index 0000000000..db6d4387f8
--- /dev/null
+++ b/spec/ruby/library/readline/vi_editing_mode_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+platform_is_not :darwin do
+ with_feature :readline do
+ describe "Readline.vi_editing_mode" do
+ it "returns nil" do
+ Readline.vi_editing_mode.should be_nil
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/resolv/get_address_spec.rb b/spec/ruby/library/resolv/get_address_spec.rb
new file mode 100644
index 0000000000..cb71bb6ec4
--- /dev/null
+++ b/spec/ruby/library/resolv/get_address_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'resolv'
+
+describe "Resolv#getaddress" do
+ platform_is_not :windows do
+ it "resolves localhost" do
+ res = Resolv.new([Resolv::Hosts.new])
+
+ lambda {
+ res.getaddress("localhost")
+ }.should_not raise_error(Resolv::ResolvError)
+ end
+ end
+
+ it "raises ResolvError if the name can not be looked up" do
+ res = Resolv.new([])
+ lambda {
+ res.getaddress("should.raise.error.")
+ }.should raise_error(Resolv::ResolvError)
+ end
+end
diff --git a/spec/ruby/library/resolv/get_addresses_spec.rb b/spec/ruby/library/resolv/get_addresses_spec.rb
new file mode 100644
index 0000000000..2ab3d35eba
--- /dev/null
+++ b/spec/ruby/library/resolv/get_addresses_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'resolv'
+
+describe "Resolv#getaddresses" do
+ platform_is_not :windows do
+ it "resolves localhost" do
+ res = Resolv.new([Resolv::Hosts.new])
+
+ addresses = res.getaddresses("localhost")
+ addresses.should_not == nil
+ addresses.size.should > 0
+ end
+ end
+end
diff --git a/spec/ruby/library/resolv/get_name_spec.rb b/spec/ruby/library/resolv/get_name_spec.rb
new file mode 100644
index 0000000000..06a27e922a
--- /dev/null
+++ b/spec/ruby/library/resolv/get_name_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'resolv'
+
+describe "Resolv#getname" do
+ platform_is_not :windows do
+ it "resolves 127.0.0.1" do
+ lambda {
+ Resolv.getname("127.0.0.1")
+ }.should_not raise_error(Resolv::ResolvError)
+ end
+ end
+
+ it "raises ResolvError when there is no result" do
+ res = Resolv.new([])
+ lambda {
+ res.getname("should.raise.error")
+ }.should raise_error(Resolv::ResolvError)
+ end
+end
diff --git a/spec/ruby/library/resolv/get_names_spec.rb b/spec/ruby/library/resolv/get_names_spec.rb
new file mode 100644
index 0000000000..f2bb08a653
--- /dev/null
+++ b/spec/ruby/library/resolv/get_names_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'resolv'
+
+describe "Resolv#getnames" do
+ platform_is_not :windows do
+ it "resolves 127.0.0.1" do
+ res = Resolv.new([Resolv::Hosts.new])
+
+ names = res.getnames("127.0.0.1")
+ names.should_not == nil
+ names.size.should > 0
+ end
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/clone_spec.rb b/spec/ruby/library/rexml/attribute/clone_spec.rb
new file mode 100644
index 0000000000..df0d9ca466
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/clone_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#clone" do
+ it "returns a copy of this Attribute" do
+ orig = REXML::Attribute.new("name", "value&&")
+ orig.should == orig.clone
+ orig.clone.to_s.should == orig.to_s
+ orig.clone.to_string.should == orig.to_string
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/element_spec.rb b/spec/ruby/library/rexml/attribute/element_spec.rb
new file mode 100644
index 0000000000..c518bb7b55
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/element_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#element" do
+ it "returns the parent element" do
+ e = REXML::Element.new "root"
+
+ REXML::Attribute.new("name", "value", e).element.should == e
+ REXML::Attribute.new("name", "default_constructor").element.should == nil
+ end
+end
+
+describe "REXML::Attribute#element=" do
+ it "sets the parent element" do
+ e = REXML::Element.new "root"
+ f = REXML::Element.new "temp"
+ a = REXML::Attribute.new("name", "value", e)
+ a.element.should == e
+
+ a.element = f
+ a.element.should == f
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/equal_value_spec.rb b/spec/ruby/library/rexml/attribute/equal_value_spec.rb
new file mode 100644
index 0000000000..2a7aa9e87e
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/equal_value_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#==" do
+ it "returns true if other has equal name and value" do
+ a1 = REXML::Attribute.new("foo", "bar")
+ a1.should == a1.clone
+
+ a2 = REXML::Attribute.new("foo", "bar")
+ a1.should == a2
+
+ a3 = REXML::Attribute.new("foo", "bla")
+ a1.should_not == a3
+
+ a4 = REXML::Attribute.new("baz", "bar")
+ a1.should_not == a4
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/hash_spec.rb b/spec/ruby/library/rexml/attribute/hash_spec.rb
new file mode 100644
index 0000000000..a77c23aada
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/hash_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#hash" do
+ # These are not really complete, any idea on how to make them more
+ # "testable" will be appreciated.
+ it "returns a hashcode made of the name and value of self" do
+ a = REXML::Attribute.new("name", "value")
+ a.hash.should be_kind_of(Numeric)
+ b = REXML::Attribute.new(a)
+ a.hash.should == b.hash
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/initialize_spec.rb b/spec/ruby/library/rexml/attribute/initialize_spec.rb
new file mode 100644
index 0000000000..637bd1b012
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/initialize_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#initialize" do
+ before :each do
+ @e = REXML::Element.new "root"
+ @name = REXML::Attribute.new("name", "Nicko")
+ @e.add_attribute @name
+ end
+
+ it "receives two strings for name and value" do
+ @e.attributes["name"].should == "Nicko"
+ @e.add_attribute REXML::Attribute.new("last_name", nil)
+ @e.attributes["last_name"].should == ""
+ end
+
+ it "receives an Attribute and clones it" do
+ copy = REXML::Attribute.new(@name)
+ copy.should == @name
+ end
+
+ it "recives a parent node" do
+ last_name = REXML::Attribute.new("last_name", "McBrain", @e)
+ last_name.element.should == @e
+
+ last_name = REXML::Attribute.new(@name, @e)
+ last_name.element.should == @e
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/inspect_spec.rb b/spec/ruby/library/rexml/attribute/inspect_spec.rb
new file mode 100644
index 0000000000..bfc764f663
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/inspect_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#inspect" do
+ it "returns the name and value as a string" do
+ a = REXML::Attribute.new("my_name", "my_value")
+ a.inspect.should == "my_name='my_value'"
+ end
+
+ it "accepts attributes with no value" do
+ a = REXML::Attribute.new("my_name")
+ a.inspect.should == "my_name=''"
+ end
+
+ it "does not escape text" do
+ a = REXML::Attribute.new("&&", "<>")
+ a.inspect.should == "&&='<>'"
+ end
+end
+
diff --git a/spec/ruby/library/rexml/attribute/namespace_spec.rb b/spec/ruby/library/rexml/attribute/namespace_spec.rb
new file mode 100644
index 0000000000..5df9742cd3
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/namespace_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#namespace" do
+ it "returns the namespace url" do
+ e = REXML::Element.new("root")
+ e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri")
+ e.namespace("ns").should == "http://some_uri"
+ end
+
+ it "returns nil if namespace is not defined" do
+ e = REXML::Element.new("root")
+ e.add_attribute REXML::Attribute.new("test", "value")
+ e.namespace("test").should == nil
+ e.namespace("ns").should == nil
+ end
+
+ it "defaults arg to nil" do
+ e = REXML::Element.new("root")
+ e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri")
+ e.namespace.should == ""
+ e.namespace("ns").should == "http://some_uri"
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/node_type_spec.rb b/spec/ruby/library/rexml/attribute/node_type_spec.rb
new file mode 100644
index 0000000000..d44695deff
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/node_type_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#node_type" do
+ it "always returns :attribute" do
+ attr = REXML::Attribute.new("foo", "bar")
+ attr.node_type.should == :attribute
+ REXML::Attribute.new(attr).node_type.should == :attribute
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/prefix_spec.rb b/spec/ruby/library/rexml/attribute/prefix_spec.rb
new file mode 100644
index 0000000000..698c8d5d7b
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/prefix_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#prefix" do
+ it "returns the namespace of the Attribute" do
+ ans = REXML::Attribute.new("ns:someattr", "some_value")
+ out = REXML::Attribute.new("out:something", "some_other_value")
+
+ ans.prefix.should == "ns"
+ out.prefix.should == "out"
+ end
+
+ it "returns an empty string for Attributes with no prefixes" do
+ attr = REXML::Attribute.new("foo", "bar")
+
+ attr.prefix.should == ""
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/remove_spec.rb b/spec/ruby/library/rexml/attribute/remove_spec.rb
new file mode 100644
index 0000000000..5a08ef3a3c
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/remove_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#remove" do
+ before :each do
+ @e = REXML::Element.new "Root"
+ @attr = REXML::Attribute.new("foo", "bar")
+ end
+
+ it "deletes this Attribute from parent" do
+ @e.add_attribute(@attr)
+ @e.attributes["foo"].should_not == nil
+ @attr.remove
+ @e.attributes["foo"].should == nil
+ end
+
+ it "does not anything if element has no parent" do
+ lambda {@attr.remove}.should_not raise_error(Exception)
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/to_s_spec.rb b/spec/ruby/library/rexml/attribute/to_s_spec.rb
new file mode 100644
index 0000000000..96831625b6
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/to_s_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#to_s" do
+ it "returns the value of the Attribute" do
+ REXML::Attribute.new("name", "some_value").to_s.should == "some_value"
+ end
+
+ it "returns the escaped value if it was created from Attribute" do
+ orig = REXML::Attribute.new("name", "<&>")
+ copy = REXML::Attribute.new(orig)
+ copy.to_s.should == "&lt;&amp;&gt;"
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/to_string_spec.rb b/spec/ruby/library/rexml/attribute/to_string_spec.rb
new file mode 100644
index 0000000000..f8cc639a9d
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/to_string_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#to_string" do
+ it "returns the attribute as XML" do
+ attr = REXML::Attribute.new("name", "value")
+ attr_empty = REXML::Attribute.new("name")
+ attr_ns = REXML::Attribute.new("xmlns:ns", "http://uri")
+
+ attr.to_string.should == "name='value'"
+ attr_empty.to_string.should == "name=''"
+ attr_ns.to_string.should == "xmlns:ns='http://uri'"
+ end
+end
+
diff --git a/spec/ruby/library/rexml/attribute/value_spec.rb b/spec/ruby/library/rexml/attribute/value_spec.rb
new file mode 100644
index 0000000000..912509cd75
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/value_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#value" do
+ it "returns the value of the Attribute unnormalized" do
+ attr = REXML::Attribute.new("name", "value")
+ attr_ents = REXML::Attribute.new("name", "<&>")
+ attr_empty = REXML::Attribute.new("name")
+
+ attr.value.should == "value"
+ attr_ents.value.should == "<&>"
+ attr_empty.value.should == ""
+ end
+end
+
diff --git a/spec/ruby/library/rexml/attribute/write_spec.rb b/spec/ruby/library/rexml/attribute/write_spec.rb
new file mode 100644
index 0000000000..b6b59930e3
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/write_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#write" do
+ before :each do
+ @attr = REXML::Attribute.new("name", "Charlotte")
+ @s = ""
+ end
+
+ it "writes the name and value to output" do
+ @attr.write(@s)
+ @s.should == "name='Charlotte'"
+ end
+
+ it "currently ignores the second argument" do
+ @attr.write(@s, 3)
+ @s.should == "name='Charlotte'"
+
+ @s = ""
+ @attr.write(@s, "foo")
+ @s.should == "name='Charlotte'"
+ end
+end
diff --git a/spec/ruby/library/rexml/attribute/xpath_spec.rb b/spec/ruby/library/rexml/attribute/xpath_spec.rb
new file mode 100644
index 0000000000..6fb80ead37
--- /dev/null
+++ b/spec/ruby/library/rexml/attribute/xpath_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attribute#xpath" do
+
+ before :each do
+ @e = REXML::Element.new "root"
+ @attr = REXML::Attribute.new("year", "1989")
+ end
+
+ it "returns the path for Attribute" do
+ @e.add_attribute @attr
+ @attr.xpath.should == "root/@year"
+ end
+
+ it "raises an error if attribute has no parent" do
+ lambda { @attr.xpath }.should raise_error(Exception)
+ end
+end
+
diff --git a/spec/ruby/library/rexml/attributes/add_spec.rb b/spec/ruby/library/rexml/attributes/add_spec.rb
new file mode 100644
index 0000000000..72e3c4c823
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/add_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/add', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#add" do
+ it_behaves_like :rexml_attribute_add, :add
+end
diff --git a/spec/ruby/library/rexml/attributes/append_spec.rb b/spec/ruby/library/rexml/attributes/append_spec.rb
new file mode 100644
index 0000000000..89f3fc3e81
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/append_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/add', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#<<" do
+ it_behaves_like :rexml_attribute_add, :<<
+end
diff --git a/spec/ruby/library/rexml/attributes/delete_all_spec.rb b/spec/ruby/library/rexml/attributes/delete_all_spec.rb
new file mode 100644
index 0000000000..f11f0d66a3
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/delete_all_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#delete_all" do
+ before :each do
+ @e = REXML::Element.new("root")
+ end
+
+ it "deletes all attributes that match name" do
+ uri = REXML::Attribute.new("uri", "http://something")
+ @e.attributes << uri
+ @e.attributes.delete_all("uri")
+ @e.attributes.should be_empty
+ @e.attributes["uri"].should == nil
+ end
+
+ it "deletes all attributes that match name with a namespace" do
+ ns_uri = REXML::Attribute.new("xmlns:uri", "http://something_here_too")
+ @e.attributes << ns_uri
+ @e.attributes.delete_all("xmlns:uri")
+ @e.attributes.should be_empty
+ @e.attributes["xmlns:uri"].should == nil
+ end
+
+ it "returns the removed attribute" do
+ uri = REXML::Attribute.new("uri", "http://something_here_too")
+ @e.attributes << uri
+ attrs = @e.attributes.delete_all("uri")
+ attrs.first.should == uri
+ end
+end
diff --git a/spec/ruby/library/rexml/attributes/delete_spec.rb b/spec/ruby/library/rexml/attributes/delete_spec.rb
new file mode 100644
index 0000000000..1c02e5c03b
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/delete_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#delete" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @name = REXML::Attribute.new("name", "Pepe")
+ end
+
+ it "takes an attribute name and deletes the attribute" do
+ @e.attributes.delete("name")
+ @e.attributes["name"].should be_nil
+ @e.attributes.should be_empty
+ end
+
+ it "takes an Attribute and deletes it" do
+ @e.attributes.delete(@name)
+ @e.attributes["name"].should be_nil
+ @e.attributes.should be_empty
+ end
+
+ it "returns the element with the attribute removed" do
+ ret_val = @e.attributes.delete(@name)
+ ret_val.should == @e
+ ret_val.attributes.should be_empty
+ end
+end
diff --git a/spec/ruby/library/rexml/attributes/each_attribute_spec.rb b/spec/ruby/library/rexml/attributes/each_attribute_spec.rb
new file mode 100644
index 0000000000..cd1649be21
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/each_attribute_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#each_attribute" do
+ it "iterates over the attributes yielding actual Attribute objects" do
+ e = REXML::Element.new("root")
+ name = REXML::Attribute.new("name", "Joe")
+ ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri")
+ e.add_attribute name
+ e.add_attribute ns_uri
+
+ attributes = []
+
+ e.attributes.each_attribute do |attr|
+ attributes << attr
+ end
+
+ attributes = attributes.sort_by {|a| a.name }
+ attributes.first.should == name
+ attributes.last.should == ns_uri
+ end
+end
+
+
+
diff --git a/spec/ruby/library/rexml/attributes/each_spec.rb b/spec/ruby/library/rexml/attributes/each_spec.rb
new file mode 100644
index 0000000000..f49bc75c0d
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/each_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#each" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @name = REXML::Attribute.new("name", "Joe")
+ @ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri")
+ @e.add_attribute @name
+ @e.add_attribute @ns_uri
+ end
+
+ it "iterates over the attributes yielding expanded-name/value" do
+ attributes = []
+ @e.attributes.each do |attr|
+ attr.should be_kind_of(Array)
+ attributes << attr
+ end
+ attributes = attributes.sort_by {|a| a.first }
+ attributes.first.should == ["name", "Joe"]
+ attributes.last.should == ["xmlns:ns", "http://some_uri"]
+ end
+end
+
+
diff --git a/spec/ruby/library/rexml/attributes/element_reference_spec.rb b/spec/ruby/library/rexml/attributes/element_reference_spec.rb
new file mode 100644
index 0000000000..0e85ecafe8
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/element_reference_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#[]" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @lang = REXML::Attribute.new("language", "english")
+ @e.attributes << @lang
+ end
+
+ it "returns the value of an attribute" do
+ @e.attributes["language"].should == "english"
+ end
+
+ it "returns nil if the attribute does not exist" do
+ @e.attributes["chunky bacon"].should == nil
+ end
+end
+
diff --git a/spec/ruby/library/rexml/attributes/element_set_spec.rb b/spec/ruby/library/rexml/attributes/element_set_spec.rb
new file mode 100644
index 0000000000..659d259df6
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/element_set_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#[]=" do
+ before :each do
+ @e = REXML::Element.new("song")
+ @name = REXML::Attribute.new("name", "Holy Smoke!")
+ @e.attributes << @name
+ end
+
+ it "sets an attribute" do
+ @e.attributes["author"] = "_why's foxes"
+ @e.attributes["author"].should == "_why's foxes"
+ end
+
+ it "overwrites an existing attribute" do
+ @e.attributes["name"] = "Chunky Bacon"
+ @e.attributes["name"].should == "Chunky Bacon"
+ end
+
+ it "deletes an attribute is value is nil" do
+ @e.attributes["name"] = nil
+ @e.attributes.length.should == 0
+ end
+end
+
diff --git a/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb b/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb
new file mode 100644
index 0000000000..f4aeb76378
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#get_attribute_ns" do
+ it "returns an attribute by name and namespace" do
+ e = REXML::Element.new("root")
+ attr = REXML::Attribute.new("xmlns:ns", "http://some_url")
+ e.attributes << attr
+ attr.prefix.should == "xmlns"
+ # This might be a bug in Attribute, commenting until those specs
+ # are ready
+ # e.attributes.get_attribute_ns(attr.prefix, "name").should == "http://some_url"
+ end
+end
diff --git a/spec/ruby/library/rexml/attributes/get_attribute_spec.rb b/spec/ruby/library/rexml/attributes/get_attribute_spec.rb
new file mode 100644
index 0000000000..b7d83f5944
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/get_attribute_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#get_attribute" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @name = REXML::Attribute.new("name", "Dave")
+ @e.attributes << @name
+ end
+
+ it "fetches an attributes" do
+ @e.attributes.get_attribute("name").should == @name
+ end
+
+ it "fetches an namespaced attribute" do
+ ns_name = REXML::Attribute.new("im:name", "Murray")
+ @e.attributes << ns_name
+ @e.attributes.get_attribute("name").should == @name
+ @e.attributes.get_attribute("im:name").should == ns_name
+ end
+
+ it "returns an Attribute" do
+ @e.attributes.get_attribute("name").should be_kind_of(REXML::Attribute)
+ end
+
+ it "returns nil if it attribute does not exist" do
+ @e.attributes.get_attribute("fake").should be_nil
+ end
+end
diff --git a/spec/ruby/library/rexml/attributes/initialize_spec.rb b/spec/ruby/library/rexml/attributes/initialize_spec.rb
new file mode 100644
index 0000000000..2bf59b1f76
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/initialize_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#initialize" do
+ it "is auto initialized by Element" do
+ e = REXML::Element.new "root"
+ e.attributes.should be_kind_of(REXML::Attributes)
+
+ e.attributes << REXML::Attribute.new("name", "Paul")
+ e.attributes["name"].should == "Paul"
+ end
+
+ it "receives a parent node" do
+ e = REXML::Element.new "root"
+ e.attributes << REXML::Attribute.new("name", "Vic")
+ e.attributes["name"].should == "Vic"
+ end
+end
diff --git a/spec/ruby/library/rexml/attributes/length_spec.rb b/spec/ruby/library/rexml/attributes/length_spec.rb
new file mode 100644
index 0000000000..cd68461e34
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/length_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#length" do
+ it_behaves_like :rexml_attribute_length, :length
+end
diff --git a/spec/ruby/library/rexml/attributes/namespaces_spec.rb b/spec/ruby/library/rexml/attributes/namespaces_spec.rb
new file mode 100644
index 0000000000..41486d0316
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/namespaces_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#namespaces" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/rexml/attributes/prefixes_spec.rb b/spec/ruby/library/rexml/attributes/prefixes_spec.rb
new file mode 100644
index 0000000000..9eca67b5ff
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/prefixes_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#prefixes" do
+ before :each do
+ @e = REXML::Element.new("root")
+ a1 = REXML::Attribute.new("xmlns:a", "bar")
+ a2 = REXML::Attribute.new("xmlns:b", "bla")
+ a3 = REXML::Attribute.new("xmlns:c", "baz")
+ @e.attributes << a1
+ @e.attributes << a2
+ @e.attributes << a3
+
+ @e.attributes << REXML::Attribute.new("xmlns", "foo")
+ end
+
+ it "returns an array with the prefixes of each attribute" do
+ @e.attributes.prefixes.sort.should == ["a", "b", "c"]
+ end
+
+ it "does not include the default namespace" do
+ @e.attributes.prefixes.include?("xmlns").should == false
+ end
+end
diff --git a/spec/ruby/library/rexml/attributes/shared/add.rb b/spec/ruby/library/rexml/attributes/shared/add.rb
new file mode 100644
index 0000000000..872f149f45
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/shared/add.rb
@@ -0,0 +1,17 @@
+describe :rexml_attribute_add, shared: true do
+ before :each do
+ @e = REXML::Element.new("root")
+ @attr = REXML::Attributes.new(@e)
+ @name = REXML::Attribute.new("name", "Joe")
+ end
+
+ it "adds an attribute" do
+ @attr.send(@method, @name)
+ @attr["name"].should == "Joe"
+ end
+
+ it "replaces an existing attribute" do
+ @attr.send(@method, REXML::Attribute.new("name", "Bruce"))
+ @attr["name"].should == "Bruce"
+ end
+end
diff --git a/spec/ruby/library/rexml/attributes/shared/length.rb b/spec/ruby/library/rexml/attributes/shared/length.rb
new file mode 100644
index 0000000000..94681882a6
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/shared/length.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe :rexml_attribute_length, shared: true do
+ it "returns the number of attributes" do
+ e = REXML::Element.new("root")
+ e.attributes.send(@method).should == 0
+
+ e.attributes << REXML::Attribute.new("name", "John")
+ e.attributes << REXML::Attribute.new("another_name", "Leo")
+ e.attributes.send(@method).should == 2
+ end
+end
diff --git a/spec/ruby/library/rexml/attributes/size_spec.rb b/spec/ruby/library/rexml/attributes/size_spec.rb
new file mode 100644
index 0000000000..761fcc1d5b
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/size_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#size" do
+ it_behaves_like :rexml_attribute_length, :size
+end
diff --git a/spec/ruby/library/rexml/attributes/to_a_spec.rb b/spec/ruby/library/rexml/attributes/to_a_spec.rb
new file mode 100644
index 0000000000..a3de48cf1c
--- /dev/null
+++ b/spec/ruby/library/rexml/attributes/to_a_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Attributes#to_a" do
+ it "returns an array with the attributes" do
+ e = REXML::Element.new("root")
+ name = REXML::Attribute.new("name", "Dave")
+ last = REXML::Attribute.new("last_name", "Murray")
+
+ e.attributes << name
+ e.attributes << last
+
+ e.attributes.to_a.sort{|a,b|a.to_s<=>b.to_s}.should == [name, last]
+ end
+
+ it "returns an empty array if it has no attributes" do
+ REXML::Element.new("root").attributes.to_a.should == []
+ end
+end
+
diff --git a/spec/ruby/library/rexml/cdata/clone_spec.rb b/spec/ruby/library/rexml/cdata/clone_spec.rb
new file mode 100644
index 0000000000..15dcf13a04
--- /dev/null
+++ b/spec/ruby/library/rexml/cdata/clone_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::CData#clone" do
+ it "makes a copy of itself" do
+ c = REXML::CData.new("some text")
+ c.clone.to_s.should == c.to_s
+ c.clone.should == c
+ end
+end
diff --git a/spec/ruby/library/rexml/cdata/initialize_spec.rb b/spec/ruby/library/rexml/cdata/initialize_spec.rb
new file mode 100644
index 0000000000..bc0bc5cd6d
--- /dev/null
+++ b/spec/ruby/library/rexml/cdata/initialize_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::CData#initialize" do
+ it "creates a new CData object" do
+ c = REXML::CData.new("some text")
+ c.should be_kind_of(REXML::CData)
+ c.should be_kind_of(REXML::Text)
+ end
+
+ it "respects whitespace if whitespace is true" do
+ c = REXML::CData.new("whitespace test", true)
+ c1 = REXML::CData.new("whitespace test", false)
+
+ c.to_s.should == "whitespace test"
+ c1.to_s.should == "whitespace test"
+ end
+
+ it "receives parent as third argument" do
+ e = REXML::Element.new("root")
+ REXML::CData.new("test", true, e)
+ e.to_s.should == "<root><![CDATA[test]]></root>"
+ end
+end
diff --git a/spec/ruby/library/rexml/cdata/shared/to_s.rb b/spec/ruby/library/rexml/cdata/shared/to_s.rb
new file mode 100644
index 0000000000..f8c4951c95
--- /dev/null
+++ b/spec/ruby/library/rexml/cdata/shared/to_s.rb
@@ -0,0 +1,11 @@
+describe :rexml_cdata_to_s, shared: true do
+ it "returns the contents of the CData" do
+ c = REXML::CData.new("some text")
+ c.send(@method).should == "some text"
+ end
+
+ it "does not escape text" do
+ c1 = REXML::CData.new("some& text\n")
+ c1.send(@method).should == "some& text\n"
+ end
+end
diff --git a/spec/ruby/library/rexml/cdata/to_s_spec.rb b/spec/ruby/library/rexml/cdata/to_s_spec.rb
new file mode 100644
index 0000000000..3fb233cdaf
--- /dev/null
+++ b/spec/ruby/library/rexml/cdata/to_s_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/to_s', __FILE__)
+require 'rexml/document'
+
+describe "REXML::CData#to_s" do
+ it_behaves_like :rexml_cdata_to_s, :to_s
+end
diff --git a/spec/ruby/library/rexml/cdata/value_spec.rb b/spec/ruby/library/rexml/cdata/value_spec.rb
new file mode 100644
index 0000000000..f9af73c0f6
--- /dev/null
+++ b/spec/ruby/library/rexml/cdata/value_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/to_s', __FILE__)
+require 'rexml/document'
+
+describe "REXML::CData#value" do
+ it_behaves_like :rexml_cdata_to_s, :value
+end
diff --git a/spec/ruby/library/rexml/document/add_element_spec.rb b/spec/ruby/library/rexml/document/add_element_spec.rb
new file mode 100644
index 0000000000..03c95727e2
--- /dev/null
+++ b/spec/ruby/library/rexml/document/add_element_spec.rb
@@ -0,0 +1,31 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Document#add_element" do
+ it "adds arg1 with attributes arg2 as root node" do
+ d = REXML::Document.new
+ e = REXML::Element.new("root")
+ d.add_element e
+ d.root.should == e
+ end
+
+ it "sets arg2 as arg1's attributes" do
+ d = REXML::Document.new
+ e = REXML::Element.new("root")
+ attr = {"foo" => "bar"}
+ d.add_element(e,attr)
+ d.root.attributes["foo"].should == attr["foo"]
+ end
+
+ it "accepts a node name as arg1 and adds it as root" do
+ d = REXML::Document.new
+ d.add_element "foo"
+ d.root.name.should == "foo"
+ end
+
+ it "sets arg1's context to the root's context" do
+ d = REXML::Document.new("", {"foo" => "bar"})
+ d.add_element "foo"
+ d.root.context.should == d.context
+ end
+end
diff --git a/spec/ruby/library/rexml/document/add_spec.rb b/spec/ruby/library/rexml/document/add_spec.rb
new file mode 100644
index 0000000000..491c28259b
--- /dev/null
+++ b/spec/ruby/library/rexml/document/add_spec.rb
@@ -0,0 +1,57 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+# This spec defines Document#add and Document#<<
+
+describe :rexml_document_add, shared: true do
+ before :each do
+ @doc = REXML::Document.new("<root/>")
+ @decl = REXML::XMLDecl.new("1.0")
+ end
+
+ it "sets document's XML declaration" do
+ @doc.send(@method, @decl)
+ @doc.xml_decl.should == @decl
+ end
+
+ it "inserts XML declaration as first node" do
+ @doc.send(@method, @decl)
+ @doc.children[0].version.should == "1.0"
+ end
+
+ it "overwrites existing XML declaration" do
+ @doc.send(@method, @decl)
+ @doc.send(@method, REXML::XMLDecl.new("2.0"))
+ @doc.xml_decl.version.should == "2.0"
+ end
+
+ it "sets document DocType" do
+ @doc.send(@method, REXML::DocType.new("transitional"))
+ @doc.doctype.name.should == "transitional"
+ end
+
+ it "overwrites existing DocType" do
+ @doc.send(@method, REXML::DocType.new("transitional"))
+ @doc.send(@method, REXML::DocType.new("strict"))
+ @doc.doctype.name.should == "strict"
+ end
+
+ it "adds root node unless it exists" do
+ d = REXML::Document.new("")
+ elem = REXML::Element.new "root"
+ d.send(@method, elem)
+ d.root.should == elem
+ end
+
+ it "refuses to add second root" do
+ lambda { @doc.send(@method, REXML::Element.new("foo")) }.should raise_error(RuntimeError)
+ end
+end
+
+describe "REXML::Document#add" do
+ it_behaves_like(:rexml_document_add, :add)
+end
+
+describe "REXML::Document#<<" do
+ it_behaves_like(:rexml_document_add, :<<)
+end
diff --git a/spec/ruby/library/rexml/document/clone_spec.rb b/spec/ruby/library/rexml/document/clone_spec.rb
new file mode 100644
index 0000000000..cf333bf4df
--- /dev/null
+++ b/spec/ruby/library/rexml/document/clone_spec.rb
@@ -0,0 +1,20 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+# According to the MRI documentation (http://www.ruby-doc.org/stdlib/libdoc/rexml/rdoc/index.html),
+# clone's behavior "should be obvious". Apparently "obvious" means cloning
+# only the attributes and the context of the document, not its children.
+describe "REXML::Document#clone" do
+ it "clones document attributes" do
+ d = REXML::Document.new("foo")
+ d.attributes["foo"] = "bar"
+ e = d.clone
+ e.attributes.should == d.attributes
+ end
+
+ it "clones document context" do
+ d = REXML::Document.new("foo", {"foo" => "bar"})
+ e = d.clone
+ e.context.should == d.context
+ end
+end
diff --git a/spec/ruby/library/rexml/document/doctype_spec.rb b/spec/ruby/library/rexml/document/doctype_spec.rb
new file mode 100644
index 0000000000..5f277f6ad6
--- /dev/null
+++ b/spec/ruby/library/rexml/document/doctype_spec.rb
@@ -0,0 +1,15 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Document#doctype" do
+ it "returns the doctype" do
+ d = REXML::Document.new
+ dt = REXML::DocType.new("foo")
+ d.add dt
+ d.doctype.should == dt
+ end
+
+ it "returns nil if there's no doctype" do
+ REXML::Document.new.doctype.should == nil
+ end
+end
diff --git a/spec/ruby/library/rexml/document/encoding_spec.rb b/spec/ruby/library/rexml/document/encoding_spec.rb
new file mode 100644
index 0000000000..d20be0f7b7
--- /dev/null
+++ b/spec/ruby/library/rexml/document/encoding_spec.rb
@@ -0,0 +1,22 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Document#encoding" do
+ before :each do
+ @doc = REXML::Document.new
+ end
+
+ it "returns encoding from XML declaration" do
+ @doc.add REXML::XMLDecl.new(nil, "UTF-16", nil)
+ @doc.encoding.should == "UTF-16"
+ end
+
+ it "returns encoding from XML declaration (for UTF-16 as well)" do
+ @doc.add REXML::XMLDecl.new("1.0", "UTF-8", nil)
+ @doc.encoding.should == "UTF-8"
+ end
+
+ it "uses UTF-8 as default encoding" do
+ @doc.encoding.should == "UTF-8"
+ end
+end
diff --git a/spec/ruby/library/rexml/document/expanded_name_spec.rb b/spec/ruby/library/rexml/document/expanded_name_spec.rb
new file mode 100644
index 0000000000..e18fd95c14
--- /dev/null
+++ b/spec/ruby/library/rexml/document/expanded_name_spec.rb
@@ -0,0 +1,16 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe :document_expanded_name, shared: true do
+ it "returns an empty string for root" do # root nodes have no expanded name
+ REXML::Document.new.send(@method).should == ""
+ end
+end
+
+describe "REXML::Document#expanded_name" do
+ it_behaves_like(:document_expanded_name, :expanded_name)
+end
+
+describe "REXML::Document#name" do
+ it_behaves_like(:document_expanded_name, :name)
+end
diff --git a/spec/ruby/library/rexml/document/new_spec.rb b/spec/ruby/library/rexml/document/new_spec.rb
new file mode 100644
index 0000000000..0caa3fd583
--- /dev/null
+++ b/spec/ruby/library/rexml/document/new_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Document#new" do
+
+ it "initializes context of {} unless specified" do
+ d = REXML::Document.new("<foo />")
+ d.context.should == {}
+ end
+
+ it "has empty attributes if source is nil" do
+ d = REXML::Document.new(nil)
+ d.elements.should be_empty
+ end
+
+ it "can use other document context" do
+ s = REXML::Document.new("")
+ d = REXML::Document.new(s)
+ d.context.should == s.context
+ end
+
+ it "clones source attributes" do
+ s = REXML::Document.new("<root />")
+ s.attributes["some_attr"] = "some_val"
+ d = REXML::Document.new(s)
+ d.attributes.should == s.attributes
+ end
+
+ it "raises an error if source is not a Document, String or IO" do
+ lambda {REXML::Document.new(3)}.should raise_error(RuntimeError)
+ end
+
+ it "does not perform XML validation" do
+ REXML::Document.new("Invalid document").should be_kind_of(REXML::Document)
+ end
+end
diff --git a/spec/ruby/library/rexml/document/node_type_spec.rb b/spec/ruby/library/rexml/document/node_type_spec.rb
new file mode 100644
index 0000000000..b18b1a0dfe
--- /dev/null
+++ b/spec/ruby/library/rexml/document/node_type_spec.rb
@@ -0,0 +1,8 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Document#node_type" do
+ it "returns :document" do
+ REXML::Document.new.node_type.should == :document
+ end
+end
diff --git a/spec/ruby/library/rexml/document/root_spec.rb b/spec/ruby/library/rexml/document/root_spec.rb
new file mode 100644
index 0000000000..55be68da6f
--- /dev/null
+++ b/spec/ruby/library/rexml/document/root_spec.rb
@@ -0,0 +1,12 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Document#root" do
+ it "returns document root tag name" do
+ REXML::Document.new("<foo/>").root.name.should == "foo"
+ end
+
+ it "returns nil if there is not root" do
+ REXML::Document.new.root.should == nil
+ end
+end
diff --git a/spec/ruby/library/rexml/document/stand_alone_spec.rb b/spec/ruby/library/rexml/document/stand_alone_spec.rb
new file mode 100644
index 0000000000..250c604dad
--- /dev/null
+++ b/spec/ruby/library/rexml/document/stand_alone_spec.rb
@@ -0,0 +1,19 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Document#stand_alone?" do
+ it "returns the XMLDecl standalone value" do
+ d = REXML::Document.new
+ decl = REXML::XMLDecl.new("1.0", "UTF-8", "yes")
+ d.add decl
+ d.stand_alone?.should == "yes"
+ end
+
+ # According to the docs this should return the default XMLDecl but that
+ # will carry some more problems when printing the document. Currently, it
+ # returns nil. See http://www.ruby-forum.com/topic/146812#650061
+ it "returns the default value when no XML declaration present" do
+ REXML::Document.new.stand_alone?.should == nil
+ end
+
+end
diff --git a/spec/ruby/library/rexml/document/version_spec.rb b/spec/ruby/library/rexml/document/version_spec.rb
new file mode 100644
index 0000000000..ca979dbf34
--- /dev/null
+++ b/spec/ruby/library/rexml/document/version_spec.rb
@@ -0,0 +1,14 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Document#version" do
+ it "returns XML version from declaration" do
+ d = REXML::Document.new
+ d.add REXML::XMLDecl.new("1.1")
+ d.version.should == "1.1"
+ end
+
+ it "returns the default version when declaration is not present" do
+ REXML::Document.new.version.should == REXML::XMLDecl::DEFAULT_VERSION
+ end
+end
diff --git a/spec/ruby/library/rexml/document/write_spec.rb b/spec/ruby/library/rexml/document/write_spec.rb
new file mode 100644
index 0000000000..f2a7e2c200
--- /dev/null
+++ b/spec/ruby/library/rexml/document/write_spec.rb
@@ -0,0 +1,35 @@
+require 'rexml/document'
+require 'rexml/formatters/transitive'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+# Maybe this can be cleaned
+describe "REXML::Document#write" do
+ before :each do
+ @d = REXML::Document.new
+ city = REXML::Element.new "Springfield"
+ street = REXML::Element.new "EvergreenTerrace"
+ address = REXML::Element.new "House742"
+ @d << city << street << address
+ @str = ""
+ end
+
+ it "returns document source as string" do
+ @d.write(@str)
+ @str.should == "<Springfield><EvergreenTerrace><House742/></EvergreenTerrace></Springfield>"
+ end
+
+ it "returns document indented" do
+ @d.write(@str, 2)
+ @str.should =~ /\s*<Springfield>\s*<EvergreenTerrace>\s*<House742\/>\s*<\/EvergreenTerrace>\s*<\/Springfield>/
+ end
+
+ it "returns document with transitive support" do
+ @d.write(@str, 2, true)
+ @str.should =~ /\s*<Springfield\s*><EvergreenTerrace\s*><House742\s*\/><\/EvergreenTerrace\s*><\/Springfield\s*>/
+ end
+
+ it "returns document with support for IE" do
+ @d.write(@str, -1, false, true)
+ @str.should == "<Springfield><EvergreenTerrace><House742 /></EvergreenTerrace></Springfield>"
+ end
+end
diff --git a/spec/ruby/library/rexml/document/xml_decl_spec.rb b/spec/ruby/library/rexml/document/xml_decl_spec.rb
new file mode 100644
index 0000000000..6a5bf07c0b
--- /dev/null
+++ b/spec/ruby/library/rexml/document/xml_decl_spec.rb
@@ -0,0 +1,15 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Document#xml_decl" do
+ it "returns XML declaration of the document" do
+ d = REXML::Document.new
+ decl = REXML::XMLDecl.new("1.0", "UTF-16", "yes")
+ d.add decl
+ d.xml_decl.should == decl
+ end
+
+ it "returns default XML declaration unless present" do
+ REXML::Document.new.xml_decl.should == REXML::XMLDecl.new
+ end
+end
diff --git a/spec/ruby/library/rexml/element/add_attribute_spec.rb b/spec/ruby/library/rexml/element/add_attribute_spec.rb
new file mode 100644
index 0000000000..998f5d6251
--- /dev/null
+++ b/spec/ruby/library/rexml/element/add_attribute_spec.rb
@@ -0,0 +1,41 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#add_attribute" do
+ before :each do
+ @person = REXML::Element.new "person"
+ @person.attributes["name"] = "Bill"
+ end
+
+ it "adds a new attribute" do
+ @person.add_attribute("age", "17")
+ @person.attributes["age"].should == "17"
+ end
+
+ it "overwrites an existing attribute" do
+ @person.add_attribute("name", "Bill")
+ @person.attributes["name"].should == "Bill"
+ end
+
+ it "accepts a pair of strings" do
+ @person.add_attribute("male", "true")
+ @person.attributes["male"].should == "true"
+ end
+
+ it "accepts an Attribute for key" do
+ attr = REXML::Attribute.new("male", "true")
+ @person.add_attribute attr
+ @person.attributes["male"].should == "true"
+ end
+
+ it "ignores value if key is an Attribute" do
+ attr = REXML::Attribute.new("male", "true")
+ @person.add_attribute(attr, "false")
+ @person.attributes["male"].should == "true"
+ end
+
+ it "returns the attribute added" do
+ attr = REXML::Attribute.new("name", "Tony")
+ @person.add_attribute(attr).should == attr
+ end
+end
diff --git a/spec/ruby/library/rexml/element/add_attributes_spec.rb b/spec/ruby/library/rexml/element/add_attributes_spec.rb
new file mode 100644
index 0000000000..aa64b677ca
--- /dev/null
+++ b/spec/ruby/library/rexml/element/add_attributes_spec.rb
@@ -0,0 +1,22 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#add_attribute" do
+ before :each do
+ @person = REXML::Element.new "person"
+ @person.attributes["name"] = "Bill"
+ end
+
+ it "adds multiple attributes from a hash" do
+ @person.add_attributes({"name" => "Joe", "age" => "27"})
+ @person.attributes["name"].should == "Joe"
+ @person.attributes["age"].should == "27"
+ end
+
+ it "adds multiple attributes from an array" do
+ attrs = { "name" => "Joe", "age" => "27"}
+ @person.add_attributes attrs.to_a
+ @person.attributes["name"].should == "Joe"
+ @person.attributes["age"].should == "27"
+ end
+end
diff --git a/spec/ruby/library/rexml/element/add_element_spec.rb b/spec/ruby/library/rexml/element/add_element_spec.rb
new file mode 100644
index 0000000000..b6aab3da6a
--- /dev/null
+++ b/spec/ruby/library/rexml/element/add_element_spec.rb
@@ -0,0 +1,39 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+
+describe "REXML::Element#add_element" do
+ before :each do
+ @root = REXML::Element.new("root")
+ end
+
+ it "adds a child without attributes" do
+ name = REXML::Element.new("name")
+ @root.add_element name
+ @root.elements["name"].name.should == name.name
+ @root.elements["name"].attributes.should == name.attributes
+ @root.elements["name"].context.should == name.context
+ end
+
+ it "adds a child with attributes" do
+ person = REXML::Element.new("person")
+ @root.add_element(person, {"name" => "Madonna"})
+ @root.elements["person"].name.should == person.name
+ @root.elements["person"].attributes.should == person.attributes
+ @root.elements["person"].context.should == person.context
+ end
+
+ it "adds a child with name" do
+ @root.add_element "name"
+ @root.elements["name"].name.should == "name"
+ @root.elements["name"].attributes.should == {}
+ @root.elements["name"].context.should == nil
+ end
+
+ it "returns the added child" do
+ name = @root.add_element "name"
+ @root.elements["name"].name.should == name.name
+ @root.elements["name"].attributes.should == name.attributes
+ @root.elements["name"].context.should == name.context
+ end
+end
diff --git a/spec/ruby/library/rexml/element/add_namespace_spec.rb b/spec/ruby/library/rexml/element/add_namespace_spec.rb
new file mode 100644
index 0000000000..60db839f02
--- /dev/null
+++ b/spec/ruby/library/rexml/element/add_namespace_spec.rb
@@ -0,0 +1,24 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#add_namespace" do
+ before :each do
+ @elem = REXML::Element.new("person")
+ end
+
+ it "adds a namespace to element" do
+ @elem.add_namespace("foo", "bar")
+ @elem.namespace("foo").should == "bar"
+ end
+
+ it "accepts a prefix string as prefix" do
+ @elem.add_namespace("xmlns:foo", "bar")
+ @elem.namespace("foo").should == "bar"
+ end
+
+ it "uses prefix as URI if uri is nil" do
+ @elem.add_namespace("some_uri", nil)
+ @elem.namespace.should == "some_uri"
+ end
+end
+
diff --git a/spec/ruby/library/rexml/element/add_text_spec.rb b/spec/ruby/library/rexml/element/add_text_spec.rb
new file mode 100644
index 0000000000..5d116ee6d3
--- /dev/null
+++ b/spec/ruby/library/rexml/element/add_text_spec.rb
@@ -0,0 +1,24 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#add_namespace" do
+ before :each do
+ @name = REXML::Element.new "Name"
+ end
+
+ it "adds text to an element" do
+ @name.add_text "Ringo"
+ @name.to_s.should == "<Name>Ringo</Name>"
+ end
+
+ it "accepts a Text" do
+ @name.add_text(REXML::Text.new("Ringo"))
+ @name.to_s.should == "<Name>Ringo</Name>"
+ end
+
+ it "joins the new text with the old one" do
+ @name.add_text "Ringo"
+ @name.add_text " Starr"
+ @name.to_s.should == "<Name>Ringo Starr</Name>"
+ end
+end
diff --git a/spec/ruby/library/rexml/element/attribute_spec.rb b/spec/ruby/library/rexml/element/attribute_spec.rb
new file mode 100644
index 0000000000..9c5fb7a20e
--- /dev/null
+++ b/spec/ruby/library/rexml/element/attribute_spec.rb
@@ -0,0 +1,17 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#attribute" do
+ it "returns an attribute by name" do
+ person = REXML::Element.new "Person"
+ attribute = REXML::Attribute.new("drink", "coffee")
+ person.add_attribute(attribute)
+ person.attribute("drink").should == attribute
+ end
+
+ it "supports attributes inside namespaces" do
+ e = REXML::Element.new("element")
+ e.add_attributes({"xmlns:ns" => "http://some_uri"})
+ e.attribute("ns", "ns").to_s.should == "http://some_uri"
+ end
+end
diff --git a/spec/ruby/library/rexml/element/attributes_spec.rb b/spec/ruby/library/rexml/element/attributes_spec.rb
new file mode 100644
index 0000000000..7cc5310ed1
--- /dev/null
+++ b/spec/ruby/library/rexml/element/attributes_spec.rb
@@ -0,0 +1,19 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#attributes" do
+ it "returns element's Attributes" do
+ p = REXML::Element.new "Person"
+
+ name = REXML::Attribute.new("name", "John")
+ attrs = REXML::Attributes.new(p)
+ attrs.add name
+
+ p.add_attribute name
+ p.attributes.should == attrs
+ end
+
+ it "returns an empty hash if element has no attributes" do
+ REXML::Element.new("Person").attributes.should == {}
+ end
+end
diff --git a/spec/ruby/library/rexml/element/cdatas_spec.rb b/spec/ruby/library/rexml/element/cdatas_spec.rb
new file mode 100644
index 0000000000..1b44abe1e7
--- /dev/null
+++ b/spec/ruby/library/rexml/element/cdatas_spec.rb
@@ -0,0 +1,24 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#cdatas" do
+ before :each do
+ @e = REXML::Element.new("Root")
+ end
+
+ it "returns the array of children cdatas" do
+ c = REXML::CData.new("Primary")
+ d = REXML::CData.new("Secondary")
+ @e << c
+ @e << d
+ @e.cdatas.should == [c, d]
+ end
+
+ it "freezes the returned array" do
+ @e.cdatas.frozen?.should == true
+ end
+
+ it "returns an empty array if element has no cdata" do
+ @e.cdatas.should == []
+ end
+end
diff --git a/spec/ruby/library/rexml/element/clone_spec.rb b/spec/ruby/library/rexml/element/clone_spec.rb
new file mode 100644
index 0000000000..08f97e7793
--- /dev/null
+++ b/spec/ruby/library/rexml/element/clone_spec.rb
@@ -0,0 +1,29 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#clone" do
+ before :each do
+ @e = REXML::Element.new "a"
+ end
+ it "creates a copy of element" do
+ @e.clone.to_s.should == @e.to_s
+ end
+
+ it "copies the attributes" do
+ @e.add_attribute("foo", "bar")
+ @e.clone.to_s.should == @e.to_s
+ end
+
+ it "does not copy the text" do
+ @e.add_text "some text..."
+ @e.clone.to_s.should_not == @e
+ @e.clone.to_s.should == "<a/>"
+ end
+
+ it "does not copy the child elements" do
+ b = REXML::Element.new "b"
+ @e << b
+ @e.clone.should_not == @e
+ @e.clone.to_s.should == "<a/>"
+ end
+end
diff --git a/spec/ruby/library/rexml/element/comments_spec.rb b/spec/ruby/library/rexml/element/comments_spec.rb
new file mode 100644
index 0000000000..158b008b4f
--- /dev/null
+++ b/spec/ruby/library/rexml/element/comments_spec.rb
@@ -0,0 +1,20 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#comments" do
+ before :each do
+ @e = REXML::Element.new "root"
+ @c1 = REXML::Comment.new "this is a comment"
+ @c2 = REXML::Comment.new "this is another comment"
+ @e << @c1
+ @e << @c2
+ end
+
+ it "returns the array of comments" do
+ @e.comments.should == [@c1, @c2]
+ end
+
+ it "returns a frozen object" do
+ @e.comments.frozen?.should == true
+ end
+end
diff --git a/spec/ruby/library/rexml/element/delete_attribute_spec.rb b/spec/ruby/library/rexml/element/delete_attribute_spec.rb
new file mode 100644
index 0000000000..930db603b8
--- /dev/null
+++ b/spec/ruby/library/rexml/element/delete_attribute_spec.rb
@@ -0,0 +1,39 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#delete_attribute" do
+ before :each do
+ @e = REXML::Element.new("Person")
+ @attr = REXML::Attribute.new("name", "Sean")
+ @e.add_attribute(@attr)
+ end
+
+ it "deletes an attribute from the element" do
+ @e.delete_attribute("name")
+ @e.attributes["name"].should be_nil
+ end
+
+# Bug was filled with a patch in Ruby's tracker #20298
+ quarantine! do
+ it "receives an Attribute" do
+ @e.add_attribute(@attr)
+ @e.delete_attribute(@attr)
+ @e.attributes["name"].should be_nil
+ end
+ end
+
+ # Docs say that it returns the removed attribute but then examples
+ # show it returns the element with the attribute removed.
+ # Also fixed in #20298
+ it "returns the element with the attribute removed" do
+ elem = @e.delete_attribute("name")
+ elem.attributes.should be_empty
+ elem.to_s.should eql("<Person/>")
+ end
+
+ it "returns nil if the attribute does not exist" do
+ @e.delete_attribute("name")
+ at = @e.delete_attribute("name")
+ at.should be_nil
+ end
+end
diff --git a/spec/ruby/library/rexml/element/delete_element_spec.rb b/spec/ruby/library/rexml/element/delete_element_spec.rb
new file mode 100644
index 0000000000..e6e36364ba
--- /dev/null
+++ b/spec/ruby/library/rexml/element/delete_element_spec.rb
@@ -0,0 +1,49 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#delete_element" do
+ before :each do
+ @root = REXML::Element.new("root")
+ end
+
+ it "deletes the child element" do
+ node = REXML::Element.new("some_node")
+ @root.add_element node
+ @root.delete_element node
+ @root.elements.size.should == 0
+ end
+
+ it "deletes a child via XPath" do
+ @root.add_element "some_node"
+ @root.delete_element "some_node"
+ @root.elements.size.should == 0
+ end
+
+ it "deletes the child at index" do
+ @root.add_element "some_node"
+ @root.delete_element 1
+ @root.elements.size.should == 0
+ end
+
+ # According to the docs this should return the deleted element
+ # but it won't if it's an Element.
+ it "deletes Element and returns it" do
+ node = REXML::Element.new("some_node")
+ @root.add_element node
+ del_node = @root.delete_element node
+ del_node.should == node
+ end
+
+ # Note how passing the string will return the removed element
+ # but passing the Element as above won't.
+ it "deletes an element and returns it" do
+ node = REXML::Element.new("some_node")
+ @root.add_element node
+ del_node = @root.delete_element "some_node"
+ del_node.should == node
+ end
+
+ it "returns nil unless element exists" do
+ @root.delete_element("something").should == nil
+ end
+end
diff --git a/spec/ruby/library/rexml/element/delete_namespace_spec.rb b/spec/ruby/library/rexml/element/delete_namespace_spec.rb
new file mode 100644
index 0000000000..10de705076
--- /dev/null
+++ b/spec/ruby/library/rexml/element/delete_namespace_spec.rb
@@ -0,0 +1,25 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#delete_namespace" do
+
+ before :each do
+ @doc = REXML::Document.new "<a xmlns:foo='bar' xmlns='twiddle'/>"
+ end
+
+ it "deletes a namespace from the element" do
+ @doc.root.delete_namespace 'foo'
+ @doc.root.namespace("foo").should be_nil
+ @doc.root.to_s.should == "<a xmlns='twiddle'/>"
+ end
+
+ it "deletes default namespace when called with no args" do
+ @doc.root.delete_namespace
+ @doc.root.namespace.should be_empty
+ @doc.root.to_s.should == "<a xmlns:foo='bar'/>"
+ end
+
+ it "returns the element" do
+ @doc.root.delete_namespace.should == @doc.root
+ end
+end
diff --git a/spec/ruby/library/rexml/element/document_spec.rb b/spec/ruby/library/rexml/element/document_spec.rb
new file mode 100644
index 0000000000..bdf9205a85
--- /dev/null
+++ b/spec/ruby/library/rexml/element/document_spec.rb
@@ -0,0 +1,18 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#document" do
+
+ it "returns the element's document" do
+ d = REXML::Document.new("<root><elem/></root>")
+ d << REXML::XMLDecl.new
+ d.root.document.should == d
+ d.root.document.to_s.should == d.to_s
+ end
+
+ it "returns nil if it belongs to no document" do
+ REXML::Element.new("standalone").document.should be_nil
+ end
+end
+
+
diff --git a/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb b/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb
new file mode 100644
index 0000000000..2769fd2d26
--- /dev/null
+++ b/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb
@@ -0,0 +1,35 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#each_element_with_attributes" do
+ before :each do
+ @document = REXML::Element.new("people")
+ @father = REXML::Element.new("Person")
+ @father.attributes["name"] = "Joe"
+ @son = REXML::Element.new("Child")
+ @son.attributes["name"] = "Fred"
+ @document.root << @father
+ @document.root << @son
+ @childs = []
+ end
+
+ it "returns childs with attribute" do
+ @document.each_element_with_attribute("name") { |elem| @childs << elem }
+ @childs[0].should == @father
+ @childs[1].should == @son
+ end
+
+ it "takes attribute value as second argument" do
+ @document.each_element_with_attribute("name", "Fred"){ |elem| elem.should == @son }
+ end
+
+ it "takes max number of childs as third argument" do
+ @document.each_element_with_attribute("name", nil, 1) { |elem| @childs << elem }
+ @childs.size.should == 1
+ @childs[0].should == @father
+ end
+
+ it "takes XPath filter as fourth argument" do
+ @document.each_element_with_attribute("name", nil, 0, "Child"){ |elem| elem.should == @son}
+ end
+end
diff --git a/spec/ruby/library/rexml/element/each_element_with_text_spec.rb b/spec/ruby/library/rexml/element/each_element_with_text_spec.rb
new file mode 100644
index 0000000000..79848c779c
--- /dev/null
+++ b/spec/ruby/library/rexml/element/each_element_with_text_spec.rb
@@ -0,0 +1,31 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#each_element_with_text" do
+ before :each do
+ @document = REXML::Element.new("people")
+
+ @joe = REXML::Element.new("Person")
+ @joe.text = "Joe"
+ @fred = REXML::Element.new("Person")
+ @fred.text = "Fred"
+ @another = REXML::Element.new("AnotherPerson")
+ @another.text = "Fred"
+ @document.root << @joe
+ @document.root << @fred
+ @document.root << @another
+ @childs = []
+ end
+
+ it "returns childs with text" do
+ @document.each_element_with_text("Joe"){|c| c.should == @joe}
+ end
+
+ it "takes max as second argument" do
+ @document.each_element_with_text("Fred", 1){ |c| c.should == @fred}
+ end
+
+ it "takes XPath filter as third argument" do
+ @document.each_element_with_text("Fred", 0, "Person"){ |c| c.should == @fred}
+ end
+end
diff --git a/spec/ruby/library/rexml/element/get_text_spec.rb b/spec/ruby/library/rexml/element/get_text_spec.rb
new file mode 100644
index 0000000000..9ae343e097
--- /dev/null
+++ b/spec/ruby/library/rexml/element/get_text_spec.rb
@@ -0,0 +1,18 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#get_text" do
+ before :each do
+ @doc = REXML::Document.new "<p>some text<b>this is bold!</b> more text</p>"
+ end
+
+ it "returns the first text child node" do
+ @doc.root.get_text.value.should == "some text"
+ @doc.root.get_text.should be_kind_of(REXML::Text)
+ end
+
+ it "returns text from an element matching path" do
+ @doc.root.get_text("b").value.should == "this is bold!"
+ @doc.root.get_text("b").should be_kind_of(REXML::Text)
+ end
+end
diff --git a/spec/ruby/library/rexml/element/has_attributes_spec.rb b/spec/ruby/library/rexml/element/has_attributes_spec.rb
new file mode 100644
index 0000000000..f6c1c45e31
--- /dev/null
+++ b/spec/ruby/library/rexml/element/has_attributes_spec.rb
@@ -0,0 +1,17 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#has_attributes?" do
+ before :each do
+ @e = REXML::Element.new("test_elem")
+ end
+
+ it "returns true when element has any attributes" do
+ @e.add_attribute("name", "Joe")
+ @e.has_attributes?.should be_true
+ end
+
+ it "returns false if element has no attributes" do
+ @e.has_attributes?.should be_false
+ end
+end
diff --git a/spec/ruby/library/rexml/element/has_elements_spec.rb b/spec/ruby/library/rexml/element/has_elements_spec.rb
new file mode 100644
index 0000000000..54898b0d19
--- /dev/null
+++ b/spec/ruby/library/rexml/element/has_elements_spec.rb
@@ -0,0 +1,18 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#has_elements?" do
+ before :each do
+ @e = REXML::Element.new("root")
+ end
+
+ it "returns true if element has child elements" do
+ child = REXML::Element.new("child")
+ @e << child
+ @e.has_elements?.should be_true
+ end
+
+ it "returns false if element doesn't have child elements" do
+ @e.has_elements?.should be_false
+ end
+end
diff --git a/spec/ruby/library/rexml/element/has_text_spec.rb b/spec/ruby/library/rexml/element/has_text_spec.rb
new file mode 100644
index 0000000000..4747149ac7
--- /dev/null
+++ b/spec/ruby/library/rexml/element/has_text_spec.rb
@@ -0,0 +1,16 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#has_text?" do
+
+ it "returns true if element has a Text child" do
+ e = REXML::Element.new("Person")
+ e.text = "My text"
+ e.has_text?.should be_true
+ end
+
+ it "returns false if it has no Text childs" do
+ e = REXML::Element.new("Person")
+ e.has_text?.should be_false
+ end
+end
diff --git a/spec/ruby/library/rexml/element/inspect_spec.rb b/spec/ruby/library/rexml/element/inspect_spec.rb
new file mode 100644
index 0000000000..8e93afb562
--- /dev/null
+++ b/spec/ruby/library/rexml/element/inspect_spec.rb
@@ -0,0 +1,27 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#inspect" do
+
+ before :each do
+ @name = REXML::Element.new "name"
+ end
+
+ it "returns the node as a string" do
+ @name.inspect.should == "<name/>"
+ end
+
+ it "inserts '...' if the node has children" do
+ e = REXML::Element.new "last_name"
+ @name << e
+ @name.inspect.should == "<name> ... </>"
+ # This might make more sense but differs from MRI's default behavior
+ # @name.inspect.should == "<name> ... </name>"
+ end
+
+ it "inserts the attributes in the string" do
+ @name.add_attribute "language"
+ @name.attributes["language"] = "english"
+ @name.inspect.should == "<name language='english'/>"
+ end
+end
diff --git a/spec/ruby/library/rexml/element/instructions_spec.rb b/spec/ruby/library/rexml/element/instructions_spec.rb
new file mode 100644
index 0000000000..01a2374820
--- /dev/null
+++ b/spec/ruby/library/rexml/element/instructions_spec.rb
@@ -0,0 +1,21 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#instructions" do
+ before :each do
+ @elem = REXML::Element.new("root")
+ end
+ it "returns the Instruction children nodes" do
+ inst = REXML::Instruction.new("xml-stylesheet", "href='headlines.css'")
+ @elem << inst
+ @elem.instructions.first.should == inst
+ end
+
+ it "returns an empty array if it has no Instruction children" do
+ @elem.instructions.should be_empty
+ end
+
+ it "freezes the returned array" do
+ @elem.instructions.frozen?.should be_true
+ end
+end
diff --git a/spec/ruby/library/rexml/element/namespace_spec.rb b/spec/ruby/library/rexml/element/namespace_spec.rb
new file mode 100644
index 0000000000..a0b7ba0c83
--- /dev/null
+++ b/spec/ruby/library/rexml/element/namespace_spec.rb
@@ -0,0 +1,27 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#namespace" do
+ before :each do
+ @doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
+ @elem = @doc.elements["//b"]
+ end
+
+ it "returns the default namespace" do
+ @elem.namespace.should == "1"
+ end
+
+ it "accepts a namespace prefix" do
+ @elem.namespace("y").should == "2"
+ @doc.elements["//c"].namespace("z").should == "3"
+ end
+
+ it "returns an empty String if default namespace is not defined" do
+ e = REXML::Document.new("<a/>")
+ e.root.namespace.should be_empty
+ end
+
+ it "returns nil if namespace is not defined" do
+ @elem.namespace("z").should be_nil
+ end
+end
diff --git a/spec/ruby/library/rexml/element/namespaces_spec.rb b/spec/ruby/library/rexml/element/namespaces_spec.rb
new file mode 100644
index 0000000000..646503e184
--- /dev/null
+++ b/spec/ruby/library/rexml/element/namespaces_spec.rb
@@ -0,0 +1,32 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#namespaces" do
+ before :each do
+ doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
+ @elem = doc.elements["//c"]
+ end
+
+ it "returns a hash of the namespaces" do
+ ns = {"y"=>"2", "z"=>"3", "xmlns"=>"1"}
+ @elem.namespaces.keys.sort.should == ns.keys.sort
+ @elem.namespaces.values.sort.should == ns.values.sort
+ end
+
+ it "returns an empty hash if no namespaces exist" do
+ e = REXML::Element.new "element"
+ e.namespaces.kind_of?(Hash).should == true
+ e.namespaces.should be_empty
+ end
+
+ it "uses namespace prefixes as keys" do
+ prefixes = ["y", "z", "xmlns"]
+ @elem.namespaces.keys.sort.should == prefixes.sort
+ end
+
+ it "uses namespace values as the hash values" do
+ values = ["2", "3", "1"]
+ @elem.namespaces.values.sort.should == values.sort
+ end
+
+end
diff --git a/spec/ruby/library/rexml/element/new_spec.rb b/spec/ruby/library/rexml/element/new_spec.rb
new file mode 100644
index 0000000000..c18a33624b
--- /dev/null
+++ b/spec/ruby/library/rexml/element/new_spec.rb
@@ -0,0 +1,35 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#new" do
+
+ it "creates element from tag name" do
+ REXML::Element.new("foo").name.should == "foo"
+ end
+
+ it "creates element with default attributes" do
+ e = REXML::Element.new
+ e.name.should == REXML::Element::UNDEFINED
+ e.context.should == nil
+ e.parent.should == nil
+ end
+
+ it "creates element from another element" do
+ e = REXML::Element.new "foo"
+ f = REXML::Element.new e
+ e.name.should == f.name
+ e.context.should == f.context
+ e.parent.should == f.parent
+ end
+
+ it "takes parent as second argument" do
+ parent = REXML::Element.new "foo"
+ child = REXML::Element.new "bar", parent
+ child.parent.should == parent
+ end
+
+ it "takes context as third argument" do
+ context = {"some_key" => "some_value"}
+ REXML::Element.new("foo", nil, context).context.should == context
+ end
+end
diff --git a/spec/ruby/library/rexml/element/next_element_spec.rb b/spec/ruby/library/rexml/element/next_element_spec.rb
new file mode 100644
index 0000000000..51b8438ba7
--- /dev/null
+++ b/spec/ruby/library/rexml/element/next_element_spec.rb
@@ -0,0 +1,19 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#next_element" do
+ before :each do
+ @a = REXML::Element.new "a"
+ @b = REXML::Element.new "b"
+ @c = REXML::Element.new "c"
+ @a.root << @b
+ @a.root << @c
+ end
+ it "returns next existing element" do
+ @a.elements["b"].next_element.should == @c
+ end
+
+ it "returns nil on last element" do
+ @a.elements["c"].next_element.should == nil
+ end
+end
diff --git a/spec/ruby/library/rexml/element/node_type_spec.rb b/spec/ruby/library/rexml/element/node_type_spec.rb
new file mode 100644
index 0000000000..3c9b713fde
--- /dev/null
+++ b/spec/ruby/library/rexml/element/node_type_spec.rb
@@ -0,0 +1,8 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#node_type" do
+ it "returns :element" do
+ REXML::Element.new("MyElem").node_type.should == :element
+ end
+end
diff --git a/spec/ruby/library/rexml/element/prefixes_spec.rb b/spec/ruby/library/rexml/element/prefixes_spec.rb
new file mode 100644
index 0000000000..03c46eab9e
--- /dev/null
+++ b/spec/ruby/library/rexml/element/prefixes_spec.rb
@@ -0,0 +1,23 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#prefixes" do
+ before :each do
+ doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
+ @elem = doc.elements["//c"]
+ end
+
+ it "returns an array of the prefixes of the namespaces" do
+ @elem.prefixes.should == ["y", "z"]
+ end
+
+ it "does not include the default namespace" do
+ @elem.prefixes.include?("xmlns").should == false
+ end
+
+ it "returns an empty array if no namespace was defined" do
+ doc = REXML::Document.new "<root><something/></root>"
+ root = doc.elements["//root"]
+ root.prefixes.should == []
+ end
+end
diff --git a/spec/ruby/library/rexml/element/previous_element_spec.rb b/spec/ruby/library/rexml/element/previous_element_spec.rb
new file mode 100644
index 0000000000..49279e8e94
--- /dev/null
+++ b/spec/ruby/library/rexml/element/previous_element_spec.rb
@@ -0,0 +1,20 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#previous_element" do
+ before :each do
+ @a = REXML::Element.new "a"
+ @b = REXML::Element.new "b"
+ @c = REXML::Element.new "c"
+ @a.root << @b
+ @a.root << @c
+ end
+
+ it "returns previous element" do
+ @a.elements["c"].previous_element.should == @b
+ end
+
+ it "returns nil on first element" do
+ @a.elements["b"].previous_element.should == nil
+ end
+end
diff --git a/spec/ruby/library/rexml/element/raw_spec.rb b/spec/ruby/library/rexml/element/raw_spec.rb
new file mode 100644
index 0000000000..a872c36c8b
--- /dev/null
+++ b/spec/ruby/library/rexml/element/raw_spec.rb
@@ -0,0 +1,24 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#raw" do
+ it "returns true if raw mode is set to all" do
+ REXML::Element.new("MyElem", nil, {raw: :all}).raw.should == true
+ end
+
+ it "returns true if raw mode is set to expanded_name" do
+ REXML::Element.new("MyElem", nil, {raw: "MyElem"}).raw.should == true
+ end
+
+ it "returns false if raw mode is not set" do
+ REXML::Element.new("MyElem", nil, {raw: ""}).raw.should == false
+ end
+
+ it "returns false if raw is not :all or expanded_name" do
+ REXML::Element.new("MyElem", nil, {raw: "Something"}).raw.should == false
+ end
+
+ it "returns nil if context is not set" do
+ REXML::Element.new("MyElem").raw.should == nil
+ end
+end
diff --git a/spec/ruby/library/rexml/element/root_spec.rb b/spec/ruby/library/rexml/element/root_spec.rb
new file mode 100644
index 0000000000..24e488e701
--- /dev/null
+++ b/spec/ruby/library/rexml/element/root_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Element#root" do
+ before :each do
+ @doc = REXML::Document.new
+ @root = REXML::Element.new "root"
+ @node = REXML::Element.new "node"
+ @doc << @root << @node
+ end
+
+ it "returns first child on documents" do
+ @doc.root.should == @root
+ end
+
+ it "returns self on root nodes" do
+ @root.root.should == @root
+ end
+
+ it "returns parent's root on child nodes" do
+ @node.root.should == @root
+ end
+
+ it "returns self on standalone nodes" do
+ e = REXML::Element.new "Elem" # Note that it doesn't have a parent node
+ e.root.should == e
+ end
+end
diff --git a/spec/ruby/library/rexml/element/text_spec.rb b/spec/ruby/library/rexml/element/text_spec.rb
new file mode 100644
index 0000000000..25791d6397
--- /dev/null
+++ b/spec/ruby/library/rexml/element/text_spec.rb
@@ -0,0 +1,46 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#text" do
+ before :each do
+ @e = REXML::Element.new "name"
+ @e.text = "John"
+ end
+
+ it "returns the text node of element" do
+ @e.text.should == "John"
+ end
+
+ it "returns the text node value" do
+ t = REXML::Text.new "Joe"
+ @e.text = t
+ @e.text.should == "Joe"
+ @e.text.should_not == t
+ end
+
+ it "returns nil if no text is attached" do
+ elem = REXML::Element.new "name"
+ elem.text.should == nil
+ end
+end
+
+describe "REXML::Element#text=" do
+ before :each do
+ @e = REXML::Element.new "name"
+ @e.text = "John"
+ end
+
+ it "sets the text node" do
+ @e.to_s.should == "<name>John</name>"
+ end
+
+ it "replaces existing text" do
+ @e.text = "Joe"
+ @e.to_s.should == "<name>Joe</name>"
+ end
+
+ it "receives nil as an argument" do
+ @e.text = nil
+ @e.to_s.should == "<name/>"
+ end
+end
diff --git a/spec/ruby/library/rexml/element/texts_spec.rb b/spec/ruby/library/rexml/element/texts_spec.rb
new file mode 100644
index 0000000000..de3a818866
--- /dev/null
+++ b/spec/ruby/library/rexml/element/texts_spec.rb
@@ -0,0 +1,16 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#texts" do
+
+ it "returns an array of the Text children" do
+ e = REXML::Element.new("root")
+ e.add_text "First"
+ e.add_text "Second"
+ e.texts.should == ["FirstSecond"]
+ end
+
+ it "returns an empty array if it has no Text children" do
+ REXML::Element.new("root").texts.should == []
+ end
+end
diff --git a/spec/ruby/library/rexml/element/whitespace_spec.rb b/spec/ruby/library/rexml/element/whitespace_spec.rb
new file mode 100644
index 0000000000..ea9ff42c03
--- /dev/null
+++ b/spec/ruby/library/rexml/element/whitespace_spec.rb
@@ -0,0 +1,23 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#whitespace" do
+ it "returns true if whitespace is respected in the element" do
+ e = REXML::Element.new("root")
+ e.whitespace.should be_true
+
+ e = REXML::Element.new("root", nil, respect_whitespace: :all)
+ e.whitespace.should be_true
+
+ e = REXML::Element.new("root", nil, respect_whitespace: ["root"])
+ e.whitespace.should be_true
+ end
+
+ it "returns false if whitespace is ignored inside element" do
+ e = REXML::Element.new("root", nil, compress_whitespace: :all)
+ e.whitespace.should be_false
+
+ e = REXML::Element.new("root", nil, compress_whitespace: ["root"])
+ e.whitespace.should be_false
+ end
+end
diff --git a/spec/ruby/library/rexml/node/each_recursive_spec.rb b/spec/ruby/library/rexml/node/each_recursive_spec.rb
new file mode 100644
index 0000000000..5f26c898ea
--- /dev/null
+++ b/spec/ruby/library/rexml/node/each_recursive_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Node#each_recursive" do
+ before :each do
+ @doc = REXML::Document.new
+ @doc << REXML::XMLDecl.new
+ @root = REXML::Element.new "root"
+ @child1 = REXML::Element.new "child1"
+ @child2 = REXML::Element.new "child2"
+ @root << @child1
+ @root << @child2
+ @doc << @root
+ end
+
+ it "visits all subnodes of self" do
+ nodes = []
+ @doc.each_recursive { |node| nodes << node}
+ nodes.should == [@root, @child1, @child2]
+ end
+end
diff --git a/spec/ruby/library/rexml/node/find_first_recursive_spec.rb b/spec/ruby/library/rexml/node/find_first_recursive_spec.rb
new file mode 100644
index 0000000000..20e87fe9e9
--- /dev/null
+++ b/spec/ruby/library/rexml/node/find_first_recursive_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Node#find_first_recursive" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @node1 = REXML::Element.new("node")
+ @node2 = REXML::Element.new("another node")
+ @subnode = REXML::Element.new("another node")
+ @node1 << @subnode
+ @e << @node1
+ @e << @node2
+ end
+
+ it "finds the first element that matches block" do
+ found = @e.find_first_recursive { |n| n.to_s == "<node><another node/></node>"}
+ found.should == @node1
+ end
+
+ it "visits the nodes in preorder" do
+ found = @e.find_first_recursive { |n| n.to_s == "<another node/>"}
+ found.should == @subnode
+ found.should_not == @node2
+ end
+end
diff --git a/spec/ruby/library/rexml/node/index_in_parent_spec.rb b/spec/ruby/library/rexml/node/index_in_parent_spec.rb
new file mode 100644
index 0000000000..018a4c08ac
--- /dev/null
+++ b/spec/ruby/library/rexml/node/index_in_parent_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Node#index_in_parent" do
+ it "returns the index (starting from 1) of self in parent" do
+ e = REXML::Element.new("root")
+ node1 = REXML::Element.new("node")
+ node2 = REXML::Element.new("another node")
+ e << node1
+ e << node2
+
+ node1.index_in_parent.should == 1
+ node2.index_in_parent.should == 2
+ end
+end
diff --git a/spec/ruby/library/rexml/node/next_sibling_node_spec.rb b/spec/ruby/library/rexml/node/next_sibling_node_spec.rb
new file mode 100644
index 0000000000..9ca91c9149
--- /dev/null
+++ b/spec/ruby/library/rexml/node/next_sibling_node_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Node#next_sibling_node" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @node1 = REXML::Element.new("node")
+ @node2 = REXML::Element.new("another node")
+ @e << @node1
+ @e << @node2
+ end
+
+ it "returns the next child node in parent" do
+ @node1.next_sibling_node.should == @node2
+ end
+
+ it "returns nil if there are no more child nodes next" do
+ @node2.next_sibling_node.should == nil
+ @e.next_sibling_node.should == nil
+ end
+end
diff --git a/spec/ruby/library/rexml/node/parent_spec.rb b/spec/ruby/library/rexml/node/parent_spec.rb
new file mode 100644
index 0000000000..ee3c234534
--- /dev/null
+++ b/spec/ruby/library/rexml/node/parent_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Node#parent?" do
+ it "returns true for Elements" do
+ e = REXML::Element.new("foo")
+ e.parent?.should == true
+ end
+
+ it "returns true for Documents" do
+ e = REXML::Document.new
+ e.parent?.should == true
+ end
+
+ # This includes attributes, CDatas and declarations.
+ it "returns false for Texts" do
+ e = REXML::Text.new("foo")
+ e.parent?.should == false
+ end
+end
+
diff --git a/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb b/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb
new file mode 100644
index 0000000000..b8e4465979
--- /dev/null
+++ b/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Node#previous_sibling_node" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @node1 = REXML::Element.new("node")
+ @node2 = REXML::Element.new("another node")
+ @e << @node1
+ @e << @node2
+ end
+
+ it "returns the previous child node in parent" do
+ @node2.previous_sibling_node.should == @node1
+ end
+
+ it "returns nil if there are no more child nodes before" do
+ @node1.previous_sibling_node.should == nil
+ @e.previous_sibling_node.should == nil
+ end
+end
diff --git a/spec/ruby/library/rexml/shared/each_element.rb b/spec/ruby/library/rexml/shared/each_element.rb
new file mode 100644
index 0000000000..1cb79c8d3a
--- /dev/null
+++ b/spec/ruby/library/rexml/shared/each_element.rb
@@ -0,0 +1,36 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe :rexml_each_element, shared: true do
+ before :each do
+ @e = REXML::Element.new "root"
+ s1 = REXML::Element.new "node1"
+ s2 = REXML::Element.new "node2"
+ s3 = REXML::Element.new "node3"
+ s4 = REXML::Element.new "sub_node"
+ @e << s1
+ @e << s2
+ @e << s3
+ @e << s4
+ end
+
+ it "iterates through element" do
+ str = ""
+ @e.send(@method) { |elem| str << elem.name << " " }
+ str.should == "node1 node2 node3 sub_node "
+ end
+
+ it "iterates through element filtering with XPath" do
+ str = ""
+ @e.send(@method, "/*"){ |e| str << e.name << " "}
+ str.should == "node1 node2 node3 sub_node "
+ end
+end
+
+describe "REXML::Element#each_element" do
+ it_behaves_like :rexml_each_element, :each_element
+end
+
+describe "REXML::Elements#each" do
+ it_behaves_like :rexml_each_element, :each
+end
diff --git a/spec/ruby/library/rexml/shared/elements_to_a.rb b/spec/ruby/library/rexml/shared/elements_to_a.rb
new file mode 100644
index 0000000000..6299c628c3
--- /dev/null
+++ b/spec/ruby/library/rexml/shared/elements_to_a.rb
@@ -0,0 +1,34 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe :rexml_elements_to_a, shared: true do
+ before :each do
+ @e = REXML::Element.new "root"
+ @first = REXML::Element.new("FirstChild")
+ @second = REXML::Element.new("SecondChild")
+ @e << @first
+ @e << @second
+ end
+
+ it "returns elements that match xpath" do
+ @e.elements.send(@method, "FirstChild").first.should == @first
+ end
+
+ # According to the docs REXML::Element#get_elements is an alias for
+ # REXML::Elements.to_a. Implementation wise there's a difference, get_elements
+ # always needs the first param (even if it's nil).
+ # A patch was submitted:
+ # http://rubyforge.org/tracker/index.php?func=detail&aid=19354&group_id=426&atid=1698
+ it "returns all childs if xpath is nil" do
+ @e.elements.send(@method).should == [@first, @second]
+ end
+
+end
+
+describe "REXML::REXML::Elements#to_a" do
+ it_behaves_like :rexml_elements_to_a, :to_a
+end
+
+describe "REXML::REXML::Element#get_elements" do
+ it_behaves_like :rexml_elements_to_a, :get_elements
+end
diff --git a/spec/ruby/library/rexml/text/append_spec.rb b/spec/ruby/library/rexml/text/append_spec.rb
new file mode 100644
index 0000000000..c8f73f9393
--- /dev/null
+++ b/spec/ruby/library/rexml/text/append_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#<<" do
+ it "appends a string to this text node" do
+ text = REXML::Text.new("foo")
+ text << "bar"
+ text.should == "foobar"
+ end
+end
diff --git a/spec/ruby/library/rexml/text/clone_spec.rb b/spec/ruby/library/rexml/text/clone_spec.rb
new file mode 100644
index 0000000000..c7d16e0d85
--- /dev/null
+++ b/spec/ruby/library/rexml/text/clone_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#clone" do
+ it "creates a copy of this node" do
+ text = REXML::Text.new("foo")
+ text.clone.should == "foo"
+ text.clone.should == text
+ end
+end
diff --git a/spec/ruby/library/rexml/text/comparison_spec.rb b/spec/ruby/library/rexml/text/comparison_spec.rb
new file mode 100644
index 0000000000..ba637ea37e
--- /dev/null
+++ b/spec/ruby/library/rexml/text/comparison_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#<=>" do
+ before :each do
+ @first = REXML::Text.new("abc")
+ @last = REXML::Text.new("def")
+ end
+
+ it "returns -1 if lvalue is less than rvalue" do
+ val = @first <=> @last
+ val.should == -1
+ end
+
+ it "returns -1 if lvalue is greater than rvalue" do
+ val = @last <=> @first
+ val.should == 1
+ end
+
+ it "returns 0 if both values are equal" do
+ tmp = REXML::Text.new("tmp")
+ val = tmp <=> tmp
+ val.should == 0
+ end
+end
diff --git a/spec/ruby/library/rexml/text/empty_spec.rb b/spec/ruby/library/rexml/text/empty_spec.rb
new file mode 100644
index 0000000000..7102e1586e
--- /dev/null
+++ b/spec/ruby/library/rexml/text/empty_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#empty?" do
+ it "returns true if the text is empty" do
+ REXML::Text.new("").empty?.should == true
+ end
+
+ it "returns false if the text is not empty" do
+ REXML::Text.new("some_text").empty?.should == false
+ end
+end
diff --git a/spec/ruby/library/rexml/text/indent_text_spec.rb b/spec/ruby/library/rexml/text/indent_text_spec.rb
new file mode 100644
index 0000000000..2aa908826b
--- /dev/null
+++ b/spec/ruby/library/rexml/text/indent_text_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#indent_text" do
+ before :each do
+ @t = REXML::Text.new("")
+ end
+ it "indents a string with default parameters" do
+ @t.indent_text("foo").should == "\tfoo"
+ end
+
+ it "accepts a custom indentation level as second argument" do
+ @t.indent_text("foo", 2, "\t", true).should == "\t\tfoo"
+ end
+
+ it "accepts a custom separator as third argument" do
+ @t.indent_text("foo", 1, "\n", true).should == "\nfoo"
+ end
+
+ it "accepts a fourth parameter to skip the first line" do
+ @t.indent_text("foo", 1, "\t", false).should == "foo"
+ end
+end
+
diff --git a/spec/ruby/library/rexml/text/inspect_spec.rb b/spec/ruby/library/rexml/text/inspect_spec.rb
new file mode 100644
index 0000000000..655e42fcdf
--- /dev/null
+++ b/spec/ruby/library/rexml/text/inspect_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#inspect" do
+ it "inspects the string attribute as a string" do
+ REXML::Text.new("a text").inspect.should == "a text".inspect
+ end
+end
diff --git a/spec/ruby/library/rexml/text/new_spec.rb b/spec/ruby/library/rexml/text/new_spec.rb
new file mode 100644
index 0000000000..0d7a750a1d
--- /dev/null
+++ b/spec/ruby/library/rexml/text/new_spec.rb
@@ -0,0 +1,49 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text.new" do
+
+ it "creates a Text child node with no parent" do
+ t = REXML::Text.new("test")
+ t.should be_kind_of(REXML::Child)
+ t.should == "test"
+ t.parent.should == nil
+ end
+
+ it "respects whitespace if second argument is true" do
+ t = REXML::Text.new("testing whitespace", true)
+ t.should == "testing whitespace"
+ t = REXML::Text.new(" ", true)
+ t.should == " "
+ end
+
+ it "receives a parent as third argument" do
+ e = REXML::Element.new("root")
+ t = REXML::Text.new("test", false, e)
+ t.parent.should == e
+ e.to_s.should == "<root>test</root>"
+ end
+
+ it "expects escaped text if raw is true" do
+ t = REXML::Text.new("&lt;&amp;&gt;", false, nil, true)
+ t.should == "&lt;&amp;&gt;"
+
+ lambda{ REXML::Text.new("<&>", false, nil, true)}.should raise_error(Exception)
+ end
+
+ it "uses raw value of the parent if raw is nil" do
+ e1 = REXML::Element.new("root", nil, { raw: :all})
+ lambda {REXML::Text.new("<&>", false, e1)}.should raise_error(Exception)
+
+ e2 = REXML::Element.new("root", nil, { raw: []})
+ e2.raw.should be_false
+ t1 = REXML::Text.new("<&>", false, e2)
+ t1.should == "&lt;&amp;&gt;"
+ end
+
+ it "escapes the values if raw is false" do
+ t = REXML::Text.new("<&>", false, nil, false)
+ t.should == "&lt;&amp;&gt;"
+ end
+end
+
diff --git a/spec/ruby/library/rexml/text/node_type_spec.rb b/spec/ruby/library/rexml/text/node_type_spec.rb
new file mode 100644
index 0000000000..a1c51b5b91
--- /dev/null
+++ b/spec/ruby/library/rexml/text/node_type_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#node_type" do
+ it "returns :text" do
+ REXML::Text.new("test").node_type.should == :text
+ end
+end
diff --git a/spec/ruby/library/rexml/text/normalize_spec.rb b/spec/ruby/library/rexml/text/normalize_spec.rb
new file mode 100644
index 0000000000..1725c38146
--- /dev/null
+++ b/spec/ruby/library/rexml/text/normalize_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text.normalize" do
+ it "escapes a string with <, >, &, ' and \" " do
+ REXML::Text.normalize("< > & \" '").should == "&lt; &gt; &amp; &quot; &apos;"
+ end
+end
diff --git a/spec/ruby/library/rexml/text/read_with_substitution_spec.rb b/spec/ruby/library/rexml/text/read_with_substitution_spec.rb
new file mode 100644
index 0000000000..7e42c40248
--- /dev/null
+++ b/spec/ruby/library/rexml/text/read_with_substitution_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text.read_with_substitution" do
+ it "reads a text and escapes entities" do
+ REXML::Text.read_with_substitution("&lt; &gt; &amp; &quot; &apos;").should == "< > & \" '"
+ end
+
+ it "accepts an regex for invalid expressions and raises an error if text matches" do
+ lambda {REXML::Text.read_with_substitution("this is illegal", /illegal/)}.should raise_error(Exception)
+ end
+end
+
diff --git a/spec/ruby/library/rexml/text/to_s_spec.rb b/spec/ruby/library/rexml/text/to_s_spec.rb
new file mode 100644
index 0000000000..94356ff075
--- /dev/null
+++ b/spec/ruby/library/rexml/text/to_s_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#to_s" do
+ it "returns the string of this Text node" do
+ u = REXML::Text.new("sean russell", false, nil, true)
+ u.to_s.should == "sean russell"
+
+ t = REXML::Text.new("some test text")
+ t.to_s.should == "some test text"
+ end
+
+ it "escapes the text" do
+ t = REXML::Text.new("& < >")
+ t.to_s.should == "&amp; &lt; &gt;"
+ end
+end
+
diff --git a/spec/ruby/library/rexml/text/unnormalize_spec.rb b/spec/ruby/library/rexml/text/unnormalize_spec.rb
new file mode 100644
index 0000000000..6406589694
--- /dev/null
+++ b/spec/ruby/library/rexml/text/unnormalize_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text.unnormalize" do
+ it "unescapes a string with the values defined in SETUTITSBUS" do
+ REXML::Text.unnormalize("&lt; &gt; &amp; &quot; &apos;").should == "< > & \" '"
+ end
+end
diff --git a/spec/ruby/library/rexml/text/value_spec.rb b/spec/ruby/library/rexml/text/value_spec.rb
new file mode 100644
index 0000000000..d14e8aca6b
--- /dev/null
+++ b/spec/ruby/library/rexml/text/value_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#value" do
+ it "returns the text value of this node" do
+ REXML::Text.new("test").value.should == "test"
+ end
+
+ it "does not escape entities" do
+ REXML::Text.new("& \"").value.should == "& \""
+ end
+
+ it "follows the respect_whitespace attribute" do
+ REXML::Text.new("test bar", false).value.should == "test bar"
+ REXML::Text.new("test bar", true).value.should == "test bar"
+ end
+
+ it "ignores the raw attribute" do
+ REXML::Text.new("sean russell", false, nil, true).value.should == "sean russell"
+ end
+end
+
+describe "REXML::Text#value=" do
+ before :each do
+ @t = REXML::Text.new("new")
+ end
+
+ it "sets the text of the node" do
+ @t.value = "another text"
+ @t.to_s.should == "another text"
+ end
+
+ it "escapes entities" do
+ @t.value = "<a>"
+ @t.to_s.should == "&lt;a&gt;"
+ end
+end
diff --git a/spec/ruby/library/rexml/text/wrap_spec.rb b/spec/ruby/library/rexml/text/wrap_spec.rb
new file mode 100644
index 0000000000..a56759b0f4
--- /dev/null
+++ b/spec/ruby/library/rexml/text/wrap_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#wrap" do
+ before :each do
+ @t = REXML::Text.new("abc def")
+ end
+
+ it "wraps the text at width" do
+ @t.wrap("abc def", 3, false).should == "abc\ndef"
+ end
+
+ it "returns the string if width is greater than the size of the string" do
+ @t.wrap("abc def", 10, false).should == "abc def"
+ end
+
+ it "takes a newline at the beginning option as the third parameter" do
+ @t.wrap("abc def", 3, true).should == "\nabc\ndef"
+ end
+end
+
diff --git a/spec/ruby/library/rexml/text/write_with_substitution_spec.rb b/spec/ruby/library/rexml/text/write_with_substitution_spec.rb
new file mode 100644
index 0000000000..e5f027f297
--- /dev/null
+++ b/spec/ruby/library/rexml/text/write_with_substitution_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'rexml/document'
+
+describe "REXML::Text#write_with_substitution" do
+ before :each do
+ @t = REXML::Text.new("test")
+ @f = tmp("rexml_spec")
+ @file = File.open(@f, "w+")
+ end
+
+ after :each do
+ @file.close
+ rm_r @f
+ end
+
+ it "writes out the input to a String" do
+ s = ""
+ @t.write_with_substitution(s, "some text")
+ s.should == "some text"
+ end
+
+ it "writes out the input to an IO" do
+ @t.write_with_substitution(@file, "some text")
+ @file.rewind
+ @file.gets.should == "some text"
+ end
+
+ it "escapes characters" do
+ @t.write_with_substitution(@file, "& < >")
+ @file.rewind
+ @file.gets.should == "&amp; &lt; &gt;"
+ end
+end
diff --git a/spec/ruby/library/scanf/io/block_scanf_spec.rb b/spec/ruby/library/scanf/io/block_scanf_spec.rb
new file mode 100644
index 0000000000..0f6188f91c
--- /dev/null
+++ b/spec/ruby/library/scanf/io/block_scanf_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/block_scanf.rb', __FILE__)
+require 'scanf'
+
+describe "IO#block_scanf" do
+ it_behaves_like(:scanf_io_block_scanf, :block_scanf)
+end
diff --git a/spec/ruby/library/scanf/io/fixtures/date.txt b/spec/ruby/library/scanf/io/fixtures/date.txt
new file mode 100644
index 0000000000..a1bd635c0c
--- /dev/null
+++ b/spec/ruby/library/scanf/io/fixtures/date.txt
@@ -0,0 +1,4 @@
+Beethoven 1770
+Bach 1685
+Handel 1685
+
diff --git a/spec/ruby/library/scanf/io/fixtures/helloworld.txt b/spec/ruby/library/scanf/io/fixtures/helloworld.txt
new file mode 100644
index 0000000000..3b18e512db
--- /dev/null
+++ b/spec/ruby/library/scanf/io/fixtures/helloworld.txt
@@ -0,0 +1 @@
+hello world
diff --git a/spec/ruby/library/scanf/io/scanf_spec.rb b/spec/ruby/library/scanf/io/scanf_spec.rb
new file mode 100644
index 0000000000..27c3142678
--- /dev/null
+++ b/spec/ruby/library/scanf/io/scanf_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/block_scanf.rb', __FILE__)
+require 'scanf'
+
+describe "IO#scanf" do
+ before :each do
+ @hw = File.open(File.dirname(__FILE__) + '/fixtures/helloworld.txt', 'r')
+ @data = File.open(File.dirname(__FILE__) + '/fixtures/date.txt', 'r')
+ end
+
+ after :each do
+ @hw.close unless @hw.closed?
+ @data.close unless @data.closed?
+ end
+
+ it "returns an array containing the input converted in the specified type" do
+ @hw.scanf("%s%s").should == ["hello", "world"]
+ @data.scanf("%s%d").should == ["Beethoven", 1770]
+ end
+
+ it "returns an array containing the input converted in the specified type with given maximum field width" do
+ @hw.scanf("%2s").should == ["he"]
+ @data.scanf("%2c").should == ["Be"]
+ end
+
+ it "returns an empty array when a wrong specifier is passed" do
+ @hw.scanf("%a").should == []
+ @hw.scanf("%1").should == []
+ @data.scanf("abc").should == []
+ end
+end
+
+describe "IO#scanf with block" do
+ it_behaves_like(:scanf_io_block_scanf, :scanf)
+end
diff --git a/spec/ruby/library/scanf/io/shared/block_scanf.rb b/spec/ruby/library/scanf/io/shared/block_scanf.rb
new file mode 100644
index 0000000000..8c5bffb93b
--- /dev/null
+++ b/spec/ruby/library/scanf/io/shared/block_scanf.rb
@@ -0,0 +1,28 @@
+require 'scanf'
+
+describe :scanf_io_block_scanf, shared: true do
+ before :each do
+ @data= File.open(File.dirname(__FILE__) + '/../fixtures/date.txt', 'r')
+ end
+
+ after :each do
+ @data.close unless @data.closed?
+ end
+
+ it "passes each match to the block as an array" do
+ res = @data.send(@method, "%s%d") { |name, year| "#{name} was born in #{year}." }
+ res.should == ["Beethoven was born in 1770.", "Bach was born in 1685.", "Handel was born in 1685."]
+ end
+
+ it "keeps scanning the input and cycling back to the beginning of the input string" do
+ a = []
+ @data.send(@method, "%s"){|w| a << w}
+ a.should == [["Beethoven"], ["1770"], ["Bach"], ["1685"], ["Handel"], ["1685"]]
+ end
+
+ it "returns an empty array when a wrong specifier is passed" do
+ a = []
+ @data.send(@method, "%z"){|w| a << w}
+ a.empty?.should be_true
+ end
+end
diff --git a/spec/ruby/library/scanf/string/block_scanf_spec.rb b/spec/ruby/library/scanf/string/block_scanf_spec.rb
new file mode 100644
index 0000000000..1444cc2975
--- /dev/null
+++ b/spec/ruby/library/scanf/string/block_scanf_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/block_scanf.rb', __FILE__)
+require 'scanf'
+
+describe "String#block_scanf" do
+ it_behaves_like(:scanf_string_block_scanf, :block_scanf)
+end
diff --git a/spec/ruby/library/scanf/string/scanf_spec.rb b/spec/ruby/library/scanf/string/scanf_spec.rb
new file mode 100644
index 0000000000..360c72fba8
--- /dev/null
+++ b/spec/ruby/library/scanf/string/scanf_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/block_scanf.rb', __FILE__)
+require 'scanf'
+
+describe "String#scanf" do
+ it "returns an array containing the input converted in the specified type" do
+ "hello world".scanf("%s").should == ["hello"]
+ "hello world".scanf("%s%d").should == ["hello"]
+ "hello world".scanf("%s%c").should == ["hello", " "]
+ "hello world".scanf("%c%s").should == ["h", "ello"]
+ "hello world".scanf("%s%s").should == ["hello", "world"]
+ "hello world".scanf("%c").should == ["h"]
+ "123".scanf("%s").should == ["123"]
+ "123".scanf("%c").should == ["1"]
+ "123".scanf("%d").should == [123]
+ "123".scanf("%u").should == [123]
+ "123".scanf("%o").should == [83]
+ "123".scanf("%x").should == [291]
+ "123".scanf("%i").should == [123]
+ "0123".scanf("%i").should == [83]
+ "123".scanf("%f").should == [123.0]
+ "0X123".scanf("%i").should == [291]
+ "0x123".scanf("%i").should == [291]
+ end
+
+ it "returns an array containing the input converted in the specified type with given maximum field width" do
+ "hello world".scanf("%2s").should == ["he"]
+ "hello world".scanf("%2c").should == ["he"]
+ "123".scanf("%2s").should == ["12"]
+ "123".scanf("%2c").should == ["12"]
+ "123".scanf("%2d").should == [12]
+ "123".scanf("%2u").should == [12]
+ "123".scanf("%2o").should == [10]
+ "123".scanf("%2x").should == [18]
+ "123".scanf("%2i").should == [12]
+ "0123".scanf("%2i").should == [1]
+ "123".scanf("%2f").should == [12.0]
+ "0X123".scanf("%2i").should == [0]
+ "0X123".scanf("%3i").should == [1]
+ "0X123".scanf("%4i").should == [18]
+ end
+
+ it "returns an empty array when a wrong specifier is passed" do
+ "hello world".scanf("%a").should == []
+ "123".scanf("%1").should == []
+ "123".scanf("abc").should == []
+ "123".scanf(:d).should == []
+ end
+end
+
+describe "String#scanf with block" do
+ it_behaves_like(:scanf_string_block_scanf, :scanf)
+end
diff --git a/spec/ruby/library/scanf/string/shared/block_scanf.rb b/spec/ruby/library/scanf/string/shared/block_scanf.rb
new file mode 100644
index 0000000000..25ab3f442a
--- /dev/null
+++ b/spec/ruby/library/scanf/string/shared/block_scanf.rb
@@ -0,0 +1,25 @@
+require 'scanf'
+
+describe :scanf_string_block_scanf, shared: true do
+ it "passes each match to the block as an array" do
+ a = []
+ "hello world".send(@method, "%s%s"){|w| a << w}
+ a.should == [["hello", "world"]]
+ end
+
+ it "keeps scanning the input and cycling back to the beginning of the input string" do
+ a = []
+ "hello world".send(@method, "%s"){|w| a << w}
+ a.should == [["hello"], ["world"]]
+
+ string = "123 abc 456 def 789 ghi"
+ s = string.send(@method, "%d%s"){|num,str| [num * 2, str.upcase]}
+ s.should == [[246, "ABC"], [912, "DEF"], [1578, "GHI"]]
+ end
+
+ it "returns an empty array when a wrong specifier is passed" do
+ a = []
+ "hello world".send(@method, "%z"){|w| a << w}
+ a.empty?.should be_true
+ end
+end
diff --git a/spec/ruby/library/securerandom/base64_spec.rb b/spec/ruby/library/securerandom/base64_spec.rb
new file mode 100644
index 0000000000..68e61c9ecb
--- /dev/null
+++ b/spec/ruby/library/securerandom/base64_spec.rb
@@ -0,0 +1,55 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+require 'securerandom'
+
+describe "SecureRandom.base64" do
+ it "generates a random base64 string out of specified number of random bytes" do
+ (16..128).each do |idx|
+ base64 = SecureRandom.base64(idx)
+ base64.should be_kind_of(String)
+ base64.length.should < 2 * idx
+ base64.should =~ /^[A-Za-z0-9\+\/]+={0,2}$/
+ end
+
+ base64 = SecureRandom.base64(16.5)
+ base64.should be_kind_of(String)
+ base64.length.should < 2 * 16
+ end
+
+ it "returns an empty string when argument is 0" do
+ SecureRandom.base64(0).should == ""
+ end
+
+ it "generates different base64 strings with subsequent invocations" do
+ # quick and dirty check, but good enough
+ values = []
+ 256.times do
+ base64 = SecureRandom.base64
+ # make sure the random values are not repeating
+ values.include?(base64).should == false
+ values << base64
+ end
+ end
+
+ it "generates a random base64 string out of 32 random bytes" do
+ SecureRandom.base64.should be_kind_of(String)
+ SecureRandom.base64.length.should < 32 * 2
+ end
+
+ it "treats nil agrument as default one and generates a random base64 string" do
+ SecureRandom.base64(nil).should be_kind_of(String)
+ SecureRandom.base64(nil).length.should < 32 * 2
+ end
+
+ it "raises ArgumentError on negative arguments" do
+ lambda {
+ SecureRandom.base64(-1)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(5)
+ SecureRandom.base64(obj).size.should < 10
+ end
+end
diff --git a/spec/ruby/library/securerandom/hex_spec.rb b/spec/ruby/library/securerandom/hex_spec.rb
new file mode 100644
index 0000000000..691392a7b9
--- /dev/null
+++ b/spec/ruby/library/securerandom/hex_spec.rb
@@ -0,0 +1,54 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+require 'securerandom'
+
+describe "SecureRandom.hex" do
+ it "generates a random hex string of length twice the specified argement" do
+ (1..64).each do |idx|
+ hex = SecureRandom.hex(idx)
+ hex.should be_kind_of(String)
+ hex.length.should == 2 * idx
+ end
+
+ base64 = SecureRandom.hex(5.5)
+ base64.should be_kind_of(String)
+ base64.length.should eql(10)
+ end
+
+ it "returns an empty string when argument is 0" do
+ SecureRandom.hex(0).should == ""
+ end
+
+ it "generates different hex strings with subsequent invocations" do
+ # quick and dirty check, but good enough
+ values = []
+ 256.times do
+ hex = SecureRandom.hex
+ # make sure the random values are not repeating
+ values.include?(hex).should == false
+ values << hex
+ end
+ end
+
+ it "generates a random hex string of length 32 if no argument is provided" do
+ SecureRandom.hex.should be_kind_of(String)
+ SecureRandom.hex.length.should == 32
+ end
+
+ it "treats nil agrument as default one and generates a random hex string of length 32" do
+ SecureRandom.hex(nil).should be_kind_of(String)
+ SecureRandom.hex(nil).length.should == 32
+ end
+
+ it "raises ArgumentError on negative arguments" do
+ lambda {
+ SecureRandom.hex(-1)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(5)
+ SecureRandom.hex(obj).size.should eql(10)
+ end
+end
diff --git a/spec/ruby/library/securerandom/random_bytes_spec.rb b/spec/ruby/library/securerandom/random_bytes_spec.rb
new file mode 100644
index 0000000000..37d82f55a6
--- /dev/null
+++ b/spec/ruby/library/securerandom/random_bytes_spec.rb
@@ -0,0 +1,50 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+require 'securerandom'
+
+describe "SecureRandom.random_bytes" do
+ it "generates a random binary string of length 16 if no argument is provided" do
+ bytes = SecureRandom.random_bytes
+ bytes.should be_kind_of(String)
+ bytes.length.should == 16
+ end
+
+ it "generates a random binary string of length 16 if argument is nil" do
+ bytes = SecureRandom.random_bytes(nil)
+ bytes.should be_kind_of(String)
+ bytes.length.should == 16
+ end
+
+ it "generates a random binary string of specified length" do
+ (1..64).each do |idx|
+ bytes = SecureRandom.random_bytes(idx)
+ bytes.should be_kind_of(String)
+ bytes.length.should == idx
+ end
+
+ SecureRandom.random_bytes(2.2).length.should eql(2)
+ end
+
+ it "generates different binary strings with subsequent invocations" do
+ # quick and dirty check, but good enough
+ values = []
+ 256.times do
+ val = SecureRandom.random_bytes
+ # make sure the random bytes are not repeating
+ values.include?(val).should == false
+ values << val
+ end
+ end
+
+ it "raises ArgumentError on negative arguments" do
+ lambda {
+ SecureRandom.random_bytes(-1)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(5)
+ SecureRandom.random_bytes(obj).size.should eql(5)
+ end
+end
diff --git a/spec/ruby/library/securerandom/random_number_spec.rb b/spec/ruby/library/securerandom/random_number_spec.rb
new file mode 100644
index 0000000000..a23a457df2
--- /dev/null
+++ b/spec/ruby/library/securerandom/random_number_spec.rb
@@ -0,0 +1,95 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+require 'securerandom'
+
+describe "SecureRandom.random_number" do
+ it "generates a random positive number smaller then the positive integer argument" do
+ (1..64).each do |idx|
+ num = SecureRandom.random_number(idx)
+ num.should be_kind_of(Fixnum)
+ (0 <= num).should == true
+ (num < idx).should == true
+ end
+ end
+
+ it "generates a random (potentially bignum) integer value for bignum argument" do
+ max = 12345678901234567890
+ 11.times do
+ num = SecureRandom.random_number max
+ num.should be_kind_of(Integer)
+ (0 <= num).should == true
+ (num < max).should == true
+ end
+ end
+
+ it "generates a random float number between 0.0 and 1.0 if no argument provided" do
+ 64.times do
+ num = SecureRandom.random_number
+ num.should be_kind_of(Float)
+ (0.0 <= num).should == true
+ (num < 1.0).should == true
+ end
+ end
+
+ ruby_version_is "2.3" do
+ it "generates a random value in given (integer) range limits" do
+ 64.times do
+ num = SecureRandom.random_number 11...13
+ num.should be_kind_of(Integer)
+ (11 <= num).should == true
+ (num < 13).should == true
+ end
+ end
+
+ it "generates a random value in given big (integer) range limits" do
+ lower = 12345678901234567890
+ upper = 12345678901234567890 + 5
+ 32.times do
+ num = SecureRandom.random_number lower..upper
+ num.should be_kind_of(Integer)
+ (lower <= num).should == true
+ (num <= upper).should == true
+ end
+ end
+
+ it "generates a random value in given (float) range limits" do
+ 64.times do
+ num = SecureRandom.random_number 0.6..0.9
+ num.should be_kind_of(Float)
+ (0.6 <= num).should == true
+ (num <= 0.9).should == true
+ end
+ end
+ end
+
+ it "generates a random float number between 0.0 and 1.0 if argument is negative" do
+ num = SecureRandom.random_number(-10)
+ num.should be_kind_of(Float)
+ (0.0 <= num).should == true
+ (num < 1.0).should == true
+ end
+
+ it "generates a random float number between 0.0 and 1.0 if argument is negative float" do
+ num = SecureRandom.random_number(-11.1)
+ num.should be_kind_of(Float)
+ (0.0 <= num).should == true
+ (num < 1.0).should == true
+ end
+
+ it "generates different float numbers with subsequent invocations" do
+ # quick and dirty check, but good enough
+ values = []
+ 256.times do
+ val = SecureRandom.random_number
+ # make sure the random values are not repeating
+ values.include?(val).should == false
+ values << val
+ end
+ end
+
+ it "raises ArgumentError if the argument is non-numeric" do
+ lambda {
+ SecureRandom.random_number(Object.new)
+ }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/add_spec.rb b/spec/ruby/library/set/add_spec.rb
new file mode 100644
index 0000000000..a7d6fb8a56
--- /dev/null
+++ b/spec/ruby/library/set/add_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/add', __FILE__)
+
+describe "Set#add" do
+ it_behaves_like :set_add, :add
+end
+
+describe "Set#add?" do
+ before :each do
+ @set = Set.new
+ end
+
+ it "adds the passed Object to self" do
+ @set.add?("cat")
+ @set.should include("cat")
+ end
+
+ it "returns self when the Object has not yet been added to self" do
+ @set.add?("cat").should equal(@set)
+ end
+
+ it "returns nil when the Object has already been added to self" do
+ @set.add?("cat")
+ @set.add?("cat").should be_nil
+ end
+end
diff --git a/spec/ruby/library/set/append_spec.rb b/spec/ruby/library/set/append_spec.rb
new file mode 100644
index 0000000000..b3097c0904
--- /dev/null
+++ b/spec/ruby/library/set/append_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/add', __FILE__)
+
+describe "Set#<<" do
+ it_behaves_like :set_add, :<<
+end
diff --git a/spec/ruby/library/set/case_equality_spec.rb b/spec/ruby/library/set/case_equality_spec.rb
new file mode 100644
index 0000000000..f256324d49
--- /dev/null
+++ b/spec/ruby/library/set/case_equality_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/include', __FILE__)
+require 'set'
+
+ruby_version_is "2.5" do
+ describe "Set#===" do
+ it_behaves_like :set_include, :===
+ end
+end
diff --git a/spec/ruby/library/set/classify_spec.rb b/spec/ruby/library/set/classify_spec.rb
new file mode 100644
index 0000000000..87e5b62f96
--- /dev/null
+++ b/spec/ruby/library/set/classify_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#classify" do
+ before :each do
+ @set = Set["one", "two", "three", "four"]
+ end
+
+ it "yields each Object in self" do
+ res = []
+ @set.classify { |x| res << x }
+ res.sort.should == ["one", "two", "three", "four"].sort
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.classify
+ enum.should be_an_instance_of(Enumerator)
+
+ classified = enum.each { |x| x.length }
+ classified.should == { 3 => Set["one", "two"], 4 => Set["four"], 5 => Set["three"] }
+ end
+
+ it "classifies the Objects in self based on the block's return value" do
+ classified = @set.classify { |x| x.length }
+ classified.should == { 3 => Set["one", "two"], 4 => Set["four"], 5 => Set["three"] }
+ end
+end
diff --git a/spec/ruby/library/set/clear_spec.rb b/spec/ruby/library/set/clear_spec.rb
new file mode 100644
index 0000000000..b35ce4fec0
--- /dev/null
+++ b/spec/ruby/library/set/clear_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#clear" do
+ before :each do
+ @set = Set["one", "two", "three", "four"]
+ end
+
+ it "removes all elements from self" do
+ @set.clear
+ @set.should be_empty
+ end
+
+ it "returns self" do
+ @set.clear.should equal(@set)
+ end
+end
diff --git a/spec/ruby/library/set/collect_spec.rb b/spec/ruby/library/set/collect_spec.rb
new file mode 100644
index 0000000000..03c00c9794
--- /dev/null
+++ b/spec/ruby/library/set/collect_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/collect', __FILE__)
+
+describe "Set#collect!" do
+ it_behaves_like :set_collect_bang, :collect!
+end
diff --git a/spec/ruby/library/set/constructor_spec.rb b/spec/ruby/library/set/constructor_spec.rb
new file mode 100644
index 0000000000..75c7ba8bc8
--- /dev/null
+++ b/spec/ruby/library/set/constructor_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set[]" do
+ it "returns a new Set populated with the passed Objects" do
+ set = Set[1, 2, 3]
+
+ set.instance_of?(Set).should be_true
+ set.size.should eql(3)
+
+ set.should include(1)
+ set.should include(2)
+ set.should include(3)
+ end
+end
diff --git a/spec/ruby/library/set/delete_if_spec.rb b/spec/ruby/library/set/delete_if_spec.rb
new file mode 100644
index 0000000000..b6bd28a59f
--- /dev/null
+++ b/spec/ruby/library/set/delete_if_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#delete_if" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.delete_if { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "deletes every element from self for which the passed block returns true" do
+ @set.delete_if { |x| x.size == 3 }
+ @set.size.should eql(1)
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+
+ it "returns self" do
+ @set.delete_if { |x| x }.should equal(@set)
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.delete_if
+ enum.should be_an_instance_of(Enumerator)
+
+ enum.each { |x| x.size == 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/library/set/delete_spec.rb b/spec/ruby/library/set/delete_spec.rb
new file mode 100644
index 0000000000..4f0326e37a
--- /dev/null
+++ b/spec/ruby/library/set/delete_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#delete" do
+ before :each do
+ @set = Set["a", "b", "c"]
+ end
+
+ it "deletes the passed Object from self" do
+ @set.delete("a")
+ @set.should_not include("a")
+ end
+
+ it "returns self" do
+ @set.delete("a").should equal(@set)
+ @set.delete("x").should equal(@set)
+ end
+end
+
+describe "Set#delete?" do
+ before :each do
+ @set = Set["a", "b", "c"]
+ end
+
+ it "deletes the passed Object from self" do
+ @set.delete?("a")
+ @set.should_not include("a")
+ end
+
+ it "returns self when the passed Object is in self" do
+ @set.delete?("a").should equal(@set)
+ end
+
+ it "returns nil when the passed Object is not in self" do
+ @set.delete?("x").should be_nil
+ end
+end
diff --git a/spec/ruby/library/set/difference_spec.rb b/spec/ruby/library/set/difference_spec.rb
new file mode 100644
index 0000000000..416dffe802
--- /dev/null
+++ b/spec/ruby/library/set/difference_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/difference', __FILE__)
+
+describe "Set#difference" do
+ it_behaves_like :set_difference, :difference
+end
diff --git a/spec/ruby/library/set/divide_spec.rb b/spec/ruby/library/set/divide_spec.rb
new file mode 100644
index 0000000000..930c69885f
--- /dev/null
+++ b/spec/ruby/library/set/divide_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#divide" do
+ it "divides self into a set of subsets based on the blocks return values" do
+ set = Set["one", "two", "three", "four", "five"].divide { |x| x.length }
+ set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
+ end
+
+ it "yields each Object to the block" do
+ ret = []
+ Set["one", "two", "three", "four", "five"].divide { |x| ret << x }
+ ret.sort.should == ["five", "four", "one", "three", "two"]
+ end
+
+ # BUG: Does not raise a LocalJumpError, but a NoMethodError
+ #
+ # it "raises a LocalJumpError when not passed a block" do
+ # lambda { Set[1].divide }.should raise_error(LocalJumpError)
+ # end
+end
+
+describe "Set#divide when passed a block with an arity of 2" do
+ it "divides self into a set of subsets based on the blocks return values" do
+ set = Set[1, 3, 4, 6, 9, 10, 11].divide { |x, y| (x - y).abs == 1 }
+ set.map{ |x| x.to_a.sort }.sort.should == [[1], [3, 4], [6], [9, 10, 11]]
+ end
+
+ it "yields each two Object to the block" do
+ ret = []
+ Set[1, 2].divide { |x, y| ret << [x, y] }
+ ret.sort.should == [[1, 1], [1, 2], [2, 1], [2, 2]]
+ end
+end
diff --git a/spec/ruby/library/set/each_spec.rb b/spec/ruby/library/set/each_spec.rb
new file mode 100644
index 0000000000..867e94ff0b
--- /dev/null
+++ b/spec/ruby/library/set/each_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#each" do
+ before :each do
+ @set = Set[1, 2, 3]
+ end
+
+ it "yields each Object in self" do
+ ret = []
+ @set.each { |x| ret << x }
+ ret.sort.should == [1, 2, 3]
+ end
+
+ it "returns self" do
+ @set.each { |x| x }.should equal(@set)
+ end
+
+ it "returns an Enumerator when not passed a block" do
+ enum = @set.each
+
+ ret = []
+ enum.each { |x| ret << x }
+ ret.sort.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/library/set/empty_spec.rb b/spec/ruby/library/set/empty_spec.rb
new file mode 100644
index 0000000000..044d58727c
--- /dev/null
+++ b/spec/ruby/library/set/empty_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#empty?" do
+ it "returns true if self is empty" do
+ Set[].empty?.should be_true
+ Set[1].empty?.should be_false
+ Set[1,2,3].empty?.should be_false
+ end
+end
diff --git a/spec/ruby/library/set/enumerable/to_set_spec.rb b/spec/ruby/library/set/enumerable/to_set_spec.rb
new file mode 100644
index 0000000000..41ca039de6
--- /dev/null
+++ b/spec/ruby/library/set/enumerable/to_set_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Emumerable#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 "allows passing an alternate class for Set" do
+ sorted_set = [1, 2, 3].to_set(SortedSet)
+ sorted_set.should == SortedSet[1, 2, 3]
+ sorted_set.instance_of?(SortedSet).should == true
+ end
+
+ it "passes down passed blocks" do
+ [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9]
+ end
+end
diff --git a/spec/ruby/library/set/eql_spec.rb b/spec/ruby/library/set/eql_spec.rb
new file mode 100644
index 0000000000..ed62e20d7a
--- /dev/null
+++ b/spec/ruby/library/set/eql_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#eql?" do
+ it "returns true when the passed argument is a Set and contains the same elements" do
+ Set[].should eql(Set[])
+ Set[1, 2, 3].should eql(Set[1, 2, 3])
+ Set[1, 2, 3].should eql(Set[3, 2, 1])
+ Set["a", :b, ?c].should eql(Set[?c, :b, "a"])
+
+ Set[1, 2, 3].should_not eql(Set[1.0, 2, 3])
+ Set[1, 2, 3].should_not eql(Set[2, 3])
+ Set[1, 2, 3].should_not eql(Set[])
+ end
+end
diff --git a/spec/ruby/library/set/equal_value_spec.rb b/spec/ruby/library/set/equal_value_spec.rb
new file mode 100644
index 0000000000..2e2c875407
--- /dev/null
+++ b/spec/ruby/library/set/equal_value_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#==" do
+ it "returns true when the passed Object is a Set and self and the Object contain the same elements" do
+ Set[].should == Set[]
+ Set[1, 2, 3].should == Set[1, 2, 3]
+ Set["1", "2", "3"].should == Set["1", "2", "3"]
+
+ Set[1, 2, 3].should_not == Set[1.0, 2, 3]
+ Set[1, 2, 3].should_not == [1, 2, 3]
+ end
+
+ it "does not depend on the order of the elements" do
+ Set[1, 2, 3].should == Set[3, 2, 1]
+ Set[:a, "b", ?c].should == Set[?c, "b", :a]
+ end
+
+ it "does not depend on the order of nested Sets" do
+ Set[Set[1], Set[2], Set[3]].should == Set[Set[3], Set[2], Set[1]]
+
+ set1 = Set[Set["a", "b"], Set["c", "d"], Set["e", "f"]]
+ set2 = Set[Set["c", "d"], Set["a", "b"], Set["e", "f"]]
+ set1.should == set2
+ end
+end
diff --git a/spec/ruby/library/set/exclusion_spec.rb b/spec/ruby/library/set/exclusion_spec.rb
new file mode 100644
index 0000000000..d2923ba2d7
--- /dev/null
+++ b/spec/ruby/library/set/exclusion_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#^" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns a new Set containing elements that are not in both self and the passed Enumberable" do
+ (@set ^ Set[3, 4, 5]).should == Set[1, 2, 5]
+ (@set ^ [3, 4, 5]).should == Set[1, 2, 5]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { @set ^ 3 }.should raise_error(ArgumentError)
+ lambda { @set ^ Object.new }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/flatten_merge_spec.rb b/spec/ruby/library/set/flatten_merge_spec.rb
new file mode 100644
index 0000000000..bbddec7076
--- /dev/null
+++ b/spec/ruby/library/set/flatten_merge_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#flatten_merge" do
+ it "is protected" do
+ Set.should have_protected_instance_method("flatten_merge")
+ end
+
+ it "flattens the passed Set and merges it into self" do
+ set1 = Set[1, 2]
+ set2 = Set[3, 4, Set[5, 6]]
+
+ set1.send(:flatten_merge, set2).should == Set[1, 2, 3, 4, 5, 6]
+ end
+
+ it "raises an ArgumentError when trying to flatten a recursive Set" do
+ set1 = Set[1, 2, 3]
+ set2 = Set[5, 6, 7]
+ set2 << set2
+
+ lambda { set1.send(:flatten_merge, set2) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/flatten_spec.rb b/spec/ruby/library/set/flatten_spec.rb
new file mode 100644
index 0000000000..2fa7f9f6e5
--- /dev/null
+++ b/spec/ruby/library/set/flatten_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#flatten" do
+ it "returns a copy of self with each included Set flattened" do
+ set = Set[1, 2, Set[3, 4, Set[5, 6, Set[7, 8]]], 9, 10]
+ flattened_set = set.flatten
+
+ flattened_set.should_not equal(set)
+ flattened_set.should == Set[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ end
+
+ it "raises an ArgumentError when self is recursive" do
+ (set = Set[]) << set
+ lambda { set.flatten }.should raise_error(ArgumentError)
+ end
+end
+
+describe "Set#flatten!" do
+ it "flattens self" do
+ set = Set[1, 2, Set[3, 4, Set[5, 6, Set[7, 8]]], 9, 10]
+ set.flatten!
+ set.should == Set[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ end
+
+ it "returns self when self was modified" do
+ set = Set[1, 2, Set[3, 4]]
+ set.flatten!.should equal(set)
+ end
+
+ it "returns nil when self was not modified" do
+ set = Set[1, 2, 3, 4]
+ set.flatten!.should be_nil
+ end
+
+ it "raises an ArgumentError when self is recursive" do
+ (set = Set[]) << set
+ lambda { set.flatten! }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/hash_spec.rb b/spec/ruby/library/set/hash_spec.rb
new file mode 100644
index 0000000000..ea39105937
--- /dev/null
+++ b/spec/ruby/library/set/hash_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#hash" do
+ it "is static" do
+ Set[].hash.should == Set[].hash
+ Set[1, 2, 3].hash.should == Set[1, 2, 3].hash
+ Set[:a, "b", ?c].hash.should == Set[?c, "b", :a].hash
+
+ Set[].hash.should_not == Set[1, 2, 3].hash
+ Set[1, 2, 3].hash.should_not == Set[:a, "b", ?c].hash
+ end
+end
diff --git a/spec/ruby/library/set/include_spec.rb b/spec/ruby/library/set/include_spec.rb
new file mode 100644
index 0000000000..693b8b997f
--- /dev/null
+++ b/spec/ruby/library/set/include_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/include', __FILE__)
+require 'set'
+
+describe "Set#include?" do
+ it_behaves_like :set_include, :include?
+end
diff --git a/spec/ruby/library/set/initialize_spec.rb b/spec/ruby/library/set/initialize_spec.rb
new file mode 100644
index 0000000000..e14cbaacc2
--- /dev/null
+++ b/spec/ruby/library/set/initialize_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#initialize" do
+ it "is private" do
+ Set.should have_private_instance_method(:initialize)
+ end
+
+ it "adds all elements of the passed Enumerable to self" do
+ s = Set.new([1, 2, 3])
+ s.size.should eql(3)
+ s.should include(1)
+ s.should include(2)
+ s.should include(3)
+ end
+
+ it "preprocesses all elements by a passed block before adding to self" do
+ s = Set.new([1, 2, 3]) { |x| x * x }
+ s.size.should eql(3)
+ s.should include(1)
+ s.should include(4)
+ s.should include(9)
+ end
+end
diff --git a/spec/ruby/library/set/inspect_spec.rb b/spec/ruby/library/set/inspect_spec.rb
new file mode 100644
index 0000000000..8a6c565c2e
--- /dev/null
+++ b/spec/ruby/library/set/inspect_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#inspect" do
+ it "returns a String representation of self" do
+ Set[].inspect.should be_kind_of(String)
+ Set[nil, false, true].inspect.should be_kind_of(String)
+ Set[1, 2, 3].inspect.should be_kind_of(String)
+ Set["1", "2", "3"].inspect.should be_kind_of(String)
+ Set[:a, "b", Set[?c]].inspect.should be_kind_of(String)
+ end
+
+ it "correctly handles self-references" do
+ (set = Set[]) << set
+ set.inspect.should be_kind_of(String)
+ set.inspect.should include("#<Set: {...}>")
+ end
+end
diff --git a/spec/ruby/library/set/intersection_spec.rb b/spec/ruby/library/set/intersection_spec.rb
new file mode 100644
index 0000000000..c5adef5fc4
--- /dev/null
+++ b/spec/ruby/library/set/intersection_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/intersection', __FILE__)
+require 'set'
+
+describe "Set#intersection" do
+ it_behaves_like :set_intersection, :intersection
+end
+
+describe "Set#&" do
+ it_behaves_like :set_intersection, :&
+end
diff --git a/spec/ruby/library/set/keep_if_spec.rb b/spec/ruby/library/set/keep_if_spec.rb
new file mode 100644
index 0000000000..45f2cbf07a
--- /dev/null
+++ b/spec/ruby/library/set/keep_if_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#keep_if" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.keep_if { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "keeps every element from self for which the passed block returns true" do
+ @set.keep_if { |x| x.size != 3 }
+ @set.size.should eql(1)
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+
+ it "returns self" do
+ @set.keep_if {}.should equal(@set)
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.keep_if
+ enum.should be_an_instance_of(Enumerator)
+
+ enum.each { |x| x.size != 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/library/set/length_spec.rb b/spec/ruby/library/set/length_spec.rb
new file mode 100644
index 0000000000..274abcde83
--- /dev/null
+++ b/spec/ruby/library/set/length_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+require 'set'
+
+describe "Set#length" do
+ it_behaves_like :set_length, :length
+end
diff --git a/spec/ruby/library/set/map_spec.rb b/spec/ruby/library/set/map_spec.rb
new file mode 100644
index 0000000000..8610982ba9
--- /dev/null
+++ b/spec/ruby/library/set/map_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/collect', __FILE__)
+
+describe "Set#map!" do
+ it_behaves_like :set_collect_bang, :map!
+end
diff --git a/spec/ruby/library/set/member_spec.rb b/spec/ruby/library/set/member_spec.rb
new file mode 100644
index 0000000000..1a807c061b
--- /dev/null
+++ b/spec/ruby/library/set/member_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/include', __FILE__)
+require 'set'
+
+describe "Set#member?" do
+ it_behaves_like :set_include, :member?
+end
diff --git a/spec/ruby/library/set/merge_spec.rb b/spec/ruby/library/set/merge_spec.rb
new file mode 100644
index 0000000000..ecee51b951
--- /dev/null
+++ b/spec/ruby/library/set/merge_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#merge" do
+ it "adds the elements of the passed Enumerable to self" do
+ Set[:a, :b].merge(Set[:b, :c, :d]).should == Set[:a, :b, :c, :d]
+ Set[1, 2].merge([3, 4]).should == Set[1, 2, 3, 4]
+ end
+
+ it "returns self" do
+ set = Set[1, 2]
+ set.merge([3, 4]).should equal(set)
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { Set[1, 2].merge(1) }.should raise_error(ArgumentError)
+ lambda { Set[1, 2].merge(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/minus_spec.rb b/spec/ruby/library/set/minus_spec.rb
new file mode 100644
index 0000000000..3b14d6649d
--- /dev/null
+++ b/spec/ruby/library/set/minus_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/difference', __FILE__)
+
+describe "Set#-" do
+ it_behaves_like :set_difference, :-
+end
diff --git a/spec/ruby/library/set/plus_spec.rb b/spec/ruby/library/set/plus_spec.rb
new file mode 100644
index 0000000000..38b78b6330
--- /dev/null
+++ b/spec/ruby/library/set/plus_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/union', __FILE__)
+require 'set'
+
+describe "Set#+" do
+ it_behaves_like :set_union, :+
+end
diff --git a/spec/ruby/library/set/pretty_print_cycle_spec.rb b/spec/ruby/library/set/pretty_print_cycle_spec.rb
new file mode 100644
index 0000000000..a7eaab337b
--- /dev/null
+++ b/spec/ruby/library/set/pretty_print_cycle_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#pretty_print_cycle" do
+ it "passes the 'pretty print' representation of a self-referencing Set to the pretty print writer" do
+ pp = mock("PrettyPrint")
+ pp.should_receive(:text).with("#<Set: {...}>")
+ Set[1, 2, 3].pretty_print_cycle(pp)
+ end
+end
diff --git a/spec/ruby/library/set/pretty_print_spec.rb b/spec/ruby/library/set/pretty_print_spec.rb
new file mode 100644
index 0000000000..60f3ba7d3d
--- /dev/null
+++ b/spec/ruby/library/set/pretty_print_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#pretty_print" do
+ it "passes the 'pretty print' representation of self to the pretty print writer" do
+ pp = mock("PrettyPrint")
+ set = Set[1, 2, 3]
+
+ pp.should_receive(:text).with("#<Set: {")
+ pp.should_receive(:text).with("}>")
+
+ pp.should_receive(:nest).with(1).and_yield
+ pp.should_receive(:seplist).with(set)
+
+ set.pretty_print(pp)
+ end
+end
diff --git a/spec/ruby/library/set/proper_subset_spec.rb b/spec/ruby/library/set/proper_subset_spec.rb
new file mode 100644
index 0000000000..1a1fa13c3c
--- /dev/null
+++ b/spec/ruby/library/set/proper_subset_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#proper_subset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that self is a proper subset of" do
+ Set[].proper_subset?(@set).should be_true
+ Set[].proper_subset?(Set[1, 2, 3]).should be_true
+ Set[].proper_subset?(Set["a", :b, ?c]).should be_true
+
+ Set[1, 2, 3].proper_subset?(@set).should be_true
+ Set[1, 3].proper_subset?(@set).should be_true
+ Set[1, 2].proper_subset?(@set).should be_true
+ Set[1].proper_subset?(@set).should be_true
+
+ Set[5].proper_subset?(@set).should be_false
+ Set[1, 5].proper_subset?(@set).should be_false
+ Set[nil].proper_subset?(@set).should be_false
+ Set["test"].proper_subset?(@set).should be_false
+
+ @set.proper_subset?(@set).should be_false
+ Set[].proper_subset?(Set[]).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ lambda { Set[].proper_subset?([]) }.should raise_error(ArgumentError)
+ lambda { Set[].proper_subset?(1) }.should raise_error(ArgumentError)
+ lambda { Set[].proper_subset?("test") }.should raise_error(ArgumentError)
+ lambda { Set[].proper_subset?(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/proper_superset_spec.rb b/spec/ruby/library/set/proper_superset_spec.rb
new file mode 100644
index 0000000000..61c7984a6b
--- /dev/null
+++ b/spec/ruby/library/set/proper_superset_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#proper_superset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that self is a proper superset of" do
+ @set.proper_superset?(Set[]).should be_true
+ Set[1, 2, 3].proper_superset?(Set[]).should be_true
+ Set["a", :b, ?c].proper_superset?(Set[]).should be_true
+
+ @set.proper_superset?(Set[1, 2, 3]).should be_true
+ @set.proper_superset?(Set[1, 3]).should be_true
+ @set.proper_superset?(Set[1, 2]).should be_true
+ @set.proper_superset?(Set[1]).should be_true
+
+ @set.proper_superset?(Set[5]).should be_false
+ @set.proper_superset?(Set[1, 5]).should be_false
+ @set.proper_superset?(Set[nil]).should be_false
+ @set.proper_superset?(Set["test"]).should be_false
+
+ @set.proper_superset?(@set).should be_false
+ Set[].proper_superset?(Set[]).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ lambda { Set[].proper_superset?([]) }.should raise_error(ArgumentError)
+ lambda { Set[].proper_superset?(1) }.should raise_error(ArgumentError)
+ lambda { Set[].proper_superset?("test") }.should raise_error(ArgumentError)
+ lambda { Set[].proper_superset?(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/reject_spec.rb b/spec/ruby/library/set/reject_spec.rb
new file mode 100644
index 0000000000..32d3a92801
--- /dev/null
+++ b/spec/ruby/library/set/reject_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#reject!" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.reject! { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "deletes every element from self for which the passed block returns true" do
+ @set.reject! { |x| x.size == 3 }
+ @set.size.should eql(1)
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+
+ it "returns self when self was modified" do
+ @set.reject! { |x| true }.should equal(@set)
+ end
+
+ it "returns nil when self was not modified" do
+ @set.reject! { |x| false }.should be_nil
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.reject!
+ enum.should be_an_instance_of(Enumerator)
+
+ enum.each { |x| x.size == 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/library/set/replace_spec.rb b/spec/ruby/library/set/replace_spec.rb
new file mode 100644
index 0000000000..6f0c45b7ed
--- /dev/null
+++ b/spec/ruby/library/set/replace_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#replace" do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "replaces the contents with other and returns self" do
+ @set.replace(Set[1, 2, 3]).should == @set
+ @set.should == Set[1, 2, 3]
+ end
+
+ it "accepts any enumerable as other" do
+ @set.replace([1, 2, 3]).should == Set[1, 2, 3]
+ end
+end
diff --git a/spec/ruby/library/set/select_spec.rb b/spec/ruby/library/set/select_spec.rb
new file mode 100644
index 0000000000..34274a7c46
--- /dev/null
+++ b/spec/ruby/library/set/select_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#select!" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.select! { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "keeps every element from self for which the passed block returns true" do
+ @set.select! { |x| x.size != 3 }
+ @set.size.should eql(1)
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+
+ it "returns self when self was modified" do
+ @set.select! { false }.should equal(@set)
+ end
+
+ it "returns nil when self was not modified" do
+ @set.select! { true }.should be_nil
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.select!
+ enum.should be_an_instance_of(Enumerator)
+
+ enum.each { |x| x.size != 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/library/set/shared/add.rb b/spec/ruby/library/set/shared/add.rb
new file mode 100644
index 0000000000..9e797f5df9
--- /dev/null
+++ b/spec/ruby/library/set/shared/add.rb
@@ -0,0 +1,14 @@
+describe :set_add, shared: true do
+ before :each do
+ @set = Set.new
+ end
+
+ it "adds the passed Object to self" do
+ @set.send(@method, "dog")
+ @set.should include("dog")
+ end
+
+ it "returns self" do
+ @set.send(@method, "dog").should equal(@set)
+ end
+end
diff --git a/spec/ruby/library/set/shared/collect.rb b/spec/ruby/library/set/shared/collect.rb
new file mode 100644
index 0000000000..bc58c231be
--- /dev/null
+++ b/spec/ruby/library/set/shared/collect.rb
@@ -0,0 +1,20 @@
+describe :set_collect_bang, shared: true do
+ before :each do
+ @set = Set[1, 2, 3, 4, 5]
+ end
+
+ it "yields each Object in self" do
+ res = []
+ @set.send(@method) { |x| res << x }
+ res.sort.should == [1, 2, 3, 4, 5].sort
+ end
+
+ it "returns self" do
+ @set.send(@method) { |x| x }.should equal(@set)
+ end
+
+ it "replaces self with the return values of the block" do
+ @set.send(@method) { |x| x * 2 }
+ @set.should == Set[2, 4, 6, 8, 10]
+ end
+end
diff --git a/spec/ruby/library/set/shared/difference.rb b/spec/ruby/library/set/shared/difference.rb
new file mode 100644
index 0000000000..9439715da7
--- /dev/null
+++ b/spec/ruby/library/set/shared/difference.rb
@@ -0,0 +1,15 @@
+describe :set_difference, shared: true do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "returns a new Set containting self's elements excluding the elements in the passed Enumerable" do
+ @set.send(@method, Set[:a, :b]).should == Set[:c]
+ @set.send(@method, [:b, :c]).should == Set[:a]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { @set.send(@method, 1) }.should raise_error(ArgumentError)
+ lambda { @set.send(@method, Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/shared/include.rb b/spec/ruby/library/set/shared/include.rb
new file mode 100644
index 0000000000..d41f8f4102
--- /dev/null
+++ b/spec/ruby/library/set/shared/include.rb
@@ -0,0 +1,7 @@
+describe :set_include, shared: true do
+ it "returns true when self contains the passed Object" do
+ set = Set[:a, :b, :c]
+ set.send(@method, :a).should be_true
+ set.send(@method, :e).should be_false
+ end
+end
diff --git a/spec/ruby/library/set/shared/intersection.rb b/spec/ruby/library/set/shared/intersection.rb
new file mode 100644
index 0000000000..ed0db7457d
--- /dev/null
+++ b/spec/ruby/library/set/shared/intersection.rb
@@ -0,0 +1,15 @@
+describe :set_intersection, shared: true do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "returns a new Set containing only elements shared by self and the passed Enumerable" do
+ @set.send(@method, Set[:b, :c, :d, :e]).should == Set[:b, :c]
+ @set.send(@method, [:b, :c, :d]).should == Set[:b, :c]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { @set.send(@method, 1) }.should raise_error(ArgumentError)
+ lambda { @set.send(@method, Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/shared/length.rb b/spec/ruby/library/set/shared/length.rb
new file mode 100644
index 0000000000..a8fcee9f39
--- /dev/null
+++ b/spec/ruby/library/set/shared/length.rb
@@ -0,0 +1,6 @@
+describe :set_length, shared: true do
+ it "returns the number of elements in the set" do
+ set = Set[:a, :b, :c]
+ set.send(@method).should == 3
+ end
+end
diff --git a/spec/ruby/library/set/shared/union.rb b/spec/ruby/library/set/shared/union.rb
new file mode 100644
index 0000000000..81920f5687
--- /dev/null
+++ b/spec/ruby/library/set/shared/union.rb
@@ -0,0 +1,15 @@
+describe :set_union, shared: true do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "returns a new Set containing all elements of self and the passed Enumerable" do
+ @set.send(@method, Set[:b, :d, :e]).should == Set[:a, :b, :c, :d, :e]
+ @set.send(@method, [:b, :e]).should == Set[:a, :b, :c, :e]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { @set.send(@method, 1) }.should raise_error(ArgumentError)
+ lambda { @set.send(@method, Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/size_spec.rb b/spec/ruby/library/set/size_spec.rb
new file mode 100644
index 0000000000..f33740c5cd
--- /dev/null
+++ b/spec/ruby/library/set/size_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+require 'set'
+
+describe "Set#size" do
+ it_behaves_like :set_length, :size
+end
diff --git a/spec/ruby/library/set/sortedset/add_spec.rb b/spec/ruby/library/set/sortedset/add_spec.rb
new file mode 100644
index 0000000000..bdc5c077d8
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/add_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/add', __FILE__)
+
+describe "SortedSet#add" do
+ it_behaves_like :sorted_set_add, :add
+
+ it "takes only values which responds <=>" do
+ obj = mock('no_comparison_operator')
+ obj.should_receive(:respond_to?).with(:<=>).and_return(false)
+ lambda { SortedSet["hello"].add(obj) }.should raise_error(ArgumentError)
+ end
+end
+
+describe "SortedSet#add?" do
+ before :each do
+ @set = SortedSet.new
+ end
+
+ it "adds the passed Object to self" do
+ @set.add?("cat")
+ @set.should include("cat")
+ end
+
+ it "returns self when the Object has not yet been added to self" do
+ @set.add?("cat").should equal(@set)
+ end
+
+ it "returns nil when the Object has already been added to self" do
+ @set.add?("cat")
+ @set.add?("cat").should be_nil
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/append_spec.rb b/spec/ruby/library/set/sortedset/append_spec.rb
new file mode 100644
index 0000000000..62933f3e42
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/append_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/add', __FILE__)
+
+describe "SortedSet#<<" do
+ it_behaves_like :sorted_set_add, :<<
+end
diff --git a/spec/ruby/library/set/sortedset/case_equality_spec.rb b/spec/ruby/library/set/sortedset/case_equality_spec.rb
new file mode 100644
index 0000000000..cea52dedbd
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/case_equality_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/include', __FILE__)
+require 'set'
+
+ruby_version_is "2.5" do
+ describe "SortedSet#===" do
+ it_behaves_like :sorted_set_include, :===
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/classify_spec.rb b/spec/ruby/library/set/sortedset/classify_spec.rb
new file mode 100644
index 0000000000..1e8c814699
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/classify_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#classify" do
+ before :each do
+ @set = SortedSet["one", "two", "three", "four"]
+ end
+
+ it "yields each Object in self in sorted order" do
+ res = []
+ @set.classify { |x| res << x }
+ res.should == ["one", "two", "three", "four"].sort
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.classify
+ enum.should be_an_instance_of(Enumerator)
+
+ classified = enum.each { |x| x.length }
+ classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] }
+ end
+
+ it "classifies the Objects in self based on the block's return value" do
+ classified = @set.classify { |x| x.length }
+ classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] }
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/clear_spec.rb b/spec/ruby/library/set/sortedset/clear_spec.rb
new file mode 100644
index 0000000000..3a3277dd8a
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/clear_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#clear" do
+ before :each do
+ @set = SortedSet["one", "two", "three", "four"]
+ end
+
+ it "removes all elements from self" do
+ @set.clear
+ @set.should be_empty
+ end
+
+ it "returns self" do
+ @set.clear.should equal(@set)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/collect_spec.rb b/spec/ruby/library/set/sortedset/collect_spec.rb
new file mode 100644
index 0000000000..18274e6353
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/collect_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/collect', __FILE__)
+
+describe "SortedSet#collect!" do
+ it_behaves_like :sorted_set_collect_bang, :collect!
+end
diff --git a/spec/ruby/library/set/sortedset/constructor_spec.rb b/spec/ruby/library/set/sortedset/constructor_spec.rb
new file mode 100644
index 0000000000..45b6749e27
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/constructor_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet[]" do
+ it "returns a new SortedSet populated with the passed Objects" do
+ set = SortedSet[1, 2, 3]
+
+ set.instance_of?(SortedSet).should be_true
+ set.size.should eql(3)
+
+ set.should include(1)
+ set.should include(2)
+ set.should include(3)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/delete_if_spec.rb b/spec/ruby/library/set/sortedset/delete_if_spec.rb
new file mode 100644
index 0000000000..c809ff75f0
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/delete_if_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#delete_if" do
+ before :each do
+ @set = SortedSet["one", "two", "three"]
+ end
+
+ it "yields each Object in self in sorted order" do
+ ret = []
+ @set.delete_if { |x| ret << x }
+ ret.should == ["one", "two", "three"].sort
+ end
+
+ it "deletes every element from self for which the passed block returns true" do
+ @set.delete_if { |x| x.size == 3 }
+ @set.size.should eql(1)
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+
+ it "returns self" do
+ @set.delete_if { |x| x }.should equal(@set)
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.delete_if
+ enum.should be_an_instance_of(Enumerator)
+
+ enum.each { |x| x.size == 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/delete_spec.rb b/spec/ruby/library/set/sortedset/delete_spec.rb
new file mode 100644
index 0000000000..7123f79bcf
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/delete_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#delete" do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
+
+ it "deletes the passed Object from self" do
+ @set.delete("a")
+ @set.should_not include("a")
+ end
+
+ it "returns self" do
+ @set.delete("a").should equal(@set)
+ @set.delete("x").should equal(@set)
+ end
+end
+
+describe "SortedSet#delete?" do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
+
+ it "deletes the passed Object from self" do
+ @set.delete?("a")
+ @set.should_not include("a")
+ end
+
+ it "returns self when the passed Object is in self" do
+ @set.delete?("a").should equal(@set)
+ end
+
+ it "returns nil when the passed Object is not in self" do
+ @set.delete?("x").should be_nil
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/difference_spec.rb b/spec/ruby/library/set/sortedset/difference_spec.rb
new file mode 100644
index 0000000000..bc3650c55c
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/difference_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/difference', __FILE__)
+
+describe "SortedSet#difference" do
+ it_behaves_like :sorted_set_difference, :difference
+end
diff --git a/spec/ruby/library/set/sortedset/divide_spec.rb b/spec/ruby/library/set/sortedset/divide_spec.rb
new file mode 100644
index 0000000000..adb152b7e6
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/divide_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#divide" do
+ it "divides self into a set of subsets based on the blocks return values" do
+ set = SortedSet["one", "two", "three", "four", "five"].divide { |x| x.length }
+ set.map { |x| x.to_a }.to_a.sort.should == [["five", "four"], ["one", "two"], ["three"]]
+ end
+
+ it "yields each Object in self in sorted order" do
+ ret = []
+ SortedSet["one", "two", "three", "four", "five"].divide { |x| ret << x }
+ ret.should == ["one", "two", "three", "four", "five"].sort
+ end
+
+ # BUG: Does not raise a LocalJumpError, but a NoMethodError
+ #
+ # it "raises a LocalJumpError when not passed a block" do
+ # lambda { SortedSet[1].divide }.should raise_error(LocalJumpError)
+ # end
+end
+
+describe "SortedSet#divide when passed a block with an arity of 2" do
+ it "divides self into a set of subsets based on the blocks return values" do
+ set = SortedSet[1, 3, 4, 6, 9, 10, 11].divide { |x, y| (x - y).abs == 1 }
+ set.map { |x| x.to_a }.to_a.sort.should == [[1], [3, 4], [6], [9, 10, 11]]
+ end
+
+ it "yields each two Objects to the block" do
+ ret = []
+ SortedSet[1, 2].divide { |x, y| ret << [x, y] }
+ ret.should == [[1, 1], [1, 2], [2, 1], [2, 2]]
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/each_spec.rb b/spec/ruby/library/set/sortedset/each_spec.rb
new file mode 100644
index 0000000000..c715c403b2
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/each_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#each" do
+ before :each do
+ @set = SortedSet[1, 2, 3]
+ end
+
+ it "yields each Object in self in sorted order" do
+ ret = []
+ SortedSet["one", "two", "three"].each { |x| ret << x }
+ ret.should == ["one", "two", "three"].sort
+ end
+
+ it "returns self" do
+ @set.each { |x| x }.should equal(@set)
+ end
+
+ it "returns an Enumerator when not passed a block" do
+ enum = @set.each
+
+ ret = []
+ enum.each { |x| ret << x }
+ ret.sort.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/empty_spec.rb b/spec/ruby/library/set/sortedset/empty_spec.rb
new file mode 100644
index 0000000000..50d046e4c0
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/empty_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#empty?" do
+ it "returns true if self is empty" do
+ SortedSet[].empty?.should be_true
+ SortedSet[1].empty?.should be_false
+ SortedSet[1,2,3].empty?.should be_false
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/eql_spec.rb b/spec/ruby/library/set/sortedset/eql_spec.rb
new file mode 100644
index 0000000000..e7b3e7b624
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/eql_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#eql?" do
+ it "returns true when the passed argument is a SortedSet and contains the same elements" do
+ SortedSet[].should eql(SortedSet[])
+ SortedSet[1, 2, 3].should eql(SortedSet[1, 2, 3])
+ SortedSet[1, 2, 3].should eql(SortedSet[3, 2, 1])
+
+# SortedSet["a", :b, ?c].should eql(SortedSet[?c, :b, "a"])
+
+ SortedSet[1, 2, 3].should_not eql(SortedSet[1.0, 2, 3])
+ SortedSet[1, 2, 3].should_not eql(SortedSet[2, 3])
+ SortedSet[1, 2, 3].should_not eql(SortedSet[])
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/equal_value_spec.rb b/spec/ruby/library/set/sortedset/equal_value_spec.rb
new file mode 100644
index 0000000000..e358372aa4
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/equal_value_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#==" do
+ it "returns true when the passed Object is a SortedSet and self and the Object contain the same elements" do
+ SortedSet[].should == SortedSet[]
+ SortedSet[1, 2, 3].should == SortedSet[1, 2, 3]
+ SortedSet["1", "2", "3"].should == SortedSet["1", "2", "3"]
+
+ SortedSet[1, 2, 3].should_not == SortedSet[1.0, 2, 3]
+ SortedSet[1, 2, 3].should_not == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/exclusion_spec.rb b/spec/ruby/library/set/sortedset/exclusion_spec.rb
new file mode 100644
index 0000000000..193dbb7725
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/exclusion_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#^" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
+
+ it "returns a new SortedSet containing elements that are not in both self and the passed Enumberable" do
+ (@set ^ SortedSet[3, 4, 5]).should == SortedSet[1, 2, 5]
+ (@set ^ [3, 4, 5]).should == SortedSet[1, 2, 5]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { @set ^ 3 }.should raise_error(ArgumentError)
+ lambda { @set ^ Object.new }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/flatten_merge_spec.rb b/spec/ruby/library/set/sortedset/flatten_merge_spec.rb
new file mode 100644
index 0000000000..2a2505a58b
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/flatten_merge_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#flatten_merge" do
+ it "is protected" do
+ SortedSet.should have_protected_instance_method("flatten_merge")
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/flatten_spec.rb b/spec/ruby/library/set/sortedset/flatten_spec.rb
new file mode 100644
index 0000000000..80d064b846
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/flatten_spec.rb
@@ -0,0 +1,44 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+# Note: Flatten make little sens on sorted sets, because SortedSets are not (by default)
+# comparable. For a SortedSet to be both valid and nested, we need to define a comparison operator:
+module SortedSet_FlattenSpecs
+ class ComparableSortedSet < SortedSet
+ def <=>(other)
+ return puts "#{other} vs #{self}" unless other.is_a?(ComparableSortedSet)
+ to_a <=> other.to_a
+ end
+ end
+end
+
+describe "SortedSet#flatten" do
+ it "returns a copy of self with each included SortedSet flattened" do
+ klass = SortedSet_FlattenSpecs::ComparableSortedSet
+ set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]]
+ flattened_set = set.flatten
+
+ flattened_set.should_not equal(set)
+ flattened_set.should == klass[1, 2, 3, 4, 5, 6, 7, 8]
+ end
+end
+
+describe "SortedSet#flatten!" do
+ it "flattens self" do
+ klass = SortedSet_FlattenSpecs::ComparableSortedSet
+ set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]]
+ set.flatten!
+ set.should == klass[1, 2, 3, 4, 5, 6, 7, 8]
+ end
+
+ it "returns self when self was modified" do
+ klass = SortedSet_FlattenSpecs::ComparableSortedSet
+ set = klass[klass[1,2], klass[3,4]]
+ set.flatten!.should equal(set)
+ end
+
+ it "returns nil when self was not modified" do
+ set = SortedSet[1, 2, 3, 4]
+ set.flatten!.should be_nil
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/hash_spec.rb b/spec/ruby/library/set/sortedset/hash_spec.rb
new file mode 100644
index 0000000000..176cb7e8dc
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/hash_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#hash" do
+ it "is static" do
+ SortedSet[].hash.should == SortedSet[].hash
+ SortedSet[1, 2, 3].hash.should == SortedSet[1, 2, 3].hash
+ SortedSet["a", "b", "c"].hash.should == SortedSet["c", "b", "a"].hash
+
+ SortedSet[].hash.should_not == SortedSet[1, 2, 3].hash
+ SortedSet[1, 2, 3].hash.should_not == SortedSet["a", "b", "c"].hash
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/include_spec.rb b/spec/ruby/library/set/sortedset/include_spec.rb
new file mode 100644
index 0000000000..bb8ceda708
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/include_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/include', __FILE__)
+require 'set'
+
+describe "SortedSet#include?" do
+ it_behaves_like :sorted_set_include, :include?
+end
diff --git a/spec/ruby/library/set/sortedset/initialize_spec.rb b/spec/ruby/library/set/sortedset/initialize_spec.rb
new file mode 100644
index 0000000000..04ad908667
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/initialize_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#initialize" do
+ it "is private" do
+ SortedSet.should have_private_instance_method("initialize")
+ end
+
+ it "adds all elements of the passed Enumerable to self" do
+ s = SortedSet.new([1, 2, 3])
+ s.size.should eql(3)
+ s.should include(1)
+ s.should include(2)
+ s.should include(3)
+ end
+
+ it "preprocesses all elements by a passed block before adding to self" do
+ s = SortedSet.new([1, 2, 3]) { |x| x * x }
+ s.size.should eql(3)
+ s.should include(1)
+ s.should include(4)
+ s.should include(9)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/inspect_spec.rb b/spec/ruby/library/set/sortedset/inspect_spec.rb
new file mode 100644
index 0000000000..64b3f3d882
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/inspect_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#inspect" do
+ it "returns a String representation of self" do
+ SortedSet[].inspect.should be_kind_of(String)
+ SortedSet[1, 2, 3].inspect.should be_kind_of(String)
+ SortedSet["1", "2", "3"].inspect.should be_kind_of(String)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/intersection_spec.rb b/spec/ruby/library/set/sortedset/intersection_spec.rb
new file mode 100644
index 0000000000..d3f5b49ceb
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/intersection_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/intersection', __FILE__)
+require 'set'
+
+describe "SortedSet#intersection" do
+ it_behaves_like :sorted_set_intersection, :intersection
+end
+
+describe "SortedSet#&" do
+ it_behaves_like :sorted_set_intersection, :&
+end
diff --git a/spec/ruby/library/set/sortedset/keep_if_spec.rb b/spec/ruby/library/set/sortedset/keep_if_spec.rb
new file mode 100644
index 0000000000..7a117fbc87
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/keep_if_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#keep_if" do
+ before :each do
+ @set = SortedSet["one", "two", "three"]
+ end
+
+ it "yields each Object in self in sorted order" do
+ ret = []
+ @set.keep_if { |x| ret << x }
+ ret.should == ["one", "two", "three"].sort
+ end
+
+ it "keeps every element from self for which the passed block returns true" do
+ @set.keep_if { |x| x.size != 3 }
+ @set.to_a.should == ["three"]
+ end
+
+ it "returns self" do
+ @set.keep_if {}.should equal(@set)
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.keep_if
+ enum.should be_an_instance_of(Enumerator)
+
+ enum.each { |x| x.size != 3 }
+ @set.to_a.should == ["three"]
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/length_spec.rb b/spec/ruby/library/set/sortedset/length_spec.rb
new file mode 100644
index 0000000000..d829b3e08e
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/length_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+require 'set'
+
+describe "SortedSet#length" do
+ it_behaves_like :sorted_set_length, :length
+end
diff --git a/spec/ruby/library/set/sortedset/map_spec.rb b/spec/ruby/library/set/sortedset/map_spec.rb
new file mode 100644
index 0000000000..1f0828f347
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/map_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/collect', __FILE__)
+
+describe "SortedSet#map!" do
+ it_behaves_like :sorted_set_collect_bang, :map!
+end
diff --git a/spec/ruby/library/set/sortedset/member_spec.rb b/spec/ruby/library/set/sortedset/member_spec.rb
new file mode 100644
index 0000000000..d64e318b83
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/member_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/include', __FILE__)
+require 'set'
+
+describe "SortedSet#member?" do
+ it_behaves_like :sorted_set_include, :member?
+end
diff --git a/spec/ruby/library/set/sortedset/merge_spec.rb b/spec/ruby/library/set/sortedset/merge_spec.rb
new file mode 100644
index 0000000000..c422fe9513
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/merge_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#merge" do
+ it "adds the elements of the passed Enumerable to self" do
+ SortedSet["a", "b"].merge(SortedSet["b", "c", "d"]).should == SortedSet["a", "b", "c", "d"]
+ SortedSet[1, 2].merge([3, 4]).should == SortedSet[1, 2, 3, 4]
+ end
+
+ it "returns self" do
+ set = SortedSet[1, 2]
+ set.merge([3, 4]).should equal(set)
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { SortedSet[1, 2].merge(1) }.should raise_error(ArgumentError)
+ lambda { SortedSet[1, 2].merge(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/minus_spec.rb b/spec/ruby/library/set/sortedset/minus_spec.rb
new file mode 100644
index 0000000000..1f56d57037
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/minus_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+require File.expand_path('../shared/difference', __FILE__)
+
+describe "SortedSet#-" do
+ it_behaves_like :sorted_set_difference, :-
+end
diff --git a/spec/ruby/library/set/sortedset/plus_spec.rb b/spec/ruby/library/set/sortedset/plus_spec.rb
new file mode 100644
index 0000000000..af9bdf82fa
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/plus_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/union', __FILE__)
+require 'set'
+
+describe "SortedSet#+" do
+ it_behaves_like :sorted_set_union, :+
+end
diff --git a/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb b/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb
new file mode 100644
index 0000000000..6e79245e18
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#pretty_print_cycle" do
+ it "passes the 'pretty print' representation of a self-referencing SortedSet to the pretty print writer" do
+ pp = mock("PrettyPrint")
+ pp.should_receive(:text).with("#<SortedSet: {...}>")
+ SortedSet[1, 2, 3].pretty_print_cycle(pp)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/pretty_print_spec.rb b/spec/ruby/library/set/sortedset/pretty_print_spec.rb
new file mode 100644
index 0000000000..5317357b8f
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/pretty_print_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#pretty_print" do
+ it "passes the 'pretty print' representation of self to the pretty print writer" do
+ pp = mock("PrettyPrint")
+ set = SortedSet[1, 2, 3]
+
+ pp.should_receive(:text).with("#<SortedSet: {")
+ pp.should_receive(:text).with("}>")
+
+ pp.should_receive(:nest).with(1).and_yield
+ pp.should_receive(:seplist).with(set)
+
+ set.pretty_print(pp)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/proper_subset_spec.rb b/spec/ruby/library/set/sortedset/proper_subset_spec.rb
new file mode 100644
index 0000000000..7e94774c1f
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/proper_subset_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#proper_subset?" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a SortedSet that self is a proper subset of" do
+ SortedSet[].proper_subset?(@set).should be_true
+ SortedSet[].proper_subset?(SortedSet[1, 2, 3]).should be_true
+ SortedSet[].proper_subset?(SortedSet["a", "b", "c"]).should be_true
+
+ SortedSet[1, 2, 3].proper_subset?(@set).should be_true
+ SortedSet[1, 3].proper_subset?(@set).should be_true
+ SortedSet[1, 2].proper_subset?(@set).should be_true
+ SortedSet[1].proper_subset?(@set).should be_true
+
+ SortedSet[5].proper_subset?(@set).should be_false
+ SortedSet[1, 5].proper_subset?(@set).should be_false
+ SortedSet["test"].proper_subset?(@set).should be_false
+
+ @set.proper_subset?(@set).should be_false
+ SortedSet[].proper_subset?(SortedSet[]).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-SortedSet" do
+ lambda { SortedSet[].proper_subset?([]) }.should raise_error(ArgumentError)
+ lambda { SortedSet[].proper_subset?(1) }.should raise_error(ArgumentError)
+ lambda { SortedSet[].proper_subset?("test") }.should raise_error(ArgumentError)
+ lambda { SortedSet[].proper_subset?(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/proper_superset_spec.rb b/spec/ruby/library/set/sortedset/proper_superset_spec.rb
new file mode 100644
index 0000000000..ccfa37988d
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/proper_superset_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#proper_superset?" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a SortedSet that self is a proper superset of" do
+ @set.proper_superset?(SortedSet[]).should be_true
+ SortedSet[1, 2, 3].proper_superset?(SortedSet[]).should be_true
+ SortedSet["a", "b", "c"].proper_superset?(SortedSet[]).should be_true
+
+ @set.proper_superset?(SortedSet[1, 2, 3]).should be_true
+ @set.proper_superset?(SortedSet[1, 3]).should be_true
+ @set.proper_superset?(SortedSet[1, 2]).should be_true
+ @set.proper_superset?(SortedSet[1]).should be_true
+
+ @set.proper_superset?(SortedSet[5]).should be_false
+ @set.proper_superset?(SortedSet[1, 5]).should be_false
+ @set.proper_superset?(SortedSet["test"]).should be_false
+
+ @set.proper_superset?(@set).should be_false
+ SortedSet[].proper_superset?(SortedSet[]).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-SortedSet" do
+ lambda { SortedSet[].proper_superset?([]) }.should raise_error(ArgumentError)
+ lambda { SortedSet[].proper_superset?(1) }.should raise_error(ArgumentError)
+ lambda { SortedSet[].proper_superset?("test") }.should raise_error(ArgumentError)
+ lambda { SortedSet[].proper_superset?(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/reject_spec.rb b/spec/ruby/library/set/sortedset/reject_spec.rb
new file mode 100644
index 0000000000..e357d55052
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/reject_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#reject!" do
+ before :each do
+ @set = SortedSet["one", "two", "three"]
+ end
+
+ it "yields each Object in self in sorted order" do
+ res = []
+ @set.reject! { |x| res << x }
+ res.should == ["one", "two", "three"].sort
+ end
+
+ it "deletes every element from self for which the passed block returns true" do
+ @set.reject! { |x| x.size == 3 }
+ @set.size.should eql(1)
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+
+ it "returns self when self was modified" do
+ @set.reject! { |x| true }.should equal(@set)
+ end
+
+ it "returns nil when self was not modified" do
+ @set.reject! { |x| false }.should be_nil
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.reject!
+ enum.should be_an_instance_of(Enumerator)
+
+ enum.each { |x| x.size == 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/replace_spec.rb b/spec/ruby/library/set/sortedset/replace_spec.rb
new file mode 100644
index 0000000000..a5bf333e87
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/replace_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#replace" do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
+
+ it "replaces the contents with other and returns self" do
+ @set.replace(SortedSet[1, 2, 3]).should == @set
+ @set.should == SortedSet[1, 2, 3]
+ end
+
+ it "accepts any enumerable as other" do
+ @set.replace([1, 2, 3]).should == SortedSet[1, 2, 3]
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/select_spec.rb b/spec/ruby/library/set/sortedset/select_spec.rb
new file mode 100644
index 0000000000..3ca748350a
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/select_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#select!" do
+ before :each do
+ @set = SortedSet["one", "two", "three"]
+ end
+
+ it "yields each Object in self in sorted order" do
+ res = []
+ @set.select! { |x| res << x }
+ res.should == ["one", "two", "three"].sort
+ end
+
+ it "keeps every element from self for which the passed block returns true" do
+ @set.select! { |x| x.size != 3 }
+ @set.to_a.should == ["three"]
+ end
+
+ it "returns self when self was modified" do
+ @set.select! { false }.should equal(@set)
+ end
+
+ it "returns nil when self was not modified" do
+ @set.select! { true }.should be_nil
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.select!
+ enum.should be_an_instance_of(Enumerator)
+
+ enum.each { |x| x.size != 3 }
+ @set.to_a.should == ["three"]
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/shared/add.rb b/spec/ruby/library/set/sortedset/shared/add.rb
new file mode 100644
index 0000000000..95ef1b090e
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/shared/add.rb
@@ -0,0 +1,14 @@
+describe :sorted_set_add, shared: true do
+ before :each do
+ @set = SortedSet.new
+ end
+
+ it "adds the passed Object to self" do
+ @set.send(@method, "dog")
+ @set.should include("dog")
+ end
+
+ it "returns self" do
+ @set.send(@method, "dog").should equal(@set)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/shared/collect.rb b/spec/ruby/library/set/sortedset/shared/collect.rb
new file mode 100644
index 0000000000..e53304d427
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/shared/collect.rb
@@ -0,0 +1,20 @@
+describe :sorted_set_collect_bang, shared: true do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4, 5]
+ end
+
+ it "yields each Object in self in sorted order" do
+ res = []
+ SortedSet["one", "two", "three"].send(@method) { |x| res << x; x }
+ res.should == ["one", "two", "three"].sort
+ end
+
+ it "returns self" do
+ @set.send(@method) { |x| x }.should equal(@set)
+ end
+
+ it "replaces self with the return values of the block" do
+ @set.send(@method) { |x| x * 2 }
+ @set.should == SortedSet[2, 4, 6, 8, 10]
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/shared/difference.rb b/spec/ruby/library/set/sortedset/shared/difference.rb
new file mode 100644
index 0000000000..ec57015ac2
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/shared/difference.rb
@@ -0,0 +1,15 @@
+describe :sorted_set_difference, shared: true do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
+
+ it "returns a new SortedSet containting self's elements excluding the elements in the passed Enumerable" do
+ @set.send(@method, SortedSet["a", "b"]).should == SortedSet["c"]
+ @set.send(@method, ["b", "c"]).should == SortedSet["a"]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { @set.send(@method, 1) }.should raise_error(ArgumentError)
+ lambda { @set.send(@method, Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/shared/include.rb b/spec/ruby/library/set/sortedset/shared/include.rb
new file mode 100644
index 0000000000..cd1758819d
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/shared/include.rb
@@ -0,0 +1,7 @@
+describe :sorted_set_include, shared: true do
+ it "returns true when self contains the passed Object" do
+ set = SortedSet["a", "b", "c"]
+ set.send(@method, "a").should be_true
+ set.send(@method, "e").should be_false
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/shared/intersection.rb b/spec/ruby/library/set/sortedset/shared/intersection.rb
new file mode 100644
index 0000000000..d3cfa96656
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/shared/intersection.rb
@@ -0,0 +1,15 @@
+describe :sorted_set_intersection, shared: true do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
+
+ it "returns a new SortedSet containing only elements shared by self and the passed Enumerable" do
+ @set.send(@method, SortedSet["b", "c", "d", "e"]).should == SortedSet["b", "c"]
+ @set.send(@method, ["b", "c", "d"]).should == SortedSet["b", "c"]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { @set.send(@method, 1) }.should raise_error(ArgumentError)
+ lambda { @set.send(@method, Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/shared/length.rb b/spec/ruby/library/set/sortedset/shared/length.rb
new file mode 100644
index 0000000000..d1dfee1cff
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/shared/length.rb
@@ -0,0 +1,6 @@
+describe :sorted_set_length, shared: true do
+ it "returns the number of elements in the set" do
+ set = SortedSet["a", "b", "c"]
+ set.send(@method).should == 3
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/shared/union.rb b/spec/ruby/library/set/sortedset/shared/union.rb
new file mode 100644
index 0000000000..4ff07ef5cc
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/shared/union.rb
@@ -0,0 +1,15 @@
+describe :sorted_set_union, shared: true do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
+
+ it "returns a new SortedSet containing all elements of self and the passed Enumerable" do
+ @set.send(@method, SortedSet["b", "d", "e"]).should == SortedSet["a", "b", "c", "d", "e"]
+ @set.send(@method, ["b", "e"]).should == SortedSet["a", "b", "c", "e"]
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ lambda { @set.send(@method, 1) }.should raise_error(ArgumentError)
+ lambda { @set.send(@method, Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/size_spec.rb b/spec/ruby/library/set/sortedset/size_spec.rb
new file mode 100644
index 0000000000..dbcdc3ded3
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/size_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+require 'set'
+
+describe "SortedSet#size" do
+ it_behaves_like :sorted_set_length, :size
+end
diff --git a/spec/ruby/library/set/sortedset/subset_spec.rb b/spec/ruby/library/set/sortedset/subset_spec.rb
new file mode 100644
index 0000000000..81f938317c
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/subset_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#subset?" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a SortedSet that is equal to self or self is a subset of" do
+ @set.subset?(@set).should be_true
+ SortedSet[].subset?(SortedSet[]).should be_true
+
+ SortedSet[].subset?(@set).should be_true
+ SortedSet[].subset?(SortedSet[1, 2, 3]).should be_true
+ SortedSet[].subset?(SortedSet["a", "b", "c"]).should be_true
+
+ SortedSet[1, 2, 3].subset?(@set).should be_true
+ SortedSet[1, 3].subset?(@set).should be_true
+ SortedSet[1, 2].subset?(@set).should be_true
+ SortedSet[1].subset?(@set).should be_true
+
+ SortedSet[5].subset?(@set).should be_false
+ SortedSet[1, 5].subset?(@set).should be_false
+ SortedSet["test"].subset?(@set).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-SortedSet" do
+ lambda { SortedSet[].subset?([]) }.should raise_error(ArgumentError)
+ lambda { SortedSet[].subset?(1) }.should raise_error(ArgumentError)
+ lambda { SortedSet[].subset?("test") }.should raise_error(ArgumentError)
+ lambda { SortedSet[].subset?(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/subtract_spec.rb b/spec/ruby/library/set/sortedset/subtract_spec.rb
new file mode 100644
index 0000000000..207748cfb9
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/subtract_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#subtract" do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
+
+ it "deletes any elements contained in other and returns self" do
+ @set.subtract(SortedSet["b", "c"]).should == @set
+ @set.should == SortedSet["a"]
+ end
+
+ it "accepts any enumerable as other" do
+ @set.subtract(["c"]).should == SortedSet["a", "b"]
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/superset_spec.rb b/spec/ruby/library/set/sortedset/superset_spec.rb
new file mode 100644
index 0000000000..fc54e618a2
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/superset_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#superset?" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a SortedSet that equals self or self is a proper superset of" do
+ @set.superset?(@set).should be_true
+ SortedSet[].superset?(SortedSet[]).should be_true
+
+ @set.superset?(SortedSet[]).should be_true
+ SortedSet[1, 2, 3].superset?(SortedSet[]).should be_true
+ SortedSet["a", "b", "c"].superset?(SortedSet[]).should be_true
+
+ @set.superset?(SortedSet[1, 2, 3]).should be_true
+ @set.superset?(SortedSet[1, 3]).should be_true
+ @set.superset?(SortedSet[1, 2]).should be_true
+ @set.superset?(SortedSet[1]).should be_true
+
+ @set.superset?(SortedSet[5]).should be_false
+ @set.superset?(SortedSet[1, 5]).should be_false
+ @set.superset?(SortedSet["test"]).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-SortedSet" do
+ lambda { SortedSet[].superset?([]) }.should raise_error(ArgumentError)
+ lambda { SortedSet[].superset?(1) }.should raise_error(ArgumentError)
+ lambda { SortedSet[].superset?("test") }.should raise_error(ArgumentError)
+ lambda { SortedSet[].superset?(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/to_a_spec.rb b/spec/ruby/library/set/sortedset/to_a_spec.rb
new file mode 100644
index 0000000000..f288cfb9d2
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/to_a_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'set'
+
+describe "SortedSet#to_a" do
+ it "returns an array containing elements of self" do
+ SortedSet[1, 2, 3].to_a.sort.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/library/set/sortedset/union_spec.rb b/spec/ruby/library/set/sortedset/union_spec.rb
new file mode 100644
index 0000000000..c7255c3d2f
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/union_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/union', __FILE__)
+require 'set'
+
+describe "SortedSet#union" do
+ it_behaves_like :sorted_set_union, :union
+end
+
+describe "SortedSet#|" do
+ it_behaves_like :sorted_set_union, :|
+end
diff --git a/spec/ruby/library/set/subset_spec.rb b/spec/ruby/library/set/subset_spec.rb
new file mode 100644
index 0000000000..6503a7539f
--- /dev/null
+++ b/spec/ruby/library/set/subset_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#subset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that is equal to self or self is a subset of" do
+ @set.subset?(@set).should be_true
+ Set[].subset?(Set[]).should be_true
+
+ Set[].subset?(@set).should be_true
+ Set[].subset?(Set[1, 2, 3]).should be_true
+ Set[].subset?(Set["a", :b, ?c]).should be_true
+
+ Set[1, 2, 3].subset?(@set).should be_true
+ Set[1, 3].subset?(@set).should be_true
+ Set[1, 2].subset?(@set).should be_true
+ Set[1].subset?(@set).should be_true
+
+ Set[5].subset?(@set).should be_false
+ Set[1, 5].subset?(@set).should be_false
+ Set[nil].subset?(@set).should be_false
+ Set["test"].subset?(@set).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ lambda { Set[].subset?([]) }.should raise_error(ArgumentError)
+ lambda { Set[].subset?(1) }.should raise_error(ArgumentError)
+ lambda { Set[].subset?("test") }.should raise_error(ArgumentError)
+ lambda { Set[].subset?(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/subtract_spec.rb b/spec/ruby/library/set/subtract_spec.rb
new file mode 100644
index 0000000000..b0889bb675
--- /dev/null
+++ b/spec/ruby/library/set/subtract_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#subtract" do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "deletes any elements contained in other and returns self" do
+ @set.subtract(Set[:b, :c]).should == @set
+ @set.should == Set[:a]
+ end
+
+ it "accepts any enumerable as other" do
+ @set.subtract([:c]).should == Set[:a, :b]
+ end
+end
diff --git a/spec/ruby/library/set/superset_spec.rb b/spec/ruby/library/set/superset_spec.rb
new file mode 100644
index 0000000000..b7364f529e
--- /dev/null
+++ b/spec/ruby/library/set/superset_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#superset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that equals self or self is a proper superset of" do
+ @set.superset?(@set).should be_true
+ Set[].superset?(Set[]).should be_true
+
+ @set.superset?(Set[]).should be_true
+ Set[1, 2, 3].superset?(Set[]).should be_true
+ Set["a", :b, ?c].superset?(Set[]).should be_true
+
+ @set.superset?(Set[1, 2, 3]).should be_true
+ @set.superset?(Set[1, 3]).should be_true
+ @set.superset?(Set[1, 2]).should be_true
+ @set.superset?(Set[1]).should be_true
+
+ @set.superset?(Set[5]).should be_false
+ @set.superset?(Set[1, 5]).should be_false
+ @set.superset?(Set[nil]).should be_false
+ @set.superset?(Set["test"]).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ lambda { Set[].superset?([]) }.should raise_error(ArgumentError)
+ lambda { Set[].superset?(1) }.should raise_error(ArgumentError)
+ lambda { Set[].superset?("test") }.should raise_error(ArgumentError)
+ lambda { Set[].superset?(Object.new) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/set/to_a_spec.rb b/spec/ruby/library/set/to_a_spec.rb
new file mode 100644
index 0000000000..daee014e90
--- /dev/null
+++ b/spec/ruby/library/set/to_a_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+describe "Set#to_a" do
+ it "returns an array containing elements of self" do
+ Set[1, 2, 3].to_a.sort.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/library/set/union_spec.rb b/spec/ruby/library/set/union_spec.rb
new file mode 100644
index 0000000000..c705497928
--- /dev/null
+++ b/spec/ruby/library/set/union_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/union', __FILE__)
+require 'set'
+
+describe "Set#union" do
+ it_behaves_like :set_union, :union
+end
+
+describe "Set#|" do
+ it_behaves_like :set_union, :|
+end
diff --git a/spec/ruby/library/shellwords/shellwords_spec.rb b/spec/ruby/library/shellwords/shellwords_spec.rb
new file mode 100644
index 0000000000..aa35c1a5c3
--- /dev/null
+++ b/spec/ruby/library/shellwords/shellwords_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'shellwords'
+include Shellwords
+
+describe "Shellwords#shellwords" do
+ it "honors quoted strings" do
+ shellwords('a "b b" a').should == ['a', 'b b', 'a']
+ end
+
+ it "honors escaped double quotes" do
+ shellwords('a "\"b\" c" d').should == ['a', '"b" c', 'd']
+ end
+
+ it "honors escaped single quotes" do
+ shellwords("a \"'b' c\" d").should == ['a', "'b' c", 'd']
+ end
+
+ it "honors escaped spaces" do
+ shellwords('a b\ c d').should == ['a', 'b c', 'd']
+ end
+
+ it "raises ArgumentError when double quoted strings are misquoted" do
+ lambda { shellwords('a "b c d e') }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError when single quoted strings are misquoted" do
+ lambda { shellwords("a 'b c d e") }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/singleton/allocate_spec.rb b/spec/ruby/library/singleton/allocate_spec.rb
new file mode 100644
index 0000000000..ce6a501db7
--- /dev/null
+++ b/spec/ruby/library/singleton/allocate_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Singleton.allocate" do
+ it "is a private method" do
+ lambda { SingletonSpecs::MyClass.allocate }.should raise_error(NoMethodError)
+ end
+end
diff --git a/spec/ruby/library/singleton/clone_spec.rb b/spec/ruby/library/singleton/clone_spec.rb
new file mode 100644
index 0000000000..964a57bdee
--- /dev/null
+++ b/spec/ruby/library/singleton/clone_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Singleton#clone" do
+ it "is prevented" do
+ lambda { SingletonSpecs::MyClass.instance.clone }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/singleton/dump_spec.rb b/spec/ruby/library/singleton/dump_spec.rb
new file mode 100644
index 0000000000..03f94cffd2
--- /dev/null
+++ b/spec/ruby/library/singleton/dump_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Singleton#_dump" do
+
+ it "returns an empty string" do
+ SingletonSpecs::MyClass.instance.send(:_dump).should == ""
+ end
+
+ it "returns an empty string from a singleton subclass" do
+ SingletonSpecs::MyClassChild.instance.send(:_dump).should == ""
+ end
+
+end
diff --git a/spec/ruby/library/singleton/dup_spec.rb b/spec/ruby/library/singleton/dup_spec.rb
new file mode 100644
index 0000000000..16fe147f26
--- /dev/null
+++ b/spec/ruby/library/singleton/dup_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Singleton#dup" do
+ it "is prevented" do
+ lambda { SingletonSpecs::MyClass.instance.dup }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/singleton/fixtures/classes.rb b/spec/ruby/library/singleton/fixtures/classes.rb
new file mode 100644
index 0000000000..c718ebaec8
--- /dev/null
+++ b/spec/ruby/library/singleton/fixtures/classes.rb
@@ -0,0 +1,18 @@
+require 'singleton'
+
+module SingletonSpecs
+ class MyClass
+ attr_accessor :data
+ include Singleton
+ end
+
+ class NewSpec
+ include Singleton
+ end
+
+ class MyClassChild < MyClass
+ end
+
+ class NotInstantiated < MyClass
+ end
+end
diff --git a/spec/ruby/library/singleton/instance_spec.rb b/spec/ruby/library/singleton/instance_spec.rb
new file mode 100644
index 0000000000..84cc081510
--- /dev/null
+++ b/spec/ruby/library/singleton/instance_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Singleton.instance" do
+ it "returns an instance of the singleton class" do
+ SingletonSpecs::MyClass.instance.should be_kind_of(SingletonSpecs::MyClass)
+ end
+
+ it "returns the same instance for multiple calls to instance" do
+ SingletonSpecs::MyClass.instance.should equal(SingletonSpecs::MyClass.instance)
+ end
+
+ it "returns an instance of the singleton's subclasses" do
+ SingletonSpecs::MyClassChild.instance.should be_kind_of(SingletonSpecs::MyClassChild)
+ end
+
+ it "returns the same instance for multiple class to instance on subclasses" do
+ SingletonSpecs::MyClassChild.instance.should equal(SingletonSpecs::MyClassChild.instance)
+ end
+
+ it "returns an instance of the singleton's clone" do
+ klone = SingletonSpecs::MyClassChild.clone
+ klone.instance.should be_kind_of(klone)
+ end
+
+ it "returns the same instance for multiple class to instance on clones" do
+ klone = SingletonSpecs::MyClassChild.clone
+ klone.instance.should equal(klone.instance)
+ end
+end
diff --git a/spec/ruby/library/singleton/load_spec.rb b/spec/ruby/library/singleton/load_spec.rb
new file mode 100644
index 0000000000..fa5868693b
--- /dev/null
+++ b/spec/ruby/library/singleton/load_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+# TODO: change to a.should be_equal(b)
+# TODO: write spec for cloning classes and calling private methods
+# TODO: write spec for private_methods not showing up via extended
+describe "Singleton._load" do
+ it "returns the singleton instance for anything passed in" do
+ klass = SingletonSpecs::MyClass
+ klass._load("").should equal(klass.instance)
+ klass._load("42").should equal(klass.instance)
+ klass._load(42).should equal(klass.instance)
+ end
+
+ it "returns the singleton instance for anything passed in to subclass" do
+ subklass = SingletonSpecs::MyClassChild
+ subklass._load("").should equal(subklass.instance)
+ subklass._load("42").should equal(subklass.instance)
+ subklass._load(42).should equal(subklass.instance)
+ end
+end
diff --git a/spec/ruby/library/singleton/new_spec.rb b/spec/ruby/library/singleton/new_spec.rb
new file mode 100644
index 0000000000..cd20bebc2b
--- /dev/null
+++ b/spec/ruby/library/singleton/new_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "Singleton.new" do
+ it "is a private method" do
+ lambda { SingletonSpecs::NewSpec.new }.should raise_error(NoMethodError)
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/afamily_spec.rb b/spec/ruby/library/socket/addrinfo/afamily_spec.rb
new file mode 100644
index 0000000000..1845ab5e04
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/afamily_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#afamily" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns Socket::AF_INET" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns Socket::AF_INET6" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::AF_UNIX" do
+ @addrinfo.afamily.should == Socket::AF_UNIX
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/bind_spec.rb b/spec/ruby/library/socket/addrinfo/bind_spec.rb
new file mode 100644
index 0000000000..c892b05756
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/bind_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'socket'
+
+describe "Addrinfo#bind" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 0)
+ end
+
+ after :each do
+ @socket.close unless @socket.closed?
+ end
+
+ it "returns a bound socket when no block is given" do
+ @socket = @addrinfo.bind
+ @socket.should be_kind_of(Socket)
+ @socket.closed?.should be_false
+ end
+
+ it "yields the socket if a block is given" do
+ @addrinfo.bind do |sock|
+ @socket = sock
+ sock.should be_kind_of(Socket)
+ end
+ @socket.closed?.should be_true
+ end
+
+end
diff --git a/spec/ruby/library/socket/addrinfo/canonname_spec.rb b/spec/ruby/library/socket/addrinfo/canonname_spec.rb
new file mode 100644
index 0000000000..15dfe86467
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/canonname_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'socket'
+
+describe "Addrinfo#canonname" do
+
+ before :each do
+ @addrinfos = Addrinfo.getaddrinfo("localhost", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME)
+ end
+
+ it "returns the canonical name for a host" do
+ canonname = @addrinfos.map { |a| a.canonname }.find { |name| name and name.include?("localhost") }
+ if canonname
+ canonname.should include("localhost")
+ else
+ canonname.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/initialize_spec.rb b/spec/ruby/library/socket/addrinfo/initialize_spec.rb
new file mode 100644
index 0000000000..254539f95e
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/initialize_spec.rb
@@ -0,0 +1,253 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#initialize" do
+
+ describe "with a sockaddr string" do
+
+ describe "without a family" do
+ before :each do
+ @addrinfo = Addrinfo.new(Socket.sockaddr_in("smtp", "2001:DB8::1"))
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "2001:db8::1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 25
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_UNSPEC
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == 0
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family given" do
+ before :each do
+ @addrinfo = Addrinfo.new(Socket.sockaddr_in("smtp", "2001:DB8::1"), Socket::PF_INET6)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "2001:db8::1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 25
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET6
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == 0
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family and socket type" do
+ before :each do
+ @addrinfo = Addrinfo.new(Socket.sockaddr_in("smtp", "2001:DB8::1"), Socket::PF_INET6, Socket::SOCK_STREAM)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "2001:db8::1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 25
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET6
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family, socket type and protocol" do
+ before :each do
+ @addrinfo = Addrinfo.new(Socket.sockaddr_in("smtp", "2001:DB8::1"), Socket::PF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "2001:db8::1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 25
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET6
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+
+ it "returns the specified socket type" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it "returns the specified protocol" do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+ end
+
+ end
+
+ describe "with a sockaddr array" do
+
+ describe "without a family" do
+ before :each do
+ @addrinfo = Addrinfo.new(["AF_INET", 46102, "localhost", "127.0.0.1"])
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 46102
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == 0
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family given" do
+ before :each do
+ @addrinfo = Addrinfo.new(["AF_INET", 46102, "localhost", "127.0.0.1"], Socket::PF_INET)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 46102
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == 0
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family and socket type" do
+ before :each do
+ @addrinfo = Addrinfo.new(["AF_INET", 46102, "localhost", "127.0.0.1"], Socket::PF_INET, Socket::SOCK_STREAM)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 46102
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family, socket type and protocol" do
+ before :each do
+ @addrinfo = Addrinfo.new(["AF_INET", 46102, "localhost", "127.0.0.1"], Socket::PF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 46102
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it "returns the specified protocol" do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb b/spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb
new file mode 100644
index 0000000000..c7d69db760
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+require 'socket'
+
+describe 'Addrinfo#inspect_sockaddr' do
+ it 'IPv4' do
+ Addrinfo.tcp('127.0.0.1', 80).inspect_sockaddr.should == '127.0.0.1:80'
+ Addrinfo.tcp('127.0.0.1', 0).inspect_sockaddr.should == '127.0.0.1'
+ end
+
+ it 'IPv6' do
+ Addrinfo.tcp('::1', 80).inspect_sockaddr.should == '[::1]:80'
+ Addrinfo.tcp('::1', 0).inspect_sockaddr.should == '::1'
+ ip = '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
+ Addrinfo.tcp(ip, 80).inspect_sockaddr.should == '[2001:db8:85a3::8a2e:370:7334]:80'
+ Addrinfo.tcp(ip, 0).inspect_sockaddr.should == '2001:db8:85a3::8a2e:370:7334'
+ end
+
+ platform_is_not :windows do
+ it 'UNIX' do
+ Addrinfo.unix('/tmp/sock').inspect_sockaddr.should == '/tmp/sock'
+ Addrinfo.unix('rel').inspect_sockaddr.should == 'UNIX rel'
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ip_address_spec.rb b/spec/ruby/library/socket/addrinfo/ip_address_spec.rb
new file mode 100644
index 0000000000..f82cef0812
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ip_address_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ip_address" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns the ip address" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns the ip address" do
+ @addrinfo.ip_address.should == "::1"
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.ip_address }.should raise_error(SocketError)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ip_port_spec.rb b/spec/ruby/library/socket/addrinfo/ip_port_spec.rb
new file mode 100644
index 0000000000..e437b88ca1
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ip_port_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ip_port" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns the port" do
+ @addrinfo.ip_port.should == 80
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns the port" do
+ @addrinfo.ip_port.should == 80
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.ip_port }.should raise_error(SocketError)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ip_spec.rb b/spec/ruby/library/socket/addrinfo/ip_spec.rb
new file mode 100644
index 0000000000..2e4b613ae5
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ip_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ip?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns true" do
+ @addrinfo.ip?.should be_true
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns true" do
+ @addrinfo.ip?.should be_true
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::AF_INET6" do
+ @addrinfo.ip?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb b/spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb
new file mode 100644
index 0000000000..2b4a9372cc
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ip_unpack" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns the ip address and port pair" do
+ @addrinfo.ip_unpack.should == ["127.0.0.1", 80]
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns the ip address and port pair" do
+ @addrinfo.ip_unpack.should == ["::1", 80]
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.ip_unpack }.should raise_error(SocketError)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb
new file mode 100644
index 0000000000..457bd7cebf
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv4_loopback?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @loopback = Addrinfo.tcp("127.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for the loopback address" do
+ @loopback.ipv4_loopback?.should be_true
+ end
+
+ it "returns false for another address" do
+ @other.ipv4_loopback?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @loopback = Addrinfo.tcp("::1", 80)
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false for the loopback address" do
+ @loopback.ipv4_loopback?.should be_false
+ end
+
+ it "returns false for another address" do
+ @other.ipv4_loopback?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4_loopback?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb
new file mode 100644
index 0000000000..01f6a6ebf7
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv4_multicast?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @multicast = Addrinfo.tcp("224.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for the loopback address" do
+ @multicast.ipv4_multicast?.should be_true
+ end
+
+ it "returns false for another address" do
+ @other.ipv4_multicast?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @multicast = Addrinfo.tcp("ff02::1", 80)
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false for the loopback address" do
+ @multicast.ipv4_multicast?.should be_false
+ end
+
+ it "returns false for another address" do
+ @other.ipv4_multicast?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4_multicast?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb
new file mode 100644
index 0000000000..cf8bd8c1aa
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv4_private?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @private = Addrinfo.tcp("10.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for a private address" do
+ @private.ipv4_private?.should be_true
+ end
+
+ it "returns false for a public address" do
+ @other.ipv4_private?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false" do
+ @other.ipv4_private?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4_private?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_spec.rb
new file mode 100644
index 0000000000..3d4560532e
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ipv4_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv4?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("10.0.0.1", 80)
+ end
+
+ it "returns true" do
+ @addrinfo.ipv4?.should be_true
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb
new file mode 100644
index 0000000000..b0060378e6
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv6_loopback?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @loopback = Addrinfo.tcp("127.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for the loopback address" do
+ @loopback.ipv6_loopback?.should be_false
+ end
+
+ it "returns false for another address" do
+ @other.ipv6_loopback?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @loopback = Addrinfo.tcp("::1", 80)
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false for the loopback address" do
+ @loopback.ipv6_loopback?.should be_true
+ end
+
+ it "returns false for another address" do
+ @other.ipv6_loopback?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6_loopback?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb
new file mode 100644
index 0000000000..d8b3a96ebb
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv6_multicast?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @multicast = Addrinfo.tcp("224.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for the loopback address" do
+ @multicast.ipv6_multicast?.should be_false
+ end
+
+ it "returns false for another address" do
+ @other.ipv6_multicast?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @multicast = Addrinfo.tcp("ff02::1", 80)
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false for the loopback address" do
+ @multicast.ipv6_multicast?.should be_true
+ end
+
+ it "returns false for another address" do
+ @other.ipv6_multicast?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6_multicast?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_spec.rb
new file mode 100644
index 0000000000..b66bc0d70b
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/ipv6_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv6?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("10.0.0.1", 80)
+ end
+
+ it "returns true" do
+ @addrinfo.ipv6?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6?.should be_true
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/pfamily_spec.rb b/spec/ruby/library/socket/addrinfo/pfamily_spec.rb
new file mode 100644
index 0000000000..d37ed73e1e
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/pfamily_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#pfamily" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns Socket::PF_INET" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns Socket::PF_INET6" do
+ @addrinfo.pfamily.should == Socket::PF_INET6
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::PF_UNIX" do
+ @addrinfo.pfamily.should == Socket::PF_UNIX
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/protocol_spec.rb b/spec/ruby/library/socket/addrinfo/protocol_spec.rb
new file mode 100644
index 0000000000..4ff11dc017
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/protocol_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#protocol" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns Socket::IPPROTO_TCP" do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns Socket::IPPROTO_TCP" do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns 0" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb b/spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb
new file mode 100644
index 0000000000..86819a31b0
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb
@@ -0,0 +1,35 @@
+describe :socket_addrinfo_to_sockaddr, :shared => true do
+
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns a sockaddr packed structure" do
+ @addrinfo.send(@method).should be_kind_of(String)
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns a sockaddr packed structure" do
+ @addrinfo.send(@method).should be_kind_of(String)
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns a sockaddr packed structure" do
+ @addrinfo.send(@method).should be_kind_of(String)
+ end
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/addrinfo/socktype_spec.rb b/spec/ruby/library/socket/addrinfo/socktype_spec.rb
new file mode 100644
index 0000000000..e1c8c0f3f5
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/socktype_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#socktype" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns Socket::SOCK_STREAM" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns Socket::SOCK_STREAM" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::SOCK_STREAM" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/tcp_spec.rb b/spec/ruby/library/socket/addrinfo/tcp_spec.rb
new file mode 100644
index 0000000000..b5c18cefea
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/tcp_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo.tcp" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("localhost", "smtp")
+ end
+
+ it "creates a addrinfo for a tcp socket" do
+ ["::1", "127.0.0.1"].should include(@addrinfo.ip_address)
+ [Socket::PF_INET, Socket::PF_INET6].should include(@addrinfo.pfamily)
+ @addrinfo.ip_port.should == 25
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ platform_is_not :solaris do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/addrinfo/to_s_spec.rb b/spec/ruby/library/socket/addrinfo/to_s_spec.rb
new file mode 100644
index 0000000000..7205bdc823
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/to_s_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/to_sockaddr', __FILE__)
+require 'socket'
+
+describe "Addrinfo#to_s" do
+ it_behaves_like(:socket_addrinfo_to_sockaddr, :to_s)
+end
diff --git a/spec/ruby/library/socket/addrinfo/to_sockaddr_spec.rb b/spec/ruby/library/socket/addrinfo/to_sockaddr_spec.rb
new file mode 100644
index 0000000000..f3f926c2b6
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/to_sockaddr_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/to_sockaddr', __FILE__)
+require 'socket'
+
+describe "Addrinfo#to_sockaddr" do
+ it_behaves_like(:socket_addrinfo_to_sockaddr, :to_sockaddr)
+end
diff --git a/spec/ruby/library/socket/addrinfo/udp_spec.rb b/spec/ruby/library/socket/addrinfo/udp_spec.rb
new file mode 100644
index 0000000000..712d730e05
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/udp_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo.udp" do
+
+ before :each do
+ @addrinfo = Addrinfo.udp("localhost", "daytime")
+ end
+
+ it "creates a addrinfo for a tcp socket" do
+ ["::1", "127.0.0.1"].should include(@addrinfo.ip_address)
+ [Socket::PF_INET, Socket::PF_INET6].should include(@addrinfo.pfamily)
+ @addrinfo.ip_port.should == 13
+ @addrinfo.socktype.should == Socket::SOCK_DGRAM
+ platform_is_not :solaris do
+ @addrinfo.protocol.should == Socket::IPPROTO_UDP
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/addrinfo/unix_path_spec.rb b/spec/ruby/library/socket/addrinfo/unix_path_spec.rb
new file mode 100644
index 0000000000..3f7e03dd7b
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/unix_path_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+platform_is_not :windows do
+ describe "Addrinfo#unix_path" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.unix_path }.should raise_error(SocketError)
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.unix_path }.should raise_error(SocketError)
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns the socket path" do
+ @addrinfo.unix_path.should == "/tmp/sock"
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/unix_spec.rb b/spec/ruby/library/socket/addrinfo/unix_spec.rb
new file mode 100644
index 0000000000..00eedc96e7
--- /dev/null
+++ b/spec/ruby/library/socket/addrinfo/unix_spec.rb
@@ -0,0 +1,54 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo.unix" do
+
+ platform_is_not :windows do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "creates a addrinfo for a unix socket" do
+ @addrinfo.pfamily.should == Socket::PF_UNIX
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ @addrinfo.protocol.should == 0
+ @addrinfo.unix_path.should == "/tmp/sock"
+ end
+ end
+end
+
+describe "Addrinfo#unix?" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns false" do
+ @addrinfo.unix?.should be_false
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns false" do
+ @addrinfo.unix?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns true" do
+ @addrinfo.unix?.should be_true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/close_read_spec.rb b/spec/ruby/library/socket/basicsocket/close_read_spec.rb
new file mode 100644
index 0000000000..c71e1acaf9
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/close_read_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#close_read" do
+ before :each do
+ @server = TCPServer.new(0)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it "closes the reading end of the socket" do
+ @server.close_read
+ lambda { @server.read }.should raise_error(IOError)
+ end
+
+ it "it works on sockets with closed ends" do
+ @server.close_read
+ lambda { @server.close_read }.should_not raise_error(Exception)
+ lambda { @server.read }.should raise_error(IOError)
+ end
+
+ it "does not close the socket" do
+ @server.close_read
+ @server.closed?.should be_false
+ end
+
+ it "fully closes the socket if it was already closed for writing" do
+ @server.close_write
+ @server.close_read
+ @server.closed?.should be_true
+ end
+
+ it "raises IOError on closed socket" do
+ @server.close
+ lambda { @server.close_read }.should raise_error(IOError)
+ end
+
+ it "returns nil" do
+ @server.close_read.should be_nil
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/close_write_spec.rb b/spec/ruby/library/socket/basicsocket/close_write_spec.rb
new file mode 100644
index 0000000000..a00f5d5870
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/close_write_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#close_write" do
+ before :each do
+ @server = TCPServer.new(0)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it "closes the writing end of the socket" do
+ @server.close_write
+ lambda { @server.write("foo") }.should raise_error(IOError)
+ end
+
+ it "works on sockets with closed write ends" do
+ @server.close_write
+ lambda { @server.close_write }.should_not raise_error(Exception)
+ lambda { @server.write("foo") }.should raise_error(IOError)
+ end
+
+ it "does not close the socket" do
+ @server.close_write
+ @server.closed?.should be_false
+ end
+
+ it "does not prevent reading" do
+ @server.close_write
+ @server.read(0).should == ""
+ end
+
+ it "fully closes the socket if it was already closed for reading" do
+ @server.close_read
+ @server.close_write
+ @server.closed?.should be_true
+ end
+
+ it "raises IOError on closed socket" do
+ @server.close
+ lambda { @server.close_write }.should raise_error(IOError)
+ end
+
+ it "returns nil" do
+ @server.close_write.should be_nil
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/do_not_reverse_lookup_spec.rb b/spec/ruby/library/socket/basicsocket/do_not_reverse_lookup_spec.rb
new file mode 100644
index 0000000000..3ef3a686e2
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/do_not_reverse_lookup_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket.do_not_reverse_lookup" do
+ before :each do
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
+ @server = TCPServer.new('127.0.0.1', 0)
+ @port = @server.addr[1]
+ @socket = TCPSocket.new('127.0.0.1', @port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @socket.close unless @socket.closed?
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
+ end
+
+ it "defaults to true" do
+ BasicSocket.do_not_reverse_lookup.should be_true
+ end
+
+ it "causes 'peeraddr' to avoid name lookups" do
+ @socket.do_not_reverse_lookup = true
+ BasicSocket.do_not_reverse_lookup = true
+ @socket.peeraddr.should == ["AF_INET", @port, "127.0.0.1", "127.0.0.1"]
+ end
+
+ it "looks for hostnames when set to false" do
+ @socket.do_not_reverse_lookup = false
+ BasicSocket.do_not_reverse_lookup = false
+ @socket.peeraddr[2].should == SocketSpecs.hostname
+ end
+
+ it "looks for numeric addresses when set to true" do
+ @socket.do_not_reverse_lookup = true
+ BasicSocket.do_not_reverse_lookup = true
+ @socket.peeraddr[2].should == "127.0.0.1"
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/for_fd_spec.rb b/spec/ruby/library/socket/basicsocket/for_fd_spec.rb
new file mode 100644
index 0000000000..164e4dc93c
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/for_fd_spec.rb
@@ -0,0 +1,21 @@
+
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#for_fd" do
+ before :each do
+ @server = TCPServer.new(0)
+ @s2 = nil
+ end
+
+ after :each do
+ @server.close if @server
+ end
+
+ it "return a Socket instance wrapped around the descriptor" do
+ @s2 = TCPServer.for_fd(@server.fileno)
+ @s2.autoclose = false
+ @s2.should be_kind_of(TCPServer)
+ @s2.fileno.should == @server.fileno
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/getpeername_spec.rb b/spec/ruby/library/socket/basicsocket/getpeername_spec.rb
new file mode 100644
index 0000000000..cecf590092
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/getpeername_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#getpeername" do
+
+ before :each do
+ @server = TCPServer.new("127.0.0.1", 0)
+ @port = @server.addr[1]
+ @client = TCPSocket.new("127.0.0.1", @port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ it "returns the sockaddr of the other end of the connection" do
+ server_sockaddr = Socket.pack_sockaddr_in(@port, "127.0.0.1")
+ @client.getpeername.should == server_sockaddr
+ end
+
+ # Catch general exceptions to prevent NotImplementedError
+ it "raises an error if socket's not connected" do
+ lambda { @server.getpeername }.should raise_error(Exception)
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/getsockname_spec.rb b/spec/ruby/library/socket/basicsocket/getsockname_spec.rb
new file mode 100644
index 0000000000..cb3a45eb5f
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/getsockname_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#getsockname" do
+ after :each do
+ @socket.closed?.should be_false
+ @socket.close
+ end
+
+ it "returns the sockaddr associacted with the socket" do
+ @socket = TCPServer.new("127.0.0.1", 0)
+ sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
+ sockaddr.should == [@socket.addr[1], "127.0.0.1"]
+ end
+
+ it "works on sockets listening in ipaddr_any" do
+ @socket = TCPServer.new(0)
+ sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
+ ["::", "0.0.0.0", "::ffff:0.0.0.0"].include?(sockaddr[1]).should be_true
+ sockaddr[0].should == @socket.addr[1]
+ end
+
+ it "returns empty sockaddr for unbinded sockets" do
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
+ sockaddr.should == [0, "0.0.0.0"]
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/getsockopt_spec.rb b/spec/ruby/library/socket/basicsocket/getsockopt_spec.rb
new file mode 100644
index 0000000000..dc4fffa5c1
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/getsockopt_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#getsockopt" do
+ before :each do
+ @sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ end
+
+ after :each do
+ @sock.closed?.should be_false
+ @sock.close
+ end
+
+ platform_is_not :aix do
+ # A known bug in AIX. getsockopt(2) does not properly set
+ # the fifth argument for SO_TYPE, SO_OOBINLINE, SO_BROADCAST, etc.
+
+ it "gets a socket option Socket::SO_TYPE" do
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).to_s
+ n.should == [Socket::SOCK_STREAM].pack("i")
+ end
+
+ it "gets a socket option Socket::SO_OOBINLINE" do
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+ end
+ end
+
+ it "gets a socket option Socket::SO_LINGER" do
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
+ if (n.size == 8) # linger struct on some platforms, not just a value
+ n.should == [0, 0].pack("ii")
+ else
+ n.should == [0].pack("i")
+ end
+ end
+
+ it "gets a socket option Socket::SO_SNDBUF" do
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should > 0
+ end
+
+ it "raises a SystemCallError with an invalid socket option" do
+ lambda { @sock.getsockopt Socket::SOL_SOCKET, -1 }.should raise_error(Errno::ENOPROTOOPT)
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/ioctl_spec.rb b/spec/ruby/library/socket/basicsocket/ioctl_spec.rb
new file mode 100644
index 0000000000..9a7f535317
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/ioctl_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Socket::BasicSocket#ioctl" do
+ platform_is :linux do
+ it "passes data from and to a String correctly" do
+ s = Socket.new Socket::AF_INET, Socket::SOCK_DGRAM, 0
+ # /usr/include/net/if.h, structure ifreq
+ # The structure is 32 bytes on x86, 40 bytes on x86_64
+ if_name = ['lo'].pack('a16')
+ buffer = if_name + 'z' * 24
+ # SIOCGIFADDR in /usr/include/bits/ioctls.h
+ s.ioctl 0x8915, buffer
+ s.close
+
+ # Interface name should remain unchanged.
+ buffer[0, 16].should == if_name
+ # lo should have an IPv4 address of 127.0.0.1
+ buffer[16, 2].unpack('S!').first.should == Socket::AF_INET
+ buffer[20, 4].should == "\x7f\0\0\x01"
+ end
+ end
+
+ platform_is :freebsd do
+ it "passes data from and to a String correctly" do
+ s = Socket.new Socket::AF_INET, Socket::SOCK_DGRAM, 0
+ # /usr/include/net/if.h, structure ifreq
+ # The structure is 32 bytes on x86, 40 bytes on x86_64
+ if_name = ['lo0'].pack('a16')
+ buffer = if_name + 'z' * 24
+ # SIOCGIFADDR in /usr/include/bits/ioctls.h
+ s.ioctl 0xc0206921, buffer
+ s.close
+
+ # Interface name should remain unchanged.
+ buffer[0, 16].should == if_name
+ # lo should have an IPv4 address of 127.0.0.1
+ buffer[16, 1].unpack('C').first.should == 16
+ buffer[17, 1].unpack('C').first.should == Socket::AF_INET
+ buffer[20, 4].should == "\x7f\0\0\x01"
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb b/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb
new file mode 100644
index 0000000000..2c948eaa2f
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../shared/recv_nonblock', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#recv_nonblock" do
+ it_behaves_like :socket_recv_nonblock, :recv_nonblock
+end
diff --git a/spec/ruby/library/socket/basicsocket/recv_spec.rb b/spec/ruby/library/socket/basicsocket/recv_spec.rb
new file mode 100644
index 0000000000..5891bf9c87
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/recv_spec.rb
@@ -0,0 +1,96 @@
+# -*- encoding: binary -*-
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#recv" do
+
+ before :each do
+ @server = TCPServer.new('127.0.0.1', 0)
+ @port = @server.addr[1]
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ ScratchPad.clear
+ end
+
+ it "receives a specified number of bytes of a message from another socket" do
+ t = Thread.new do
+ client = @server.accept
+ ScratchPad.record client.recv(10)
+ client.recv(1) # this recv is important
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.send('hello', 0)
+ socket.close
+
+ t.join
+ ScratchPad.recorded.should == 'hello'
+ end
+
+ platform_is_not :solaris do
+ it "accepts flags to specify unusual receiving behaviour" do
+ t = Thread.new do
+ client = @server.accept
+
+ # in-band data (TCP), doesn't receive the flag.
+ ScratchPad.record client.recv(10)
+
+ # this recv is important (TODO: explain)
+ client.recv(10)
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.send('helloU', Socket::MSG_OOB)
+ socket.shutdown(1)
+ t.join
+ socket.close
+ ScratchPad.recorded.should == 'hello'
+ end
+ end
+
+ it "gets lines delimited with a custom separator" do
+ t = Thread.new do
+ client = @server.accept
+ ScratchPad.record client.gets("\377")
+
+ # this call is important (TODO: explain)
+ client.gets(nil)
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.write("firstline\377secondline\377")
+ socket.close
+
+ t.join
+ ScratchPad.recorded.should == "firstline\377"
+ end
+
+ ruby_version_is "2.3" do
+ it "allows an output buffer as third argument" do
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.write("data")
+
+ client = @server.accept
+ buf = "foo"
+ begin
+ client.recv(4, 0, buf)
+ ensure
+ client.close
+ end
+ buf.should == "data"
+
+ socket.close
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/send_spec.rb b/spec/ruby/library/socket/basicsocket/send_spec.rb
new file mode 100644
index 0000000000..4df0d04a10
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/send_spec.rb
@@ -0,0 +1,85 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#send" do
+ before :each do
+ @server = TCPServer.new('127.0.0.1', 0)
+ @port = @server.addr[1]
+ @socket = TCPSocket.new('127.0.0.1', @port)
+ end
+
+ after :each do
+ @server.closed?.should be_false
+ @socket.closed?.should be_false
+
+ @server.close
+ @socket.close
+ end
+
+ it "sends a message to another socket and returns the number of bytes sent" do
+ data = ""
+ t = Thread.new do
+ client = @server.accept
+ loop do
+ got = client.recv(5)
+ break if got.empty?
+ data << got
+ end
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @socket.send('hello', 0).should == 5
+ @socket.shutdown(1) # indicate, that we are done sending
+ @socket.recv(10)
+
+ t.join
+ data.should == 'hello'
+ end
+
+ platform_is_not :solaris, :windows do
+ it "accepts flags to specify unusual sending behaviour" do
+ data = nil
+ peek_data = nil
+ t = Thread.new do
+ client = @server.accept
+ peek_data = client.recv(6, Socket::MSG_PEEK)
+ data = client.recv(6)
+ client.recv(10) # this recv is important
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @socket.send('helloU', Socket::MSG_PEEK | Socket::MSG_OOB).should == 6
+ @socket.shutdown # indicate, that we are done sending
+
+ t.join
+ peek_data.should == "hello"
+ data.should == 'hello'
+ end
+ end
+
+ it "accepts a sockaddr as recipient address" do
+ data = ""
+ t = Thread.new do
+ client = @server.accept
+ loop do
+ got = client.recv(5)
+ break if got.empty?
+ data << got
+ end
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ sockaddr = Socket.pack_sockaddr_in(@port, "127.0.0.1")
+ @socket.send('hello', 0, sockaddr).should == 5
+ @socket.shutdown # indicate, that we are done sending
+
+ t.join
+ data.should == 'hello'
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/setsockopt_spec.rb b/spec/ruby/library/socket/basicsocket/setsockopt_spec.rb
new file mode 100644
index 0000000000..523a22d957
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/setsockopt_spec.rb
@@ -0,0 +1,213 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#setsockopt" do
+
+ before :each do
+ @sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ end
+
+ after :each do
+ @sock.close unless @sock.closed?
+ end
+
+ it "sets the socket linger to 0" do
+ linger = [0, 0].pack("ii")
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
+
+ if (n.size == 8) # linger struct on some platforms, not just a value
+ n.should == [0, 0].pack("ii")
+ else
+ n.should == [0].pack("i")
+ end
+ end
+
+ it "sets the socket linger to some positive value" do
+ linger = [64, 64].pack("ii")
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
+ if (n.size == 8) # linger struct on some platforms, not just a value
+ a = n.unpack('ii')
+ a[0].should_not == 0
+ a[1].should == 64
+ else
+ n.should == [64].pack("i")
+ end
+ end
+
+ platform_is_not :windows do
+ it "raises EINVAL if passed wrong linger value" do
+ lambda do
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, 0)
+ end.should raise_error(Errno::EINVAL)
+ end
+ end
+
+ platform_is_not :aix do
+ # A known bug in AIX. getsockopt(2) does not properly set
+ # the fifth argument for SO_TYPE, SO_OOBINLINE, SO_BROADCAST, etc.
+
+ it "sets the socket option Socket::SO_OOBINLINE" do
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, true).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, false).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 1).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 0).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 2).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ platform_is_not :windows do
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "")
+ }.should raise_error(SystemCallError)
+ end
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "blah").should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ platform_is_not :windows do
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "0")
+ }.should raise_error(SystemCallError)
+ end
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "\x00\x00\x00\x00").should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+
+ platform_is_not :windows do
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "1")
+ }.should raise_error(SystemCallError)
+ end
+
+ platform_is_not :windows do
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "\x00\x00\x00")
+ }.should raise_error(SystemCallError)
+ end
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, [1].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, [0].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, [1000].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+ end
+ end
+
+ it "sets the socket option Socket::SO_SNDBUF" do
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 4000).should == 0
+ sndbuf = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ # might not always be possible to set to exact size
+ sndbuf.unpack('i')[0].should >= 4000
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, true).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 1
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, nil).should == 0
+ }.should raise_error(TypeError)
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 1).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 1
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 2).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 2
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "")
+ }.should raise_error(SystemCallError)
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "bla")
+ }.should raise_error(SystemCallError)
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "0")
+ }.should raise_error(SystemCallError)
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "1")
+ }.should raise_error(SystemCallError)
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "\x00\x00\x00")
+ }.should raise_error(SystemCallError)
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "\x00\x00\x01\x00").should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= "\x00\x00\x01\x00".unpack('i')[0]
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, [4000].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 4000
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, [1000].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 1000
+ end
+
+ platform_is_not :aix do
+ describe 'accepts Socket::Option as argument' do
+ it 'boolean' do
+ option = Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
+ @sock.setsockopt(option).should == 0
+ @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE).bool.should == true
+ end
+
+ it 'int' do
+ option = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
+ @sock.setsockopt(option).should == 0
+ @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE).bool.should == true
+ end
+ end
+ end
+
+ platform_is :aix do
+ describe 'accepts Socket::Option as argument' do
+ it 'boolean' do
+ option = Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
+ @sock.setsockopt(option).should == 0
+ end
+
+ it 'int' do
+ option = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
+ @sock.setsockopt(option).should == 0
+ end
+ end
+ end
+
+ describe 'accepts Socket::Option as argument' do
+ it 'linger' do
+ option = Socket::Option.linger(true, 10)
+ @sock.setsockopt(option).should == 0
+ onoff, seconds = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).linger
+ seconds.should == 10
+ # Both results can be produced depending on the OS and value of Socket::SO_LINGER
+ [true, Socket::SO_LINGER].should include(onoff)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/shutdown_spec.rb b/spec/ruby/library/socket/basicsocket/shutdown_spec.rb
new file mode 100644
index 0000000000..c874f08697
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/shutdown_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#shutdown" do
+
+end
diff --git a/spec/ruby/library/socket/constants/constants_spec.rb b/spec/ruby/library/socket/constants/constants_spec.rb
new file mode 100644
index 0000000000..9b8a0e55b3
--- /dev/null
+++ b/spec/ruby/library/socket/constants/constants_spec.rb
@@ -0,0 +1,90 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+include Socket::Constants
+
+describe "Socket::Constants" do
+ it "defines socket types" do
+ consts = ["SOCK_DGRAM", "SOCK_RAW", "SOCK_RDM", "SOCK_SEQPACKET", "SOCK_STREAM"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ it "defines protocol families" do
+ consts = ["PF_INET6", "PF_INET", "PF_UNIX", "PF_UNSPEC"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ platform_is_not :aix do
+ it "defines PF_IPX protocol" do
+ Socket::Constants.should have_constant("PF_IPX")
+ end
+ end
+
+ it "defines address families" do
+ consts = ["AF_INET6", "AF_INET", "AF_UNIX", "AF_UNSPEC"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ platform_is_not :aix do
+ it "defines AF_IPX address" do
+ Socket::Constants.should have_constant("AF_IPX")
+ end
+ end
+
+ it "defines send/receive options" do
+ consts = ["MSG_DONTROUTE", "MSG_OOB", "MSG_PEEK"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ it "defines socket level options" do
+ consts = ["SOL_SOCKET"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ it "defines socket options" do
+ consts = ["SO_BROADCAST", "SO_DEBUG", "SO_DONTROUTE", "SO_ERROR", "SO_KEEPALIVE", "SO_LINGER",
+ "SO_OOBINLINE", "SO_RCVBUF", "SO_REUSEADDR", "SO_SNDBUF", "SO_TYPE"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ it "defines multicast options" do
+ consts = ["IP_ADD_MEMBERSHIP",
+ "IP_MULTICAST_LOOP", "IP_MULTICAST_TTL"]
+ platform_is_not :windows do
+ consts += ["IP_DEFAULT_MULTICAST_LOOP", "IP_DEFAULT_MULTICAST_TTL"]
+ end
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ platform_is_not :solaris, :windows, :aix do
+ it "defines multicast options" do
+ consts = ["IP_MAX_MEMBERSHIPS"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+ end
+
+ it "defines TCP options" do
+ consts = ["TCP_NODELAY"]
+ platform_is_not :windows do
+ consts << "TCP_MAXSEG"
+ end
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/fixtures/classes.rb b/spec/ruby/library/socket/fixtures/classes.rb
new file mode 100644
index 0000000000..b8e5d2a38d
--- /dev/null
+++ b/spec/ruby/library/socket/fixtures/classes.rb
@@ -0,0 +1,93 @@
+require 'socket'
+
+module SocketSpecs
+ # helper to get the hostname associated to 127.0.0.1
+ def self.hostname
+ # Calculate each time, without caching, since the result might
+ # depend on things like do_not_reverse_lookup mode, which is
+ # changing from test to test
+ Socket.getaddrinfo("127.0.0.1", nil)[0][2]
+ end
+
+ def self.hostnamev6
+ Socket.getaddrinfo("::1", nil)[0][2]
+ end
+
+ def self.addr(which=:ipv4)
+ case which
+ when :ipv4
+ host = "127.0.0.1"
+ when :ipv6
+ host = "::1"
+ end
+ Socket.getaddrinfo(host, nil)[0][3]
+ end
+
+ def self.reserved_unused_port
+ # https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
+ 0
+ end
+
+ def self.sockaddr_in(port, host)
+ Socket::SockAddr_In.new(Socket.sockaddr_in(port, host))
+ end
+
+ def self.socket_path
+ path = tmp("unix.sock", false)
+ # Check for too long unix socket path (max 108 bytes including \0 => 107)
+ # Note that Linux accepts not null-terminated paths but the man page advises against it.
+ if path.bytesize > 107
+ path = "/tmp/unix_server_spec.socket"
+ end
+ rm_socket(path)
+ path
+ end
+
+ def self.rm_socket(path)
+ File.delete(path) if File.exist?(path)
+ end
+
+ # TCPServer echo server accepting one connection
+ class SpecTCPServer
+ attr_reader :hostname, :port
+
+ def initialize
+ @hostname = SocketSpecs.hostname
+ @server = TCPServer.new @hostname, 0
+ @port = @server.addr[1]
+
+ log "SpecTCPServer starting on #{@hostname}:#{@port}"
+
+ @thread = Thread.new do
+ socket = @server.accept
+ log "SpecTCPServer accepted connection: #{socket}"
+ service socket
+ end
+ end
+
+ def service(socket)
+ begin
+ data = socket.recv(1024)
+
+ return if data.empty?
+ log "SpecTCPServer received: #{data.inspect}"
+
+ return if data == "QUIT"
+
+ socket.send data, 0
+ ensure
+ socket.close
+ end
+ end
+
+ def shutdown
+ log "SpecTCPServer shutting down"
+ @thread.join
+ @server.close
+ end
+
+ def log(message)
+ @logger.puts message if @logger
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/fixtures/send_io.txt b/spec/ruby/library/socket/fixtures/send_io.txt
new file mode 100644
index 0000000000..eaaa1eb3ec
--- /dev/null
+++ b/spec/ruby/library/socket/fixtures/send_io.txt
@@ -0,0 +1 @@
+This data is magic.
diff --git a/spec/ruby/library/socket/ipsocket/addr_spec.rb b/spec/ruby/library/socket/ipsocket/addr_spec.rb
new file mode 100644
index 0000000000..2184082c51
--- /dev/null
+++ b/spec/ruby/library/socket/ipsocket/addr_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::IPSocket#addr" do
+ before :each do
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
+ @socket = TCPServer.new("127.0.0.1", 0)
+ end
+
+ after :each do
+ @socket.close unless @socket.closed?
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
+ end
+
+ it "returns an array with the socket's information" do
+ @socket.do_not_reverse_lookup = false
+ BasicSocket.do_not_reverse_lookup = false
+ addrinfo = @socket.addr
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should be_kind_of(Integer)
+ addrinfo[2].should == SocketSpecs.hostname
+ addrinfo[3].should == "127.0.0.1"
+ end
+
+ it "returns an address in the array if do_not_reverse_lookup is true" do
+ @socket.do_not_reverse_lookup = true
+ BasicSocket.do_not_reverse_lookup = true
+ addrinfo = @socket.addr
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should be_kind_of(Integer)
+ addrinfo[2].should == "127.0.0.1"
+ addrinfo[3].should == "127.0.0.1"
+ end
+
+ it "returns an address in the array if passed false" do
+ addrinfo = @socket.addr(false)
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should be_kind_of(Integer)
+ addrinfo[2].should == "127.0.0.1"
+ addrinfo[3].should == "127.0.0.1"
+ end
+end
diff --git a/spec/ruby/library/socket/ipsocket/getaddress_spec.rb b/spec/ruby/library/socket/ipsocket/getaddress_spec.rb
new file mode 100644
index 0000000000..c574c7d267
--- /dev/null
+++ b/spec/ruby/library/socket/ipsocket/getaddress_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::IPSocket#getaddress" do
+
+ it "returns the IP address of hostname" do
+ addr_local = IPSocket.getaddress(SocketSpecs.hostname)
+ ["127.0.0.1", "::1"].include?(addr_local).should == true
+ end
+
+ it "returns the IP address when passed an IP" do
+ IPSocket.getaddress("127.0.0.1").should == "127.0.0.1"
+ IPSocket.getaddress("0.0.0.0").should == "0.0.0.0"
+ end
+
+ # There is no way to make this fail-proof on all machines, because
+ # DNS servers like opendns return A records for ANY host, including
+ # traditionally invalidly named ones.
+ quarantine! do
+ it "raises an error on unknown hostnames" do
+ lambda {
+ IPSocket.getaddress("rubyspecdoesntexist.fallingsnow.net")
+ }.should raise_error(SocketError)
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/ipsocket/peeraddr_spec.rb b/spec/ruby/library/socket/ipsocket/peeraddr_spec.rb
new file mode 100644
index 0000000000..dfd4e050ce
--- /dev/null
+++ b/spec/ruby/library/socket/ipsocket/peeraddr_spec.rb
@@ -0,0 +1,49 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::IPSocket#peeraddr" do
+ before :each do
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
+ @server = TCPServer.new("127.0.0.1", 0)
+ @port = @server.addr[1]
+ @client = TCPSocket.new("127.0.0.1", @port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
+ end
+
+ it "raises error if socket is not connected" do
+ lambda { @server.peeraddr }.should raise_error
+ end
+
+ it "returns an array of information on the peer" do
+ @client.do_not_reverse_lookup = false
+ BasicSocket.do_not_reverse_lookup = false
+ addrinfo = @client.peeraddr
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should == @port
+ addrinfo[2].should == SocketSpecs.hostname
+ addrinfo[3].should == "127.0.0.1"
+ end
+
+ it "returns an IP instead of hostname if do_not_reverse_lookup is true" do
+ @client.do_not_reverse_lookup = true
+ BasicSocket.do_not_reverse_lookup = true
+ addrinfo = @client.peeraddr
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should == @port
+ addrinfo[2].should == "127.0.0.1"
+ addrinfo[3].should == "127.0.0.1"
+ end
+
+ it "returns an IP instead of hostname if passed false" do
+ addrinfo = @client.peeraddr(false)
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should == @port
+ addrinfo[2].should == "127.0.0.1"
+ addrinfo[3].should == "127.0.0.1"
+ end
+end
diff --git a/spec/ruby/library/socket/ipsocket/recvfrom_spec.rb b/spec/ruby/library/socket/ipsocket/recvfrom_spec.rb
new file mode 100644
index 0000000000..54f150decf
--- /dev/null
+++ b/spec/ruby/library/socket/ipsocket/recvfrom_spec.rb
@@ -0,0 +1,72 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::IPSocket#recvfrom" do
+
+ before :each do
+ @server = TCPServer.new("127.0.0.1", 0)
+ @port = @server.addr[1]
+ @client = TCPSocket.new("127.0.0.1", @port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ it "reads data from the connection" do
+ data = nil
+ t = Thread.new do
+ client = @server.accept
+ begin
+ data = client.recvfrom(6)
+ ensure
+ client.close
+ end
+ end
+
+ @client.send('hello', 0)
+ @client.shutdown rescue nil
+ # shutdown may raise Errno::ENOTCONN when sent data is pending.
+ t.join
+
+ data.first.should == 'hello'
+ end
+
+ it "reads up to len bytes" do
+ data = nil
+ t = Thread.new do
+ client = @server.accept
+ begin
+ data = client.recvfrom(3)
+ ensure
+ client.close
+ end
+ end
+
+ @client.send('hello', 0)
+ @client.shutdown rescue nil
+ t.join
+
+ data.first.should == 'hel'
+ end
+
+ it "returns an array with the data and connection info" do
+ data = nil
+ t = Thread.new do
+ client = @server.accept
+ data = client.recvfrom(3)
+ client.close
+ end
+
+ @client.send('hello', 0)
+ @client.shutdown rescue nil
+ t.join
+
+ data.size.should == 2
+ data.first.should == "hel"
+ # This does not apply to every platform, dependant on recvfrom(2)
+ # data.last.should == nil
+ end
+
+end
diff --git a/spec/ruby/library/socket/option/bool_spec.rb b/spec/ruby/library/socket/option/bool_spec.rb
new file mode 100644
index 0000000000..74c832a0ad
--- /dev/null
+++ b/spec/ruby/library/socket/option/bool_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::Option.bool" do
+ it "creates a new Socket::Option" do
+ so = Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
+ so.should be_an_instance_of(Socket::Option)
+ so.family.should == Socket::AF_INET
+ so.level.should == Socket::SOL_SOCKET
+ so.optname.should == Socket::SO_KEEPALIVE
+ so.data.should == [1].pack('i')
+ end
+end
+
+describe "Socket::Option#bool" do
+ it "returns boolean value" do
+ Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true).bool.should == true
+ Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, false).bool.should == false
+ end
+
+ it "raises TypeError if option has not good size" do
+ so = Socket::Option.new(:UNSPEC, :SOCKET, :SO_LINGER, [0, 0].pack('i*'))
+ lambda { so.bool }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/socket/option/inspect_spec.rb b/spec/ruby/library/socket/option/inspect_spec.rb
new file mode 100644
index 0000000000..df72f227a9
--- /dev/null
+++ b/spec/ruby/library/socket/option/inspect_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe 'Socket::Option#inspect' do
+ it 'correctly returns SO_LINGER value' do
+ value = Socket::Option.linger(nil, 0).inspect
+ value.should == '#<Socket::Option: UNSPEC SOCKET LINGER off 0sec>'
+
+ value = Socket::Option.linger(false, 30).inspect
+ value.should == '#<Socket::Option: UNSPEC SOCKET LINGER off 30sec>'
+
+ value = Socket::Option.linger(true, 0).inspect
+ value.should == '#<Socket::Option: UNSPEC SOCKET LINGER on 0sec>'
+
+ value = Socket::Option.linger(true, 30).inspect
+ value.should == '#<Socket::Option: UNSPEC SOCKET LINGER on 30sec>'
+ end
+end
diff --git a/spec/ruby/library/socket/option/int_spec.rb b/spec/ruby/library/socket/option/int_spec.rb
new file mode 100644
index 0000000000..f926ff7968
--- /dev/null
+++ b/spec/ruby/library/socket/option/int_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::Option.int" do
+ it "creates a new Socket::Option" do
+ so = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 5)
+ so.should be_an_instance_of(Socket::Option)
+ so.family.should == Socket::Constants::AF_INET
+ so.level.should == Socket::Constants::SOL_SOCKET
+ so.optname.should == Socket::Constants::SO_KEEPALIVE
+ so.data.should == [5].pack('i')
+ end
+end
+
+describe "Socket::Option#int" do
+ it "returns int value" do
+ so = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 17)
+ so.int.should == 17
+
+ so = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 32765)
+ so.int.should == 32765
+ end
+
+ it "raises TypeError if option has not good size" do
+ so = Socket::Option.new(:UNSPEC, :SOCKET, :SO_LINGER, [0, 0].pack('i*'))
+ lambda { so.int }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/socket/option/linger_spec.rb b/spec/ruby/library/socket/option/linger_spec.rb
new file mode 100644
index 0000000000..687d421af3
--- /dev/null
+++ b/spec/ruby/library/socket/option/linger_spec.rb
@@ -0,0 +1,62 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+option_pack = 'i*'
+platform_is :windows do
+ option_pack = 's*'
+end
+
+describe "Socket::Option.linger" do
+ it "creates a new Socket::Option for SO_LINGER" do
+ so = Socket::Option.linger(1, 10)
+ so.should be_an_instance_of(Socket::Option)
+ so.family.should == Socket::Constants::AF_UNSPEC
+ so.level.should == Socket::Constants::SOL_SOCKET
+ so.optname.should == Socket::Constants::SO_LINGER
+ so.data.should == [1, 10].pack(option_pack)
+ end
+
+ it "accepts boolean as onoff argument" do
+ so = Socket::Option.linger(false, 0)
+ so.data.should == [0, 0].pack(option_pack)
+
+ so = Socket::Option.linger(true, 1)
+ so.data.should == [1, 1].pack(option_pack)
+ end
+end
+
+describe "Socket::Option#linger" do
+ it "returns linger option" do
+ so = Socket::Option.linger(0, 5)
+ ary = so.linger
+ ary[0].should be_false
+ ary[1].should == 5
+
+ so = Socket::Option.linger(false, 4)
+ ary = so.linger
+ ary[0].should be_false
+ ary[1].should == 4
+
+ so = Socket::Option.linger(1, 10)
+ ary = so.linger
+ ary[0].should be_true
+ ary[1].should == 10
+
+ so = Socket::Option.linger(true, 9)
+ ary = so.linger
+ ary[0].should be_true
+ ary[1].should == 9
+ end
+
+ it "raises TypeError if not a SO_LINGER" do
+ so = Socket::Option.int(:AF_UNSPEC, :SOL_SOCKET, :KEEPALIVE, 1)
+ lambda { so.linger }.should raise_error(TypeError)
+ end
+
+ platform_is_not :windows do
+ it "raises TypeError if option has not good size" do
+ so = Socket::Option.int(:AF_UNSPEC, :SOL_SOCKET, :LINGER, 1)
+ lambda { so.linger }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/option/new_spec.rb b/spec/ruby/library/socket/option/new_spec.rb
new file mode 100644
index 0000000000..4f2d0c5386
--- /dev/null
+++ b/spec/ruby/library/socket/option/new_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::Option.new" do
+ it "should accept integers" do
+ so = Socket::Option.new(Socket::AF_INET, Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, [0].pack('i'))
+ so.family.should == Socket::AF_INET
+ so.level.should == Socket::SOL_SOCKET
+ so.optname.should == Socket::SO_KEEPALIVE
+ end
+
+ it "should accept symbols" do
+ so = Socket::Option.new(:AF_INET, :SOL_SOCKET, :SO_KEEPALIVE, [0].pack('i'))
+ so.family.should == Socket::AF_INET
+ so.level.should == Socket::SOL_SOCKET
+ so.optname.should == Socket::SO_KEEPALIVE
+
+ so = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [0].pack('i'))
+ so.family.should == Socket::AF_INET
+ so.level.should == Socket::SOL_SOCKET
+ so.optname.should == Socket::SO_KEEPALIVE
+ end
+
+ it "should raise error on unknown family" do
+ lambda { Socket::Option.new(:INET4, :SOCKET, :KEEPALIVE, [0].pack('i')) }.should raise_error(SocketError)
+ end
+
+ it "should raise error on unknown level" do
+ lambda { Socket::Option.new(:INET, :ROCKET, :KEEPALIVE, [0].pack('i')) }.should raise_error(SocketError)
+ end
+
+ it "should raise error on unknown option name" do
+ lambda { Socket::Option.new(:INET, :SOCKET, :ALIVE, [0].pack('i')) }.should raise_error(SocketError)
+ end
+end
diff --git a/spec/ruby/library/socket/shared/pack_sockaddr.rb b/spec/ruby/library/socket/shared/pack_sockaddr.rb
new file mode 100644
index 0000000000..4ffa02a8d8
--- /dev/null
+++ b/spec/ruby/library/socket/shared/pack_sockaddr.rb
@@ -0,0 +1,50 @@
+# coding: utf-8
+describe :socket_pack_sockaddr_in, shared: true do
+ it "packs and unpacks" do
+ sockaddr_in = Socket.public_send(@method, 0, nil)
+ port, addr = Socket.unpack_sockaddr_in(sockaddr_in)
+ ["127.0.0.1", "::1"].include?(addr).should == true
+ port.should == 0
+
+ sockaddr_in = Socket.public_send(@method, 0, '')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [0, '0.0.0.0']
+
+ sockaddr_in = Socket.public_send(@method, 80, '127.0.0.1')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
+
+ sockaddr_in = Socket.public_send(@method, '80', '127.0.0.1')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
+
+ sockaddr_in = Socket.public_send(@method, nil, '127.0.0.1')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [0, '127.0.0.1']
+ end
+end
+
+describe :socket_pack_sockaddr_un, shared: true do
+ platform_is_not :windows do
+ it 'should be idempotent' do
+ bytes = Socket.public_send(@method, '/tmp/foo').bytes
+ bytes[2..9].should == [47, 116, 109, 112, 47, 102, 111, 111]
+ bytes[10..-1].all?(&:zero?).should == true
+ end
+
+ it "packs and unpacks" do
+ sockaddr_un = Socket.public_send(@method, '/tmp/s')
+ Socket.unpack_sockaddr_un(sockaddr_un).should == '/tmp/s'
+ end
+
+ it "handles correctly paths with multibyte chars" do
+ sockaddr_un = Socket.public_send(@method, '/home/вася/sock')
+ path = Socket.unpack_sockaddr_un(sockaddr_un).encode('UTF-8', 'UTF-8')
+ path.should == '/home/вася/sock'
+ end
+ end
+
+ platform_is_not :windows, :aix do
+ it "raises if path length exceeds max size" do
+ # AIX doesn't raise error
+ long_path = Array.new(512, 0).join
+ lambda { Socket.public_send(@method, long_path) }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/shared/partially_closable_sockets.rb b/spec/ruby/library/socket/shared/partially_closable_sockets.rb
new file mode 100644
index 0000000000..1bdff08bf6
--- /dev/null
+++ b/spec/ruby/library/socket/shared/partially_closable_sockets.rb
@@ -0,0 +1,13 @@
+describe "partially closable sockets", shared: true do
+ it "if the write end is closed then the other side can read past EOF without blocking" do
+ @s1.write("foo")
+ @s1.close_write
+ @s2.read("foo".size + 1).should == "foo"
+ end
+
+ it "closing the write end ensures that the other side can read until EOF" do
+ @s1.write("hello world")
+ @s1.close_write
+ @s2.read.should == "hello world"
+ end
+end
diff --git a/spec/ruby/library/socket/shared/recv_nonblock.rb b/spec/ruby/library/socket/shared/recv_nonblock.rb
new file mode 100644
index 0000000000..a5f6c6812e
--- /dev/null
+++ b/spec/ruby/library/socket/shared/recv_nonblock.rb
@@ -0,0 +1,54 @@
+describe :socket_recv_nonblock, shared: true do
+ before :each do
+ @s1 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
+ @s2 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
+ end
+
+ after :each do
+ @s1.close unless @s1.closed?
+ @s2.close unless @s2.closed?
+ end
+
+ it "raises an exception extending IO::WaitReadable if there's no data available" do
+ @s1.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
+ lambda {
+ @s1.recv_nonblock(5)
+ }.should raise_error(IO::WaitReadable) { |e|
+ platform_is_not :windows do
+ e.should be_kind_of(Errno::EAGAIN)
+ end
+ platform_is :windows do
+ e.should be_kind_of(Errno::EWOULDBLOCK)
+ end
+ }
+ end
+
+ it "receives data after it's ready" do
+ @s1.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
+ @s2.send("aaa", 0, @s1.getsockname)
+ IO.select([@s1], nil, nil, 2)
+ @s1.recv_nonblock(5).should == "aaa"
+ end
+
+ ruby_version_is "2.3" do
+ it "allows an output buffer as third argument" do
+ @s1.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
+ @s2.send("data", 0, @s1.getsockname)
+ IO.select([@s1], nil, nil, 2)
+
+ buf = "foo"
+ @s1.recv_nonblock(5, 0, buf)
+ buf.should == "data"
+ end
+ end
+
+ it "does not block if there's no data available" do
+ @s1.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
+ @s2.send("a", 0, @s1.getsockname)
+ IO.select([@s1], nil, nil, 2)
+ @s1.recv_nonblock(1).should == "a"
+ lambda {
+ @s1.recv_nonblock(5)
+ }.should raise_error(IO::WaitReadable)
+ end
+end
diff --git a/spec/ruby/library/socket/shared/socketpair.rb b/spec/ruby/library/socket/shared/socketpair.rb
new file mode 100644
index 0000000000..03ee0e1a52
--- /dev/null
+++ b/spec/ruby/library/socket/shared/socketpair.rb
@@ -0,0 +1,23 @@
+describe :socket_socketpair, shared: true do
+ platform_is_not :windows do
+ it "ensures the returned sockets are connected" do
+ s1, s2 = Socket.public_send(@method, Socket::AF_UNIX, 1, 0)
+ s1.puts("test")
+ s2.gets.should == "test\n"
+ s1.close
+ s2.close
+ end
+
+ it "responses with array of two sockets" do
+ begin
+ s1, s2 = Socket.public_send(@method, :UNIX, :STREAM)
+
+ s1.should be_an_instance_of(Socket)
+ s2.should be_an_instance_of(Socket)
+ ensure
+ s1.close
+ s2.close
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/socket/accept_nonblock_spec.rb b/spec/ruby/library/socket/socket/accept_nonblock_spec.rb
new file mode 100644
index 0000000000..be0bbf5f03
--- /dev/null
+++ b/spec/ruby/library/socket/socket/accept_nonblock_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket#accept_nonblock" do
+ before :each do
+ @hostname = "127.0.0.1"
+ @addr = Socket.sockaddr_in(0, @hostname)
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ @socket.bind(@addr)
+ @socket.listen(1)
+ end
+
+ after :each do
+ @socket.close
+ end
+
+ it "raises IO::WaitReadable if the connection is not accepted yet" do
+ lambda {
+ @socket.accept_nonblock
+ }.should raise_error(IO::WaitReadable) { |e|
+ platform_is_not :windows do
+ e.should be_kind_of(Errno::EAGAIN)
+ end
+ platform_is :windows do
+ e.should be_kind_of(Errno::EWOULDBLOCK)
+ end
+ }
+ end
+
+ ruby_version_is '2.3' do
+ it 'returns :wait_readable in exceptionless mode' do
+ @socket.accept_nonblock(exception: false).should == :wait_readable
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/socket/accept_spec.rb b/spec/ruby/library/socket/socket/accept_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/ruby/library/socket/socket/accept_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/ruby/library/socket/socket/bind_spec.rb b/spec/ruby/library/socket/socket/bind_spec.rb
new file mode 100644
index 0000000000..399c988b32
--- /dev/null
+++ b/spec/ruby/library/socket/socket/bind_spec.rb
@@ -0,0 +1,81 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+include Socket::Constants
+
+describe "Socket#bind on SOCK_DGRAM socket" do
+ before :each do
+ @sock = Socket.new(AF_INET, SOCK_DGRAM, 0)
+ @sockaddr = Socket.pack_sockaddr_in(0, "127.0.0.1")
+ end
+
+ after :each do
+ @sock.closed?.should be_false
+ @sock.close
+ end
+
+ it "binds to a port" do
+ lambda { @sock.bind(@sockaddr) }.should_not raise_error
+ end
+
+ it "returns 0 if successful" do
+ @sock.bind(@sockaddr).should == 0
+ end
+
+ it "raises Errno::EINVAL when already bound" do
+ @sock.bind(@sockaddr)
+
+ lambda { @sock.bind(@sockaddr) }.should raise_error(Errno::EINVAL)
+ end
+
+ it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do
+ sockaddr1 = Socket.pack_sockaddr_in(0, "4.3.2.1")
+ lambda { @sock.bind(sockaddr1) }.should raise_error(Errno::EADDRNOTAVAIL)
+ end
+
+ platform_is_not :windows, :cygwin do
+ it "raises Errno::EACCES when the current user does not have permission to bind" do
+ sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1")
+ lambda { @sock.bind(sockaddr1) }.should raise_error(Errno::EACCES)
+ end
+ end
+end
+
+describe "Socket#bind on SOCK_STREAM socket" do
+ before :each do
+ @sock = Socket.new(AF_INET, SOCK_STREAM, 0)
+ @sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, true)
+ @sockaddr = Socket.pack_sockaddr_in(0, "127.0.0.1")
+ end
+
+ after :each do
+ @sock.closed?.should be_false
+ @sock.close
+ end
+
+ it "binds to a port" do
+ lambda { @sock.bind(@sockaddr) }.should_not raise_error
+ end
+
+ it "returns 0 if successful" do
+ @sock.bind(@sockaddr).should == 0
+ end
+
+ it "raises Errno::EINVAL when already bound" do
+ @sock.bind(@sockaddr)
+
+ lambda { @sock.bind(@sockaddr) }.should raise_error(Errno::EINVAL)
+ end
+
+ it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do
+ sockaddr1 = Socket.pack_sockaddr_in(0, "4.3.2.1")
+ lambda { @sock.bind(sockaddr1) }.should raise_error(Errno::EADDRNOTAVAIL)
+ end
+
+ platform_is_not :windows, :cygwin do
+ it "raises Errno::EACCES when the current user does not have permission to bind" do
+ sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1")
+ lambda { @sock.bind(sockaddr1) }.should raise_error(Errno::EACCES)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/socket/connect_nonblock_spec.rb b/spec/ruby/library/socket/socket/connect_nonblock_spec.rb
new file mode 100644
index 0000000000..26bceabb51
--- /dev/null
+++ b/spec/ruby/library/socket/socket/connect_nonblock_spec.rb
@@ -0,0 +1,73 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket#connect_nonblock" do
+ before :each do
+ @hostname = "127.0.0.1"
+ @server = TCPServer.new(@hostname, 0) # started, but no accept
+ @addr = Socket.sockaddr_in(@server.addr[1], @hostname)
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ @thread = nil
+ end
+
+ after :each do
+ @socket.close
+ @server.close
+ @thread.join if @thread
+ end
+
+ it "connects the socket to the remote side" do
+ port = nil
+ accept = false
+ @thread = Thread.new do
+ server = TCPServer.new(@hostname, 0)
+ port = server.addr[1]
+ Thread.pass until accept
+ conn = server.accept
+ conn << "hello!"
+ conn.close
+ server.close
+ end
+
+ Thread.pass until port
+
+ addr = Socket.sockaddr_in(port, @hostname)
+ begin
+ @socket.connect_nonblock(addr)
+ rescue Errno::EINPROGRESS
+ end
+
+ accept = true
+ IO.select nil, [@socket]
+
+ begin
+ @socket.connect_nonblock(addr)
+ rescue Errno::EISCONN
+ # Not all OS's use this errno, so we trap and ignore it
+ end
+
+ @socket.read(6).should == "hello!"
+ end
+
+ platform_is_not :freebsd, :solaris, :aix do
+ it "raises Errno::EINPROGRESS when the connect would block" do
+ lambda do
+ @socket.connect_nonblock(@addr)
+ end.should raise_error(Errno::EINPROGRESS)
+ end
+
+ it "raises Errno::EINPROGRESS with IO::WaitWritable mixed in when the connect would block" do
+ lambda do
+ @socket.connect_nonblock(@addr)
+ end.should raise_error(IO::WaitWritable)
+ end
+
+ ruby_version_is "2.3" do
+ it "returns :wait_writable in exceptionless mode when the connect would block" do
+ @socket.connect_nonblock(@addr, exception: false).should == :wait_writable
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/socket/connect_spec.rb b/spec/ruby/library/socket/socket/connect_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/ruby/library/socket/socket/connect_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/ruby/library/socket/socket/for_fd_spec.rb b/spec/ruby/library/socket/socket/for_fd_spec.rb
new file mode 100644
index 0000000000..6688988448
--- /dev/null
+++ b/spec/ruby/library/socket/socket/for_fd_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'socket'
+
+describe "Socket.for_fd" do
+ before :each do
+ @server = TCPServer.new("127.0.0.1", 0)
+ @port = @server.addr[1]
+ @client = TCPSocket.open("127.0.0.1", @port)
+ end
+
+ after :each do
+ @socket.close
+ @client.close
+ @host.close
+ @server.close
+ end
+
+ it "creates a new Socket that aliases the existing Socket's file descriptor" do
+ @socket = Socket.for_fd(@client.fileno)
+ @socket.autoclose = false
+ @socket.fileno.should == @client.fileno
+
+ @socket.send("foo", 0)
+ @client.send("bar", 0)
+
+ @host = @server.accept
+ @host.read(3).should == "foo"
+ @host.read(3).should == "bar"
+ end
+end
diff --git a/spec/ruby/library/socket/socket/getaddrinfo_spec.rb b/spec/ruby/library/socket/socket/getaddrinfo_spec.rb
new file mode 100644
index 0000000000..fa8112c010
--- /dev/null
+++ b/spec/ruby/library/socket/socket/getaddrinfo_spec.rb
@@ -0,0 +1,112 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket#getaddrinfo" do
+ before :each do
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
+ BasicSocket.do_not_reverse_lookup = true
+ end
+
+ after :each do
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
+ end
+
+ platform_is_not :solaris, :windows do
+ it "gets the address information" do
+ expected = []
+ # The check for AP_INET6's class is needed because ipaddr.rb adds
+ # fake AP_INET6 even in case when IPv6 is not really supported.
+ # Without such check, this test might fail when ipaddr was required
+ # by some other specs.
+ if (Socket.constants.include? 'AF_INET6') &&
+ (Socket::AF_INET6.class != Object) then
+ expected.concat [
+ ['AF_INET6', 9, SocketSpecs.hostname, '::1', Socket::AF_INET6,
+ Socket::SOCK_DGRAM, Socket::IPPROTO_UDP],
+ ['AF_INET6', 9, SocketSpecs.hostname, '::1', Socket::AF_INET6,
+ Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ['AF_INET6', 9, SocketSpecs.hostname, 'fe80::1%lo0', Socket::AF_INET6,
+ Socket::SOCK_DGRAM, Socket::IPPROTO_UDP],
+ ['AF_INET6', 9, SocketSpecs.hostname, 'fe80::1%lo0', Socket::AF_INET6,
+ Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ]
+ end
+
+ expected.concat [
+ ['AF_INET', 9, SocketSpecs.hostname, '127.0.0.1', Socket::AF_INET,
+ Socket::SOCK_DGRAM, Socket::IPPROTO_UDP],
+ ['AF_INET', 9, SocketSpecs.hostname, '127.0.0.1', Socket::AF_INET,
+ Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ]
+
+ addrinfo = Socket.getaddrinfo SocketSpecs.hostname, 'discard'
+ addrinfo.each do |a|
+ case a.last
+ when Socket::IPPROTO_UDP, Socket::IPPROTO_TCP
+ expected.should include(a)
+ else
+ # don't check this. It's some weird protocol we don't know about
+ # so we can't spec it.
+ end
+ end
+ end
+
+ # #getaddrinfo will return a INADDR_ANY address (0.0.0.0
+ # or "::") if it's a passive socket. In the case of non-passive
+ # sockets (AI_PASSIVE not set) it should return the loopback
+ # address (127.0.0.1 or "::1".
+
+ it "accepts empty addresses for IPv4 passive sockets" do
+ res = Socket.getaddrinfo(nil, "discard",
+ Socket::AF_INET,
+ Socket::SOCK_STREAM,
+ Socket::IPPROTO_TCP,
+ Socket::AI_PASSIVE)
+
+ expected = [["AF_INET", 9, "0.0.0.0", "0.0.0.0", Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]]
+ res.should == expected
+ end
+
+ it "accepts empty addresses for IPv4 non-passive sockets" do
+ res = Socket.getaddrinfo(nil, "discard",
+ Socket::AF_INET,
+ Socket::SOCK_STREAM,
+ Socket::IPPROTO_TCP,
+ 0)
+
+ expected = [["AF_INET", 9, "127.0.0.1", "127.0.0.1", Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]]
+ res.should == expected
+ end
+
+
+ it "accepts empty addresses for IPv6 passive sockets" do
+ res = Socket.getaddrinfo(nil, "discard",
+ Socket::AF_INET6,
+ Socket::SOCK_STREAM,
+ Socket::IPPROTO_TCP,
+ Socket::AI_PASSIVE)
+
+ expected = [
+ ["AF_INET6", 9, "::", "::", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ["AF_INET6", 9, "0:0:0:0:0:0:0:0", "0:0:0:0:0:0:0:0", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]
+ ]
+ res.each { |a| expected.should include (a) }
+ end
+
+ it "accepts empty addresses for IPv6 non-passive sockets" do
+ res = Socket.getaddrinfo(nil, "discard",
+ Socket::AF_INET6,
+ Socket::SOCK_STREAM,
+ Socket::IPPROTO_TCP,
+ 0)
+
+ expected = [
+ ["AF_INET6", 9, "::1", "::1", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ["AF_INET6", 9, "0:0:0:0:0:0:0:1", "0:0:0:0:0:0:0:1", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]
+ ]
+ res.each { |a| expected.should include(a) }
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb b/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/ruby/library/socket/socket/gethostbyname_spec.rb b/spec/ruby/library/socket/socket/gethostbyname_spec.rb
new file mode 100644
index 0000000000..a93c9ffb98
--- /dev/null
+++ b/spec/ruby/library/socket/socket/gethostbyname_spec.rb
@@ -0,0 +1,17 @@
+# -*- encoding: binary -*-
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket#gethostbyname" do
+ it "returns broadcast address info for '<broadcast>'" do
+ addr = Socket.gethostbyname('<broadcast>');
+ addr.should == ["255.255.255.255", [], 2, "\377\377\377\377"]
+ end
+
+ it "returns broadcast address info for '<any>'" do
+ addr = Socket.gethostbyname('<any>');
+ addr.should == ["0.0.0.0", [], 2, "\000\000\000\000"]
+ end
+end
diff --git a/spec/ruby/library/socket/socket/gethostname_spec.rb b/spec/ruby/library/socket/socket/gethostname_spec.rb
new file mode 100644
index 0000000000..c61e6b3eb4
--- /dev/null
+++ b/spec/ruby/library/socket/socket/gethostname_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket.gethostname" do
+ it "returns the host name" do
+ Socket.gethostname.should == `hostname`.strip
+ end
+end
diff --git a/spec/ruby/library/socket/socket/getnameinfo_spec.rb b/spec/ruby/library/socket/socket/getnameinfo_spec.rb
new file mode 100644
index 0000000000..9fc55dd61b
--- /dev/null
+++ b/spec/ruby/library/socket/socket/getnameinfo_spec.rb
@@ -0,0 +1,66 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket.getnameinfo" do
+ before :each do
+ @reverse_lookup = BasicSocket.do_not_reverse_lookup
+ BasicSocket.do_not_reverse_lookup = true
+ end
+
+ after :each do
+ BasicSocket.do_not_reverse_lookup = @reverse_lookup
+ end
+
+ it "gets the name information and don't resolve it" do
+ sockaddr = Socket.sockaddr_in 3333, '127.0.0.1'
+ name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
+ name_info.should == ['127.0.0.1', "3333"]
+ end
+
+ def should_be_valid_dns_name(name)
+ # http://stackoverflow.com/questions/106179/regular-expression-to-match-hostname-or-ip-address
+ # ftp://ftp.rfc-editor.org/in-notes/rfc3696.txt
+ # http://domainkeys.sourceforge.net/underscore.html
+ valid_dns = /^(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\-_]*[a-zA-Z0-9_])\.)*([A-Za-z_]|[A-Za-z_][A-Za-z0-9\-_]*[A-Za-z0-9_])\.?$/
+ name.should =~ valid_dns
+ end
+
+ it "gets the name information and resolve the host" do
+ sockaddr = Socket.sockaddr_in 3333, '127.0.0.1'
+ name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICSERV)
+ should_be_valid_dns_name(name_info[0])
+ name_info[1].should == 3333.to_s
+ end
+
+ it "gets the name information and resolves the service" do
+ sockaddr = Socket.sockaddr_in 9, '127.0.0.1'
+ name_info = Socket.getnameinfo(sockaddr)
+ name_info.size.should == 2
+ should_be_valid_dns_name(name_info[0])
+ # see http://www.iana.org/assignments/port-numbers
+ name_info[1].should == 'discard'
+ end
+
+ it "gets a 3-element array and doesn't resolve hostname" do
+ name_info = Socket.getnameinfo(["AF_INET", 3333, '127.0.0.1'], Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
+ name_info.should == ['127.0.0.1', "3333"]
+ end
+
+ it "gets a 3-element array and resolves the service" do
+ name_info = Socket.getnameinfo ["AF_INET", 9, '127.0.0.1']
+ name_info[1].should == 'discard'
+ end
+
+ it "gets a 4-element array and doesn't resolve hostname" do
+ name_info = Socket.getnameinfo(["AF_INET", 3333, 'foo', '127.0.0.1'], Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
+ name_info.should == ['127.0.0.1', "3333"]
+ end
+
+ it "gets a 4-element array and resolves the service" do
+ name_info = Socket.getnameinfo ["AF_INET", 9, 'foo', '127.0.0.1']
+ name_info[1].should == 'discard'
+ end
+
+end
diff --git a/spec/ruby/library/socket/socket/getservbyname_spec.rb b/spec/ruby/library/socket/socket/getservbyname_spec.rb
new file mode 100644
index 0000000000..a48b5753b4
--- /dev/null
+++ b/spec/ruby/library/socket/socket/getservbyname_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket#getservbyname" do
+ it "returns the port for service 'discard'" do
+ Socket.getservbyname('discard').should == 9
+ end
+
+ it "returns the port for service 'discard' with protocol 'tcp'" do
+ Socket.getservbyname('discard', 'tcp').should == 9
+ end
+
+ it "returns the port for service 'domain' with protocol 'udp'" do
+ Socket.getservbyname('domain', 'udp').should == 53
+ end
+
+ it "returns the port for service 'daytime'" do
+ Socket.getservbyname('daytime').should == 13
+ end
+
+ it "raises a SocketError when the service or port is invalid" do
+ lambda { Socket.getservbyname('invalid') }.should raise_error(SocketError)
+ end
+end
diff --git a/spec/ruby/library/socket/socket/listen_spec.rb b/spec/ruby/library/socket/socket/listen_spec.rb
new file mode 100644
index 0000000000..bea87f4ec5
--- /dev/null
+++ b/spec/ruby/library/socket/socket/listen_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+include Socket::Constants
+
+describe "Socket#listen" do
+ before :each do
+ @socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ end
+
+ after :each do
+ @socket.closed?.should be_false
+ @socket.close
+ end
+
+ it "verifies we can listen for incoming connections" do
+ sockaddr = Socket.pack_sockaddr_in(0, "127.0.0.1")
+ @socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
+ @socket.bind(sockaddr)
+ @socket.listen(1).should == 0
+ end
+end
diff --git a/spec/ruby/library/socket/socket/new_spec.rb b/spec/ruby/library/socket/socket/new_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/ruby/library/socket/socket/new_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/ruby/library/socket/socket/pack_sockaddr_in_spec.rb b/spec/ruby/library/socket/socket/pack_sockaddr_in_spec.rb
new file mode 100644
index 0000000000..8c95b948dc
--- /dev/null
+++ b/spec/ruby/library/socket/socket/pack_sockaddr_in_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/pack_sockaddr', __FILE__)
+
+describe "Socket#pack_sockaddr_in" do
+ it_behaves_like :socket_pack_sockaddr_in, :pack_sockaddr_in
+end
diff --git a/spec/ruby/library/socket/socket/pack_sockaddr_un_spec.rb b/spec/ruby/library/socket/socket/pack_sockaddr_un_spec.rb
new file mode 100644
index 0000000000..aacb6d54dc
--- /dev/null
+++ b/spec/ruby/library/socket/socket/pack_sockaddr_un_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/pack_sockaddr', __FILE__)
+
+describe "Socket#pack_sockaddr_un" do
+ it_behaves_like :socket_pack_sockaddr_un, :pack_sockaddr_un
+end
diff --git a/spec/ruby/library/socket/socket/pair_spec.rb b/spec/ruby/library/socket/socket/pair_spec.rb
new file mode 100644
index 0000000000..663ca3f183
--- /dev/null
+++ b/spec/ruby/library/socket/socket/pair_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/socketpair', __FILE__)
+
+describe "Socket#pair" do
+ it_behaves_like :socket_socketpair, :pair
+end
diff --git a/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb b/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/ruby/library/socket/socket/recvfrom_spec.rb b/spec/ruby/library/socket/socket/recvfrom_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/ruby/library/socket/socket/recvfrom_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/ruby/library/socket/socket/sockaddr_in_spec.rb b/spec/ruby/library/socket/socket/sockaddr_in_spec.rb
new file mode 100644
index 0000000000..59e0318fda
--- /dev/null
+++ b/spec/ruby/library/socket/socket/sockaddr_in_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/pack_sockaddr', __FILE__)
+
+describe "Socket#sockaddr_in" do
+ it_behaves_like :socket_pack_sockaddr_in, :sockaddr_in
+end
diff --git a/spec/ruby/library/socket/socket/sockaddr_un_spec.rb b/spec/ruby/library/socket/socket/sockaddr_un_spec.rb
new file mode 100644
index 0000000000..fa233587d9
--- /dev/null
+++ b/spec/ruby/library/socket/socket/sockaddr_un_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/pack_sockaddr', __FILE__)
+
+describe "Socket#sockaddr_un" do
+ it_behaves_like :socket_pack_sockaddr_un, :sockaddr_un
+end
diff --git a/spec/ruby/library/socket/socket/socket_spec.rb b/spec/ruby/library/socket/socket/socket_spec.rb
new file mode 100644
index 0000000000..dbaed17af4
--- /dev/null
+++ b/spec/ruby/library/socket/socket/socket_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket" do
+ it "inherits from BasicSocket and IO" do
+ Socket.superclass.should == BasicSocket
+ BasicSocket.superclass.should == IO
+ end
+end
+
+describe "The socket class hierarchy" do
+ it "has an IPSocket in parallel to Socket" do
+ Socket.ancestors.include?(IPSocket).should == false
+ IPSocket.ancestors.include?(Socket).should == false
+ IPSocket.superclass.should == BasicSocket
+ end
+
+ it "has TCPSocket and UDPSocket subclasses of IPSocket" do
+ TCPSocket.superclass.should == IPSocket
+ UDPSocket.superclass.should == IPSocket
+ end
+
+ platform_is_not :windows do
+ it "has a UNIXSocket in parallel to Socket" do
+ Socket.ancestors.include?(UNIXSocket).should == false
+ UNIXSocket.ancestors.include?(Socket).should == false
+ UNIXSocket.superclass.should == BasicSocket
+ end
+ end
+end
+
+platform_is_not :windows do
+ describe "Server class hierarchy" do
+ it "contains UNIXServer" do
+ UNIXServer.superclass.should == UNIXSocket
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/socket/socketpair_spec.rb b/spec/ruby/library/socket/socket/socketpair_spec.rb
new file mode 100644
index 0000000000..80b07170a6
--- /dev/null
+++ b/spec/ruby/library/socket/socket/socketpair_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/socketpair', __FILE__)
+
+describe "Socket#socketpair" do
+ it_behaves_like :socket_socketpair, :socketpair
+end
diff --git a/spec/ruby/library/socket/socket/sysaccept_spec.rb b/spec/ruby/library/socket/socket/sysaccept_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/ruby/library/socket/socket/sysaccept_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb b/spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb
new file mode 100644
index 0000000000..91d2b947a1
--- /dev/null
+++ b/spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'socket'
+
+describe "Socket.unpack_sockaddr_in" do
+
+ it "decodes the host name and port number of a packed sockaddr_in" do
+ sockaddr = Socket.sockaddr_in 3333, '127.0.0.1'
+ Socket.unpack_sockaddr_in(sockaddr).should == [3333, '127.0.0.1']
+ end
+
+ it "gets the hostname and port number from a passed Addrinfo" do
+ addrinfo = Addrinfo.tcp('127.0.0.1', 3333)
+ Socket.unpack_sockaddr_in(addrinfo).should == [3333, '127.0.0.1']
+ end
+
+ platform_is_not :windows do
+ it "raises an ArgumentError when the sin_family is not AF_INET" do
+ sockaddr = Socket.sockaddr_un '/tmp/x'
+ lambda { Socket.unpack_sockaddr_in sockaddr }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when passed addrinfo is not AF_INET/AF_INET6" do
+ addrinfo = Addrinfo.unix('/tmp/sock')
+ lambda { Socket.unpack_sockaddr_in(addrinfo) }.should raise_error(ArgumentError)
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb b/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb
new file mode 100644
index 0000000000..f81d36f7e9
--- /dev/null
+++ b/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe 'Socket.unpack_sockaddr_un' do
+ platform_is_not :windows do
+ it 'decodes sockaddr to unix path' do
+ sockaddr = Socket.sockaddr_un('/tmp/sock')
+ Socket.unpack_sockaddr_un(sockaddr).should == '/tmp/sock'
+ end
+
+ it 'returns unix path from a passed Addrinfo' do
+ addrinfo = Addrinfo.unix('/tmp/sock')
+ Socket.unpack_sockaddr_un(addrinfo).should == '/tmp/sock'
+ end
+
+ it 'raises an ArgumentError when the sin_family is not AF_UNIX' do
+ sockaddr = Socket.sockaddr_in(0, '127.0.0.1')
+ lambda { Socket.unpack_sockaddr_un(sockaddr) }.should raise_error(ArgumentError)
+ end
+
+ it 'raises an ArgumentError when passed addrinfo is not AF_UNIX' do
+ addrinfo = Addrinfo.tcp('127.0.0.1', 0)
+ lambda { Socket.unpack_sockaddr_un(addrinfo) }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/tcpserver/accept_nonblock_spec.rb b/spec/ruby/library/socket/tcpserver/accept_nonblock_spec.rb
new file mode 100644
index 0000000000..d6f7448084
--- /dev/null
+++ b/spec/ruby/library/socket/tcpserver/accept_nonblock_spec.rb
@@ -0,0 +1,50 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::TCPServer.accept_nonblock" do
+ before :each do
+ @server = TCPServer.new("127.0.0.1", 0)
+ @port = @server.addr[1]
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it "accepts non blocking connections" do
+ @server.listen(5)
+ lambda {
+ @server.accept_nonblock
+ }.should raise_error(IO::WaitReadable)
+
+ c = TCPSocket.new("127.0.0.1", @port)
+ sleep 0.1
+ s = @server.accept_nonblock
+
+ port, address = Socket.unpack_sockaddr_in(s.getsockname)
+
+ port.should == @port
+ address.should == "127.0.0.1"
+ s.should be_kind_of(TCPSocket)
+
+ c.close
+ s.close
+ end
+
+ it "raises an IOError if the socket is closed" do
+ @server.close
+ lambda { @server.accept }.should raise_error(IOError)
+ end
+
+ describe 'without a connected client' do
+ it 'raises error' do
+ lambda { @server.accept_nonblock }.should raise_error(IO::WaitReadable)
+ end
+
+ ruby_version_is '2.3' do
+ it 'returns :wait_readable in exceptionless mode' do
+ @server.accept_nonblock(exception: false).should == :wait_readable
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/tcpserver/accept_spec.rb b/spec/ruby/library/socket/tcpserver/accept_spec.rb
new file mode 100644
index 0000000000..f7b017d014
--- /dev/null
+++ b/spec/ruby/library/socket/tcpserver/accept_spec.rb
@@ -0,0 +1,65 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+
+describe "TCPServer#accept" do
+ before :each do
+ @server = TCPServer.new("127.0.0.1", 0)
+ @port = @server.addr[1]
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it "accepts a connection and returns a TCPSocket" do
+ data = nil
+ t = Thread.new do
+ client = @server.accept
+ client.should be_kind_of(TCPSocket)
+ data = client.read(5)
+ client << "goodbye"
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.write('hello')
+ socket.shutdown(1) # we are done with sending
+ socket.read.should == 'goodbye'
+ t.join
+ data.should == 'hello'
+ socket.close
+ end
+
+ it "can be interrupted by Thread#kill" do
+ t = Thread.new { @server.accept }
+
+ Thread.pass while t.status and t.status != "sleep"
+
+ # kill thread, ensure it dies in a reasonable amount of time
+ t.kill
+ a = 0
+ while t.alive? and a < 5000
+ sleep 0.001
+ a += 1
+ end
+ a.should < 5000
+ end
+
+ it "can be interrupted by Thread#raise" do
+ t = Thread.new { @server.accept }
+
+ Thread.pass while t.status and t.status != "sleep"
+
+ # raise in thread, ensure the raise happens
+ ex = Exception.new
+ t.raise ex
+ lambda { t.join }.should raise_error(Exception)
+ end
+
+ it "raises an IOError if the socket is closed" do
+ @server.close
+ lambda { @server.accept }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/socket/tcpserver/gets_spec.rb b/spec/ruby/library/socket/tcpserver/gets_spec.rb
new file mode 100644
index 0000000000..86ba65eae2
--- /dev/null
+++ b/spec/ruby/library/socket/tcpserver/gets_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPServer#gets" do
+ before :each do
+ @server = TCPServer.new(SocketSpecs.hostname, 0)
+ end
+
+ after :each do
+ @server.close
+ end
+
+ it "raises Errno::ENOTCONN on gets" do
+ lambda { @server.gets }.should raise_error(Errno::ENOTCONN)
+ end
+end
diff --git a/spec/ruby/library/socket/tcpserver/listen_spec.rb b/spec/ruby/library/socket/tcpserver/listen_spec.rb
new file mode 100644
index 0000000000..d764b4ce70
--- /dev/null
+++ b/spec/ruby/library/socket/tcpserver/listen_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe 'TCPServer#listen' do
+ before :each do
+ @server = TCPServer.new(SocketSpecs.hostname, 0)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it 'returns 0' do
+ @server.listen(10).should == 0
+ end
+end
diff --git a/spec/ruby/library/socket/tcpserver/new_spec.rb b/spec/ruby/library/socket/tcpserver/new_spec.rb
new file mode 100644
index 0000000000..ddbe96d89d
--- /dev/null
+++ b/spec/ruby/library/socket/tcpserver/new_spec.rb
@@ -0,0 +1,96 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPServer.new" do
+ after :each do
+ @server.close if @server && !@server.closed?
+ end
+
+ it "binds to a host and a port" do
+ @server = TCPServer.new('127.0.0.1', 0)
+ addr = @server.addr
+ addr[0].should == 'AF_INET'
+ addr[1].should be_kind_of(Fixnum)
+ # on some platforms (Mac), MRI
+ # returns comma at the end.
+ addr[2].should =~ /^#{SocketSpecs.hostname}\b/
+ addr[3].should == '127.0.0.1'
+ end
+
+ it "binds to localhost and a port with either IPv4 or IPv6" do
+ @server = TCPServer.new(SocketSpecs.hostname, 0)
+ addr = @server.addr
+ addr[1].should be_kind_of(Fixnum)
+ if addr[0] == 'AF_INET'
+ addr[2].should =~ /^#{SocketSpecs.hostname}\b/
+ addr[3].should == '127.0.0.1'
+ else
+ addr[2].should =~ /^#{SocketSpecs.hostnamev6}\b/
+ addr[3].should == '::1'
+ end
+ end
+
+ it "binds to INADDR_ANY if the hostname is empty" do
+ @server = TCPServer.new('', 0)
+ addr = @server.addr
+ addr[0].should == 'AF_INET'
+ addr[1].should be_kind_of(Fixnum)
+ addr[2].should == '0.0.0.0'
+ addr[3].should == '0.0.0.0'
+ end
+
+ it "binds to INADDR_ANY if the hostname is empty and the port is a string" do
+ @server = TCPServer.new('', 0)
+ addr = @server.addr
+ addr[0].should == 'AF_INET'
+ addr[1].should be_kind_of(Fixnum)
+ addr[2].should == '0.0.0.0'
+ addr[3].should == '0.0.0.0'
+ end
+
+ it "coerces port to string, then determines port from that number or service name" do
+ lambda { TCPServer.new(SocketSpecs.hostname, Object.new) }.should raise_error(TypeError)
+
+ port = Object.new
+ port.should_receive(:to_str).and_return("0")
+
+ @server = TCPServer.new(SocketSpecs.hostname, port)
+ addr = @server.addr
+ addr[1].should be_kind_of(Fixnum)
+
+ # TODO: This should also accept strings like 'https', but I don't know how to
+ # pick such a service port that will be able to reliably bind...
+ end
+
+ it "raises Errno::EADDRNOTAVAIL when the adress is unknown" do
+ lambda { TCPServer.new("1.2.3.4", 0) }.should raise_error(Errno::EADDRNOTAVAIL)
+ end
+
+ # There is no way to make this fail-proof on all machines, because
+ # DNS servers like opendns return A records for ANY host, including
+ # traditionally invalidly named ones.
+ quarantine! do
+ it "raises a SocketError when the host is unknown" do
+ lambda {
+ TCPServer.new("--notavalidname", 0)
+ }.should raise_error(SocketError)
+ end
+ end
+
+ it "raises Errno::EADDRINUSE when address is already in use" do
+ @server = TCPServer.new('127.0.0.1', 0)
+ lambda {
+ @server = TCPServer.new('127.0.0.1', @server.addr[1])
+ }.should raise_error(Errno::EADDRINUSE)
+ end
+
+ platform_is_not :windows, :aix do
+ # A known bug in AIX. getsockopt(2) does not properly set
+ # the fifth argument for SO_REUSEADDR.
+ it "sets SO_REUSEADDR on the resulting server" do
+ @server = TCPServer.new('127.0.0.1', 0)
+ @server.getsockopt(:SOCKET, :REUSEADDR).data.should_not == "\x00\x00\x00\x00"
+ @server.getsockopt(:SOCKET, :REUSEADDR).int.should_not == 0
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/tcpserver/sysaccept_spec.rb b/spec/ruby/library/socket/tcpserver/sysaccept_spec.rb
new file mode 100644
index 0000000000..93c1ffe152
--- /dev/null
+++ b/spec/ruby/library/socket/tcpserver/sysaccept_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "TCPServer#sysaccept" do
+ before :each do
+ @server = TCPServer.new(SocketSpecs.hostname, 0)
+ @port = @server.addr[1]
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it 'blocks if no connections' do
+ lambda { @server.sysaccept }.should block_caller
+ end
+
+ it 'returns file descriptor of an accepted connection' do
+ begin
+ sock = TCPSocket.new(SocketSpecs.hostname, @port)
+
+ fd = @server.sysaccept
+
+ fd.should be_an_instance_of(Fixnum)
+ ensure
+ sock.close if sock && !sock.closed?
+ IO.for_fd(fd).close if fd
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb b/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb
new file mode 100644
index 0000000000..11838aca27
--- /dev/null
+++ b/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+# TODO: verify these for windows
+describe "TCPSocket#gethostbyname" do
+ before :each do
+ @host_info = TCPSocket.gethostbyname(SocketSpecs.hostname)
+ end
+
+ it "returns an array elements of information on the hostname" do
+ @host_info.should be_kind_of(Array)
+ end
+
+ platform_is_not :windows do
+ it "returns the canonical name as first value" do
+ @host_info[0].should == SocketSpecs.hostname
+ end
+
+ it "returns the address type as the third value" do
+ address_type = @host_info[2]
+ [Socket::AF_INET, Socket::AF_INET6].include?(address_type).should be_true
+ end
+
+ it "returns the IP address as the fourth value" do
+ ip = @host_info[3]
+ ["127.0.0.1", "::1"].include?(ip).should be_true
+ end
+ end
+
+ platform_is :windows do
+ quarantine! do # name lookup seems not working on Windows CI
+ it "returns the canonical name as first value" do
+ host = "#{ENV['COMPUTERNAME'].downcase}"
+ host << ".#{ENV['USERDNSDOMAIN'].downcase}" if ENV['USERDNSDOMAIN']
+ @host_info[0].should == host
+ end
+ end
+
+ it "returns the address type as the third value" do
+ @host_info[2].should == Socket::AF_INET
+ end
+
+ it "returns the IP address as the fourth value" do
+ @host_info[3].should == "127.0.0.1"
+ end
+ end
+
+ it "returns any aliases to the address as second value" do
+ @host_info[1].should be_kind_of(Array)
+ end
+end
diff --git a/spec/ruby/library/socket/tcpsocket/new_spec.rb b/spec/ruby/library/socket/tcpsocket/new_spec.rb
new file mode 100644
index 0000000000..279576272b
--- /dev/null
+++ b/spec/ruby/library/socket/tcpsocket/new_spec.rb
@@ -0,0 +1,5 @@
+require File.expand_path('../shared/new', __FILE__)
+
+describe "TCPSocket.new" do
+ it_behaves_like :tcpsocket_new, :new
+end
diff --git a/spec/ruby/library/socket/tcpsocket/open_spec.rb b/spec/ruby/library/socket/tcpsocket/open_spec.rb
new file mode 100644
index 0000000000..fb4cc4629a
--- /dev/null
+++ b/spec/ruby/library/socket/tcpsocket/open_spec.rb
@@ -0,0 +1,5 @@
+require File.expand_path('../shared/new', __FILE__)
+
+describe "TCPSocket.open" do
+ it_behaves_like :tcpsocket_new, :open
+end
diff --git a/spec/ruby/library/socket/tcpsocket/partially_closable_spec.rb b/spec/ruby/library/socket/tcpsocket/partially_closable_spec.rb
new file mode 100644
index 0000000000..6a43eea625
--- /dev/null
+++ b/spec/ruby/library/socket/tcpsocket/partially_closable_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/partially_closable_sockets', __FILE__)
+
+describe "TCPSocket partial closability" do
+
+ before :each do
+ @server = TCPServer.new("127.0.0.1", 0)
+ @s1 = TCPSocket.new("127.0.0.1", @server.addr[1])
+ @s2 = @server.accept
+ end
+
+ after :each do
+ @server.close
+ @s1.close
+ @s2.close
+ end
+
+ it_should_behave_like "partially closable sockets"
+
+end
diff --git a/spec/ruby/library/socket/tcpsocket/recv_nonblock_spec.rb b/spec/ruby/library/socket/tcpsocket/recv_nonblock_spec.rb
new file mode 100644
index 0000000000..237ff781a3
--- /dev/null
+++ b/spec/ruby/library/socket/tcpsocket/recv_nonblock_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPSocket#recv_nonblock" do
+ before :each do
+ @server = SocketSpecs::SpecTCPServer.new
+ @hostname = @server.hostname
+ end
+
+ after :each do
+ if @socket
+ @socket.write "QUIT"
+ @socket.close
+ end
+ @server.shutdown
+ end
+
+ it "returns a String read from the socket" do
+ @socket = TCPSocket.new @hostname, @server.port
+ @socket.write "TCPSocket#recv_nonblock"
+
+ # Wait for the server to echo. This spec is testing the return
+ # value, not the non-blocking behavior.
+ #
+ # TODO: Figure out a good way to test non-blocking.
+ IO.select([@socket])
+ @socket.recv_nonblock(50).should == "TCPSocket#recv_nonblock"
+ end
+
+ ruby_version_is '2.3' do
+ it 'returns :wait_readable in exceptionless mode' do
+ @socket = TCPSocket.new @hostname, @server.port
+ @socket.recv_nonblock(50, exception: false).should == :wait_readable
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/tcpsocket/setsockopt_spec.rb b/spec/ruby/library/socket/tcpsocket/setsockopt_spec.rb
new file mode 100644
index 0000000000..8a0cb443b5
--- /dev/null
+++ b/spec/ruby/library/socket/tcpsocket/setsockopt_spec.rb
@@ -0,0 +1,45 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPSocket#setsockopt" do
+ before :each do
+ @server = SocketSpecs::SpecTCPServer.new
+ @hostname = @server.hostname
+ @sock = TCPSocket.new @hostname, @server.port
+ end
+
+ after :each do
+ @sock.close unless @sock.closed?
+ @server.shutdown
+ end
+
+ describe "using constants" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1).should == 0
+ end
+ end
+
+ describe "using symbols" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt(:IPPROTO_TCP, :TCP_NODELAY, 1).should == 0
+ end
+
+ context "without prefix" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt(:TCP, :NODELAY, 1).should == 0
+ end
+ end
+ end
+
+ describe "using strings" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt('IPPROTO_TCP', 'TCP_NODELAY', 1).should == 0
+ end
+
+ context "without prefix" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt('TCP', 'NODELAY', 1).should == 0
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/tcpsocket/shared/new.rb b/spec/ruby/library/socket/tcpsocket/shared/new.rb
new file mode 100644
index 0000000000..912208c86c
--- /dev/null
+++ b/spec/ruby/library/socket/tcpsocket/shared/new.rb
@@ -0,0 +1,79 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/classes', __FILE__)
+
+describe :tcpsocket_new, shared: true do
+ it "requires a hostname and a port as arguments" do
+ lambda { TCPSocket.send(@method) }.should raise_error(ArgumentError)
+ end
+
+ it "refuses the connection when there is no server to connect to" do
+ lambda do
+ TCPSocket.send(@method, SocketSpecs.hostname, SocketSpecs.reserved_unused_port)
+ end.should raise_error(SystemCallError) {|e|
+ [Errno::ECONNREFUSED, Errno::EADDRNOTAVAIL].should include(e.class)
+ }
+ end
+
+ describe "with a running server" do
+ before :each do
+ @server = SocketSpecs::SpecTCPServer.new
+ @hostname = @server.hostname
+ end
+
+ after :each do
+ if @socket
+ @socket.write "QUIT"
+ @socket.close
+ end
+ @server.shutdown
+ end
+
+ it "silently ignores 'nil' as the third parameter" do
+ @socket = TCPSocket.send(@method, @hostname, @server.port, nil)
+ @socket.should be_an_instance_of(TCPSocket)
+ end
+
+ it "connects to a listening server with host and port" do
+ @socket = TCPSocket.send(@method, @hostname, @server.port)
+ @socket.should be_an_instance_of(TCPSocket)
+ end
+
+ it "connects to a server when passed local_host argument" do
+ @socket = TCPSocket.send(@method, @hostname, @server.port, @hostname)
+ @socket.should be_an_instance_of(TCPSocket)
+ end
+
+ it "connects to a server when passed local_host and local_port arguments" do
+ server = TCPServer.new(SocketSpecs.hostname, 0)
+ begin
+ available_port = server.addr[1]
+ ensure
+ server.close
+ end
+ @socket = TCPSocket.send(@method, @hostname, @server.port,
+ @hostname, available_port)
+ @socket.should be_an_instance_of(TCPSocket)
+ end
+
+ it "has an address once it has connected to a listening server" do
+ @socket = TCPSocket.send(@method, @hostname, @server.port)
+ @socket.should be_an_instance_of(TCPSocket)
+
+ # TODO: Figure out how to abstract this. You can get AF_INET
+ # from 'Socket.getaddrinfo(hostname, nil)[0][3]' but socket.addr
+ # will return AF_INET6. At least this check will weed out clearly
+ # erroneous values.
+ @socket.addr[0].should =~ /^AF_INET6?/
+
+ case @socket.addr[0]
+ when 'AF_INET'
+ @socket.addr[3].should == SocketSpecs.addr(:ipv4)
+ when 'AF_INET6'
+ @socket.addr[3].should == SocketSpecs.addr(:ipv6)
+ end
+
+ @socket.addr[1].should be_kind_of(Fixnum)
+ @socket.addr[2].should =~ /^#{@hostname}/
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/udpsocket/bind_spec.rb b/spec/ruby/library/socket/udpsocket/bind_spec.rb
new file mode 100644
index 0000000000..bdc3c3d33f
--- /dev/null
+++ b/spec/ruby/library/socket/udpsocket/bind_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UDPSocket.bind" do
+
+ before :each do
+ @socket = UDPSocket.new
+ end
+
+ after :each do
+ @socket.close unless @socket.closed?
+ end
+
+ it "binds the socket to a port" do
+ @socket.bind(SocketSpecs.hostname, 0)
+ @socket.addr[1].should be_kind_of(Integer)
+ end
+
+ it "raises Errno::EINVAL when already bound" do
+ @socket.bind(SocketSpecs.hostname, 0)
+
+ lambda {
+ @socket.bind(SocketSpecs.hostname, @socket.addr[1])
+ }.should raise_error(Errno::EINVAL)
+ end
+
+ it "receives a hostname and a port" do
+ @socket.bind(SocketSpecs.hostname, 0)
+
+ port, host = Socket.unpack_sockaddr_in(@socket.getsockname)
+
+ host.should == "127.0.0.1"
+ port.should == @socket.addr[1]
+ end
+
+ it "binds to INADDR_ANY if the hostname is empty" do
+ @socket.bind("", 0)
+ port, host = Socket.unpack_sockaddr_in(@socket.getsockname)
+ host.should == "0.0.0.0"
+ port.should == @socket.addr[1]
+ end
+end
diff --git a/spec/ruby/library/socket/udpsocket/new_spec.rb b/spec/ruby/library/socket/udpsocket/new_spec.rb
new file mode 100644
index 0000000000..5a2e4e1f31
--- /dev/null
+++ b/spec/ruby/library/socket/udpsocket/new_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe 'UDPSocket.new' do
+ after :each do
+ @socket.close if @socket && !@socket.closed?
+ end
+
+ it 'without arguments' do
+ @socket = UDPSocket.new
+ @socket.should be_an_instance_of(UDPSocket)
+ end
+
+ it 'using Fixnum argument' do
+ @socket = UDPSocket.new(Socket::AF_INET)
+ @socket.should be_an_instance_of(UDPSocket)
+ end
+
+ it 'using Symbol argument' do
+ @socket = UDPSocket.new(:INET)
+ @socket.should be_an_instance_of(UDPSocket)
+ end
+
+ it 'using String argument' do
+ @socket = UDPSocket.new('INET')
+ @socket.should be_an_instance_of(UDPSocket)
+ end
+
+ it 'raises Errno::EAFNOSUPPORT if unsupported family passed' do
+ lambda { UDPSocket.new(-1) }.should raise_error(Errno::EAFNOSUPPORT)
+ end
+end
diff --git a/spec/ruby/library/socket/udpsocket/open_spec.rb b/spec/ruby/library/socket/udpsocket/open_spec.rb
new file mode 100644
index 0000000000..188f879ed1
--- /dev/null
+++ b/spec/ruby/library/socket/udpsocket/open_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UDPSocket.open" do
+ after :each do
+ @socket.close if @socket && !@socket.closed?
+ end
+
+ it "allows calls to open without arguments" do
+ @socket = UDPSocket.open
+ @socket.should be_kind_of(UDPSocket)
+ end
+end
diff --git a/spec/ruby/library/socket/udpsocket/send_spec.rb b/spec/ruby/library/socket/udpsocket/send_spec.rb
new file mode 100644
index 0000000000..1a6f44b26e
--- /dev/null
+++ b/spec/ruby/library/socket/udpsocket/send_spec.rb
@@ -0,0 +1,78 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UDPSocket.send" do
+ before :each do
+ @port = nil
+ @server_thread = Thread.new do
+ @server = UDPSocket.open
+ begin
+ @server.bind(nil, 0)
+ @port = @server.addr[1]
+ begin
+ @msg = @server.recvfrom_nonblock(64)
+ rescue IO::WaitReadable
+ IO.select([@server])
+ retry
+ end
+ ensure
+ @server.close if !@server.closed?
+ end
+ end
+ Thread.pass while @server_thread.status and !@port
+ end
+
+ after :each do
+ @server_thread.join
+ end
+
+ it "sends data in ad hoc mode" do
+ @socket = UDPSocket.open
+ @socket.send("ad hoc", 0, SocketSpecs.hostname, @port)
+ @socket.close
+ @server_thread.join
+
+ @msg[0].should == "ad hoc"
+ @msg[1][0].should == "AF_INET"
+ @msg[1][1].should be_kind_of(Fixnum)
+ @msg[1][3].should == "127.0.0.1"
+ end
+
+ it "sends data in ad hoc mode (with port given as a String)" do
+ @socket = UDPSocket.open
+ @socket.send("ad hoc", 0, SocketSpecs.hostname, @port.to_s)
+ @socket.close
+ @server_thread.join
+
+ @msg[0].should == "ad hoc"
+ @msg[1][0].should == "AF_INET"
+ @msg[1][1].should be_kind_of(Fixnum)
+ @msg[1][3].should == "127.0.0.1"
+ end
+
+ it "sends data in connection mode" do
+ @socket = UDPSocket.open
+ @socket.connect(SocketSpecs.hostname, @port)
+ @socket.send("connection-based", 0)
+ @socket.close
+ @server_thread.join
+
+ @msg[0].should == "connection-based"
+ @msg[1][0].should == "AF_INET"
+ @msg[1][1].should be_kind_of(Fixnum)
+ @msg[1][3].should == "127.0.0.1"
+ end
+
+ it "raises EMSGSIZE if data is too too big" do
+ @socket = UDPSocket.open
+ begin
+ lambda do
+ @socket.send('1' * 100_000, 0, SocketSpecs.hostname, @port.to_s)
+ end.should raise_error(Errno::EMSGSIZE)
+ ensure
+ @socket.send("ad hoc", 0, SocketSpecs.hostname, @port)
+ @socket.close
+ @server_thread.join
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/udpsocket/write_spec.rb b/spec/ruby/library/socket/udpsocket/write_spec.rb
new file mode 100644
index 0000000000..11e38bb470
--- /dev/null
+++ b/spec/ruby/library/socket/udpsocket/write_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UDPSocket#write" do
+ it "raises EMSGSIZE if msg is too long" do
+ begin
+ host = SocketSpecs.hostname
+ s1 = UDPSocket.new
+ s1.bind(host, 0)
+ s2 = UDPSocket.new
+ s2.connect(host, s1.addr[1])
+
+ lambda do
+ s2.write('1' * 100_000)
+ end.should raise_error(Errno::EMSGSIZE)
+ ensure
+ s1.close if s1 && !s1.closed?
+ s2.close if s2 && !s2.closed?
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb b/spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb
new file mode 100644
index 0000000000..b94e91e879
--- /dev/null
+++ b/spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXServer#accept_nonblock" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+
+ @socket = @server.accept_nonblock
+ @client.send("foobar", 0)
+ end
+
+ after :each do
+ @socket.close
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "accepts a connection in a non-blocking way" do
+ data = @socket.recvfrom(6).first
+ data.should == "foobar"
+ end
+
+ it "returns a UNIXSocket" do
+ @socket.should be_kind_of(UNIXSocket)
+ end
+
+ ruby_version_is '2.3' do
+ it 'returns :wait_readable in exceptionless mode' do
+ @server.accept_nonblock(exception: false).should == :wait_readable
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixserver/accept_spec.rb b/spec/ruby/library/socket/unixserver/accept_spec.rb
new file mode 100644
index 0000000000..90b22d7eb1
--- /dev/null
+++ b/spec/ruby/library/socket/unixserver/accept_spec.rb
@@ -0,0 +1,61 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is_not :windows do
+ describe "UNIXServer#accept" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ end
+
+ after :each do
+ @server.close if @server
+ SocketSpecs.rm_socket @path
+ end
+
+ it "accepts what is written by the client" do
+ client = UNIXSocket.open(@path)
+
+ client.send('hello', 0)
+
+ sock = @server.accept
+ begin
+ data, info = sock.recvfrom(5)
+
+ data.should == 'hello'
+ info.should_not be_empty
+ ensure
+ sock.close
+ client.close
+ end
+ end
+
+ it "can be interrupted by Thread#kill" do
+ t = Thread.new {
+ @server.accept
+ }
+ Thread.pass while t.status and t.status != "sleep"
+
+ # kill thread, ensure it dies in a reasonable amount of time
+ t.kill
+ a = 0
+ while t.alive? and a < 5000
+ sleep 0.001
+ a += 1
+ end
+ a.should < 5000
+ end
+
+ it "can be interrupted by Thread#raise" do
+ t = Thread.new {
+ @server.accept
+ }
+ Thread.pass while t.status and t.status != "sleep"
+
+ # raise in thread, ensure the raise happens
+ ex = Exception.new
+ t.raise ex
+ lambda { t.join }.should raise_error(Exception)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixserver/for_fd_spec.rb b/spec/ruby/library/socket/unixserver/for_fd_spec.rb
new file mode 100644
index 0000000000..c3cfd86a1c
--- /dev/null
+++ b/spec/ruby/library/socket/unixserver/for_fd_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is_not :windows do
+ describe "UNIXServer#for_fd" do
+ before :each do
+ @unix_path = SocketSpecs.socket_path
+ @unix = UNIXServer.new(@unix_path)
+ end
+
+ after :each do
+ @unix.close if @unix
+ SocketSpecs.rm_socket @unix_path
+ end
+
+ it "can calculate the path" do
+ b = UNIXServer.for_fd(@unix.fileno)
+ b.autoclose = false
+
+ b.path.should == @unix_path
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixserver/new_spec.rb b/spec/ruby/library/socket/unixserver/new_spec.rb
new file mode 100644
index 0000000000..d34aa0ca03
--- /dev/null
+++ b/spec/ruby/library/socket/unixserver/new_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new', __FILE__)
+
+describe "UNIXServer.new" do
+ it_behaves_like :unixserver_new, :new
+end
diff --git a/spec/ruby/library/socket/unixserver/open_spec.rb b/spec/ruby/library/socket/unixserver/open_spec.rb
new file mode 100644
index 0000000000..47c76eb9b4
--- /dev/null
+++ b/spec/ruby/library/socket/unixserver/open_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new', __FILE__)
+
+describe "UNIXServer.open" do
+ it_behaves_like :unixserver_new, :open
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ end
+
+ after :each do
+ @server.close if @server
+ @server = nil
+ SocketSpecs.rm_socket @path
+ end
+
+ it "yields the new UNIXServer object to the block, if given" do
+ UNIXServer.open(@path) do |unix|
+ unix.path.should == @path
+ unix.addr.should == ["AF_UNIX", @path]
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixserver/shared/new.rb b/spec/ruby/library/socket/unixserver/shared/new.rb
new file mode 100644
index 0000000000..2018140caa
--- /dev/null
+++ b/spec/ruby/library/socket/unixserver/shared/new.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/classes', __FILE__)
+require 'tempfile'
+
+describe :unixserver_new, shared: true do
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ end
+
+ after :each do
+ @server.close if @server
+ @server = nil
+ SocketSpecs.rm_socket @path
+ end
+
+ it "creates a new UNIXServer" do
+ @server = UNIXServer.send(@method, @path)
+ @server.path.should == @path
+ @server.addr.should == ["AF_UNIX", @path]
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixsocket/addr_spec.rb b/spec/ruby/library/socket/unixsocket/addr_spec.rb
new file mode 100644
index 0000000000..34c62e083f
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/addr_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#addr" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
+
+ after :each do
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "returns the address family of this socket in an array" do
+ @client.addr[0].should == "AF_UNIX"
+ end
+
+ it "returns the path of the socket in an array if it's a server" do
+ @server.addr[1].should == @path
+ end
+
+ it "returns an empty string for path if it's a client" do
+ @client.addr[1].should == ""
+ end
+
+ it "returns an array" do
+ @client.addr.should be_kind_of(Array)
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/unixsocket/inspect_spec.rb b/spec/ruby/library/socket/unixsocket/inspect_spec.rb
new file mode 100644
index 0000000000..8ea25ec1e9
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/inspect_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#inspect" do
+ platform_is_not :windows do
+ it "returns sockets fd for unnamed sockets" do
+ begin
+ s1, s2 = UNIXSocket.socketpair
+ s1.inspect.should == "#<UNIXSocket:fd #{s1.fileno}>"
+ s2.inspect.should == "#<UNIXSocket:fd #{s2.fileno}>"
+ ensure
+ s1.close
+ s2.close
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixsocket/new_spec.rb b/spec/ruby/library/socket/unixsocket/new_spec.rb
new file mode 100644
index 0000000000..7db8613b96
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/new_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new', __FILE__)
+
+describe "UNIXSocket.new" do
+ it_behaves_like :unixsocket_new, :new
+end
diff --git a/spec/ruby/library/socket/unixsocket/open_spec.rb b/spec/ruby/library/socket/unixsocket/open_spec.rb
new file mode 100644
index 0000000000..5b9b19ee33
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/open_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new', __FILE__)
+
+describe "UNIXSocket.open" do
+ it_behaves_like :unixsocket_new, :open
+end
+
+describe "UNIXSocket.open" do
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ end
+
+ after :each do
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "opens a unix socket on the specified file and yields it to the block" do
+ UNIXSocket.send(@method, @path) do |client|
+ client.addr[0].should == "AF_UNIX"
+ client.closed?.should == false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixsocket/pair_spec.rb b/spec/ruby/library/socket/unixsocket/pair_spec.rb
new file mode 100644
index 0000000000..5cd75e2906
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/pair_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/partially_closable_sockets', __FILE__)
+
+describe "UNIXSocket#pair" do
+ platform_is_not :windows do
+
+ it_should_behave_like "partially closable sockets"
+
+ before :each do
+ @s1, @s2 = UNIXSocket.pair
+ end
+
+ after :each do
+ @s1.close
+ @s2.close
+ end
+
+ it "returns a pair of connected sockets" do
+ @s1.puts "foo"
+ @s2.gets.should == "foo\n"
+ end
+
+ it "returns sockets with no name" do
+ @s1.path.should == @s2.path
+ @s1.path.should == ""
+ end
+
+ it "returns sockets with no address" do
+ @s1.addr.should == ["AF_UNIX", ""]
+ @s2.addr.should == ["AF_UNIX", ""]
+ end
+
+ it "returns sockets with no peeraddr" do
+ @s1.peeraddr.should == ["AF_UNIX", ""]
+ @s2.peeraddr.should == ["AF_UNIX", ""]
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb b/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb
new file mode 100644
index 0000000000..f43274db2e
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/partially_closable_sockets', __FILE__)
+
+platform_is_not :windows do
+ describe "UNIXSocket partial closability" do
+
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @s1 = UNIXSocket.new(@path)
+ @s2 = @server.accept
+ end
+
+ after :each do
+ @server.close
+ @s1.close
+ @s2.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it_should_behave_like "partially closable sockets"
+
+ end
+end
diff --git a/spec/ruby/library/socket/unixsocket/path_spec.rb b/spec/ruby/library/socket/unixsocket/path_spec.rb
new file mode 100644
index 0000000000..a2beaffeea
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/path_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#path" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
+
+ after :each do
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "returns the path of the socket if it's a server" do
+ @server.path.should == @path
+ end
+
+ it "returns an empty string for path if it's a client" do
+ @client.path.should == ""
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb b/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb
new file mode 100644
index 0000000000..14dccf7917
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#peeraddr" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
+
+ after :each do
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "returns the address familly and path of the server end of the connection" do
+ @client.peeraddr.should == ["AF_UNIX", @path]
+ end
+
+ it "raises an error in server sockets" do
+ lambda { @server.peeraddr }.should raise_error
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/unixsocket/recv_io_spec.rb b/spec/ruby/library/socket/unixsocket/recv_io_spec.rb
new file mode 100644
index 0000000000..c7a8946ceb
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/recv_io_spec.rb
@@ -0,0 +1,44 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#recv_io" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+
+ @send_io_path = File.expand_path('../../fixtures/send_io.txt', __FILE__)
+ @file = File.open(@send_io_path)
+ end
+
+ after :each do
+ @io.close if @io
+ @socket.close if @socket
+
+ @file.close
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "reads an IO object across the socket" do
+ @client.send_io(@file)
+
+ @socket = @server.accept
+ @io = @socket.recv_io
+
+ @io.read.should == File.read(@send_io_path)
+ end
+
+ it "takes an optional class to use" do
+ @client.send_io(@file)
+
+ @socket = @server.accept
+ @io = @socket.recv_io(File)
+
+ @io.should be_kind_of(File)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb b/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb
new file mode 100644
index 0000000000..78e272bfe2
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb
@@ -0,0 +1,47 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#recvfrom" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
+
+ after :each do
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "receives len bytes from sock" do
+ @client.send("foobar", 0)
+ sock = @server.accept
+ sock.recvfrom(6).first.should == "foobar"
+ sock.close
+ end
+
+ it "returns an array with data and information on the sender" do
+ @client.send("foobar", 0)
+ sock = @server.accept
+ data = sock.recvfrom(6)
+ data.first.should == "foobar"
+ data.last.should == ["AF_UNIX", ""]
+ sock.close
+ end
+
+ it "uses different message options" do
+ @client.send("foobar", Socket::MSG_PEEK)
+ sock = @server.accept
+ peek_data = sock.recvfrom(6, Socket::MSG_PEEK) # Does not retrieve the message
+ real_data = sock.recvfrom(6)
+
+ real_data.should == peek_data
+ peek_data.should == ["foobar", ["AF_UNIX", ""]]
+ sock.close
+ end
+ end
+
+end
diff --git a/spec/ruby/library/socket/unixsocket/send_io_spec.rb b/spec/ruby/library/socket/unixsocket/send_io_spec.rb
new file mode 100644
index 0000000000..ec8d6b2314
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/send_io_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#send_io" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+
+ @send_io_path = File.expand_path('../../fixtures/send_io.txt', __FILE__)
+ @file = File.open(@send_io_path)
+ end
+
+ after :each do
+ @io.close if @io
+ @socket.close if @socket
+
+ @file.close
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "sends the fd for an IO object across the socket" do
+ @client.send_io(@file)
+
+ @socket = @server.accept
+ @io = @socket.recv_io
+
+ @io.read.should == File.read(@send_io_path)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixsocket/shared/new.rb b/spec/ruby/library/socket/unixsocket/shared/new.rb
new file mode 100644
index 0000000000..76c0d07b83
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/shared/new.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/classes', __FILE__)
+
+describe :unixsocket_new, shared: true do
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ end
+
+ after :each do
+ @client.close if @client
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "opens a unix socket on the specified file" do
+ @client = UNIXSocket.send(@method, @path)
+
+ @client.addr[0].should == "AF_UNIX"
+ @client.closed?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/append_spec.rb b/spec/ruby/library/stringio/append_spec.rb
new file mode 100644
index 0000000000..ff0dc233cd
--- /dev/null
+++ b/spec/ruby/library/stringio/append_spec.rb
@@ -0,0 +1,84 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#<< when passed [Object]" do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "returns self" do
+ (@io << "just testing").should equal(@io)
+ end
+
+ it "writes the passed argument onto self" do
+ (@io << "just testing")
+ @io.string.should == "just testing"
+ (@io << " and more testing")
+ @io.string.should == "just testing and more testing"
+ end
+
+ it "writes the passed argument at the current position" do
+ @io.pos = 5
+ @io << "<test>"
+ @io.string.should == "examp<test>"
+ end
+
+ it "pads self with \\000 when the current position is after the end" do
+ @io.pos = 15
+ @io << "just testing"
+ @io.string.should == "example\000\000\000\000\000\000\000\000just testing"
+ end
+
+ it "taints self's String when the passed argument is tainted" do
+ (@io << "test".taint)
+ @io.string.tainted?.should be_true
+ end
+
+ it "does not taint self when the passed argument is tainted" do
+ (@io << "test".taint)
+ @io.tainted?.should be_false
+ end
+
+ it "updates self's position" do
+ @io << "test"
+ @io.pos.should eql(4)
+ end
+
+ it "tries to convert the passed argument to a String using #to_s" do
+ obj = mock("to_s")
+ obj.should_receive(:to_s).and_return("Test")
+
+ (@io << obj).string.should == "Testple"
+ end
+end
+
+describe "StringIO#<< when self is not writable" do
+ it "raises an IOError" do
+ io = StringIO.new("test", "r")
+ lambda { io << "test" }.should raise_error(IOError)
+
+ io = StringIO.new("test")
+ io.close_write
+ lambda { io << "test" }.should raise_error(IOError)
+ end
+end
+
+describe "StringIO#<< when in append mode" do
+ before :each do
+ @io = StringIO.new("example", "a")
+ end
+
+ it "appends the passed argument to the end of self, ignoring current position" do
+ (@io << ", just testing")
+ @io.string.should == "example, just testing"
+
+ @io.pos = 3
+ (@io << " and more testing")
+ @io.string.should == "example, just testing and more testing"
+ end
+
+ it "correctly updates self's position" do
+ @io << ", testing"
+ @io.pos.should eql(16)
+ end
+end
diff --git a/spec/ruby/library/stringio/binmode_spec.rb b/spec/ruby/library/stringio/binmode_spec.rb
new file mode 100644
index 0000000000..11fbbaadeb
--- /dev/null
+++ b/spec/ruby/library/stringio/binmode_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#binmode" do
+ it "returns self" do
+ io = StringIO.new("example")
+ io.binmode.should equal(io)
+ end
+end
diff --git a/spec/ruby/library/stringio/bytes_spec.rb b/spec/ruby/library/stringio/bytes_spec.rb
new file mode 100644
index 0000000000..22d990dff7
--- /dev/null
+++ b/spec/ruby/library/stringio/bytes_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/each_byte', __FILE__)
+
+describe "StringIO#bytes" do
+ it_behaves_like :stringio_each_byte, :bytes
+end
+
+describe "StringIO#bytes when self is not readable" do
+ it_behaves_like :stringio_each_byte_not_readable, :bytes
+end
diff --git a/spec/ruby/library/stringio/chars_spec.rb b/spec/ruby/library/stringio/chars_spec.rb
new file mode 100644
index 0000000000..c5ffde23db
--- /dev/null
+++ b/spec/ruby/library/stringio/chars_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/each_char', __FILE__)
+
+describe "StringIO#chars" do
+ it_behaves_like :stringio_each_char, :chars
+end
+
+describe "StringIO#chars when self is not readable" do
+ it_behaves_like :stringio_each_char_not_readable, :chars
+end
diff --git a/spec/ruby/library/stringio/close_read_spec.rb b/spec/ruby/library/stringio/close_read_spec.rb
new file mode 100644
index 0000000000..59e16385d2
--- /dev/null
+++ b/spec/ruby/library/stringio/close_read_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#close_read" do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "returns nil" do
+ @io.close_read.should be_nil
+ end
+
+ it "prevents further reading" do
+ @io.close_read
+ lambda { @io.read(1) }.should raise_error(IOError)
+ end
+
+ it "allows further writing" do
+ @io.close_read
+ @io.write("x").should == 1
+ end
+
+ it "raises an IOError when in write-only mode" do
+ io = StringIO.new("example", "w")
+ lambda { io.close_read }.should raise_error(IOError)
+
+ io = StringIO.new("example")
+ io.close_read
+ ruby_version_is ''...'2.3' do
+ lambda { io.close_read }.should raise_error(IOError)
+ end
+ ruby_version_is '2.3' do
+ io.close_read.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/close_spec.rb b/spec/ruby/library/stringio/close_spec.rb
new file mode 100644
index 0000000000..423aad4bd1
--- /dev/null
+++ b/spec/ruby/library/stringio/close_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#close" do
+ before :each do
+ @io = StringIOSpecs.build
+ end
+
+ it "returns nil" do
+ @io.close.should be_nil
+ end
+
+ it "prevents further reading and/or writing" do
+ @io.close
+ lambda { @io.read(1) }.should raise_error(IOError)
+ lambda { @io.write('x') }.should raise_error(IOError)
+ end
+
+ ruby_version_is ''...'2.3' do
+ it "raises an IOError when self was already closed" do
+ @io.close
+ lambda { @io.close }.should raise_error(IOError)
+ end
+ end
+
+ ruby_version_is "2.3" do
+ it "does not raise anything when self was already closed" do
+ @io.close
+ lambda { @io.close }.should_not raise_error(IOError)
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/close_write_spec.rb b/spec/ruby/library/stringio/close_write_spec.rb
new file mode 100644
index 0000000000..6637fe6043
--- /dev/null
+++ b/spec/ruby/library/stringio/close_write_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#close_write" do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "returns nil" do
+ @io.close_write.should be_nil
+ end
+
+ it "prevents further writing" do
+ @io.close_write
+ lambda { @io.write('x') }.should raise_error(IOError)
+ end
+
+ it "allows further reading" do
+ @io.close_write
+ @io.read(1).should == 'e'
+ end
+
+ it "raises an IOError when in read-only mode" do
+ io = StringIO.new("example", "r")
+ lambda { io.close_write }.should raise_error(IOError)
+
+ io = StringIO.new("example")
+ io.close_write
+ ruby_version_is ''...'2.3' do
+ lambda { io.close_write }.should raise_error(IOError)
+ end
+ ruby_version_is '2.3' do
+ io.close_write.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/closed_read_spec.rb b/spec/ruby/library/stringio/closed_read_spec.rb
new file mode 100644
index 0000000000..971eb5f71c
--- /dev/null
+++ b/spec/ruby/library/stringio/closed_read_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#closed_read?" do
+ it "returns true if self is not readable" do
+ io = StringIO.new("example", "r+")
+ io.close_write
+ io.closed_read?.should be_false
+ io.close_read
+ io.closed_read?.should be_true
+ end
+end
diff --git a/spec/ruby/library/stringio/closed_spec.rb b/spec/ruby/library/stringio/closed_spec.rb
new file mode 100644
index 0000000000..4026d78775
--- /dev/null
+++ b/spec/ruby/library/stringio/closed_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#closed?" do
+ it "returns true if self is completely closed" do
+ io = StringIO.new("example", "r+")
+ io.close_read
+ io.closed?.should be_false
+ io.close_write
+ io.closed?.should be_true
+
+ io = StringIO.new("example", "r+")
+ io.close
+ io.closed?.should be_true
+ end
+end
diff --git a/spec/ruby/library/stringio/closed_write_spec.rb b/spec/ruby/library/stringio/closed_write_spec.rb
new file mode 100644
index 0000000000..52707aa240
--- /dev/null
+++ b/spec/ruby/library/stringio/closed_write_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#closed_write?" do
+ it "returns true if self is not writable" do
+ io = StringIO.new("example", "r+")
+ io.close_read
+ io.closed_write?.should be_false
+ io.close_write
+ io.closed_write?.should be_true
+ end
+end
diff --git a/spec/ruby/library/stringio/codepoints_spec.rb b/spec/ruby/library/stringio/codepoints_spec.rb
new file mode 100644
index 0000000000..098bd3c4c3
--- /dev/null
+++ b/spec/ruby/library/stringio/codepoints_spec.rb
@@ -0,0 +1,9 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/codepoints', __FILE__)
+
+# See redmine #1667
+describe "StringIO#codepoints" do
+ it_behaves_like(:stringio_codepoints, :codepoints)
+end
diff --git a/spec/ruby/library/stringio/each_byte_spec.rb b/spec/ruby/library/stringio/each_byte_spec.rb
new file mode 100644
index 0000000000..8e88997bc0
--- /dev/null
+++ b/spec/ruby/library/stringio/each_byte_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/each_byte', __FILE__)
+
+describe "StringIO#each_byte" do
+ it_behaves_like :stringio_each_byte, :each_byte
+end
+
+describe "StringIO#each_byte when self is not readable" do
+ it_behaves_like :stringio_each_byte_not_readable, :each_byte
+end
diff --git a/spec/ruby/library/stringio/each_char_spec.rb b/spec/ruby/library/stringio/each_char_spec.rb
new file mode 100644
index 0000000000..a141ae03fe
--- /dev/null
+++ b/spec/ruby/library/stringio/each_char_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/each_char', __FILE__)
+
+describe "StringIO#each_char" do
+ it_behaves_like :stringio_each_char, :each_char
+end
+
+describe "StringIO#each_char when self is not readable" do
+ it_behaves_like :stringio_each_char_not_readable, :chars
+end
diff --git a/spec/ruby/library/stringio/each_codepoint_spec.rb b/spec/ruby/library/stringio/each_codepoint_spec.rb
new file mode 100644
index 0000000000..25a0bf4c81
--- /dev/null
+++ b/spec/ruby/library/stringio/each_codepoint_spec.rb
@@ -0,0 +1,10 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/codepoints', __FILE__)
+
+# See redmine #1667
+describe "StringIO#each_codepoint" do
+ it_behaves_like(:stringio_codepoints, :codepoints)
+end
+
diff --git a/spec/ruby/library/stringio/each_line_spec.rb b/spec/ruby/library/stringio/each_line_spec.rb
new file mode 100644
index 0000000000..e4deb9b3e9
--- /dev/null
+++ b/spec/ruby/library/stringio/each_line_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/each', __FILE__)
+
+describe "StringIO#each_line when passed a separator" do
+ it_behaves_like :stringio_each_separator, :each_line
+end
+
+describe "StringIO#each_line when passed no arguments" do
+ it_behaves_like :stringio_each_no_arguments, :each_line
+end
+
+describe "StringIO#each_line when self is not readable" do
+ it_behaves_like :stringio_each_not_readable, :each_line
+end
diff --git a/spec/ruby/library/stringio/each_spec.rb b/spec/ruby/library/stringio/each_spec.rb
new file mode 100644
index 0000000000..07ad070192
--- /dev/null
+++ b/spec/ruby/library/stringio/each_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/each', __FILE__)
+
+describe "StringIO#each when passed a separator" do
+ it_behaves_like :stringio_each_separator, :each
+end
+
+describe "StringIO#each when passed no arguments" do
+ it_behaves_like :stringio_each_no_arguments, :each
+end
+
+describe "StringIO#each when self is not readable" do
+ it_behaves_like :stringio_each_not_readable, :each
+end
diff --git a/spec/ruby/library/stringio/eof_spec.rb b/spec/ruby/library/stringio/eof_spec.rb
new file mode 100644
index 0000000000..a5bb3dbe3d
--- /dev/null
+++ b/spec/ruby/library/stringio/eof_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/eof', __FILE__)
+
+describe "StringIO#eof?" do
+ it_behaves_like :stringio_eof, :eof?
+end
+
+describe "StringIO#eof" do
+ it_behaves_like :stringio_eof, :eof
+end
diff --git a/spec/ruby/library/stringio/external_encoding_spec.rb b/spec/ruby/library/stringio/external_encoding_spec.rb
new file mode 100644
index 0000000000..9bf2d8ee8c
--- /dev/null
+++ b/spec/ruby/library/stringio/external_encoding_spec.rb
@@ -0,0 +1,21 @@
+require 'stringio'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "StringIO#external_encoding" do
+ it "gets the encoding of the underlying String" do
+ io = StringIO.new
+ io.set_encoding Encoding::EUC_JP
+ io.external_encoding.should == Encoding::EUC_JP
+ end
+
+ ruby_version_is "2.3" do
+ it "does not set the encoding of its buffer string if the string is frozen" do
+ str = "foo".freeze
+ enc = str.encoding
+ io = StringIO.new(str)
+ io.set_encoding Encoding::EUC_JP
+ io.external_encoding.should == Encoding::EUC_JP
+ str.encoding.should == enc
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/fcntl_spec.rb b/spec/ruby/library/stringio/fcntl_spec.rb
new file mode 100644
index 0000000000..5250359a79
--- /dev/null
+++ b/spec/ruby/library/stringio/fcntl_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#fcntl" do
+ it "raises a NotImplementedError" do
+ lambda { StringIO.new("boom").fcntl }.should raise_error(NotImplementedError)
+ end
+end
diff --git a/spec/ruby/library/stringio/fileno_spec.rb b/spec/ruby/library/stringio/fileno_spec.rb
new file mode 100644
index 0000000000..a5ae820830
--- /dev/null
+++ b/spec/ruby/library/stringio/fileno_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/each', __FILE__)
+
+describe "StringIO#fileno" do
+ it "returns nil" do
+ StringIO.new("nuffin").fileno.should be_nil
+ end
+end
diff --git a/spec/ruby/library/stringio/fixtures/classes.rb b/spec/ruby/library/stringio/fixtures/classes.rb
new file mode 100644
index 0000000000..bb8dc354cc
--- /dev/null
+++ b/spec/ruby/library/stringio/fixtures/classes.rb
@@ -0,0 +1,15 @@
+require 'stringio'
+
+class StringSubclass < String; end
+
+module StringIOSpecs
+ def self.build
+ str = <<-EOS
+ each
+ peach
+ pear
+ plum
+ EOS
+ StringIO.new(str)
+ end
+end
diff --git a/spec/ruby/library/stringio/flush_spec.rb b/spec/ruby/library/stringio/flush_spec.rb
new file mode 100644
index 0000000000..75a92db85a
--- /dev/null
+++ b/spec/ruby/library/stringio/flush_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#flush" do
+ it "returns self" do
+ io = StringIO.new("flush")
+ io.flush.should equal(io)
+ end
+end
diff --git a/spec/ruby/library/stringio/fsync_spec.rb b/spec/ruby/library/stringio/fsync_spec.rb
new file mode 100644
index 0000000000..509f4a972f
--- /dev/null
+++ b/spec/ruby/library/stringio/fsync_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#fsync" do
+ it "returns zero" do
+ io = StringIO.new("fsync")
+ io.fsync.should eql(0)
+ end
+end
diff --git a/spec/ruby/library/stringio/getbyte_spec.rb b/spec/ruby/library/stringio/getbyte_spec.rb
new file mode 100644
index 0000000000..163cb9d0c6
--- /dev/null
+++ b/spec/ruby/library/stringio/getbyte_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/getc', __FILE__)
+
+describe "StringIO#getbyte" do
+ it_behaves_like :stringio_getc, :getbyte
+
+ it "returns the 8-bit byte at the current position" do
+ io = StringIO.new("example")
+
+ io.send(@method).should == 101
+ io.send(@method).should == 120
+ io.send(@method).should == 97
+ end
+end
+
+describe "StringIO#getbyte when self is not readable" do
+ it_behaves_like :stringio_getc_not_readable, :getbyte
+end
diff --git a/spec/ruby/library/stringio/getc_spec.rb b/spec/ruby/library/stringio/getc_spec.rb
new file mode 100644
index 0000000000..f7e98d2a33
--- /dev/null
+++ b/spec/ruby/library/stringio/getc_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/getc', __FILE__)
+
+describe "StringIO#getc" do
+ it_behaves_like :stringio_getc, :getc
+
+ it "returns the charactor at the current position" do
+ io = StringIO.new("example")
+
+ io.send(@method).should == ?e
+ io.send(@method).should == ?x
+ io.send(@method).should == ?a
+ end
+end
+
+describe "StringIO#getc when self is not readable" do
+ it_behaves_like :stringio_getc_not_readable, :getc
+end
diff --git a/spec/ruby/library/stringio/getch_spec.rb b/spec/ruby/library/stringio/getch_spec.rb
new file mode 100644
index 0000000000..c7fdfe9080
--- /dev/null
+++ b/spec/ruby/library/stringio/getch_spec.rb
@@ -0,0 +1,46 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/getc', __FILE__)
+
+# This method is added by io/console on require.
+describe "StringIO#getch" do
+ require 'io/console'
+
+ it_behaves_like :stringio_getc, :getch
+
+ it "returns the charactor at the current position" do
+ io = StringIO.new("example")
+
+ io.send(@method).should == ?e
+ io.send(@method).should == ?x
+ io.send(@method).should == ?a
+ end
+
+ with_feature :encoding do
+ it "increments #pos by the byte size of the character in multibyte strings" do
+ io = StringIO.new("föóbar")
+
+ io.send(@method); io.pos.should == 1 # "f" has byte size 1
+ io.send(@method); io.pos.should == 3 # "ö" has byte size 2
+ io.send(@method); io.pos.should == 5 # "ó" has byte size 2
+ io.send(@method); io.pos.should == 6 # "b" has byte size 1
+ end
+ end
+
+ it "returns nil at the end of the string" do
+ # empty string case
+ io = StringIO.new("")
+ io.send(@method).should == nil
+ io.send(@method).should == nil
+
+ # non-empty string case
+ io = StringIO.new("a")
+ io.send(@method) # skip one
+ io.send(@method).should == nil
+ end
+
+ describe "StringIO#getch when self is not readable" do
+ it_behaves_like :stringio_getc_not_readable, :getch
+ end
+end
diff --git a/spec/ruby/library/stringio/gets_spec.rb b/spec/ruby/library/stringio/gets_spec.rb
new file mode 100644
index 0000000000..307f564a6e
--- /dev/null
+++ b/spec/ruby/library/stringio/gets_spec.rb
@@ -0,0 +1,238 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "stringio"
+
+describe "StringIO#gets when passed [separator]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read till the next occurence of the passed separator" do
+ @io.gets(">").should == "this>"
+ @io.gets(">").should == "is>"
+ @io.gets(">").should == "an>"
+ @io.gets(">").should == "example"
+ end
+
+ it "sets $_ to the read content" do
+ @io.gets(">")
+ $_.should == "this>"
+ @io.gets(">")
+ $_.should == "is>"
+ @io.gets(">")
+ $_.should == "an>"
+ @io.gets(">")
+ $_.should == "example"
+ @io.gets(">")
+ $_.should be_nil
+ end
+
+ it "accepts string as separator" do
+ @io.gets("is>")
+ $_.should == "this>"
+ @io.gets("an>")
+ $_.should == "is>an>"
+ @io.gets("example")
+ $_.should == "example"
+ @io.gets("ple")
+ $_.should be_nil
+ end
+
+ it "updates self's lineno by one" do
+ @io.gets(">")
+ @io.lineno.should eql(1)
+
+ @io.gets(">")
+ @io.lineno.should eql(2)
+
+ @io.gets(">")
+ @io.lineno.should eql(3)
+ end
+
+ it "returns the next paragraph when the passed separator is an empty String" do
+ io = StringIO.new("this is\n\nan example")
+ io.gets("").should == "this is\n\n"
+ io.gets("").should == "an example"
+ end
+
+ it "returns the remaining content starting at the current position when passed nil" do
+ io = StringIO.new("this is\n\nan example")
+ io.pos = 5
+ io.gets(nil).should == "is\n\nan example"
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return(">")
+ @io.gets(obj).should == "this>"
+ end
+end
+
+describe "StringIO#gets when passed no argument" do
+ before :each do
+ @io = StringIO.new("this is\nan example\nfor StringIO#gets")
+ end
+
+ it "returns the data read till the next occurence of $/ or till eof" do
+ @io.gets.should == "this is\n"
+
+ begin
+ old_sep, $/ = $/, " "
+ @io.gets.should == "an "
+ @io.gets.should == "example\nfor "
+ @io.gets.should == "StringIO#gets"
+ ensure
+ $/ = old_sep
+ end
+ end
+
+ it "sets $_ to the read content" do
+ @io.gets
+ $_.should == "this is\n"
+ @io.gets
+ $_.should == "an example\n"
+ @io.gets
+ $_.should == "for StringIO#gets"
+ @io.gets
+ $_.should be_nil
+ end
+
+ it "updates self's position" do
+ @io.gets
+ @io.pos.should eql(8)
+
+ @io.gets
+ @io.pos.should eql(19)
+
+ @io.gets
+ @io.pos.should eql(36)
+ end
+
+ it "updates self's lineno" do
+ @io.gets
+ @io.lineno.should eql(1)
+
+ @io.gets
+ @io.lineno.should eql(2)
+
+ @io.gets
+ @io.lineno.should eql(3)
+ end
+
+ it "returns nil if self is at the end" do
+ @io.pos = 36
+ @io.gets.should be_nil
+ @io.gets.should be_nil
+ end
+end
+
+describe "StringIO#gets when passed [limit]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read until the limit is met" do
+ @io.gets(4).should == "this"
+ @io.gets(3).should == ">is"
+ @io.gets(5).should == ">an>e"
+ @io.gets(6).should == "xample"
+ end
+
+ it "sets $_ to the read content" do
+ @io.gets(4)
+ $_.should == "this"
+ @io.gets(3)
+ $_.should == ">is"
+ @io.gets(5)
+ $_.should == ">an>e"
+ @io.gets(6)
+ $_.should == "xample"
+ @io.gets(3)
+ $_.should be_nil
+ end
+
+ it "updates self's lineno by one" do
+ @io.gets(3)
+ @io.lineno.should eql(1)
+
+ @io.gets(3)
+ @io.lineno.should eql(2)
+
+ @io.gets(3)
+ @io.lineno.should eql(3)
+ end
+
+ it "tries to convert the passed limit to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(4)
+ @io.gets(obj).should == "this"
+ end
+
+ it "returns a blank string when passed a limit of 0" do
+ @io.gets(0).should == ""
+ end
+end
+
+describe "StringIO#gets when passed [separator] and [limit]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read until the limit is consumed or the separator is met" do
+ @io.gets('>', 8).should == "this>"
+ @io.gets('>', 2).should == "is"
+ @io.gets('>', 10).should == ">"
+ @io.gets('>', 6).should == "an>"
+ @io.gets('>', 5).should == "examp"
+ end
+
+ it "sets $_ to the read content" do
+ @io.gets('>', 8)
+ $_.should == "this>"
+ @io.gets('>', 2)
+ $_.should == "is"
+ @io.gets('>', 10)
+ $_.should == ">"
+ @io.gets('>', 6)
+ $_.should == "an>"
+ @io.gets('>', 5)
+ $_.should == "examp"
+ end
+
+ it "updates self's lineno by one" do
+ @io.gets('>', 3)
+ @io.lineno.should eql(1)
+
+ @io.gets('>', 3)
+ @io.lineno.should eql(2)
+
+ @io.gets('>', 3)
+ @io.lineno.should eql(3)
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return('>')
+ @io.gets(obj, 5).should == "this>"
+ end
+
+ it "does not raise TypeError if passed separator is nil" do
+ @io.gets(nil, 5).should == "this>"
+ end
+
+ it "tries to convert the passed limit to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(5)
+ @io.gets('>', obj).should == "this>"
+ end
+end
+
+describe "StringIO#gets when in write-only mode" do
+ it "raises an IOError" do
+ io = StringIO.new("xyz", "w")
+ lambda { io.gets }.should raise_error(IOError)
+
+ io = StringIO.new("xyz")
+ io.close_read
+ lambda { io.gets }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/initialize_spec.rb b/spec/ruby/library/stringio/initialize_spec.rb
new file mode 100644
index 0000000000..8b661a3790
--- /dev/null
+++ b/spec/ruby/library/stringio/initialize_spec.rb
@@ -0,0 +1,185 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+
+describe "StringIO#initialize when passed [Object, mode]" do
+ before :each do
+ @io = StringIO.allocate
+ end
+
+ it "uses the passed Object as the StringIO backend" do
+ @io.send(:initialize, str = "example", "r")
+ @io.string.should equal(str)
+ end
+
+ it "sets the mode based on the passed mode" do
+ io = StringIO.allocate
+ io.send(:initialize, "example", "r")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "rb")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "r+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "rb+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "w")
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "wb")
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "w+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "wb+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "a")
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "ab")
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "a+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", "ab+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+ end
+
+ it "allows passing the mode as an Integer" do
+ io = StringIO.allocate
+ io.send(:initialize, "example", IO::RDONLY)
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", IO::RDWR)
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", IO::WRONLY)
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", IO::WRONLY | IO::TRUNC)
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", IO::RDWR | IO::TRUNC)
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", IO::WRONLY | IO::APPEND)
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.allocate
+ io.send(:initialize, "example", IO::RDWR | IO::APPEND)
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+ end
+
+ it "raises a RuntimeError when passed a frozen String in truncate mode as StringIO backend" do
+ io = StringIO.allocate
+ lambda { io.send(:initialize, "example".freeze, IO::TRUNC) }.should raise_error(RuntimeError)
+ end
+
+ it "tries to convert the passed mode to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return("r")
+ @io.send(:initialize, "example", obj)
+
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_true
+ end
+
+ it "raises an Errno::EACCES error when passed a frozen string with a write-mode" do
+ (str = "example").freeze
+ lambda { @io.send(:initialize, str, "r+") }.should raise_error(Errno::EACCES)
+ lambda { @io.send(:initialize, str, "w") }.should raise_error(Errno::EACCES)
+ lambda { @io.send(:initialize, str, "a") }.should raise_error(Errno::EACCES)
+ end
+end
+
+describe "StringIO#initialize when passed [Object]" do
+ before :each do
+ @io = StringIO.allocate
+ end
+
+ it "uses the passed Object as the StringIO backend" do
+ @io.send(:initialize, str = "example")
+ @io.string.should equal(str)
+ end
+
+ it "sets the mode to read-write" do
+ @io.send(:initialize, "example")
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_false
+ end
+
+ it "tries to convert the passed Object to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return("example")
+ @io.send(:initialize, obj)
+ @io.string.should == "example"
+ end
+
+ it "automatically sets the mode to read-only when passed a frozen string" do
+ (str = "example").freeze
+ @io.send(:initialize, str)
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_true
+ end
+end
+
+describe "StringIO#initialize when passed no arguments" do
+ before :each do
+ @io = StringIO.allocate
+ end
+
+ it "is private" do
+ StringIO.should have_private_instance_method(:initialize)
+ end
+
+ it "sets the mode to read-write" do
+ @io.send(:initialize, "example")
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_false
+ end
+
+ it "uses an empty String as the StringIO backend" do
+ @io.send(:initialize)
+ @io.string.should == ""
+ end
+end
diff --git a/spec/ruby/library/stringio/internal_encoding_spec.rb b/spec/ruby/library/stringio/internal_encoding_spec.rb
new file mode 100644
index 0000000000..f8ecb35989
--- /dev/null
+++ b/spec/ruby/library/stringio/internal_encoding_spec.rb
@@ -0,0 +1,10 @@
+require 'stringio'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "StringIO#internal_encoding" do
+ it "returns nil" do
+ io = StringIO.new
+ io.set_encoding Encoding::UTF_8
+ io.internal_encoding.should == nil
+ end
+end
diff --git a/spec/ruby/library/stringio/isatty_spec.rb b/spec/ruby/library/stringio/isatty_spec.rb
new file mode 100644
index 0000000000..c07dc2f6cc
--- /dev/null
+++ b/spec/ruby/library/stringio/isatty_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/isatty', __FILE__)
+
+describe "StringIO#isatty" do
+ it_behaves_like :stringio_isatty, :isatty
+end
diff --git a/spec/ruby/library/stringio/length_spec.rb b/spec/ruby/library/stringio/length_spec.rb
new file mode 100644
index 0000000000..ae8eb15502
--- /dev/null
+++ b/spec/ruby/library/stringio/length_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "StringIO#length" do
+ it_behaves_like :stringio_length, :length
+end
diff --git a/spec/ruby/library/stringio/lineno_spec.rb b/spec/ruby/library/stringio/lineno_spec.rb
new file mode 100644
index 0000000000..b7ef83c7e1
--- /dev/null
+++ b/spec/ruby/library/stringio/lineno_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "stringio"
+
+describe "StringIO#lineno" do
+ before :each do
+ @io = StringIO.new("this\nis\nan\nexample")
+ end
+
+ it "returns the number of lines read" do
+ @io.gets
+ @io.gets
+ @io.gets
+ @io.lineno.should eql(3)
+ end
+end
+
+describe "StringIO#lineno=" do
+ before :each do
+ @io = StringIO.new("this\nis\nan\nexample")
+ end
+
+ it "sets the current line number, but has no impact on the position" do
+ @io.lineno = 3
+ @io.pos.should eql(0)
+
+ @io.gets.should == "this\n"
+ @io.lineno.should eql(4)
+ @io.pos.should eql(5)
+ end
+end
diff --git a/spec/ruby/library/stringio/lines_spec.rb b/spec/ruby/library/stringio/lines_spec.rb
new file mode 100644
index 0000000000..550b25549e
--- /dev/null
+++ b/spec/ruby/library/stringio/lines_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/each', __FILE__)
+
+describe "StringIO#lines when passed a separator" do
+ it_behaves_like :stringio_each_separator, :lines
+end
+
+describe "StringIO#lines when passed no arguments" do
+ it_behaves_like :stringio_each_no_arguments, :lines
+end
+
+describe "StringIO#lines when self is not readable" do
+ it_behaves_like :stringio_each_not_readable, :lines
+end
diff --git a/spec/ruby/library/stringio/open_spec.rb b/spec/ruby/library/stringio/open_spec.rb
new file mode 100644
index 0000000000..136ff5f972
--- /dev/null
+++ b/spec/ruby/library/stringio/open_spec.rb
@@ -0,0 +1,208 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+
+describe "StringIO.open when passed [Object, mode]" do
+ it "uses the passed Object as the StringIO backend" do
+ io = StringIO.open(str = "example", "r")
+ io.string.should equal(str)
+ end
+
+ it "returns the blocks return value when yielding" do
+ ret = StringIO.open("example", "r") { :test }
+ ret.should equal(:test)
+ end
+
+ it "yields self to the passed block" do
+ io = nil
+ StringIO.open("example", "r") { |strio| io = strio }
+ io.should be_kind_of(StringIO)
+ end
+
+ it "closes self after yielding" do
+ io = nil
+ StringIO.open("example", "r") { |strio| io = strio }
+ io.closed?.should be_true
+ end
+
+ it "even closes self when an exception is raised while yielding" do
+ io = nil
+ begin
+ StringIO.open("example", "r") do |strio|
+ io = strio
+ raise "Error"
+ end
+ rescue
+ end
+ io.closed?.should be_true
+ end
+
+ it "sets self's string to nil after yielding" do
+ io = nil
+ StringIO.open("example", "r") { |strio| io = strio }
+ io.string.should be_nil
+ end
+
+ it "even sets self's string to nil when an exception is raised while yielding" do
+ io = nil
+ begin
+ StringIO.open("example", "r") do |strio|
+ io = strio
+ raise "Error"
+ end
+ rescue
+ end
+ io.string.should be_nil
+ end
+
+ it "sets the mode based on the passed mode" do
+ io = StringIO.open("example", "r")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+
+ io = StringIO.open("example", "rb")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+
+ io = StringIO.open("example", "r+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", "rb+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", "w")
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", "wb")
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", "w+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", "wb+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", "a")
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", "ab")
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", "a+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", "ab+")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+ end
+
+ it "allows passing the mode as an Integer" do
+ io = StringIO.open("example", IO::RDONLY)
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+
+ io = StringIO.open("example", IO::RDWR)
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", IO::WRONLY)
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", IO::WRONLY | IO::TRUNC)
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", IO::RDWR | IO::TRUNC)
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", IO::WRONLY | IO::APPEND)
+ io.closed_read?.should be_true
+ io.closed_write?.should be_false
+
+ io = StringIO.open("example", IO::RDWR | IO::APPEND)
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+ end
+
+ it "raises a RuntimeError when passed a frozen String in truncate mode as StringIO backend" do
+ lambda { StringIO.open("example".freeze, IO::TRUNC) }.should raise_error(RuntimeError)
+ end
+
+ it "tries to convert the passed mode to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return("r")
+ io = StringIO.open("example", obj)
+
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+ end
+
+ it "raises an Errno::EACCES error when passed a frozen string with a write-mode" do
+ (str = "example").freeze
+ lambda { StringIO.open(str, "r+") }.should raise_error(Errno::EACCES)
+ lambda { StringIO.open(str, "w") }.should raise_error(Errno::EACCES)
+ lambda { StringIO.open(str, "a") }.should raise_error(Errno::EACCES)
+ end
+end
+
+describe "StringIO.open when passed [Object]" do
+ it "uses the passed Object as the StringIO backend" do
+ io = StringIO.open(str = "example")
+ io.string.should equal(str)
+ end
+
+ it "yields self to the passed block" do
+ io = nil
+ ret = StringIO.open("example") { |strio| io = strio }
+ io.should equal(ret)
+ end
+
+ it "sets the mode to read-write" do
+ io = StringIO.open("example")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+ end
+
+ it "tries to convert the passed Object to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return("example")
+ io = StringIO.open(obj)
+ io.string.should == "example"
+ end
+
+ it "automatically sets the mode to read-only when passed a frozen string" do
+ (str = "example").freeze
+ io = StringIO.open(str)
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+ end
+end
+
+describe "StringIO.open when passed no arguments" do
+ it "yields self to the passed block" do
+ io = nil
+ ret = StringIO.open { |strio| io = strio }
+ io.should equal(ret)
+ end
+
+ it "sets the mode to read-write" do
+ io = StringIO.open
+ io.closed_read?.should be_false
+ io.closed_write?.should be_false
+ end
+
+ it "uses an empty String as the StringIO backend" do
+ StringIO.open.string.should == ""
+ end
+end
+
diff --git a/spec/ruby/library/stringio/path_spec.rb b/spec/ruby/library/stringio/path_spec.rb
new file mode 100644
index 0000000000..6165cf97c4
--- /dev/null
+++ b/spec/ruby/library/stringio/path_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#path" do
+ it "is not defined" do
+ lambda { StringIO.new("path").path }.should raise_error(NoMethodError)
+ end
+end
diff --git a/spec/ruby/library/stringio/pid_spec.rb b/spec/ruby/library/stringio/pid_spec.rb
new file mode 100644
index 0000000000..41e60880cc
--- /dev/null
+++ b/spec/ruby/library/stringio/pid_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#pid" do
+ it "returns nil" do
+ StringIO.new("pid").pid.should be_nil
+ end
+end
diff --git a/spec/ruby/library/stringio/pos_spec.rb b/spec/ruby/library/stringio/pos_spec.rb
new file mode 100644
index 0000000000..59d0a43f12
--- /dev/null
+++ b/spec/ruby/library/stringio/pos_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/tell', __FILE__)
+
+describe "StringIO#pos" do
+ it_behaves_like :stringio_tell, :pos
+end
+
+describe "StringIO#pos=" do
+ before :each do
+ @io = StringIOSpecs.build
+ end
+
+ it "updates the current byte offset" do
+ @io.pos = 26
+ @io.read(1).should == "r"
+ end
+
+ it "raises an EINVAL if given a negative argument" do
+ lambda { @io.pos = -10 }.should raise_error(Errno::EINVAL)
+ end
+
+ it "updates the current byte offset after reaching EOF" do
+ @io.read
+ @io.pos = 26
+ @io.read(1).should == "r"
+ end
+end
diff --git a/spec/ruby/library/stringio/print_spec.rb b/spec/ruby/library/stringio/print_spec.rb
new file mode 100644
index 0000000000..0f67aeb921
--- /dev/null
+++ b/spec/ruby/library/stringio/print_spec.rb
@@ -0,0 +1,100 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#print" do
+ before :each do
+ @io = StringIO.new('example')
+ end
+
+ it "prints $_ when passed no arguments" do
+ $_ = nil
+ @io.print
+ @io.string.should == "example"
+
+ $_ = "blah"
+ @io.print
+ @io.string.should == "blahple"
+ end
+
+ it "prints the passed arguments to self" do
+ @io.print(5, 6, 7, 8)
+ @io.string.should == "5678ple"
+ end
+
+ it "tries to convert the passed Object to a String using #to_s" do
+ obj = mock("to_s")
+ obj.should_receive(:to_s).and_return("to_s")
+ @io.print(obj)
+ @io.string.should == "to_sple"
+ end
+
+ it "returns nil" do
+ @io.print(1, 2, 3).should be_nil
+ end
+
+ it "pads self with \\000 when the current position is after the end" do
+ @io.pos = 10
+ @io.print(1, 2, 3)
+ @io.string.should == "example\000\000\000123"
+ end
+
+ it "honors the output record separator global" do
+ old_rs, $\ = $\, 'x'
+
+ begin
+ @io.print(5, 6, 7, 8)
+ @io.string.should == '5678xle'
+ ensure
+ $\ = old_rs
+ end
+ end
+
+ it "updates the current position" do
+ @io.print(1, 2, 3)
+ @io.pos.should eql(3)
+
+ @io.print(1, 2, 3)
+ @io.pos.should eql(6)
+ end
+
+ it "correctly updates the current position when honoring the output record separator global" do
+ old_rs, $\ = $\, 'x'
+
+ begin
+ @io.print(5, 6, 7, 8)
+ @io.pos.should eql(5)
+ ensure
+ $\ = old_rs
+ end
+ end
+end
+
+describe "StringIO#print when in append mode" do
+ before :each do
+ @io = StringIO.new("example", "a")
+ end
+
+ it "appends the passed argument to the end of self" do
+ @io.print(", just testing")
+ @io.string.should == "example, just testing"
+
+ @io.print(" and more testing")
+ @io.string.should == "example, just testing and more testing"
+ end
+
+ it "correctly updates self's position" do
+ @io.print(", testing")
+ @io.pos.should eql(16)
+ end
+end
+
+describe "StringIO#print when self is not writable" do
+ it "raises an IOError" do
+ io = StringIO.new("test", "r")
+ lambda { io.print("test") }.should raise_error(IOError)
+
+ io = StringIO.new("test")
+ io.close_write
+ lambda { io.print("test") }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/printf_spec.rb b/spec/ruby/library/stringio/printf_spec.rb
new file mode 100644
index 0000000000..5f811547bc
--- /dev/null
+++ b/spec/ruby/library/stringio/printf_spec.rb
@@ -0,0 +1,61 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#printf" do
+ before :each do
+ @io = StringIO.new('example')
+ end
+
+ it "returns nil" do
+ @io.printf("%d %04x", 123, 123).should be_nil
+ end
+
+ it "pads self with \\000 when the current position is after the end" do
+ @io.pos = 10
+ @io.printf("%d", 123)
+ @io.string.should == "example\000\000\000123"
+ end
+
+ it "performs format conversion" do
+ @io.printf("%d %04x", 123, 123)
+ @io.string.should == "123 007b"
+ end
+
+ it "updates the current position" do
+ @io.printf("%d %04x", 123, 123)
+ @io.pos.should eql(8)
+
+ @io.printf("%d %04x", 123, 123)
+ @io.pos.should eql(16)
+ end
+end
+
+describe "StringIO#printf when in append mode" do
+ before :each do
+ @io = StringIO.new("example", "a")
+ end
+
+ it "appends the passed argument to the end of self" do
+ @io.printf("%d %04x", 123, 123)
+ @io.string.should == "example123 007b"
+
+ @io.printf("%d %04x", 123, 123)
+ @io.string.should == "example123 007b123 007b"
+ end
+
+ it "correctly updates self's position" do
+ @io.printf("%d %04x", 123, 123)
+ @io.pos.should eql(15)
+ end
+end
+
+describe "StringIO#printf when self is not writable" do
+ it "raises an IOError" do
+ io = StringIO.new("test", "r")
+ lambda { io.printf("test") }.should raise_error(IOError)
+
+ io = StringIO.new("test")
+ io.close_write
+ lambda { io.printf("test") }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/putc_spec.rb b/spec/ruby/library/stringio/putc_spec.rb
new file mode 100644
index 0000000000..783e5a405b
--- /dev/null
+++ b/spec/ruby/library/stringio/putc_spec.rb
@@ -0,0 +1,88 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#putc when passed [String]" do
+ before :each do
+ @io = StringIO.new('example')
+ end
+
+ it "overwrites the character at the current position" do
+ @io.putc("t")
+ @io.string.should == "txample"
+
+ @io.pos = 3
+ @io.putc("t")
+ @io.string.should == "txatple"
+ end
+
+ it "only writes the first character from the passed String" do
+ @io.putc("test")
+ @io.string.should == "txample"
+ end
+
+ it "returns the passed String" do
+ str = "test"
+ @io.putc(str).should equal(str)
+ end
+
+ it "correctly updates the current position" do
+ @io.putc("t")
+ @io.pos.should == 1
+
+ @io.putc("test")
+ @io.pos.should == 2
+
+ @io.putc("t")
+ @io.pos.should == 3
+ end
+end
+
+describe "StringIO#putc when passed [Object]" do
+ before :each do
+ @io = StringIO.new('example')
+ end
+
+ it "it writes the passed Integer % 256 to self" do
+ @io.putc(333) # 333 % 256 == ?M
+ @io.string.should == "Mxample"
+
+ @io.putc(-450) # -450 % 256 == ?>
+ @io.string.should == "M>ample"
+ end
+
+ it "pads self with \\000 when the current position is after the end" do
+ @io.pos = 10
+ @io.putc(?A)
+ @io.string.should == "example\000\000\000A"
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(116)
+ @io.putc(obj)
+ @io.string.should == "txample"
+ end
+
+ it "raises a TypeError when the passed argument can't be coerced to Integer" do
+ lambda { @io.putc(Object.new) }.should raise_error(TypeError)
+ end
+end
+
+describe "StringIO#putc when in append mode" do
+ it "appends to the end of self" do
+ io = StringIO.new("test", "a")
+ io.putc(?t)
+ io.string.should == "testt"
+ end
+end
+
+describe "StringIO#putc when self is not writable" do
+ it "raises an IOError" do
+ io = StringIO.new("test", "r")
+ lambda { io.putc(?a) }.should raise_error(IOError)
+
+ io = StringIO.new("test")
+ io.close_write
+ lambda { io.putc("t") }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/puts_spec.rb b/spec/ruby/library/stringio/puts_spec.rb
new file mode 100644
index 0000000000..93a676aa15
--- /dev/null
+++ b/spec/ruby/library/stringio/puts_spec.rb
@@ -0,0 +1,159 @@
+# -*- encoding: utf-8 -*-
+
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#puts when passed an Array" do
+ before :each do
+ @io = StringIO.new
+ end
+
+ it "writes each element of the passed Array to self, separated by a newline" do
+ @io.puts([1, 2, 3, 4])
+ @io.string.should == "1\n2\n3\n4\n"
+
+ @io.puts([1, 2], [3, 4])
+ @io.string.should == "1\n2\n3\n4\n1\n2\n3\n4\n"
+ end
+
+ it "flattens nested Arrays" do
+ @io.puts([1, [2, [3, [4]]]])
+ @io.string.should == "1\n2\n3\n4\n"
+ end
+
+ it "handles self-recursive arrays correctly" do
+ (ary = [5])
+ ary << ary
+ @io.puts(ary)
+ @io.string.should == "5\n[...]\n"
+ end
+
+ it "does not honor the global output record separator $\\" do
+ begin
+ old_rs, $\ = $\, "test"
+ @io.puts([1, 2, 3, 4])
+ @io.string.should == "1\n2\n3\n4\n"
+ ensure
+ $\ = old_rs
+ end
+ end
+
+ it "first tries to convert each Array element to an Array using #to_ary" do
+ obj = mock("Object")
+ obj.should_receive(:to_ary).and_return(["to_ary"])
+ @io.puts([obj])
+ @io.string.should == "to_ary\n"
+ end
+
+ it "then tries to convert each Array element to a String using #to_s" do
+ obj = mock("Object")
+ obj.should_receive(:to_s).and_return("to_s")
+ @io.puts([obj])
+ @io.string.should == "to_s\n"
+ end
+end
+
+describe "StringIO#puts when passed 1 or more objects" do
+ before :each do
+ @io = StringIO.new
+ end
+
+ it "does not honor the global output record separator $\\" do
+ begin
+ old_rs, $\ = $\, "test"
+ @io.puts(1, 2, 3, 4)
+ @io.string.should == "1\n2\n3\n4\n"
+ ensure
+ $\ = old_rs
+ end
+ end
+
+ it "does not put a \\n after each Objects that end in a newline" do
+ @io.puts("1\n", "2\n", "3\n")
+ @io.string.should == "1\n2\n3\n"
+ end
+
+ it "first tries to convert each Object to an Array using #to_ary" do
+ obj = mock("Object")
+ obj.should_receive(:to_ary).and_return(["to_ary"])
+ @io.puts(obj)
+ @io.string.should == "to_ary\n"
+ end
+
+ it "then tries to convert each Object to a String using #to_s" do
+ obj = mock("Object")
+ obj.should_receive(:to_s).and_return("to_s")
+ @io.puts(obj)
+ @io.string.should == "to_s\n"
+ end
+
+ it "prints a newline when passed an empty string" do
+ @io.puts ''
+ @io.string.should == "\n"
+ end
+end
+
+describe "StringIO#puts when passed no arguments" do
+ before :each do
+ @io = StringIO.new
+ end
+
+ it "returns nil" do
+ @io.puts.should be_nil
+ end
+
+ it "prints a newline" do
+ @io.puts
+ @io.string.should == "\n"
+ end
+
+ it "does not honor the global output record separator $\\" do
+ begin
+ old_rs, $\ = $\, "test"
+ @io.puts
+ @io.string.should == "\n"
+ ensure
+ $\ = old_rs
+ end
+ end
+end
+
+describe "StringIO#puts when in append mode" do
+ before :each do
+ @io = StringIO.new("example", "a")
+ end
+
+ it "appends the passed argument to the end of self" do
+ @io.puts(", just testing")
+ @io.string.should == "example, just testing\n"
+
+ @io.puts(" and more testing")
+ @io.string.should == "example, just testing\n and more testing\n"
+ end
+
+ it "correctly updates self's position" do
+ @io.puts(", testing")
+ @io.pos.should eql(17)
+ end
+end
+
+describe "StringIO#puts when self is not writable" do
+ it "raises an IOError" do
+ io = StringIO.new("test", "r")
+ lambda { io.puts }.should raise_error(IOError)
+
+ io = StringIO.new("test")
+ io.close_write
+ lambda { io.puts }.should raise_error(IOError)
+ end
+end
+
+describe "StringIO#puts when passed an encoded string" do
+ it "stores the bytes unmodified" do
+ io = StringIO.new("")
+ io.puts "\x00\x01\x02"
+ io.puts "æåø"
+
+ io.string.should == "\x00\x01\x02\næåø\n"
+ end
+end
diff --git a/spec/ruby/library/stringio/read_nonblock_spec.rb b/spec/ruby/library/stringio/read_nonblock_spec.rb
new file mode 100644
index 0000000000..84aefe8de7
--- /dev/null
+++ b/spec/ruby/library/stringio/read_nonblock_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "stringio"
+require File.expand_path('../shared/read', __FILE__)
+require File.expand_path('../shared/sysread', __FILE__)
+
+describe "StringIO#read_nonblock when passed length, buffer" do
+ it_behaves_like :stringio_read, :read_nonblock
+end
+
+describe "StringIO#read_nonblock when passed length" do
+ it_behaves_like :stringio_read_length, :read_nonblock
+end
+
+describe "StringIO#read_nonblock when passed nil" do
+ it_behaves_like :stringio_read_nil, :read_nonblock
+end
+
+describe "StringIO#read_nonblock when passed length" do
+ it_behaves_like :stringio_sysread_length, :read_nonblock
+end
diff --git a/spec/ruby/library/stringio/read_spec.rb b/spec/ruby/library/stringio/read_spec.rb
new file mode 100644
index 0000000000..2b9c6e10b2
--- /dev/null
+++ b/spec/ruby/library/stringio/read_spec.rb
@@ -0,0 +1,62 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "stringio"
+require File.expand_path('../shared/read', __FILE__)
+
+describe "StringIO#read when passed length, buffer" do
+ it_behaves_like :stringio_read, :read
+end
+
+describe "StringIO#read when passed [length]" do
+ it_behaves_like :stringio_read_length, :read
+end
+
+describe "StringIO#read when passed no arguments" do
+ it_behaves_like :stringio_read_no_arguments, :read
+
+ it "returns an empty string if at EOF" do
+ @io.read.should == "example"
+ @io.read.should == ""
+ end
+end
+
+describe "StringIO#read when passed nil" do
+ it_behaves_like :stringio_read_nil, :read
+
+ it "returns an empty string if at EOF" do
+ @io.read(nil).should == "example"
+ @io.read(nil).should == ""
+ end
+end
+
+describe "StringIO#read when self is not readable" do
+ it_behaves_like :stringio_read_not_readable, :read
+end
+
+describe "StringIO#read when passed [length]" do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "returns nil when self's position is at the end" do
+ @io.pos = 7
+ @io.read(10).should be_nil
+ end
+
+ it "returns an empty String when length is 0" do
+ @io.read(0).should == ""
+ end
+end
+
+describe "StringIO#read when passed length and a buffer" do
+ before :each do
+ @io = StringIO.new("abcdefghijklmnopqrstuvwxyz")
+ end
+
+ it "reads [length] characters into the buffer" do
+ buf = "foo"
+ result = @io.read(10, buf)
+
+ buf.should == "abcdefghij"
+ result.should equal(buf)
+ end
+end
diff --git a/spec/ruby/library/stringio/readbyte_spec.rb b/spec/ruby/library/stringio/readbyte_spec.rb
new file mode 100644
index 0000000000..0fbc49a4dd
--- /dev/null
+++ b/spec/ruby/library/stringio/readbyte_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/readchar', __FILE__)
+
+describe "StringIO#readbyte" do
+ it_behaves_like :stringio_readchar, :readbyte
+
+ it "reads the next 8-bit byte from self's current position" do
+ io = StringIO.new("example")
+
+ io.send(@method).should == 101
+
+ io.pos = 4
+ io.send(@method).should == 112
+ end
+end
+
+describe "StringIO#readbyte when self is not readable" do
+ it_behaves_like :stringio_readchar_not_readable, :readbyte
+end
diff --git a/spec/ruby/library/stringio/readchar_spec.rb b/spec/ruby/library/stringio/readchar_spec.rb
new file mode 100644
index 0000000000..af673c871a
--- /dev/null
+++ b/spec/ruby/library/stringio/readchar_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+require File.expand_path('../shared/readchar', __FILE__)
+
+describe "StringIO#readchar" do
+ it_behaves_like :stringio_readchar, :readchar
+
+ it "reads the next 8-bit byte from self's current position" do
+ io = StringIO.new("example")
+
+ io.send(@method).should == ?e
+
+ io.pos = 4
+ io.send(@method).should == ?p
+ end
+end
+
+describe "StringIO#readchar when self is not readable" do
+ it_behaves_like :stringio_readchar_not_readable, :readchar
+end
diff --git a/spec/ruby/library/stringio/readline_spec.rb b/spec/ruby/library/stringio/readline_spec.rb
new file mode 100644
index 0000000000..90890e3ad1
--- /dev/null
+++ b/spec/ruby/library/stringio/readline_spec.rb
@@ -0,0 +1,122 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+
+describe "StringIO#readline when passed [separator]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read till the next occurence of the passed separator" do
+ @io.readline(">").should == "this>"
+ @io.readline(">").should == "is>"
+ @io.readline(">").should == "an>"
+ @io.readline(">").should == "example"
+ end
+
+ it "sets $_ to the read content" do
+ @io.readline(">")
+ $_.should == "this>"
+ @io.readline(">")
+ $_.should == "is>"
+ @io.readline(">")
+ $_.should == "an>"
+ @io.readline(">")
+ $_.should == "example"
+ end
+
+ it "updates self's lineno by one" do
+ @io.readline(">")
+ @io.lineno.should eql(1)
+
+ @io.readline(">")
+ @io.lineno.should eql(2)
+
+ @io.readline(">")
+ @io.lineno.should eql(3)
+ end
+
+ it "returns the next paragraph when the passed separator is an empty String" do
+ io = StringIO.new("this is\n\nan example")
+ io.readline("").should == "this is\n\n"
+ io.readline("").should == "an example"
+ end
+
+ it "returns the remaining content starting at the current position when passed nil" do
+ io = StringIO.new("this is\n\nan example")
+ io.pos = 5
+ io.readline(nil).should == "is\n\nan example"
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return(">")
+ @io.readline(obj).should == "this>"
+ end
+end
+
+describe "StringIO#readline when passed no argument" do
+ before :each do
+ @io = StringIO.new("this is\nan example\nfor StringIO#readline")
+ end
+
+ it "returns the data read till the next occurence of $/ or till eof" do
+ @io.readline.should == "this is\n"
+
+ begin
+ old_sep, $/ = $/, " "
+ @io.readline.should == "an "
+ @io.readline.should == "example\nfor "
+ @io.readline.should == "StringIO#readline"
+ ensure
+ $/ = old_sep
+ end
+ end
+
+ it "sets $_ to the read content" do
+ @io.readline
+ $_.should == "this is\n"
+ @io.readline
+ $_.should == "an example\n"
+ @io.readline
+ $_.should == "for StringIO#readline"
+ end
+
+ it "updates self's position" do
+ @io.readline
+ @io.pos.should eql(8)
+
+ @io.readline
+ @io.pos.should eql(19)
+
+ @io.readline
+ @io.pos.should eql(40)
+ end
+
+ it "updates self's lineno" do
+ @io.readline
+ @io.lineno.should eql(1)
+
+ @io.readline
+ @io.lineno.should eql(2)
+
+ @io.readline
+ @io.lineno.should eql(3)
+ end
+
+ it "raises an IOError if self is at the end" do
+ @io.pos = 40
+ lambda { @io.readline }.should raise_error(IOError)
+ end
+end
+
+describe "StringIO#readline when in write-only mode" do
+ it "raises an IOError" do
+ io = StringIO.new("xyz", "w")
+ lambda { io.readline }.should raise_error(IOError)
+
+ io = StringIO.new("xyz")
+ io.close_read
+ lambda { io.readline }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/readlines_spec.rb b/spec/ruby/library/stringio/readlines_spec.rb
new file mode 100644
index 0000000000..215a6cbb2a
--- /dev/null
+++ b/spec/ruby/library/stringio/readlines_spec.rb
@@ -0,0 +1,92 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#readlines when passed [separator]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns an Array containing lines based on the passed separator" do
+ @io.readlines(">").should == ["this>", "is>", "an>", "example"]
+ end
+
+ it "updates self's position based on the number of read bytes" do
+ @io.readlines(">")
+ @io.pos.should eql(18)
+ end
+
+ it "updates self's lineno based on the number of read lines" do
+ @io.readlines(">")
+ @io.lineno.should eql(4)
+ end
+
+ it "does not change $_" do
+ $_ = "test"
+ @io.readlines(">")
+ $_.should == "test"
+ end
+
+ it "returns an Array containing all paragraphs when the passed separator is an empty String" do
+ io = StringIO.new("this is\n\nan example")
+ io.readlines("").should == ["this is\n\n", "an example"]
+ end
+
+ it "returns the remaining content as one line starting at the current position when passed nil" do
+ io = StringIO.new("this is\n\nan example")
+ io.pos = 5
+ io.readlines(nil).should == ["is\n\nan example"]
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do
+ obj = mock('to_str')
+ obj.stub!(:to_str).and_return(">")
+ @io.readlines(obj).should == ["this>", "is>", "an>", "example"]
+ end
+end
+
+describe "StringIO#readlines when passed no argument" do
+ before :each do
+ @io = StringIO.new("this is\nan example\nfor StringIO#readlines")
+ end
+
+ it "returns an Array containing lines based on $/" do
+ begin
+ old_sep, $/ = $/, " "
+ @io.readlines.should == ["this ", "is\nan ", "example\nfor ", "StringIO#readlines"]
+ ensure
+ $/ = old_sep
+ end
+ end
+
+ it "updates self's position based on the number of read bytes" do
+ @io.readlines
+ @io.pos.should eql(41)
+ end
+
+ it "updates self's lineno based on the number of read lines" do
+ @io.readlines
+ @io.lineno.should eql(3)
+ end
+
+ it "does not change $_" do
+ $_ = "test"
+ @io.readlines(">")
+ $_.should == "test"
+ end
+
+ it "returns an empty Array when self is at the end" do
+ @io.pos = 41
+ @io.readlines.should == []
+ end
+end
+
+describe "StringIO#readlines when in write-only mode" do
+ it "raises an IOError" do
+ io = StringIO.new("xyz", "w")
+ lambda { io.readlines }.should raise_error(IOError)
+
+ io = StringIO.new("xyz")
+ io.close_read
+ lambda { io.readlines }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/readpartial_spec.rb b/spec/ruby/library/stringio/readpartial_spec.rb
new file mode 100644
index 0000000000..e65e50fa41
--- /dev/null
+++ b/spec/ruby/library/stringio/readpartial_spec.rb
@@ -0,0 +1,80 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#readpartial" do
+ before :each do
+ @string = StringIO.new('Stop, look, listen')
+ end
+
+ after :each do
+ @string.close unless @string.closed?
+ end
+
+ it "raises IOError on closed stream" do
+ @string.close
+ lambda { @string.readpartial(10) }.should raise_error(IOError)
+ end
+
+ it "reads at most the specified number of bytes" do
+
+ # buffered read
+ @string.read(1).should == 'S'
+ # return only specified number, not the whole buffer
+ @string.readpartial(1).should == "t"
+ end
+
+ it "reads after ungetc with data in the buffer" do
+ c = @string.getc
+ @string.ungetc(c)
+ @string.readpartial(4).should == "Stop"
+ @string.readpartial(3).should == ", l"
+ end
+
+ it "reads after ungetc without data in the buffer" do
+ @string = StringIO.new
+ @string.write("f").should == 1
+ @string.rewind
+ c = @string.getc
+ c.should == 'f'
+ @string.ungetc(c).should == nil
+
+ @string.readpartial(2).should == "f"
+ @string.rewind
+ # now, also check that the ungot char is cleared and
+ # not returned again
+ @string.write("b").should == 1
+ @string.rewind
+ @string.readpartial(2).should == "b"
+ end
+
+ it "discards the existing buffer content upon successful read" do
+ buffer = "existing"
+ @string.readpartial(11, buffer)
+ buffer.should == "Stop, look,"
+ end
+
+ it "raises EOFError on EOF" do
+ @string.readpartial(18).should == 'Stop, look, listen'
+ lambda { @string.readpartial(10) }.should raise_error(EOFError)
+ end
+
+ it "discards the existing buffer content upon error" do
+ buffer = 'hello'
+ @string.readpartial(100)
+ lambda { @string.readpartial(1, buffer) }.should raise_error(EOFError)
+ buffer.should be_empty
+ end
+
+ it "raises IOError if the stream is closed" do
+ @string.close
+ lambda { @string.readpartial(1) }.should raise_error(IOError)
+ end
+
+ it "raises ArgumentError if the negative argument is provided" do
+ lambda { @string.readpartial(-1) }.should raise_error(ArgumentError)
+ end
+
+ it "immediately returns an empty string if the length argument is 0" do
+ @string.readpartial(0).should == ""
+ end
+end
diff --git a/spec/ruby/library/stringio/reopen_spec.rb b/spec/ruby/library/stringio/reopen_spec.rb
new file mode 100644
index 0000000000..abdecdf9de
--- /dev/null
+++ b/spec/ruby/library/stringio/reopen_spec.rb
@@ -0,0 +1,288 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#reopen when passed [Object, Integer]" do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "reopens self with the passed Object in the passed mode" do
+ @io.reopen("reopened", IO::RDONLY)
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_true
+ @io.string.should == "reopened"
+
+ @io.reopen("reopened, twice", IO::WRONLY)
+ @io.closed_read?.should be_true
+ @io.closed_write?.should be_false
+ @io.string.should == "reopened, twice"
+
+ @io.reopen("reopened, another time", IO::RDWR)
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_false
+ @io.string.should == "reopened, another time"
+ end
+
+ # NOTE: WEIRD!
+ it "does not taint self when the passed Object was tainted" do
+ @io.reopen("reopened".taint, IO::RDONLY)
+ @io.tainted?.should be_false
+
+ @io.reopen("reopened".taint, IO::WRONLY)
+ @io.tainted?.should be_false
+ end
+
+ it "tries to convert the passed Object to a String using #to_str" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return("to_str")
+ @io.reopen(obj, IO::RDWR)
+ @io.string.should == "to_str"
+ end
+
+ it "raises a TypeError when the passed Object can't be converted to a String" do
+ lambda { @io.reopen(Object.new, IO::RDWR) }.should raise_error(TypeError)
+ end
+
+ it "raises an Errno::EACCES when trying to reopen self with a frozen String in write-mode" do
+ lambda { @io.reopen("burn".freeze, IO::WRONLY) }.should raise_error(Errno::EACCES)
+ lambda { @io.reopen("burn".freeze, IO::WRONLY | IO::APPEND) }.should raise_error(Errno::EACCES)
+ end
+
+ it "raises a RuntimeError when trying to reopen self with a frozen String in truncate-mode" do
+ lambda { @io.reopen("burn".freeze, IO::RDONLY | IO::TRUNC) }.should raise_error(RuntimeError)
+ end
+
+ it "does not raise IOError when passed a frozen String in read-mode" do
+ @io.reopen("burn".freeze, IO::RDONLY)
+ @io.string.should == "burn"
+ end
+end
+
+describe "StringIO#reopen when passed [Object, Object]" do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "reopens self with the passed Object in the passed mode" do
+ @io.reopen("reopened", "r")
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_true
+ @io.string.should == "reopened"
+
+ @io.reopen("reopened, twice", "r+")
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_false
+ @io.string.should == "reopened, twice"
+
+ @io.reopen("reopened, another", "w+")
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_false
+ @io.string.should == ""
+
+ @io.reopen("reopened, another time", "r+")
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_false
+ @io.string.should == "reopened, another time"
+ end
+
+ it "truncates the passed String when opened in truncate mode" do
+ @io.reopen(str = "reopened", "w")
+ str.should == ""
+ end
+
+ # NOTE: WEIRD!
+ it "does not taint self when the passed Object was tainted" do
+ @io.reopen("reopened".taint, "r")
+ @io.tainted?.should be_false
+
+ @io.reopen("reopened".taint, "w")
+ @io.tainted?.should be_false
+ end
+
+ it "tries to convert the passed Object to a String using #to_str" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return("to_str")
+ @io.reopen(obj, "r")
+ @io.string.should == "to_str"
+ end
+
+ it "raises a TypeError when the passed Object can't be converted to a String using #to_str" do
+ lambda { @io.reopen(Object.new, "r") }.should raise_error(TypeError)
+ end
+
+ it "resets self's position to 0" do
+ @io.read(5)
+ @io.reopen("reopened")
+ @io.pos.should eql(0)
+ end
+
+ it "resets self's line number to 0" do
+ @io.gets
+ @io.reopen("reopened")
+ @io.lineno.should eql(0)
+ end
+
+ it "tries to convert the passed mode Object to an Integer using #to_str" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return("r")
+ @io.reopen("reopened", obj)
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_true
+ @io.string.should == "reopened"
+ end
+
+ it "raises an Errno::EACCES error when trying to reopen self with a frozen String in write-mode" do
+ lambda { @io.reopen("burn".freeze, 'w') }.should raise_error(Errno::EACCES)
+ lambda { @io.reopen("burn".freeze, 'w+') }.should raise_error(Errno::EACCES)
+ lambda { @io.reopen("burn".freeze, 'a') }.should raise_error(Errno::EACCES)
+ lambda { @io.reopen("burn".freeze, "r+") }.should raise_error(Errno::EACCES)
+ end
+
+ it "does not raise IOError if a frozen string is passed in read mode" do
+ @io.reopen("burn".freeze, "r")
+ @io.string.should == "burn"
+ end
+end
+
+describe "StringIO#reopen when passed [String]" do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "reopens self with the passed String in read-write mode" do
+ @io.close
+
+ @io.reopen("reopened")
+
+ @io.closed_write?.should be_false
+ @io.closed_read?.should be_false
+
+ @io.string.should == "reopened"
+ end
+
+ # NOTE: WEIRD!
+ it "does not taint self when the passed Object was tainted" do
+ @io.reopen("reopened".taint)
+ @io.tainted?.should be_false
+ end
+
+ it "resets self's position to 0" do
+ @io.read(5)
+ @io.reopen("reopened")
+ @io.pos.should eql(0)
+ end
+
+ it "resets self's line number to 0" do
+ @io.gets
+ @io.reopen("reopened")
+ @io.lineno.should eql(0)
+ end
+end
+
+describe "StringIO#reopen when passed [Object]" do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "raises a TypeError when passed an Object that can't be converted to a StringIO" do
+ lambda { @io.reopen(Object.new) }.should raise_error(TypeError)
+ end
+
+ it "does not try to convert the passed Object to a String using #to_str" do
+ obj = mock("not to_str")
+ obj.should_not_receive(:to_str)
+ lambda { @io.reopen(obj) }.should raise_error(TypeError)
+ end
+
+ it "tries to convert the passed Object to a StringIO using #to_strio" do
+ obj = mock("to_strio")
+ obj.should_receive(:to_strio).and_return(StringIO.new("to_strio"))
+ @io.reopen(obj)
+ @io.string.should == "to_strio"
+ end
+
+ # NOTE: WEIRD!
+ it "taints self when the passed Object was tainted" do
+ @io.reopen(StringIO.new("reopened").taint)
+ @io.tainted?.should be_true
+ end
+end
+
+describe "StringIO#reopen when passed no arguments" do
+ before :each do
+ @io = StringIO.new("example\nsecond line")
+ end
+
+ it "resets self's mode to read-write" do
+ @io.close
+ @io.reopen
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_false
+ end
+
+ it "resets self's position to 0" do
+ @io.read(5)
+ @io.reopen
+ @io.pos.should eql(0)
+ end
+
+ it "resets self's line number to 0" do
+ @io.gets
+ @io.reopen
+ @io.lineno.should eql(0)
+ end
+end
+
+# NOTE: Some reopen specs disabled due to MRI bugs. See:
+# http://rubyforge.org/tracker/index.php?func=detail&aid=13919&group_id=426&atid=1698
+# for details.
+describe "StringIO#reopen" do
+ before :each do
+ @io = StringIO.new('hello','a')
+ end
+
+ # TODO: find out if this is really a bug
+ it "reopens a stream when given a String argument" do
+ @io.reopen('goodbye').should == @io
+ @io.string.should == 'goodbye'
+ @io << 'x'
+ @io.string.should == 'xoodbye'
+ end
+
+ it "reopens a stream in append mode when flagged as such" do
+ @io.reopen('goodbye', 'a').should == @io
+ @io.string.should == 'goodbye'
+ @io << 'x'
+ @io.string.should == 'goodbyex'
+ end
+
+ it "reopens and truncate when reopened in write mode" do
+ @io.reopen('goodbye', 'wb').should == @io
+ @io.string.should == ''
+ @io << 'x'
+ @io.string.should == 'x'
+ end
+
+ it "truncates the given string, not a copy" do
+ str = 'goodbye'
+ @io.reopen(str, 'w')
+ @io.string.should == ''
+ str.should == ''
+ end
+
+ it "taints self if the provided StringIO argument is tainted" do
+ new_io = StringIO.new("tainted")
+ new_io.taint
+ @io.reopen(new_io)
+ @io.tainted?.should == true
+ end
+
+ it "does not truncate the content even when the StringIO argument is in the truncate mode" do
+ orig_io = StringIO.new("Original StringIO", IO::RDWR|IO::TRUNC)
+ orig_io.write("BLAH") # make sure the content is not empty
+
+ @io.reopen(orig_io)
+ @io.string.should == "BLAH"
+ end
+
+end
diff --git a/spec/ruby/library/stringio/rewind_spec.rb b/spec/ruby/library/stringio/rewind_spec.rb
new file mode 100644
index 0000000000..ef144a9f5f
--- /dev/null
+++ b/spec/ruby/library/stringio/rewind_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#rewind" do
+ before :each do
+ @io = StringIO.new("hello\nworld")
+ @io.pos = 3
+ @io.lineno = 1
+ end
+
+ it "returns 0" do
+ @io.rewind.should eql(0)
+ end
+
+ it "resets the position" do
+ @io.rewind
+ @io.pos.should == 0
+ end
+
+ it "resets the line number" do
+ @io.rewind
+ @io.lineno.should == 0
+ end
+end
diff --git a/spec/ruby/library/stringio/seek_spec.rb b/spec/ruby/library/stringio/seek_spec.rb
new file mode 100644
index 0000000000..ec79122039
--- /dev/null
+++ b/spec/ruby/library/stringio/seek_spec.rb
@@ -0,0 +1,67 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#seek" do
+ before :each do
+ @io = StringIO.new("12345678")
+ end
+
+ it "seeks from the current position when whence is IO::SEEK_CUR" do
+ @io.pos = 1
+ @io.seek(1, IO::SEEK_CUR)
+ @io.pos.should eql(2)
+
+ @io.seek(-1, IO::SEEK_CUR)
+ @io.pos.should eql(1)
+ end
+
+ it "seeks from the end of self when whence is IO::SEEK_END" do
+ @io.seek(3, IO::SEEK_END)
+ @io.pos.should eql(11) # Outside of the StringIO's content
+
+ @io.seek(-2, IO::SEEK_END)
+ @io.pos.should eql(6)
+ end
+
+ it "seeks to an absolute position when whence is IO::SEEK_SET" do
+ @io.seek(5, IO::SEEK_SET)
+ @io.pos.should == 5
+
+ @io.pos = 3
+ @io.seek(5, IO::SEEK_SET)
+ @io.pos.should == 5
+ end
+
+ it "raises an Errno::EINVAL error on negative amounts when whence is IO::SEEK_SET" do
+ lambda { @io.seek(-5, IO::SEEK_SET) }.should raise_error(Errno::EINVAL)
+ end
+
+ it "raises an Errno::EINVAL error on incorrect whence argument" do
+ lambda { @io.seek(0, 3) }.should raise_error(Errno::EINVAL)
+ lambda { @io.seek(0, -1) }.should raise_error(Errno::EINVAL)
+ lambda { @io.seek(0, 2**16) }.should raise_error(Errno::EINVAL)
+ lambda { @io.seek(0, -2**16) }.should raise_error(Errno::EINVAL)
+ end
+
+ it "tries to convert the passed Object to a String using #to_int" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(2)
+ @io.seek(obj)
+ @io.pos.should eql(2)
+ end
+
+ it "raises a TypeError when the passed Object can't be converted to an Integer" do
+ lambda { @io.seek(Object.new) }.should raise_error(TypeError)
+ end
+end
+
+describe "StringIO#seek when self is closed" do
+ before :each do
+ @io = StringIO.new("example")
+ @io.close
+ end
+
+ it "raises an IOError" do
+ lambda { @io.seek(5) }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/set_encoding_spec.rb b/spec/ruby/library/stringio/set_encoding_spec.rb
new file mode 100644
index 0000000000..c66c70ab04
--- /dev/null
+++ b/spec/ruby/library/stringio/set_encoding_spec.rb
@@ -0,0 +1,10 @@
+require 'stringio'
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "StringIO#set_encoding" do
+ it "sets the encoding of the underlying String" do
+ io = StringIO.new
+ io.set_encoding Encoding::UTF_8
+ io.string.encoding.should == Encoding::UTF_8
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/codepoints.rb b/spec/ruby/library/stringio/shared/codepoints.rb
new file mode 100644
index 0000000000..c8ca03329f
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/codepoints.rb
@@ -0,0 +1,45 @@
+# -*- encoding: utf-8 -*-
+describe :stringio_codepoints, shared: true do
+ before :each do
+ @io = StringIO.new("∂φ/∂x = gaîté")
+ @enum = @io.send(@method)
+ end
+
+ it "returns an Enumerator" do
+ @enum.should be_an_instance_of(Enumerator)
+ end
+
+ it "yields each codepoint code in turn" do
+ @enum.to_a.should == [8706, 966, 47, 8706, 120, 32, 61, 32, 103, 97, 238, 116, 233]
+ end
+
+ it "yields each codepoint starting from the current position" do
+ @io.pos = 15
+ @enum.to_a.should == [238, 116, 233]
+ end
+
+ it "raises an error if reading invalid sequence" do
+ @io.pos = 1 # inside of a multibyte sequence
+ lambda { @enum.first }.should raise_error(ArgumentError)
+ end
+
+ it "raises an IOError if not readable" do
+ @io.close_read
+ lambda { @enum.to_a }.should raise_error(IOError)
+
+ io = StringIO.new("xyz", "w")
+ lambda { io.send(@method).to_a }.should raise_error(IOError)
+ end
+
+
+ it "calls the given block" do
+ r = []
+ @io.send(@method){|c| r << c }
+ r.should == [8706, 966, 47, 8706, 120, 32, 61, 32, 103, 97, 238, 116, 233]
+ end
+
+ it "returns self" do
+ @io.send(@method) {|l| l }.should equal(@io)
+ end
+
+end
diff --git a/spec/ruby/library/stringio/shared/each.rb b/spec/ruby/library/stringio/shared/each.rb
new file mode 100644
index 0000000000..0fde23634e
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/each.rb
@@ -0,0 +1,105 @@
+describe :stringio_each_separator, shared: true do
+ before :each do
+ @io = StringIO.new("a b c d e\n1 2 3 4 5")
+ end
+
+ it "uses the passed argument as the line separator" do
+ seen = []
+ @io.send(@method, " ") {|s| seen << s}
+ seen.should == ["a ", "b ", "c ", "d ", "e\n1 ", "2 ", "3 ", "4 ", "5"]
+ end
+
+ it "does not change $_" do
+ $_ = "test"
+ @io.send(@method, " ") { |s| s}
+ $_.should == "test"
+ end
+
+ it "returns self" do
+ @io.send(@method) {|l| l }.should equal(@io)
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do
+ obj = mock("to_str")
+ obj.stub!(:to_str).and_return(" ")
+
+ seen = []
+ @io.send(@method, obj) { |l| seen << l }
+ seen.should == ["a ", "b ", "c ", "d ", "e\n1 ", "2 ", "3 ", "4 ", "5"]
+ end
+
+ it "yields self's content starting from the current position when the passed separator is nil" do
+ seen = []
+ io = StringIO.new("1 2 1 2 1 2")
+ io.pos = 2
+ io.send(@method, nil) {|s| seen << s}
+ seen.should == ["2 1 2 1 2"]
+ end
+
+ it "yields each paragraph when passed an empty String as separator" do
+ seen = []
+ io = StringIO.new("para1\n\npara2\n\n\npara3")
+ io.send(@method, "") {|s| seen << s}
+ seen.should == ["para1\n\n", "para2\n\n", "para3"]
+ end
+end
+
+describe :stringio_each_no_arguments, shared: true do
+ before :each do
+ @io = StringIO.new("a b c d e\n1 2 3 4 5")
+ end
+
+ it "yields each line to the passed block" do
+ seen = []
+ @io.send(@method) {|s| seen << s }
+ seen.should == ["a b c d e\n", "1 2 3 4 5"]
+ end
+
+ it "yields each line starting from the current position" do
+ seen = []
+ @io.pos = 4
+ @io.send(@method) {|s| seen << s }
+ seen.should == ["c d e\n", "1 2 3 4 5"]
+ end
+
+ it "does not change $_" do
+ $_ = "test"
+ @io.send(@method) { |s| s}
+ $_.should == "test"
+ end
+
+ it "uses $/ as the default line separator" do
+ seen = []
+ begin
+ old_rs, $/ = $/, " "
+ @io.send(@method) {|s| seen << s }
+ seen.should eql(["a ", "b ", "c ", "d ", "e\n1 ", "2 ", "3 ", "4 ", "5"])
+ ensure
+ $/ = old_rs
+ end
+ end
+
+ it "returns self" do
+ @io.send(@method) {|l| l }.should equal(@io)
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @io.send(@method)
+ enum.instance_of?(Enumerator).should be_true
+
+ seen = []
+ enum.each { |b| seen << b }
+ seen.should == ["a b c d e\n", "1 2 3 4 5"]
+ end
+end
+
+describe :stringio_each_not_readable, shared: true do
+ it "raises an IOError" do
+ io = StringIO.new("a b c d e", "w")
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+
+ io = StringIO.new("a b c d e")
+ io.close_read
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/each_byte.rb b/spec/ruby/library/stringio/shared/each_byte.rb
new file mode 100644
index 0000000000..1dc48ee437
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/each_byte.rb
@@ -0,0 +1,48 @@
+describe :stringio_each_byte, shared: true do
+ before :each do
+ @io = StringIO.new("xyz")
+ end
+
+ it "yields each character code in turn" do
+ seen = []
+ @io.send(@method) { |b| seen << b }
+ seen.should == [120, 121, 122]
+ end
+
+ it "updates the position before each yield" do
+ seen = []
+ @io.send(@method) { |b| seen << @io.pos }
+ seen.should == [1, 2, 3]
+ end
+
+ it "does not yield if the current position is out of bounds" do
+ @io.pos = 1000
+ seen = nil
+ @io.send(@method) { |b| seen = b }
+ seen.should be_nil
+ end
+
+ it "returns self" do
+ @io.send(@method) {}.should equal(@io)
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @io.send(@method)
+ enum.instance_of?(Enumerator).should be_true
+
+ seen = []
+ enum.each { |b| seen << b }
+ seen.should == [120, 121, 122]
+ end
+end
+
+describe :stringio_each_byte_not_readable, shared: true do
+ it "raises an IOError" do
+ io = StringIO.new("xyz", "w")
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+
+ io = StringIO.new("xyz")
+ io.close_read
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/each_char.rb b/spec/ruby/library/stringio/shared/each_char.rb
new file mode 100644
index 0000000000..35efdcb749
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/each_char.rb
@@ -0,0 +1,36 @@
+# -*- encoding: utf-8 -*-
+describe :stringio_each_char, shared: true do
+ before :each do
+ @io = StringIO.new("xyz äöü")
+ end
+
+ it "yields each character code in turn" do
+ seen = []
+ @io.send(@method) { |c| seen << c }
+ seen.should == ["x", "y", "z", " ", "ä", "ö", "ü"]
+ end
+
+ it "returns self" do
+ @io.send(@method) {}.should equal(@io)
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @io.send(@method)
+ enum.instance_of?(Enumerator).should be_true
+
+ seen = []
+ enum.each { |c| seen << c }
+ seen.should == ["x", "y", "z", " ", "ä", "ö", "ü"]
+ end
+end
+
+describe :stringio_each_char_not_readable, shared: true do
+ it "raises an IOError" do
+ io = StringIO.new("xyz", "w")
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+
+ io = StringIO.new("xyz")
+ io.close_read
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/eof.rb b/spec/ruby/library/stringio/shared/eof.rb
new file mode 100644
index 0000000000..e0368a2892
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/eof.rb
@@ -0,0 +1,24 @@
+describe :stringio_eof, shared: true do
+ before :each do
+ @io = StringIO.new("eof")
+ end
+
+ it "returns true when self's position is greater than or equal to self's size" do
+ @io.pos = 3
+ @io.send(@method).should be_true
+
+ @io.pos = 6
+ @io.send(@method).should be_true
+ end
+
+ it "returns false when self's position is less than self's size" do
+ @io.pos = 0
+ @io.send(@method).should be_false
+
+ @io.pos = 1
+ @io.send(@method).should be_false
+
+ @io.pos = 2
+ @io.send(@method).should be_false
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/getc.rb b/spec/ruby/library/stringio/shared/getc.rb
new file mode 100644
index 0000000000..3e064f9c1e
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/getc.rb
@@ -0,0 +1,43 @@
+describe :stringio_getc, shared: true do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "increases self's position by one" do
+ @io.send(@method)
+ @io.pos.should eql(1)
+
+ @io.send(@method)
+ @io.pos.should eql(2)
+
+ @io.send(@method)
+ @io.pos.should eql(3)
+ end
+
+ it "returns nil when called at the end of self" do
+ @io.pos = 7
+ @io.send(@method).should be_nil
+ @io.send(@method).should be_nil
+ @io.send(@method).should be_nil
+ end
+
+ it "does not increase self's position when called at the end of file" do
+ @io.pos = 7
+ @io.send(@method)
+ @io.pos.should eql(7)
+
+ @io.send(@method)
+ @io.pos.should eql(7)
+ end
+end
+
+describe :stringio_getc_not_readable, shared: true do
+ it "raises an IOError" do
+ io = StringIO.new("xyz", "w")
+ lambda { io.send(@method) }.should raise_error(IOError)
+
+ io = StringIO.new("xyz")
+ io.close_read
+ lambda { io.send(@method) }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/isatty.rb b/spec/ruby/library/stringio/shared/isatty.rb
new file mode 100644
index 0000000000..3da5999953
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/isatty.rb
@@ -0,0 +1,5 @@
+describe :stringio_isatty, shared: true do
+ it "returns false" do
+ StringIO.new('tty').send(@method).should be_false
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/length.rb b/spec/ruby/library/stringio/shared/length.rb
new file mode 100644
index 0000000000..60a4eb1bdd
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/length.rb
@@ -0,0 +1,5 @@
+describe :stringio_length, shared: true do
+ it "returns the length of the wrapped string" do
+ StringIO.new("example").send(@method).should == 7
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/read.rb b/spec/ruby/library/stringio/shared/read.rb
new file mode 100644
index 0000000000..025829a2b1
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/read.rb
@@ -0,0 +1,121 @@
+describe :stringio_read, shared: true do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "returns the passed buffer String" do
+ # Note: Rubinius bug:
+ # @io.send(@method, 7, buffer = "").should equal(buffer)
+ ret = @io.send(@method, 7, buffer = "")
+ ret.should equal(buffer)
+ end
+
+ it "reads length bytes and writes them to the buffer String" do
+ @io.send(@method, 7, buffer = "")
+ buffer.should == "example"
+ end
+
+ it "tries to convert the passed buffer Object to a String using #to_str" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return(buffer = "")
+
+ @io.send(@method, 7, obj)
+ buffer.should == "example"
+ end
+
+ it "raises a TypeError when the passed buffer Object can't be converted to a String" do
+ lambda { @io.send(@method, 7, Object.new) }.should raise_error(TypeError)
+ end
+
+ it "raises an error when passed a frozen String as buffer" do
+ lambda { @io.send(@method, 7, "".freeze) }.should raise_error(RuntimeError)
+ end
+end
+
+describe :stringio_read_length, shared: true do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "reads length bytes from the current position and returns them" do
+ @io.pos = 3
+ @io.send(@method, 4).should == "mple"
+ end
+
+ it "reads at most the whole content" do
+ @io.send(@method, 999).should == "example"
+ end
+
+ it "correctly updates the position" do
+ @io.send(@method, 3)
+ @io.pos.should eql(3)
+
+ @io.send(@method, 999)
+ @io.pos.should eql(7)
+ end
+
+ it "tries to convert the passed length to an Integer using #to_int" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(7)
+ @io.send(@method, obj).should == "example"
+ end
+
+ it "raises a TypeError when the passed length can't be converted to an Integer" do
+ lambda { @io.send(@method, Object.new) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when the passed length is negative" do
+ lambda { @io.send(@method, -2) }.should raise_error(ArgumentError)
+ end
+
+ it "returns a binary String" do
+ @io.send(@method, 4).encoding.should == Encoding::ASCII_8BIT
+ end
+end
+
+describe :stringio_read_no_arguments, shared: true do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "reads the whole content starting from the current position" do
+ @io.send(@method).should == "example"
+
+ @io.pos = 3
+ @io.send(@method).should == "mple"
+ end
+
+ it "correctly updates the current position" do
+ @io.send(@method)
+ @io.pos.should eql(7)
+ end
+end
+
+describe :stringio_read_nil, shared: true do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "returns the remaining content from the current position" do
+ @io.send(@method, nil).should == "example"
+
+ @io.pos = 4
+ @io.send(@method, nil).should == "ple"
+ end
+
+ it "updates the current position" do
+ @io.send(@method, nil)
+ @io.pos.should eql(7)
+ end
+end
+
+describe :stringio_read_not_readable, shared: true do
+ it "raises an IOError" do
+ io = StringIO.new("test", "w")
+ lambda { io.send(@method) }.should raise_error(IOError)
+
+ io = StringIO.new("test")
+ io.close_read
+ lambda { io.send(@method) }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/readchar.rb b/spec/ruby/library/stringio/shared/readchar.rb
new file mode 100644
index 0000000000..19194f0680
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/readchar.rb
@@ -0,0 +1,29 @@
+describe :stringio_readchar, shared: true do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "correctly updates the current position" do
+ @io.send(@method)
+ @io.pos.should == 1
+
+ @io.send(@method)
+ @io.pos.should == 2
+ end
+
+ it "raises an EOFError when self is at the end" do
+ @io.pos = 7
+ lambda { @io.send(@method) }.should raise_error(EOFError)
+ end
+end
+
+describe :stringio_readchar_not_readable, shared: true do
+ it "raises an IOError" do
+ io = StringIO.new("a b c d e", "w")
+ lambda { io.send(@method) }.should raise_error(IOError)
+
+ io = StringIO.new("a b c d e")
+ io.close_read
+ lambda { io.send(@method) }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/sysread.rb b/spec/ruby/library/stringio/shared/sysread.rb
new file mode 100644
index 0000000000..9800b2339b
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/sysread.rb
@@ -0,0 +1,15 @@
+describe :stringio_sysread_length, :shared => true do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "returns an empty String when passed 0 and no data remains" do
+ @io.send(@method, 8).should == "example"
+ @io.send(@method, 0).should == ""
+ end
+
+ it "raises an EOFError when passed length > 0 and no data remains" do
+ @io.read.should == "example"
+ lambda { @io.sysread(1) }.should raise_error(EOFError)
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/tell.rb b/spec/ruby/library/stringio/shared/tell.rb
new file mode 100644
index 0000000000..852c51c192
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/tell.rb
@@ -0,0 +1,12 @@
+describe :stringio_tell, shared: true do
+ before :each do
+ @io = StringIOSpecs.build
+ end
+
+ it "returns the current byte offset" do
+ @io.getc
+ @io.send(@method).should == 1
+ @io.read(7)
+ @io.send(@method).should == 8
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/write.rb b/spec/ruby/library/stringio/shared/write.rb
new file mode 100644
index 0000000000..bcb548bbd0
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/write.rb
@@ -0,0 +1,87 @@
+describe :stringio_write, shared: true do
+ before :each do
+ @io = StringIO.new('12345')
+ end
+
+ it "tries to convert the passed Object to a String using #to_s" do
+ obj = mock("to_s")
+ obj.should_receive(:to_s).and_return("to_s")
+ @io.send(@method, obj)
+ @io.string.should == "to_s5"
+ end
+end
+
+describe :stringio_write_string, shared: true do
+ before :each do
+ @io = StringIO.new('12345')
+ end
+
+ # TODO: RDoc says that #write appends at the current position.
+ it "writes the passed String at the current buffer position" do
+ @io.pos = 2
+ @io.send(@method, 'x').should == 1
+ @io.string.should == '12x45'
+ @io.send(@method, 7).should == 1
+ @io.string.should == '12x75'
+ end
+
+ it "pads self with \\000 when the current position is after the end" do
+ @io.pos = 8
+ @io.send(@method, 'x')
+ @io.string.should == "12345\000\000\000x"
+ @io.send(@method, 9)
+ @io.string.should == "12345\000\000\000x9"
+ end
+
+ it "returns the number of bytes written" do
+ @io.send(@method, '').should == 0
+ @io.send(@method, nil).should == 0
+ str = "1" * 100
+ @io.send(@method, str).should == 100
+ end
+
+ it "updates self's position" do
+ @io.send(@method, 'test')
+ @io.pos.should eql(4)
+ end
+
+ it "taints self's String when the passed argument is tainted" do
+ @io.send(@method, "test".taint)
+ @io.string.tainted?.should be_true
+ end
+
+ it "does not taint self when the passed argument is tainted" do
+ @io.send(@method, "test".taint)
+ @io.tainted?.should be_false
+ end
+end
+
+describe :stringio_write_not_writable, shared: true do
+ it "raises an IOError" do
+ io = StringIO.new("test", "r")
+ lambda { io.send(@method, "test") }.should raise_error(IOError)
+
+ io = StringIO.new("test")
+ io.close_write
+ lambda { io.send(@method, "test") }.should raise_error(IOError)
+ end
+end
+
+describe :stringio_write_append, shared: true do
+ before :each do
+ @io = StringIO.new("example", "a")
+ end
+
+ it "appends the passed argument to the end of self" do
+ @io.send(@method, ", just testing")
+ @io.string.should == "example, just testing"
+
+ @io.send(@method, " and more testing")
+ @io.string.should == "example, just testing and more testing"
+ end
+
+ it "correctly updates self's position" do
+ @io.send(@method, ", testing")
+ @io.pos.should eql(16)
+ end
+end
diff --git a/spec/ruby/library/stringio/size_spec.rb b/spec/ruby/library/stringio/size_spec.rb
new file mode 100644
index 0000000000..1d6a7fc15e
--- /dev/null
+++ b/spec/ruby/library/stringio/size_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+
+describe "StringIO#size" do
+ it_behaves_like :stringio_length, :size
+end
diff --git a/spec/ruby/library/stringio/string_spec.rb b/spec/ruby/library/stringio/string_spec.rb
new file mode 100644
index 0000000000..7c4181b6de
--- /dev/null
+++ b/spec/ruby/library/stringio/string_spec.rb
@@ -0,0 +1,50 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#string" do
+ it "returns the underlying string" do
+ io = StringIO.new(str = "hello")
+ io.string.should equal(str)
+ end
+end
+
+describe "StringIO#string=" do
+ before :each do
+ @io = StringIO.new("example\nstring")
+ end
+
+ it "returns the passed String" do
+ str = "test"
+ (@io.string = str).should equal(str)
+ end
+
+ it "changes the underlying string" do
+ str = "hello"
+ @io.string = str
+ @io.string.should equal(str)
+ end
+
+ it "resets the position" do
+ @io.pos = 1
+ @io.string = "other"
+ @io.pos.should eql(0)
+ end
+
+ it "resets the line number" do
+ @io.lineno = 1
+ @io.string = "other"
+ @io.lineno.should eql(0)
+ end
+
+ it "tries to convert the passed Object to a String using #to_str" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return("to_str")
+
+ @io.string = obj
+ @io.string.should == "to_str"
+ end
+
+ it "raises a TypeError when the passed Object can't be converted to an Integer" do
+ lambda { @io.seek(Object.new) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/stringio/stringio_spec.rb b/spec/ruby/library/stringio/stringio_spec.rb
new file mode 100644
index 0000000000..9e2cb9cf90
--- /dev/null
+++ b/spec/ruby/library/stringio/stringio_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "stringio"
+
+describe "StringIO" do
+ it "includes the Enumerable module" do
+ StringIO.should include(Enumerable)
+ end
+end
+
diff --git a/spec/ruby/library/stringio/sync_spec.rb b/spec/ruby/library/stringio/sync_spec.rb
new file mode 100644
index 0000000000..b662d7b7cc
--- /dev/null
+++ b/spec/ruby/library/stringio/sync_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#sync" do
+ it "returns true" do
+ StringIO.new('').sync.should be_true
+ end
+end
+
+describe "StringIO#sync=" do
+ before :each do
+ @io = StringIO.new('')
+ end
+
+ it "does not change 'sync' status" do
+ @io.sync = false
+ @io.sync.should be_true
+ end
+end
diff --git a/spec/ruby/library/stringio/sysread_spec.rb b/spec/ruby/library/stringio/sysread_spec.rb
new file mode 100644
index 0000000000..cce8d8c88a
--- /dev/null
+++ b/spec/ruby/library/stringio/sysread_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "stringio"
+require File.expand_path('../shared/read', __FILE__)
+
+describe "StringIO#sysread when passed length, buffer" do
+ it_behaves_like :stringio_read, :sysread
+end
+
+describe "StringIO#sysread when passed [length]" do
+ it_behaves_like :stringio_read_length, :sysread
+end
+
+describe "StringIO#sysread when passed no arguments" do
+ it_behaves_like :stringio_read_no_arguments, :sysread
+
+ it "returns an empty String if at EOF" do
+ @io.sysread.should == "example"
+ @io.sysread.should == ""
+ end
+end
+
+describe "StringIO#sysread when self is not readable" do
+ it_behaves_like :stringio_read_not_readable, :sysread
+end
+
+describe "StringIO#sysread when passed nil" do
+ it_behaves_like :stringio_read_nil, :sysread
+
+ it "returns an empty String if at EOF" do
+ @io.sysread(nil).should == "example"
+ @io.sysread(nil).should == ""
+ end
+end
+
+describe "StringIO#sysread when passed [length]" do
+ before :each do
+ @io = StringIO.new("example")
+ end
+
+ it "raises an EOFError when self's position is at the end" do
+ @io.pos = 7
+ lambda { @io.sysread(10) }.should raise_error(EOFError)
+ end
+
+ it "returns an empty String when length is 0" do
+ @io.sysread(0).should == ""
+ end
+end
diff --git a/spec/ruby/library/stringio/syswrite_spec.rb b/spec/ruby/library/stringio/syswrite_spec.rb
new file mode 100644
index 0000000000..8b65e81a05
--- /dev/null
+++ b/spec/ruby/library/stringio/syswrite_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/write', __FILE__)
+
+describe "StringIO#syswrite when passed [Object]" do
+ it_behaves_like :stringio_write, :syswrite
+end
+
+describe "StringIO#syswrite when passed [String]" do
+ it_behaves_like :stringio_write_string, :syswrite
+end
+
+describe "StringIO#syswrite when self is not writable" do
+ it_behaves_like :stringio_write_not_writable, :syswrite
+end
+
+describe "StringIO#syswrite when in append mode" do
+ it_behaves_like :stringio_write_append, :syswrite
+end
diff --git a/spec/ruby/library/stringio/tell_spec.rb b/spec/ruby/library/stringio/tell_spec.rb
new file mode 100644
index 0000000000..af6a01497e
--- /dev/null
+++ b/spec/ruby/library/stringio/tell_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/tell', __FILE__)
+
+describe "StringIO#tell" do
+ it_behaves_like :stringio_tell, :tell
+end
diff --git a/spec/ruby/library/stringio/truncate_spec.rb b/spec/ruby/library/stringio/truncate_spec.rb
new file mode 100644
index 0000000000..1023b3d13c
--- /dev/null
+++ b/spec/ruby/library/stringio/truncate_spec.rb
@@ -0,0 +1,70 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "stringio"
+
+describe "StringIO#truncate when passed [length]" do
+ before :each do
+ @io = StringIO.new('123456789')
+ end
+
+ # TODO: Report to Ruby-Core: The RDoc says it always returns 0
+ it "returns the passed length" do
+ @io.truncate(4).should eql(4)
+ @io.truncate(10).should eql(10)
+ end
+
+ it "truncated the underlying string down to the passed length" do
+ @io.truncate(4)
+ @io.string.should == "1234"
+ end
+
+ it "does not create a copy of the underlying string" do
+ io = StringIO.new(str = "123456789")
+ io.truncate(4)
+ io.string.should equal(str)
+ end
+
+ it "does not change the position" do
+ @io.pos = 7
+ @io.truncate(4)
+ @io.pos.should eql(7)
+ end
+
+ it "can grow a string to a larger size, padding it with \\000" do
+ @io.truncate(12)
+ @io.string.should == "123456789\000\000\000"
+ end
+
+ it "raises an Errno::EINVAL when the passed length is negative" do
+ lambda { @io.truncate(-1) }.should raise_error(Errno::EINVAL)
+ lambda { @io.truncate(-10) }.should raise_error(Errno::EINVAL)
+ end
+
+ it "tries to convert the passed length to an Integer using #to_int" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(4)
+
+ @io.truncate(obj)
+ @io.string.should == "1234"
+ end
+
+ it "returns the passed length Object, NOT the result of #to_int" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return(4)
+ @io.truncate(obj).should equal(obj)
+ end
+
+ it "raises a TypeError when the passed length can't be converted to an Integer" do
+ lambda { @io.truncate(Object.new) }.should raise_error(TypeError)
+ end
+end
+
+describe "StringIO#truncate when self is not writable" do
+ it "raises an IOError" do
+ io = StringIO.new("test", "r")
+ lambda { io.truncate(2) }.should raise_error(IOError)
+
+ io = StringIO.new("test")
+ io.close_write
+ lambda { io.truncate(2) }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/stringio/tty_spec.rb b/spec/ruby/library/stringio/tty_spec.rb
new file mode 100644
index 0000000000..7540e68a2b
--- /dev/null
+++ b/spec/ruby/library/stringio/tty_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/isatty', __FILE__)
+
+describe "StringIO#tty?" do
+ it_behaves_like :stringio_isatty, :tty?
+end
diff --git a/spec/ruby/library/stringio/ungetbyte_spec.rb b/spec/ruby/library/stringio/ungetbyte_spec.rb
new file mode 100644
index 0000000000..a7d9b28024
--- /dev/null
+++ b/spec/ruby/library/stringio/ungetbyte_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'stringio'
+
+describe "StringIO#ungetbyte" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/stringio/ungetc_spec.rb b/spec/ruby/library/stringio/ungetc_spec.rb
new file mode 100644
index 0000000000..613d49cfbd
--- /dev/null
+++ b/spec/ruby/library/stringio/ungetc_spec.rb
@@ -0,0 +1,72 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "StringIO#ungetc when passed [char]" do
+ before :each do
+ @io = StringIO.new('1234')
+ end
+
+ it "writes the passed char before the current position" do
+ @io.pos = 1
+ @io.ungetc(?A)
+ @io.string.should == 'A234'
+ end
+
+ it "returns nil" do
+ @io.pos = 1
+ @io.ungetc(?A).should be_nil
+ end
+
+ it "decreases the current position by one" do
+ @io.pos = 2
+ @io.ungetc(?A)
+ @io.pos.should eql(1)
+ end
+
+ it "pads with \\000 when the current position is after the end" do
+ @io.pos = 15
+ @io.ungetc(?A)
+ @io.string.should == "1234\000\000\000\000\000\000\000\000\000\000A"
+ end
+
+ it "tries to convert the passed argument to an String using #to_str" do
+ obj = mock("to_str")
+ obj.should_receive(:to_str).and_return(?A)
+
+ @io.pos = 1
+ @io.ungetc(obj)
+ @io.string.should == "A234"
+ end
+
+ it "raises a TypeError when the passed length can't be converted to an Integer or String" do
+ lambda { @io.ungetc(Object.new) }.should raise_error(TypeError)
+ end
+end
+
+describe "StringIO#ungetc when self is not readable" do
+ it "raises an IOError" do
+ io = StringIO.new("test", "w")
+ io.pos = 1
+ lambda { io.ungetc(?A) }.should raise_error(IOError)
+
+ io = StringIO.new("test")
+ io.pos = 1
+ io.close_read
+ lambda { io.ungetc(?A) }.should raise_error(IOError)
+ end
+end
+
+# Note: This is incorrect.
+#
+# describe "StringIO#ungetc when self is not writable" do
+# it "raises an IOError" do
+# io = StringIO.new("test", "r")
+# io.pos = 1
+# lambda { io.ungetc(?A) }.should raise_error(IOError)
+#
+# io = StringIO.new("test")
+# io.pos = 1
+# io.close_write
+# lambda { io.ungetc(?A) }.should raise_error(IOError)
+# end
+# end
diff --git a/spec/ruby/library/stringio/write_nonblock_spec.rb b/spec/ruby/library/stringio/write_nonblock_spec.rb
new file mode 100644
index 0000000000..d4d5ab5a85
--- /dev/null
+++ b/spec/ruby/library/stringio/write_nonblock_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/write', __FILE__)
+
+describe "StringIO#write_nonblock when passed [Object]" do
+ it_behaves_like :stringio_write, :write_nonblock
+end
+
+describe "StringIO#write_nonblock when passed [String]" do
+ it_behaves_like :stringio_write_string, :write_nonblock
+end
+
+describe "StringIO#write_nonblock when self is not writable" do
+ it_behaves_like :stringio_write_not_writable, :write_nonblock
+end
+
+describe "StringIO#write_nonblock when in append mode" do
+ it_behaves_like :stringio_write_append, :write_nonblock
+end
diff --git a/spec/ruby/library/stringio/write_spec.rb b/spec/ruby/library/stringio/write_spec.rb
new file mode 100644
index 0000000000..706234da7e
--- /dev/null
+++ b/spec/ruby/library/stringio/write_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+require File.expand_path('../shared/write', __FILE__)
+
+describe "StringIO#write when passed [Object]" do
+ it_behaves_like :stringio_write, :write
+end
+
+describe "StringIO#write when passed [String]" do
+ it_behaves_like :stringio_write_string, :write
+end
+
+describe "StringIO#write when self is not writable" do
+ it_behaves_like :stringio_write_not_writable, :write
+end
+
+describe "StringIO#write when in append mode" do
+ it_behaves_like :stringio_write_append, :write
+end
diff --git a/spec/ruby/library/stringscanner/append_spec.rb b/spec/ruby/library/stringscanner/append_spec.rb
new file mode 100644
index 0000000000..f75b3cc715
--- /dev/null
+++ b/spec/ruby/library/stringscanner/append_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/concat.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#<<" do
+ it_behaves_like :strscan_concat, :<<
+end
+
+describe "StringScanner#<< when passed a Fixnum" do
+ it_behaves_like :strscan_concat_fixnum, :<<
+end
diff --git a/spec/ruby/library/stringscanner/beginning_of_line_spec.rb b/spec/ruby/library/stringscanner/beginning_of_line_spec.rb
new file mode 100644
index 0000000000..192a83f2c9
--- /dev/null
+++ b/spec/ruby/library/stringscanner/beginning_of_line_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/bol.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#beginning_of_line?" do
+ it_behaves_like(:strscan_bol, :beginning_of_line?)
+end
diff --git a/spec/ruby/library/stringscanner/bol_spec.rb b/spec/ruby/library/stringscanner/bol_spec.rb
new file mode 100644
index 0000000000..ee5257529a
--- /dev/null
+++ b/spec/ruby/library/stringscanner/bol_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/bol.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#bol?" do
+ it_behaves_like(:strscan_bol, :bol?)
+end
diff --git a/spec/ruby/library/stringscanner/check_spec.rb b/spec/ruby/library/stringscanner/check_spec.rb
new file mode 100644
index 0000000000..db98197f81
--- /dev/null
+++ b/spec/ruby/library/stringscanner/check_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#check" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the value that scan would return, without advancing the scan pointer" do
+ @s.check(/This/).should == "This"
+ @s.matched.should == "This"
+ @s.pos.should == 0
+ @s.check(/is/).should == nil
+ @s.matched.should == nil
+ end
+end
diff --git a/spec/ruby/library/stringscanner/check_until_spec.rb b/spec/ruby/library/stringscanner/check_until_spec.rb
new file mode 100644
index 0000000000..e397b2e4c1
--- /dev/null
+++ b/spec/ruby/library/stringscanner/check_until_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#check_until" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the same value of scan_until, but don't advances the scan pointer" do
+ @s.check_until(/a/).should == "This is a"
+ @s.pos.should == 0
+ @s.matched.should == "a"
+ @s.check_until(/test/).should == "This is a test"
+ end
+end
diff --git a/spec/ruby/library/stringscanner/clear_spec.rb b/spec/ruby/library/stringscanner/clear_spec.rb
new file mode 100644
index 0000000000..81b2e68897
--- /dev/null
+++ b/spec/ruby/library/stringscanner/clear_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/terminate.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#clear" do
+ it_behaves_like(:strscan_terminate, :clear)
+
+ it "warns in verbose mode that the method is obsolete" do
+ s = StringScanner.new("abc")
+ lambda {
+ $VERBOSE = true
+ s.clear
+ }.should complain(/clear.*obsolete.*terminate/)
+
+ lambda {
+ $VERBOSE = false
+ s.clear
+ }.should_not complain
+ end
+end
diff --git a/spec/ruby/library/stringscanner/concat_spec.rb b/spec/ruby/library/stringscanner/concat_spec.rb
new file mode 100644
index 0000000000..dccc7d0efd
--- /dev/null
+++ b/spec/ruby/library/stringscanner/concat_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/concat.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#concat" do
+ it_behaves_like(:strscan_concat, :concat)
+end
+
+describe "StringScanner#concat when passed a Fixnum" do
+ it_behaves_like(:strscan_concat_fixnum, :concat)
+end
diff --git a/spec/ruby/library/stringscanner/dup_spec.rb b/spec/ruby/library/stringscanner/dup_spec.rb
new file mode 100644
index 0000000000..2f0feff071
--- /dev/null
+++ b/spec/ruby/library/stringscanner/dup_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#dup" do
+ before :each do
+ @string = "this is a test"
+ @orig_s = StringScanner.new(@string)
+ end
+
+ it "copies the passed StringScanner's content to self" do
+ s = @orig_s.dup
+ s.string.should == @string
+ end
+
+ it "copies the passed StringSCanner's position to self" do
+ @orig_s.pos = 5
+ s = @orig_s.dup
+ s.pos.should eql(5)
+ end
+
+ it "copies previous match state" do
+ @orig_s.scan(/\w+/)
+ @orig_s.scan(/\s/)
+
+ @orig_s.pre_match.should == "this"
+
+ s = @orig_s.dup
+ s.pre_match.should == "this"
+
+ s.unscan
+ s.scan(/\s/).should == " "
+ end
+
+ it "copies the passed StringScanner scan pointer to self" do
+ @orig_s.terminate
+ s = @orig_s.dup
+ s.eos?.should be_true
+ end
+end
diff --git a/spec/ruby/library/stringscanner/element_reference_spec.rb b/spec/ruby/library/stringscanner/element_reference_spec.rb
new file mode 100644
index 0000000000..c9acb1c7e7
--- /dev/null
+++ b/spec/ruby/library/stringscanner/element_reference_spec.rb
@@ -0,0 +1,61 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#[]" do
+ before :each do
+ @s = StringScanner.new("Fri Jun 13 2008 22:43")
+ end
+
+ it "returns nil if there is no current match" do
+ @s[0].should be_nil
+ end
+
+ it "returns the n-th subgroup in the most recent match" do
+ @s.scan(/(\w+) (\w+) (\d+) /)
+ @s[0].should == "Fri Jun 13 "
+ @s[1].should == "Fri"
+ @s[2].should == "Jun"
+ @s[3].should == "13"
+ @s[-3].should == "Fri"
+ @s[-2].should == "Jun"
+ @s[-1].should == "13"
+ end
+
+ it "returns nil if index is outside of self" do
+ @s.scan(/(\w+) (\w+) (\d+) /)
+ @s[5].should == nil
+ @s[-5].should == nil
+ end
+
+ it "calls to_int on the given index" do
+ @s.scan(/(\w+) (\w+) (\d+) /)
+ @s[0.5].should == "Fri Jun 13 "
+ end
+
+ it "raises a TypeError if the given index is nil" do
+ @s.scan(/(\w+) (\w+) (\d+) /)
+ lambda { @s[nil]}.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when a Range is as argument" do
+ @s.scan(/(\w+) (\w+) (\d+) /)
+ lambda { @s[0..2]}.should raise_error(TypeError)
+ end
+
+ it "raises a IndexError when there's no named capture" do
+ @s.scan(/(\w+) (\w+) (\d+) /)
+ lambda { @s["wday"]}.should raise_error(IndexError)
+ lambda { @s[:wday]}.should raise_error(IndexError)
+ end
+
+ it "returns named capture" do
+ @s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
+ @s["wday"].should == "Fri"
+ @s["month"].should == "Jun"
+ @s["day"].should == "13"
+ @s[:wday].should == "Fri"
+ @s[:month].should == "Jun"
+ @s[:day].should == "13"
+ end
+end
+
diff --git a/spec/ruby/library/stringscanner/empty_spec.rb b/spec/ruby/library/stringscanner/empty_spec.rb
new file mode 100644
index 0000000000..ebbc2c2703
--- /dev/null
+++ b/spec/ruby/library/stringscanner/empty_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/eos.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#empty?" do
+ it_behaves_like(:strscan_eos, :empty?)
+
+ it "warns in verbose mode that the method is obsolete" do
+ s = StringScanner.new("abc")
+ lambda {
+ $VERBOSE = true
+ s.empty?
+ }.should complain(/empty?.*obsolete.*eos?/)
+
+ lambda {
+ $VERBOSE = false
+ s.empty?
+ }.should_not complain
+ end
+end
diff --git a/spec/ruby/library/stringscanner/eos_spec.rb b/spec/ruby/library/stringscanner/eos_spec.rb
new file mode 100644
index 0000000000..3fdeceb25d
--- /dev/null
+++ b/spec/ruby/library/stringscanner/eos_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/eos.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#eos?" do
+ it_behaves_like(:strscan_eos, :eos?)
+end
diff --git a/spec/ruby/library/stringscanner/exist_spec.rb b/spec/ruby/library/stringscanner/exist_spec.rb
new file mode 100644
index 0000000000..ff13de89df
--- /dev/null
+++ b/spec/ruby/library/stringscanner/exist_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#exist?" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the index of the first occurrence of the given pattern" do
+ @s.exist?(/s/).should == 4
+ @s.scan(/This is/)
+ @s.exist?(/s/).should == 6
+ end
+
+ it "returns 0 if the pattern is empty" do
+ @s.exist?(//).should == 0
+ end
+
+ it "returns nil if the pattern isn't found in the string" do
+ @s.exist?(/S/).should == nil
+ @s.scan(/This is/)
+ @s.exist?(/i/).should == nil
+ end
+end
diff --git a/spec/ruby/library/stringscanner/get_byte_spec.rb b/spec/ruby/library/stringscanner/get_byte_spec.rb
new file mode 100644
index 0000000000..786b068042
--- /dev/null
+++ b/spec/ruby/library/stringscanner/get_byte_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/get_byte', __FILE__)
+require 'strscan'
+
+describe "StringScanner#get_byte" do
+ it_behaves_like :strscan_get_byte, :get_byte
+end
diff --git a/spec/ruby/library/stringscanner/getbyte_spec.rb b/spec/ruby/library/stringscanner/getbyte_spec.rb
new file mode 100644
index 0000000000..6d3b8c357d
--- /dev/null
+++ b/spec/ruby/library/stringscanner/getbyte_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/get_byte', __FILE__)
+require File.expand_path('../shared/extract_range', __FILE__)
+require 'strscan'
+
+describe "StringScanner#getbyte" do
+ it_behaves_like :strscan_get_byte, :getbyte
+
+ it "warns in verbose mode that the method is obsolete" do
+ s = StringScanner.new("abc")
+ lambda {
+ $VERBOSE = true
+ s.getbyte
+ }.should complain(/getbyte.*obsolete.*get_byte/)
+
+ lambda {
+ $VERBOSE = false
+ s.getbyte
+ }.should_not complain
+ end
+
+ it_behaves_like :extract_range, :getbyte
+end
diff --git a/spec/ruby/library/stringscanner/getch_spec.rb b/spec/ruby/library/stringscanner/getch_spec.rb
new file mode 100644
index 0000000000..ae2907d817
--- /dev/null
+++ b/spec/ruby/library/stringscanner/getch_spec.rb
@@ -0,0 +1,35 @@
+# -*- encoding: binary -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/extract_range', __FILE__)
+require 'strscan'
+
+describe "StringScanner#getch" do
+ it "scans one character and returns it" do
+ s = StringScanner.new('abc')
+ s.getch.should == "a"
+ s.getch.should == "b"
+ s.getch.should == "c"
+ end
+
+ it "is multi-byte character sensitive" do
+ # Japanese hiragana "A" in EUC-JP
+ src = "\244\242".force_encoding("euc-jp")
+
+ s = StringScanner.new(src)
+ s.getch.should == src
+ end
+
+ it "returns nil at the end of the string" do
+ # empty string case
+ s = StringScanner.new('')
+ s.getch.should == nil
+ s.getch.should == nil
+
+ # non-empty string case
+ s = StringScanner.new('a')
+ s.getch # skip one
+ s.getch.should == nil
+ end
+
+ it_behaves_like :extract_range, :getch
+end
diff --git a/spec/ruby/library/stringscanner/initialize_spec.rb b/spec/ruby/library/stringscanner/initialize_spec.rb
new file mode 100644
index 0000000000..ab0ea23408
--- /dev/null
+++ b/spec/ruby/library/stringscanner/initialize_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#initialize" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "is a private method" do
+ StringScanner.should have_private_instance_method(:initialize)
+ end
+
+ it "returns an instance of StringScanner" do
+ @s.should be_kind_of(StringScanner)
+ @s.tainted?.should be_false
+ @s.eos?.should be_false
+ end
+
+ it "converts the argument into a string using #to_str" do
+ m = mock(:str)
+
+ s = "test"
+ m.should_receive(:to_str).and_return(s)
+
+ scan = StringScanner.new(m)
+ scan.string.should == s
+ end
+end
diff --git a/spec/ruby/library/stringscanner/inspect_spec.rb b/spec/ruby/library/stringscanner/inspect_spec.rb
new file mode 100644
index 0000000000..2f22a29a2e
--- /dev/null
+++ b/spec/ruby/library/stringscanner/inspect_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#inspect" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns a String object" do
+ @s.inspect.should be_kind_of(String)
+ end
+
+ it "returns a string that represents the StringScanner object" do
+ @s.inspect.should == "#<StringScanner 0/14 @ \"This ...\">"
+ @s.scan_until(/is/)
+ @s.inspect.should == "#<StringScanner 4/14 \"This\" @ \" is a...\">"
+ @s.terminate
+ @s.inspect.should == "#<StringScanner fin>"
+ end
+end
diff --git a/spec/ruby/library/stringscanner/match_spec.rb b/spec/ruby/library/stringscanner/match_spec.rb
new file mode 100644
index 0000000000..227be6c3a5
--- /dev/null
+++ b/spec/ruby/library/stringscanner/match_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#match?" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the length of the match and the scan pointer is not advanced" do
+ @s.match?(/\w+/).should == 4
+ @s.match?(/\w+/).should == 4
+ @s.pos.should == 0
+ end
+
+ it "returns nil if there's no match" do
+ @s.match?(/\d+/).should == nil
+ @s.match?(/\s+/).should == nil
+ end
+
+ it "effects pre_match" do
+ @s.scan(/\w+/)
+ @s.scan(/\s/)
+
+ @s.pre_match.should == "This"
+ @s.match?(/\w+/)
+ @s.pre_match.should == "This "
+ end
+end
diff --git a/spec/ruby/library/stringscanner/matched_size_spec.rb b/spec/ruby/library/stringscanner/matched_size_spec.rb
new file mode 100644
index 0000000000..7aac71878a
--- /dev/null
+++ b/spec/ruby/library/stringscanner/matched_size_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/matched_size.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#matched_size" do
+ it_behaves_like(:strscan_matched_size, :matched_size)
+end
diff --git a/spec/ruby/library/stringscanner/matched_spec.rb b/spec/ruby/library/stringscanner/matched_spec.rb
new file mode 100644
index 0000000000..1d781bd3ef
--- /dev/null
+++ b/spec/ruby/library/stringscanner/matched_spec.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/extract_range_matched', __FILE__)
+require 'strscan'
+
+describe "StringScanner#matched" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the last matched string" do
+ @s.match?(/\w+/)
+ @s.matched.should == "This"
+ @s.getch
+ @s.matched.should == "T"
+ @s.get_byte
+ @s.matched.should == "h"
+ end
+
+ it "returns nil if there's no match" do
+ @s.match?(/\d+/)
+ @s.matched.should == nil
+ end
+
+ it_behaves_like :extract_range_matched, :matched
+end
+
+describe "StringScanner#matched?" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns true if the last match was successful" do
+ @s.match?(/\w+/)
+ @s.matched?.should be_true
+ end
+
+ it "returns false if there's no match" do
+ @s.match?(/\d+/)
+ @s.matched?.should be_false
+ end
+end
diff --git a/spec/ruby/library/stringscanner/must_C_version_spec.rb b/spec/ruby/library/stringscanner/must_C_version_spec.rb
new file mode 100644
index 0000000000..c7d24ed2f8
--- /dev/null
+++ b/spec/ruby/library/stringscanner/must_C_version_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner.must_C_version" do
+ it "returns self" do
+ StringScanner.must_C_version.should == StringScanner
+ end
+end
diff --git a/spec/ruby/library/stringscanner/peek_spec.rb b/spec/ruby/library/stringscanner/peek_spec.rb
new file mode 100644
index 0000000000..49490ec3da
--- /dev/null
+++ b/spec/ruby/library/stringscanner/peek_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/peek.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#peek" do
+ it_behaves_like(:strscan_peek, :peek)
+end
+
diff --git a/spec/ruby/library/stringscanner/peep_spec.rb b/spec/ruby/library/stringscanner/peep_spec.rb
new file mode 100644
index 0000000000..677c6f8a21
--- /dev/null
+++ b/spec/ruby/library/stringscanner/peep_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/peek.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#peep" do
+ it_behaves_like(:strscan_peek, :peep)
+
+ it "warns in verbose mode that the method is obsolete" do
+ s = StringScanner.new("abc")
+ lambda {
+ $VERBOSE = true
+ s.peep(1)
+ }.should complain(/peep.*obsolete.*peek/)
+
+ lambda {
+ $VERBOSE = false
+ s.peep(1)
+ }.should_not complain
+ end
+end
diff --git a/spec/ruby/library/stringscanner/pointer_spec.rb b/spec/ruby/library/stringscanner/pointer_spec.rb
new file mode 100644
index 0000000000..8c993c5a71
--- /dev/null
+++ b/spec/ruby/library/stringscanner/pointer_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/pos.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#pointer" do
+ it_behaves_like(:strscan_pos, :pointer)
+end
+
+describe "StringScanner#pointer=" do
+ it_behaves_like(:strscan_pos_set, :pointer=)
+end
diff --git a/spec/ruby/library/stringscanner/pos_spec.rb b/spec/ruby/library/stringscanner/pos_spec.rb
new file mode 100644
index 0000000000..059e6ff846
--- /dev/null
+++ b/spec/ruby/library/stringscanner/pos_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/pos.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#pos" do
+ it_behaves_like(:strscan_pos, :pos)
+end
+
+describe "StringScanner#pos=" do
+ it_behaves_like(:strscan_pos_set, :pos=)
+end
diff --git a/spec/ruby/library/stringscanner/post_match_spec.rb b/spec/ruby/library/stringscanner/post_match_spec.rb
new file mode 100644
index 0000000000..94064bb368
--- /dev/null
+++ b/spec/ruby/library/stringscanner/post_match_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/extract_range_matched', __FILE__)
+require 'strscan'
+
+describe "StringScanner#post_match" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the post-match (in the regular expression sense) of the last scan" do
+ @s.post_match.should == nil
+ @s.scan(/\w+\s/)
+ @s.post_match.should == "is a test"
+ @s.getch
+ @s.post_match.should == "s a test"
+ @s.get_byte
+ @s.post_match.should == " a test"
+ @s.get_byte
+ @s.post_match.should == "a test"
+ end
+
+ it "returns nil if there's no match" do
+ @s.scan(/\s+/)
+ @s.post_match.should == nil
+ end
+
+ it_behaves_like :extract_range_matched, :post_match
+end
diff --git a/spec/ruby/library/stringscanner/pre_match_spec.rb b/spec/ruby/library/stringscanner/pre_match_spec.rb
new file mode 100644
index 0000000000..0d4759dc5c
--- /dev/null
+++ b/spec/ruby/library/stringscanner/pre_match_spec.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/extract_range_matched', __FILE__)
+require 'strscan'
+
+describe "StringScanner#pre_match" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the pre-match (in the regular expression sense) of the last scan" do
+ @s.pre_match.should == nil
+ @s.scan(/\w+\s/)
+ @s.pre_match.should == ""
+ @s.getch
+ @s.pre_match.should == "This "
+ @s.get_byte
+ @s.pre_match.should == "This i"
+ @s.get_byte
+ @s.pre_match.should == "This is"
+ end
+
+ it "returns nil if there's no match" do
+ @s.scan(/\s+/)
+ @s.pre_match.should == nil
+ end
+
+ it "is more than just the data from the last match" do
+ @s.scan(/\w+/)
+ @s.scan_until(/a te/)
+ @s.pre_match.should == "This is "
+ end
+
+ it "is not changed when the scanner's position changes" do
+ @s.scan_until(/\s+/)
+ @s.pre_match.should == "This"
+ @s.pos -= 1
+ @s.pre_match.should == "This"
+ end
+
+ it_behaves_like :extract_range_matched, :pre_match
+end
diff --git a/spec/ruby/library/stringscanner/reset_spec.rb b/spec/ruby/library/stringscanner/reset_spec.rb
new file mode 100644
index 0000000000..9631d0bb4a
--- /dev/null
+++ b/spec/ruby/library/stringscanner/reset_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#reset" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "reset the scan pointer and clear matching data" do
+ @s.scan(/This/)
+ @s.reset
+ @s.pos.should == 0
+ @s.matched.should == nil
+ end
+end
diff --git a/spec/ruby/library/stringscanner/rest_size_spec.rb b/spec/ruby/library/stringscanner/rest_size_spec.rb
new file mode 100644
index 0000000000..ad019f2a6b
--- /dev/null
+++ b/spec/ruby/library/stringscanner/rest_size_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/rest_size.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#rest_size" do
+ it_behaves_like(:strscan_rest_size, :rest_size)
+end
diff --git a/spec/ruby/library/stringscanner/rest_spec.rb b/spec/ruby/library/stringscanner/rest_spec.rb
new file mode 100644
index 0000000000..87f2d056bb
--- /dev/null
+++ b/spec/ruby/library/stringscanner/rest_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/extract_range_matched', __FILE__)
+require 'strscan'
+
+describe "StringScanner#rest" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the rest of the string" do
+ @s.scan(/This\s+/)
+ @s.rest.should == "is a test"
+ end
+
+ it "returns self in the reset position" do
+ @s.reset
+ @s.rest.should == @s.string
+ end
+
+ it "returns an empty string in the terminate position" do
+ @s.terminate
+ @s.rest.should == ""
+ end
+
+ it_behaves_like :extract_range_matched, :rest
+
+end
+
+describe "StringScanner#rest?" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns true if there is more data in the string" do
+ @s.rest?.should be_true
+ @s.scan(/This/)
+ @s.rest?.should be_true
+ end
+
+ it "returns false if there is no more data in the string" do
+ @s.terminate
+ @s.rest?.should be_false
+ end
+
+ it "is the opposite of eos?" do
+ @s.rest?.should_not == @s.eos?
+ end
+end
diff --git a/spec/ruby/library/stringscanner/restsize_spec.rb b/spec/ruby/library/stringscanner/restsize_spec.rb
new file mode 100644
index 0000000000..9822d69d84
--- /dev/null
+++ b/spec/ruby/library/stringscanner/restsize_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/rest_size.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#restsize" do
+ it_behaves_like(:strscan_rest_size, :restsize)
+
+ it "warns in verbose mode that the method is obsolete" do
+ s = StringScanner.new("abc")
+ lambda {
+ $VERBOSE = true
+ s.restsize
+ }.should complain(/restsize.*obsolete.*rest_size/)
+
+ lambda {
+ $VERBOSE = false
+ s.restsize
+ }.should_not complain
+ end
+end
diff --git a/spec/ruby/library/stringscanner/scan_full_spec.rb b/spec/ruby/library/stringscanner/scan_full_spec.rb
new file mode 100644
index 0000000000..ada9578558
--- /dev/null
+++ b/spec/ruby/library/stringscanner/scan_full_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#scan_full" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the number of bytes advanced" do
+ orig_pos = @s.pos
+ @s.scan_full(/This/, false, false).should == 4
+ @s.pos.should == orig_pos
+ end
+
+ it "returns the number of bytes advanced and advances the scan pointer if the second argument is true" do
+ @s.scan_full(/This/, true, false).should == 4
+ @s.pos.should == 4
+ end
+
+ it "returns the matched string if the third argument is true" do
+ orig_pos = @s.pos
+ @s.scan_full(/This/, false, true).should == "This"
+ @s.pos.should == orig_pos
+ end
+
+ it "returns the matched string if the third argument is true and advances the scan pointer if the second argument is true" do
+ @s.scan_full(/This/, true, true).should == "This"
+ @s.pos.should == 4
+ end
+end
diff --git a/spec/ruby/library/stringscanner/scan_spec.rb b/spec/ruby/library/stringscanner/scan_spec.rb
new file mode 100644
index 0000000000..84a0f27f08
--- /dev/null
+++ b/spec/ruby/library/stringscanner/scan_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#scan" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the matched string" do
+ @s.scan(/\w+/).should == "This"
+ @s.scan(/.../).should == " is"
+ @s.scan(//).should == ""
+ @s.scan(/\s+/).should == " "
+ end
+
+ it "treats ^ as matching from the beginning of the current position" do
+ @s.scan(/\w+/).should == "This"
+ @s.scan(/^\d/).should be_nil
+ @s.scan(/^\s/).should == " "
+ end
+
+ it "returns nil if there's no match" do
+ @s.scan(/\d/).should == nil
+ end
+
+ it "returns nil when there is no more to scan" do
+ @s.scan(/[\w\s]+/).should == "This is a test"
+ @s.scan(/\w+/).should be_nil
+ end
+
+ it "returns an empty string when the pattern matches empty" do
+ @s.scan(/.*/).should == "This is a test"
+ @s.scan(/.*/).should == ""
+ @s.scan(/./).should be_nil
+ end
+
+ it "raises a TypeError if pattern isn't a Regexp" do
+ lambda { @s.scan("aoeu") }.should raise_error(TypeError)
+ lambda { @s.scan(5) }.should raise_error(TypeError)
+ lambda { @s.scan(:test) }.should raise_error(TypeError)
+ lambda { @s.scan(mock('x')) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/stringscanner/scan_until_spec.rb b/spec/ruby/library/stringscanner/scan_until_spec.rb
new file mode 100644
index 0000000000..702283ed22
--- /dev/null
+++ b/spec/ruby/library/stringscanner/scan_until_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#scan_until" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the substring up to and including the end of the match" do
+ @s.scan_until(/a/).should == "This is a"
+ @s.pre_match.should == "This is "
+ @s.post_match.should == " test"
+ end
+
+ it "returns nil if there's no match" do
+ @s.scan_until(/\d/).should == nil
+ end
+
+ it "can match anchors properly" do
+ @s.scan(/T/)
+ @s.scan_until(/^h/).should == "h"
+ end
+end
diff --git a/spec/ruby/library/stringscanner/search_full_spec.rb b/spec/ruby/library/stringscanner/search_full_spec.rb
new file mode 100644
index 0000000000..43ff840003
--- /dev/null
+++ b/spec/ruby/library/stringscanner/search_full_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#search_full" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the number of bytes advanced" do
+ orig_pos = @s.pos
+ @s.search_full(/This/, false, false).should == 4
+ @s.pos.should == orig_pos
+ end
+
+ it "returns the number of bytes advanced and advances the scan pointer if the second argument is true" do
+ @s.search_full(/This/, true, false).should == 4
+ @s.pos.should == 4
+ end
+
+ it "returns the matched string if the third argument is true" do
+ orig_pos = @s.pos
+ @s.search_full(/This/, false, true).should == "This"
+ @s.pos.should == orig_pos
+ end
+
+ it "returns the matched string if the third argument is true and advances the scan pointer if the second argument is true" do
+ @s.search_full(/This/, true, true).should == "This"
+ @s.pos.should == 4
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/bol.rb b/spec/ruby/library/stringscanner/shared/bol.rb
new file mode 100644
index 0000000000..ebcdd7938f
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/bol.rb
@@ -0,0 +1,25 @@
+describe :strscan_bol, shared: true do
+ it "returns true if the scan pointer is at the beginning of the line, false otherwise" do
+ s = StringScanner.new("This is a test")
+ s.send(@method).should be_true
+ s.scan(/This/)
+ s.send(@method).should be_false
+ s.terminate
+ s.send(@method).should be_false
+
+ s = StringScanner.new("hello\nworld")
+ s.bol?.should be_true
+ s.scan(/\w+/)
+ s.bol?.should be_false
+ s.scan(/\n/)
+ s.bol?.should be_true
+ s.unscan
+ s.bol?.should be_false
+ end
+
+ it "returns true if the scan pointer is at the end of the line of an empty string." do
+ s = StringScanner.new('')
+ s.terminate
+ s.send(@method).should be_true
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/concat.rb b/spec/ruby/library/stringscanner/shared/concat.rb
new file mode 100644
index 0000000000..28788d3ff1
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/concat.rb
@@ -0,0 +1,30 @@
+describe :strscan_concat, shared: true do
+ it "concatenates the given argument to self and returns self" do
+ s = StringScanner.new("hello ")
+ s.send(@method, 'world').should == s
+ s.string.should == "hello world"
+ s.eos?.should be_false
+ end
+
+ it "raises a TypeError if the given argument can't be converted to a String" do
+ lambda { StringScanner.new('hello').send(@method, :world) }.should raise_error(TypeError)
+ lambda { StringScanner.new('hello').send(@method, mock('x')) }.should raise_error(TypeError)
+ end
+end
+
+describe :strscan_concat_fixnum, shared: true do
+ it "raises a TypeError" do
+ a = StringScanner.new("hello world")
+ lambda { a.send(@method, 333) }.should raise_error(TypeError)
+ b = StringScanner.new("")
+ lambda { b.send(@method, (256 * 3 + 64)) }.should raise_error(TypeError)
+ lambda { b.send(@method, -200) }.should raise_error(TypeError)
+ end
+
+ it "doesn't call to_int on the argument" do
+ x = mock('x')
+ x.should_not_receive(:to_int)
+
+ lambda { "".send(@method, x) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/eos.rb b/spec/ruby/library/stringscanner/shared/eos.rb
new file mode 100644
index 0000000000..ea04c764a2
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/eos.rb
@@ -0,0 +1,17 @@
+describe :strscan_eos, shared: true do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns true if the scan pointer is at the end of the string" do
+ @s.terminate
+ @s.send(@method).should be_true
+
+ s = StringScanner.new('')
+ s.send(@method).should be_true
+ end
+
+ it "returns false if the scan pointer is not at the end of the string" do
+ @s.send(@method).should be_false
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/extract_range.rb b/spec/ruby/library/stringscanner/shared/extract_range.rb
new file mode 100644
index 0000000000..7e98540b1a
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/extract_range.rb
@@ -0,0 +1,22 @@
+describe :extract_range, shared: true do
+ it "returns an instance of String when passed a String subclass" do
+ cls = Class.new(String)
+ sub = cls.new("abc")
+
+ s = StringScanner.new(sub)
+ ch = s.send(@method)
+ ch.should_not be_kind_of(cls)
+ ch.should be_an_instance_of(String)
+ end
+
+ it "taints the returned String if the input was tainted" do
+ str = 'abc'
+ str.taint
+
+ s = StringScanner.new(str)
+
+ s.send(@method).tainted?.should be_true
+ s.send(@method).tainted?.should be_true
+ s.send(@method).tainted?.should be_true
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/extract_range_matched.rb b/spec/ruby/library/stringscanner/shared/extract_range_matched.rb
new file mode 100644
index 0000000000..fe695e8ac1
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/extract_range_matched.rb
@@ -0,0 +1,22 @@
+describe :extract_range_matched, shared: true do
+ it "returns an instance of String when passed a String subclass" do
+ cls = Class.new(String)
+ sub = cls.new("abc")
+
+ s = StringScanner.new(sub)
+ s.scan(/\w{1}/)
+
+ ch = s.send(@method)
+ ch.should_not be_kind_of(cls)
+ ch.should be_an_instance_of(String)
+ end
+
+ it "taints the returned String if the input was tainted" do
+ str = 'abc'
+ str.taint
+
+ s = StringScanner.new(str)
+ s.scan(/\w{1}/)
+ s.send(@method).tainted?.should be_true
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/get_byte.rb b/spec/ruby/library/stringscanner/shared/get_byte.rb
new file mode 100644
index 0000000000..763ab6f4a4
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/get_byte.rb
@@ -0,0 +1,29 @@
+# -*- encoding: binary -*-
+describe :strscan_get_byte, shared: true do
+ it "scans one byte and returns it" do
+ s = StringScanner.new('abc5.')
+ s.send(@method).should == 'a'
+ s.send(@method).should == 'b'
+ s.send(@method).should == 'c'
+ s.send(@method).should == '5'
+ s.send(@method).should == '.'
+ end
+
+ it "is not multi-byte character sensitive" do
+ s = StringScanner.new("\244\242")
+ s.send(@method).should == "\244"
+ s.send(@method).should == "\242"
+ end
+
+ it "returns nil at the end of the string" do
+ # empty string case
+ s = StringScanner.new('')
+ s.send(@method).should == nil
+ s.send(@method).should == nil
+
+ # non-empty string case
+ s = StringScanner.new('a')
+ s.send(@method) # skip one
+ s.send(@method).should == nil
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/matched_size.rb b/spec/ruby/library/stringscanner/shared/matched_size.rb
new file mode 100644
index 0000000000..92174733f7
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/matched_size.rb
@@ -0,0 +1,21 @@
+describe :strscan_matched_size, shared: true do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the size of the most recent match" do
+ @s.check(/This/)
+ @s.send(@method).should == 4
+ @s.send(@method).should == 4
+ @s.scan(//)
+ @s.send(@method).should == 0
+ end
+
+ it "returns nil if there was no recent match" do
+ @s.send(@method).should == nil
+ @s.check(/\d+/)
+ @s.send(@method).should == nil
+ @s.terminate
+ @s.send(@method).should == nil
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/peek.rb b/spec/ruby/library/stringscanner/shared/peek.rb
new file mode 100644
index 0000000000..418ebb6536
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/peek.rb
@@ -0,0 +1,47 @@
+describe :strscan_peek, shared: true do
+ before :each do
+ @s = StringScanner.new('This is a test')
+ end
+
+ it "returns at most the specified number of bytes from the current position" do
+ @s.send(@method, 4).should == "This"
+ @s.pos.should == 0
+ @s.pos = 5
+ @s.send(@method, 2).should == "is"
+ @s.send(@method, 1000).should == "is a test"
+
+ s = StringScanner.new("été")
+ s.send(@method, 2).should == "é"
+ end
+
+ it "returns an empty string when the passed argument is zero" do
+ @s.send(@method, 0).should == ""
+ end
+
+ it "raises a ArgumentError when the passed argument is negative" do
+ lambda { @s.send(@method, -2) }.should raise_error(ArgumentError)
+ end
+
+ it "raises a RangeError when the passed argument is a Bignum" do
+ lambda { @s.send(@method, bignum_value) }.should raise_error(RangeError)
+ end
+
+ it "returns an instance of String when passed a String subclass" do
+ cls = Class.new(String)
+ sub = cls.new("abc")
+
+ s = StringScanner.new(sub)
+
+ ch = s.send(@method, 1)
+ ch.should_not be_kind_of(cls)
+ ch.should be_an_instance_of(String)
+ end
+
+ it "taints the returned String if the input was tainted" do
+ str = 'abc'
+ str.taint
+
+ s = StringScanner.new(str)
+ s.send(@method, 1).tainted?.should be_true
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/pos.rb b/spec/ruby/library/stringscanner/shared/pos.rb
new file mode 100644
index 0000000000..80ded17b0f
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/pos.rb
@@ -0,0 +1,52 @@
+describe :strscan_pos, shared: true do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the position of the scan pointer" do
+ @s.send(@method).should == 0
+ @s.scan_until(/This is/)
+ @s.send(@method).should == 7
+ @s.get_byte
+ @s.send(@method).should == 8
+ @s.terminate
+ @s.send(@method).should == 14
+ end
+
+ it "returns 0 in the reset position" do
+ @s.reset
+ @s.send(@method).should == 0
+ end
+
+ it "returns the length of the string in the terminate position" do
+ @s.terminate
+ @s.send(@method).should == @s.string.length
+ end
+end
+
+describe :strscan_pos_set, shared: true do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "modify the scan pointer" do
+ @s.send(@method, 5)
+ @s.rest.should == "is a test"
+ end
+
+ it "positions from the end if the argument is negative" do
+ @s.send(@method, -2)
+ @s.rest.should == "st"
+ @s.pos.should == 12
+ end
+
+ it "raises a RangeError if position too far backward" do
+ lambda {
+ @s.send(@method, -20)
+ }.should raise_error(RangeError)
+ end
+
+ it "raises a RangeError when the passed argument is out of range" do
+ lambda { @s.send(@method, 20) }.should raise_error(RangeError)
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/rest_size.rb b/spec/ruby/library/stringscanner/shared/rest_size.rb
new file mode 100644
index 0000000000..4c4f49e45c
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/rest_size.rb
@@ -0,0 +1,18 @@
+describe :strscan_rest_size, shared: true do
+ before :each do
+ @s = StringScanner.new('This is a test')
+ end
+
+ it "returns the length of the rest of the string" do
+ @s.send(@method).should == 14
+ @s.scan(/This/)
+ @s.send(@method).should == 10
+ @s.terminate
+ @s.send(@method).should == 0
+ end
+
+ it "is equivalent to rest.size" do
+ @s.scan(/This/)
+ @s.send(@method).should == @s.rest.size
+ end
+end
diff --git a/spec/ruby/library/stringscanner/shared/terminate.rb b/spec/ruby/library/stringscanner/shared/terminate.rb
new file mode 100644
index 0000000000..bf41d097e2
--- /dev/null
+++ b/spec/ruby/library/stringscanner/shared/terminate.rb
@@ -0,0 +1,8 @@
+describe :strscan_terminate, shared: true do
+ it "set the scan pointer to the end of the string and clear matching data." do
+ s = StringScanner.new('This is a test')
+ s.send(@method)
+ s.bol?.should be_false
+ s.eos?.should be_true
+ end
+end
diff --git a/spec/ruby/library/stringscanner/skip_spec.rb b/spec/ruby/library/stringscanner/skip_spec.rb
new file mode 100644
index 0000000000..7426267b6e
--- /dev/null
+++ b/spec/ruby/library/stringscanner/skip_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#skip" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns length of the match" do
+ @s.skip(/\w+/).should == 4
+ @s.skip(/\s+\w+/).should == 3
+ end
+
+ it "returns nil if there's no match" do
+ @s.skip(/\s+/).should == nil
+ @s.skip(/\d+/).should == nil
+ end
+end
diff --git a/spec/ruby/library/stringscanner/skip_until_spec.rb b/spec/ruby/library/stringscanner/skip_until_spec.rb
new file mode 100644
index 0000000000..c6e17900d1
--- /dev/null
+++ b/spec/ruby/library/stringscanner/skip_until_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#skip_until" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the number of bytes advanced and advances the scan pointer until pattern is matched and consumed" do
+ @s.skip_until(/a/).should == 9
+ @s.pos.should == 9
+ @s.matched.should == "a"
+ end
+
+ it "returns nil if no match was found" do
+ @s.skip_until(/d+/).should == nil
+ end
+end
diff --git a/spec/ruby/library/stringscanner/string_spec.rb b/spec/ruby/library/stringscanner/string_spec.rb
new file mode 100644
index 0000000000..080c0dfcf1
--- /dev/null
+++ b/spec/ruby/library/stringscanner/string_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#string" do
+ before :each do
+ @string = "This is a test"
+ @s = StringScanner.new(@string)
+ end
+
+ it "returns the string being scanned" do
+ @s.string.should == "This is a test"
+ @s << " case"
+ @s.string.should == "This is a test case"
+ end
+
+ it "returns the identical object passed in" do
+ @s.string.equal?(@string).should be_true
+ end
+end
+
+describe "StringScanner#string=" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "changes the string being scanned to the argument and resets the scanner" do
+ @s.string = "Hello world"
+ @s.string.should == "Hello world"
+ end
+
+ it "converts the argument into a string using #to_str" do
+ m = mock(:str)
+
+ s = "test"
+ m.should_receive(:to_str).and_return(s)
+
+ @s.string = m
+ @s.string.should == s
+ end
+end
diff --git a/spec/ruby/library/stringscanner/terminate_spec.rb b/spec/ruby/library/stringscanner/terminate_spec.rb
new file mode 100644
index 0000000000..01cea3dbdf
--- /dev/null
+++ b/spec/ruby/library/stringscanner/terminate_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/terminate.rb', __FILE__)
+require 'strscan'
+
+describe "StringScanner#terminate" do
+ it_behaves_like(:strscan_terminate, :terminate)
+end
diff --git a/spec/ruby/library/stringscanner/unscan_spec.rb b/spec/ruby/library/stringscanner/unscan_spec.rb
new file mode 100644
index 0000000000..7663f20d61
--- /dev/null
+++ b/spec/ruby/library/stringscanner/unscan_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'strscan'
+
+describe "StringScanner#unscan" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "set the scan pointer to the previous position" do
+ @s.scan(/This/)
+ @s.unscan
+ @s.matched.should == nil
+ @s.pos.should == 0
+ end
+
+ it "remember only one previous position" do
+ @s.scan(/This/)
+ pos = @s.pos
+ @s.scan(/ is/)
+ @s.unscan
+ @s.pos.should == pos
+ end
+
+ it "raises a ScanError when the previous match had failed" do
+ lambda { @s.unscan }.should raise_error(ScanError)
+ lambda { @s.scan(/\d/); @s.unscan }.should raise_error(ScanError)
+ end
+end
diff --git a/spec/ruby/library/syslog/alert_spec.rb b/spec/ruby/library/syslog/alert_spec.rb
new file mode 100644
index 0000000000..4653fa8636
--- /dev/null
+++ b/spec/ruby/library/syslog/alert_spec.rb
@@ -0,0 +1,9 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/log', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.alert" do
+ it_behaves_like :syslog_log, :alert
+ end
+end
diff --git a/spec/ruby/library/syslog/close_spec.rb b/spec/ruby/library/syslog/close_spec.rb
new file mode 100644
index 0000000000..f7bc4ac6e9
--- /dev/null
+++ b/spec/ruby/library/syslog/close_spec.rb
@@ -0,0 +1,57 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.close" do
+ platform_is_not :windows do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "closes the log" do
+ Syslog.opened?.should be_false
+ Syslog.open
+ Syslog.opened?.should be_true
+ Syslog.close
+ Syslog.opened?.should be_false
+ end
+
+ it "raises a RuntimeError if the log's already closed" do
+ lambda { Syslog.close }.should raise_error(RuntimeError)
+ end
+
+ it "it does not work inside blocks" do
+ lambda {
+ Syslog.open { |s| s.close }
+ }.should raise_error(RuntimeError)
+ Syslog.opened?.should == false
+ end
+
+ it "sets the identity to nil" do
+ Syslog.open("rubyspec")
+ Syslog.ident.should == "rubyspec"
+ Syslog.close
+ Syslog.ident.should be_nil
+ end
+
+ it "sets the options to nil" do
+ Syslog.open("rubyspec", Syslog::LOG_PID)
+ Syslog.options.should == Syslog::LOG_PID
+ Syslog.close
+ Syslog.options.should == nil
+ end
+
+ it "sets the facility to nil" do
+ Syslog.open
+ Syslog.facility.should == 8
+ Syslog.close
+ Syslog.facility.should == nil
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/constants_spec.rb b/spec/ruby/library/syslog/constants_spec.rb
new file mode 100644
index 0000000000..c335ff46e6
--- /dev/null
+++ b/spec/ruby/library/syslog/constants_spec.rb
@@ -0,0 +1,40 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog::Constants" do
+ platform_is_not :windows, :solaris, :aix do
+ before :all do
+ @constants = %w(LOG_AUTHPRIV LOG_USER LOG_LOCAL2 LOG_NOTICE LOG_NDELAY
+ LOG_SYSLOG LOG_ALERT LOG_FTP LOG_LOCAL5 LOG_ERR LOG_AUTH
+ LOG_LOCAL1 LOG_ODELAY LOG_NEWS LOG_DAEMON LOG_LOCAL4
+ LOG_CRIT LOG_INFO LOG_PERROR LOG_LOCAL0 LOG_CONS LOG_LPR
+ LOG_LOCAL7 LOG_WARNING LOG_CRON LOG_LOCAL3 LOG_EMERG
+ LOG_NOWAIT LOG_UUCP LOG_PID LOG_KERN LOG_MAIL LOG_LOCAL6
+ LOG_DEBUG)
+ end
+
+ it "includes the Syslog constants" do
+ @constants.each do |c|
+ Syslog::Constants.should have_constant(c)
+ end
+ end
+ end
+
+ # The masks are defined in <syslog.h>
+
+ describe "Syslog::Constants.LOG_MASK" do
+ it "returns the mask value for a priority" do
+ Syslog::Constants.LOG_MASK(Syslog::LOG_DEBUG).should == 128
+ Syslog::Constants.LOG_MASK(Syslog::LOG_WARNING).should == 16
+ end
+ end
+
+ describe "Syslog::Constants.LOG_UPTO" do
+ it "returns a mask for the priorities up to a given argument" do
+ Syslog::Constants.LOG_UPTO(Syslog::LOG_ALERT).should == 3
+ Syslog::Constants.LOG_UPTO(Syslog::LOG_DEBUG).should == 255
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/crit_spec.rb b/spec/ruby/library/syslog/crit_spec.rb
new file mode 100644
index 0000000000..28e3af67cc
--- /dev/null
+++ b/spec/ruby/library/syslog/crit_spec.rb
@@ -0,0 +1,9 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/log', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.crit" do
+ it_behaves_like :syslog_log, :crit
+ end
+end
diff --git a/spec/ruby/library/syslog/debug_spec.rb b/spec/ruby/library/syslog/debug_spec.rb
new file mode 100644
index 0000000000..ff9fc5d97e
--- /dev/null
+++ b/spec/ruby/library/syslog/debug_spec.rb
@@ -0,0 +1,9 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/log', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.debug" do
+ it_behaves_like :syslog_log, :debug
+ end
+end
diff --git a/spec/ruby/library/syslog/emerg_spec.rb b/spec/ruby/library/syslog/emerg_spec.rb
new file mode 100644
index 0000000000..15cc49be32
--- /dev/null
+++ b/spec/ruby/library/syslog/emerg_spec.rb
@@ -0,0 +1,15 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/log', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.emerg" do
+ # Some way needs do be found to prevent this spec
+ # from causing output on all open terminals. If this
+ # is not possible, this spec may need a special guard
+ # that only runs when requested.
+ quarantine! do
+ it_behaves_like :syslog_log, :emerg
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/err_spec.rb b/spec/ruby/library/syslog/err_spec.rb
new file mode 100644
index 0000000000..fdadd49e09
--- /dev/null
+++ b/spec/ruby/library/syslog/err_spec.rb
@@ -0,0 +1,9 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/log', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.err" do
+ it_behaves_like :syslog_log, :err
+ end
+end
diff --git a/spec/ruby/library/syslog/facility_spec.rb b/spec/ruby/library/syslog/facility_spec.rb
new file mode 100644
index 0000000000..02ea754b6b
--- /dev/null
+++ b/spec/ruby/library/syslog/facility_spec.rb
@@ -0,0 +1,47 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.facility" do
+ platform_is_not :windows do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "returns the logging facility" do
+ Syslog.open("rubyspec", 3, Syslog::LOG_MAIL)
+ Syslog.facility.should == Syslog::LOG_MAIL
+ Syslog.close
+ end
+
+ it "returns nil if the log is closed" do
+ Syslog.opened?.should be_false
+ Syslog.facility.should == nil
+ end
+
+ it "defaults to LOG_USER" do
+ Syslog.open
+ Syslog.facility.should == Syslog::LOG_USER
+ Syslog.close
+ end
+
+ it "resets after each open call" do
+ Syslog.open
+ Syslog.facility.should == Syslog::LOG_USER
+
+ Syslog.open!("rubyspec", 3, Syslog::LOG_MAIL)
+ Syslog.facility.should == Syslog::LOG_MAIL
+ Syslog.close
+
+ Syslog.open
+ Syslog.facility.should == Syslog::LOG_USER
+ Syslog.close
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/ident_spec.rb b/spec/ruby/library/syslog/ident_spec.rb
new file mode 100644
index 0000000000..a685dfa927
--- /dev/null
+++ b/spec/ruby/library/syslog/ident_spec.rb
@@ -0,0 +1,34 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.ident" do
+ platform_is_not :windows do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "returns the logging identity" do
+ Syslog.open("rubyspec")
+ Syslog.ident.should == "rubyspec"
+ Syslog.close
+ end
+
+ it "returns nil if the log is closed" do
+ Syslog.opened?.should == false
+ Syslog.ident.should == nil
+ end
+
+ it "defaults to $0" do
+ Syslog.open
+ Syslog.ident.should == $0
+ Syslog.close
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/info_spec.rb b/spec/ruby/library/syslog/info_spec.rb
new file mode 100644
index 0000000000..88ff81994d
--- /dev/null
+++ b/spec/ruby/library/syslog/info_spec.rb
@@ -0,0 +1,9 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/log', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.info" do
+ it_behaves_like :syslog_log, :info
+ end
+end
diff --git a/spec/ruby/library/syslog/inspect_spec.rb b/spec/ruby/library/syslog/inspect_spec.rb
new file mode 100644
index 0000000000..5fd7793c22
--- /dev/null
+++ b/spec/ruby/library/syslog/inspect_spec.rb
@@ -0,0 +1,38 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.inspect" do
+ platform_is_not :windows do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "returns a string a closed log" do
+ Syslog.inspect.should =~ /opened=false/
+ end
+
+ it "returns a string for an opened log" do
+ Syslog.open
+ Syslog.inspect.should =~ /opened=true.*/
+ Syslog.close
+ end
+
+ it "includes the ident, options, facility and mask" do
+ Syslog.open("rubyspec", Syslog::LOG_PID, Syslog::LOG_USER)
+ inspect_str = Syslog.inspect.split ", "
+ inspect_str[0].should =~ /opened=true/
+ inspect_str[1].should == "ident=\"rubyspec\""
+ inspect_str[2].should == "options=#{Syslog::LOG_PID}"
+ inspect_str[3].should == "facility=#{Syslog::LOG_USER}"
+ inspect_str[4].should == "mask=255>"
+ Syslog.close
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/instance_spec.rb b/spec/ruby/library/syslog/instance_spec.rb
new file mode 100644
index 0000000000..60f43dbdea
--- /dev/null
+++ b/spec/ruby/library/syslog/instance_spec.rb
@@ -0,0 +1,12 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.instance" do
+ platform_is_not :windows do
+ it "returns the module" do
+ Syslog.instance.should == Syslog
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/log_spec.rb b/spec/ruby/library/syslog/log_spec.rb
new file mode 100644
index 0000000000..2403943cfc
--- /dev/null
+++ b/spec/ruby/library/syslog/log_spec.rb
@@ -0,0 +1,55 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.log" do
+ platform_is_not :windows, :darwin, :solaris, :aix do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "receives a priority as first argument" do
+ lambda {
+ Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s|
+ s.log(Syslog::LOG_ALERT, "Hello")
+ s.log(Syslog::LOG_CRIT, "World")
+ end
+ }.should output_to_fd("rubyspec: Hello\nrubyspec: World\n", $stderr)
+ end
+
+ it "accepts undefined priorites" do
+ lambda {
+ Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s|
+ s.log(1337, "Hello")
+ end
+ # use a regex since it'll output unknown facility/priority messages
+ }.should output_to_fd(/rubyspec: Hello/, $stderr)
+ end
+
+ it "fails with TypeError on nil log messages" do
+ Syslog.open do |s|
+ lambda { s.log(1, nil) }.should raise_error(TypeError)
+ end
+ end
+
+ it "fails if the log is closed" do
+ lambda {
+ Syslog.log(Syslog::LOG_ALERT, "test")
+ }.should raise_error(RuntimeError)
+ end
+
+ it "accepts printf parameters" do
+ lambda {
+ Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s|
+ s.log(Syslog::LOG_ALERT, "%s x %d", "chunky bacon", 2)
+ end
+ }.should output_to_fd("rubyspec: chunky bacon x 2\n", $stderr)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/mask_spec.rb b/spec/ruby/library/syslog/mask_spec.rb
new file mode 100644
index 0000000000..49be56d304
--- /dev/null
+++ b/spec/ruby/library/syslog/mask_spec.rb
@@ -0,0 +1,112 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.mask" do
+ platform_is_not :windows do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ # make sure we return the mask to the default value
+ Syslog.open { |s| s.mask = 255 }
+ end
+
+ it "returns the log priority mask" do
+ Syslog.open("rubyspec") do
+ Syslog.mask.should == 255
+ Syslog.mask = 3
+ Syslog.mask.should == 3
+ Syslog.mask = 255
+ end
+ end
+
+ it "defaults to 255" do
+ Syslog.open do |s|
+ s.mask.should == 255
+ end
+ end
+
+ it "returns nil if the log is closed" do
+ Syslog.opened?.should == false
+ Syslog.mask.should == nil
+ end
+
+ platform_is :darwin do
+ it "resets if the log is reopened" do
+ Syslog.open
+ Syslog.mask.should == 255
+ Syslog.mask = 64
+
+ Syslog.reopen("rubyspec") do
+ Syslog.mask.should == 255
+ end
+
+ Syslog.open do
+ Syslog.mask.should == 255
+ end
+ end
+ end
+
+ platform_is_not :darwin do
+ it "persists if the log is reopened" do
+ Syslog.open
+ Syslog.mask.should == 255
+ Syslog.mask = 64
+
+ Syslog.reopen("rubyspec") do
+ Syslog.mask.should == 64
+ end
+
+ Syslog.open do
+ Syslog.mask.should == 64
+ end
+ end
+ end
+ end
+ end
+
+ describe "Syslog.mask=" do
+ platform_is_not :windows do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ # make sure we return the mask to the default value
+ Syslog.open { |s| s.mask = 255 }
+ end
+
+ it "sets the log priority mask" do
+ Syslog.open do
+ Syslog.mask = 64
+ Syslog.mask.should == 64
+ end
+ end
+
+ it "raises an error if the log is closed" do
+ lambda { Syslog.mask = 1337 }.should raise_error(RuntimeError)
+ end
+
+ it "only accepts numbers" do
+ Syslog.open do
+
+ Syslog.mask = 1337
+ Syslog.mask.should == 1337
+
+ Syslog.mask = 3.1416
+ Syslog.mask.should == 3
+
+ lambda { Syslog.mask = "oh hai" }.should raise_error(TypeError)
+ lambda { Syslog.mask = "43" }.should raise_error(TypeError)
+
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/notice_spec.rb b/spec/ruby/library/syslog/notice_spec.rb
new file mode 100644
index 0000000000..7a27e23729
--- /dev/null
+++ b/spec/ruby/library/syslog/notice_spec.rb
@@ -0,0 +1,9 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/log', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.notice" do
+ it_behaves_like :syslog_log, :notice
+ end
+end
diff --git a/spec/ruby/library/syslog/open_spec.rb b/spec/ruby/library/syslog/open_spec.rb
new file mode 100644
index 0000000000..18e7f0c80e
--- /dev/null
+++ b/spec/ruby/library/syslog/open_spec.rb
@@ -0,0 +1,86 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/reopen', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.open" do
+ platform_is_not :windows do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "returns the module" do
+ Syslog.open.should == Syslog
+ Syslog.close
+ Syslog.open("Test", 5, 9).should == Syslog
+ Syslog.close
+ end
+
+ it "receives an identity as first argument" do
+ Syslog.open("rubyspec")
+ Syslog.ident.should == "rubyspec"
+ Syslog.close
+ end
+
+ it "defaults the identity to $0" do
+ Syslog.open
+ Syslog.ident.should == $0
+ Syslog.close
+ end
+
+ it "receives the logging options as second argument" do
+ Syslog.open("rubyspec", Syslog::LOG_PID)
+ Syslog.options.should == Syslog::LOG_PID
+ Syslog.close
+ end
+
+ it "defaults the logging options to LOG_PID | LOG_CONS" do
+ Syslog.open
+ Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS
+ Syslog.close
+ end
+
+ it "receives a facility as third argument" do
+ Syslog.open("rubyspec", Syslog::LOG_PID, 0)
+ Syslog.facility.should == 0
+ Syslog.close
+ end
+
+ it "defaults the facility to LOG_USER" do
+ Syslog.open
+ Syslog.facility.should == Syslog::LOG_USER
+ Syslog.close
+ end
+
+ it "receives a block and calls it with the module" do
+ Syslog.open("rubyspec", 3, 8) do |s|
+ s.should == Syslog
+ s.ident.should == "rubyspec"
+ s.options.should == 3
+ s.facility.should == Syslog::LOG_USER
+ end
+ end
+
+ it "closes the log if after it receives a block" do
+ Syslog.open{ }
+ Syslog.opened?.should be_false
+ end
+
+ it "raises an error if the log is opened" do
+ Syslog.open
+ lambda { Syslog.open}.should raise_error
+ lambda { Syslog.close; Syslog.open }.should_not raise_error
+ Syslog.close
+ end
+ end
+ end
+
+ describe "Syslog.open!" do
+ it_behaves_like :syslog_reopen, :open!
+ end
+end
diff --git a/spec/ruby/library/syslog/opened_spec.rb b/spec/ruby/library/syslog/opened_spec.rb
new file mode 100644
index 0000000000..82b8ba45f7
--- /dev/null
+++ b/spec/ruby/library/syslog/opened_spec.rb
@@ -0,0 +1,38 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.opened?" do
+ platform_is_not :windows do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "returns true if the log is opened" do
+ Syslog.open
+ Syslog.opened?.should be_true
+ Syslog.close
+ end
+
+ it "returns false otherwise" do
+ Syslog.opened?.should be_false
+ Syslog.open
+ Syslog.close
+ Syslog.opened?.should be_false
+ end
+
+ it "works inside a block" do
+ Syslog.open do |s|
+ s.opened?.should be_true
+ Syslog.opened?.should be_true
+ end
+ Syslog.opened?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/options_spec.rb b/spec/ruby/library/syslog/options_spec.rb
new file mode 100644
index 0000000000..4a3914531a
--- /dev/null
+++ b/spec/ruby/library/syslog/options_spec.rb
@@ -0,0 +1,47 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.options" do
+ platform_is_not :windows do
+
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "returns the logging options" do
+ Syslog.open("rubyspec", Syslog::LOG_PID)
+ Syslog.options.should == Syslog::LOG_PID
+ Syslog.close
+ end
+
+ it "returns nil when the log is closed" do
+ Syslog.opened?.should be_false
+ Syslog.options.should == nil
+ end
+
+ it "defaults to LOG_PID | LOG_CONS" do
+ Syslog.open
+ Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS
+ Syslog.close
+ end
+
+ it "resets after each open call" do
+ Syslog.open
+ Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS
+
+ Syslog.open!("rubyspec", Syslog::LOG_PID)
+ Syslog.options.should == Syslog::LOG_PID
+ Syslog.close
+
+ Syslog.open
+ Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS
+ Syslog.close
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/reopen_spec.rb b/spec/ruby/library/syslog/reopen_spec.rb
new file mode 100644
index 0000000000..de1ce2c255
--- /dev/null
+++ b/spec/ruby/library/syslog/reopen_spec.rb
@@ -0,0 +1,9 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/reopen', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.reopen" do
+ it_behaves_like :syslog_reopen, :reopen
+ end
+end
diff --git a/spec/ruby/library/syslog/shared/log.rb b/spec/ruby/library/syslog/shared/log.rb
new file mode 100644
index 0000000000..6d0d3a3c23
--- /dev/null
+++ b/spec/ruby/library/syslog/shared/log.rb
@@ -0,0 +1,40 @@
+describe :syslog_log, shared: true do
+ platform_is_not :windows, :darwin, :solaris, :aix do
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "logs a message" do
+ lambda {
+ Syslog.open("rubyspec", Syslog::LOG_PERROR) do
+ Syslog.send(@method, "Hello")
+ end
+ }.should output_to_fd("rubyspec: Hello\n", $stderr)
+ end
+
+ it "accepts sprintf arguments" do
+ lambda {
+ Syslog.open("rubyspec", Syslog::LOG_PERROR) do
+ Syslog.send(@method, "Hello %s", "world")
+ Syslog.send(@method, "%d dogs", 2)
+ end
+ }.should output_to_fd("rubyspec: Hello world\nrubyspec: 2 dogs\n", $stderr)
+ end
+
+ it "works as an alias for Syslog.log" do
+ level = Syslog.const_get "LOG_#{@method.to_s.upcase}"
+ response = "rubyspec: Hello\n"
+ lambda {
+ Syslog.open("rubyspec", Syslog::LOG_PERROR) do
+ Syslog.send(@method, "Hello")
+ Syslog.log(level, "Hello")
+ end
+ # make sure the same thing is written to $stderr.
+ }.should output_to_fd(response * 2, $stderr)
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/shared/reopen.rb b/spec/ruby/library/syslog/shared/reopen.rb
new file mode 100644
index 0000000000..fd30ab824a
--- /dev/null
+++ b/spec/ruby/library/syslog/shared/reopen.rb
@@ -0,0 +1,40 @@
+describe :syslog_reopen, shared: true do
+ platform_is_not :windows do
+ before :each do
+ Syslog.opened?.should be_false
+ end
+
+ after :each do
+ Syslog.opened?.should be_false
+ end
+
+ it "reopens the log" do
+ Syslog.open
+ lambda { Syslog.send(@method)}.should_not raise_error
+ Syslog.opened?.should be_true
+ Syslog.close
+ end
+
+ it "fails with RuntimeError if the log is closed" do
+ lambda { Syslog.send(@method)}.should raise_error(RuntimeError)
+ end
+
+ it "receives the same parameters as Syslog.open" do
+ Syslog.open
+ Syslog.send(@method, "rubyspec", 3, 8) do |s|
+ s.should == Syslog
+ s.ident.should == "rubyspec"
+ s.options.should == 3
+ s.facility.should == Syslog::LOG_USER
+ s.opened?.should be_true
+ end
+ Syslog.opened?.should be_false
+ end
+
+ it "returns the module" do
+ Syslog.open
+ Syslog.send(@method).should == Syslog
+ Syslog.close
+ end
+ end
+end
diff --git a/spec/ruby/library/syslog/warning_spec.rb b/spec/ruby/library/syslog/warning_spec.rb
new file mode 100644
index 0000000000..85fcb3a355
--- /dev/null
+++ b/spec/ruby/library/syslog/warning_spec.rb
@@ -0,0 +1,9 @@
+platform_is_not :windows do
+ require File.expand_path('../../../spec_helper', __FILE__)
+ require File.expand_path('../shared/log', __FILE__)
+ require 'syslog'
+
+ describe "Syslog.warning" do
+ it_behaves_like :syslog_log, :warning
+ end
+end
diff --git a/spec/ruby/library/tempfile/_close_spec.rb b/spec/ruby/library/tempfile/_close_spec.rb
new file mode 100644
index 0000000000..d91a3e1adc
--- /dev/null
+++ b/spec/ruby/library/tempfile/_close_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'tempfile'
+
+describe "Tempfile#_close" do
+ before :each do
+ @tempfile = Tempfile.new("specs")
+ end
+
+ after :each do
+ @tempfile.close!
+ end
+
+ it "is protected" do
+ Tempfile.should have_protected_instance_method(:_close)
+ end
+
+ it "closes self" do
+ @tempfile.send(:_close)
+ @tempfile.closed?.should be_true
+ end
+end
diff --git a/spec/ruby/library/tempfile/callback_spec.rb b/spec/ruby/library/tempfile/callback_spec.rb
new file mode 100644
index 0000000000..045252fec3
--- /dev/null
+++ b/spec/ruby/library/tempfile/callback_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'tempfile'
+
+describe "Tempfile.callback" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/tempfile/close_spec.rb b/spec/ruby/library/tempfile/close_spec.rb
new file mode 100644
index 0000000000..aa776b840c
--- /dev/null
+++ b/spec/ruby/library/tempfile/close_spec.rb
@@ -0,0 +1,57 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'tempfile'
+
+describe "Tempfile#close when passed no argument or [false]" do
+ before :each do
+ @tempfile = Tempfile.new("specs", tmp(""))
+ end
+
+ after :each do
+ @tempfile.close!
+ end
+
+ it "closes self" do
+ @tempfile.close
+ @tempfile.closed?.should be_true
+ end
+
+ it "does not unlink self" do
+ path = @tempfile.path
+ @tempfile.close
+ File.exist?(path).should be_true
+ end
+end
+
+describe "Tempfile#close when passed [true]" do
+ before :each do
+ @tempfile = Tempfile.new("specs", tmp(""))
+ end
+
+ it "closes self" do
+ @tempfile.close(true)
+ @tempfile.closed?.should be_true
+ end
+
+ it "unlinks self" do
+ path = @tempfile.path
+ @tempfile.close(true)
+ File.exist?(path).should be_false
+ end
+end
+
+describe "Tempfile#close!" do
+ before :each do
+ @tempfile = Tempfile.new("specs", tmp(""))
+ end
+
+ it "closes self" do
+ @tempfile.close!
+ @tempfile.closed?.should be_true
+ end
+
+ it "unlinks self" do
+ path = @tempfile.path
+ @tempfile.close!
+ File.exist?(path).should be_false
+ end
+end
diff --git a/spec/ruby/library/tempfile/delete_spec.rb b/spec/ruby/library/tempfile/delete_spec.rb
new file mode 100644
index 0000000000..8e92631e62
--- /dev/null
+++ b/spec/ruby/library/tempfile/delete_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/unlink', __FILE__)
+require 'tempfile'
+
+describe "Tempfile#delete" do
+ it_behaves_like :tempfile_unlink, :delete
+end
diff --git a/spec/ruby/library/tempfile/initialize_spec.rb b/spec/ruby/library/tempfile/initialize_spec.rb
new file mode 100644
index 0000000000..79f33e3e98
--- /dev/null
+++ b/spec/ruby/library/tempfile/initialize_spec.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'tempfile'
+
+describe "Tempfile#initialize" do
+ before :each do
+ @tempfile = Tempfile.allocate
+ end
+
+ after :each do
+ @tempfile.close!
+ end
+
+ it "opens a new tempfile with the passed name in the passed directory" do
+ @tempfile.send(:initialize, "basename", tmp(""))
+ File.exist?(@tempfile.path).should be_true
+
+ tmpdir = tmp("")
+ path = @tempfile.path
+
+ platform_is :windows do
+ # on Windows, both types of slashes are OK,
+ # but the tmp helper always uses '/'
+ path.gsub!('\\', '/')
+ end
+
+ path[0, tmpdir.length].should == tmpdir
+ path.should include("basename")
+ end
+
+ platform_is_not :windows do
+ it "sets the permisssions on the tempfile to 0600" do
+ @tempfile.send(:initialize, "basename", tmp(""))
+ File.stat(@tempfile.path).mode.should == 0100600
+ end
+ end
+
+ it "accepts encoding options" do
+ @tempfile.send(:initialize, ['shiftjis', 'yml'], encoding: 'SHIFT_JIS')
+ @tempfile.external_encoding.should == Encoding::Shift_JIS
+ end
+end
diff --git a/spec/ruby/library/tempfile/length_spec.rb b/spec/ruby/library/tempfile/length_spec.rb
new file mode 100644
index 0000000000..b4f0a3b1d4
--- /dev/null
+++ b/spec/ruby/library/tempfile/length_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+require 'tempfile'
+
+describe "Tempfile#length" do
+ it_behaves_like :tempfile_length, :length
+end
diff --git a/spec/ruby/library/tempfile/open_spec.rb b/spec/ruby/library/tempfile/open_spec.rb
new file mode 100644
index 0000000000..3ceaeec502
--- /dev/null
+++ b/spec/ruby/library/tempfile/open_spec.rb
@@ -0,0 +1,82 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'tempfile'
+
+describe "Tempfile#open" do
+ before :each do
+ @tempfile = Tempfile.new("specs")
+ @tempfile.puts("Test!")
+ end
+
+ after :each do
+ @tempfile.close!
+ end
+
+ it "reopens self" do
+ @tempfile.close
+ @tempfile.open
+ @tempfile.closed?.should be_false
+ end
+
+ it "reopens self in read and write mode and does not truncate" do
+ @tempfile.open
+ @tempfile.puts("Another Test!")
+
+ @tempfile.open
+ @tempfile.readline.should == "Another Test!\n"
+ end
+end
+
+describe "Tempfile.open" do
+ after :each do
+ @tempfile.close! if @tempfile
+ end
+
+ it "returns a new, open Tempfile instance" do
+ @tempfile = Tempfile.open("specs")
+ # Delegation messes up .should be_an_instance_of(Tempfile)
+ @tempfile.instance_of?(Tempfile).should be_true
+ end
+
+ it "is passed an array [base, suffix] as first argument" do
+ Tempfile.open(["specs", ".tt"]) { |tempfile| @tempfile = tempfile }
+ @tempfile.path.should =~ /specs.*\.tt$/
+ end
+end
+
+describe "Tempfile.open when passed a block" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ after :each do
+ # Tempfile.open with block does not unlink
+ @tempfile.close! if @tempfile
+ end
+
+ it "yields a new, open Tempfile instance to the block" do
+ Tempfile.open("specs") do |tempfile|
+ @tempfile = tempfile
+ ScratchPad.record :yielded
+
+ # Delegation messes up .should be_an_instance_of(Tempfile)
+ tempfile.instance_of?(Tempfile).should be_true
+ tempfile.closed?.should be_false
+ end
+
+ ScratchPad.recorded.should == :yielded
+ end
+
+ it "returns the value of the block" do
+ value = Tempfile.open("specs") do |tempfile|
+ @tempfile = tempfile
+ "return"
+ end
+ value.should == "return"
+ end
+
+ it "closes the yielded Tempfile after the block" do
+ Tempfile.open("specs") { |tempfile| @tempfile = tempfile }
+ @tempfile.closed?.should be_true
+ end
+end
+
diff --git a/spec/ruby/library/tempfile/path_spec.rb b/spec/ruby/library/tempfile/path_spec.rb
new file mode 100644
index 0000000000..f25e902872
--- /dev/null
+++ b/spec/ruby/library/tempfile/path_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'tempfile'
+
+describe "Tempfile#path" do
+ before :each do
+ @tempfile = Tempfile.new("specs", tmp(""))
+ end
+
+ after :each do
+ @tempfile.close!
+ end
+
+ it "returns the path to the tempfile" do
+ tmpdir = tmp("")
+ path = @tempfile.path
+
+ platform_is :windows do
+ # on Windows, both types of slashes are OK,
+ # but the tmp helper always uses '/'
+ path.gsub!('\\', '/')
+ end
+
+ path[0, tmpdir.length].should == tmpdir
+ path.should include("specs")
+ end
+end
diff --git a/spec/ruby/library/tempfile/shared/length.rb b/spec/ruby/library/tempfile/shared/length.rb
new file mode 100644
index 0000000000..4d18d1f385
--- /dev/null
+++ b/spec/ruby/library/tempfile/shared/length.rb
@@ -0,0 +1,21 @@
+describe :tempfile_length, shared: true do
+ before :each do
+ @tempfile = Tempfile.new("specs")
+ end
+
+ after :each do
+ @tempfile.close!
+ end
+
+ it "returns the size of self" do
+ @tempfile.send(@method).should eql(0)
+ @tempfile.print("Test!")
+ @tempfile.send(@method).should eql(5)
+ end
+
+ it "returns the size of self even if self is closed" do
+ @tempfile.print("Test!")
+ @tempfile.close
+ @tempfile.send(@method).should eql(5)
+ end
+end
diff --git a/spec/ruby/library/tempfile/shared/unlink.rb b/spec/ruby/library/tempfile/shared/unlink.rb
new file mode 100644
index 0000000000..2b575fd391
--- /dev/null
+++ b/spec/ruby/library/tempfile/shared/unlink.rb
@@ -0,0 +1,12 @@
+describe :tempfile_unlink, shared: true do
+ before :each do
+ @tempfile = Tempfile.new("specs")
+ end
+
+ it "unlinks self" do
+ @tempfile.close
+ path = @tempfile.path
+ @tempfile.send(@method)
+ File.exist?(path).should be_false
+ end
+end
diff --git a/spec/ruby/library/tempfile/size_spec.rb b/spec/ruby/library/tempfile/size_spec.rb
new file mode 100644
index 0000000000..ac66d35906
--- /dev/null
+++ b/spec/ruby/library/tempfile/size_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/length', __FILE__)
+require 'tempfile'
+
+describe "Tempfile#size" do
+ it_behaves_like :tempfile_length, :size
+end
diff --git a/spec/ruby/library/tempfile/unlink_spec.rb b/spec/ruby/library/tempfile/unlink_spec.rb
new file mode 100644
index 0000000000..d4ef343c8d
--- /dev/null
+++ b/spec/ruby/library/tempfile/unlink_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/unlink', __FILE__)
+require 'tempfile'
+
+describe "Tempfile#unlink" do
+ it_behaves_like :tempfile_unlink, :unlink
+end
diff --git a/spec/ruby/library/thread/exclusive_spec.rb b/spec/ruby/library/thread/exclusive_spec.rb
new file mode 100644
index 0000000000..9d30188976
--- /dev/null
+++ b/spec/ruby/library/thread/exclusive_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'thread'
+
+describe "Thread.exclusive" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "returns the result of yielding" do
+ Thread.exclusive { :result }.should == :result
+ end
+end
diff --git a/spec/ruby/library/thread/queue/append_spec.rb b/spec/ruby/library/thread/queue/append_spec.rb
new file mode 100644
index 0000000000..8a9e6a21ec
--- /dev/null
+++ b/spec/ruby/library/thread/queue/append_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/enque', __FILE__)
+
+describe "Thread::Queue#<<" do
+ it_behaves_like :queue_enq, :<<, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/queue/clear_spec.rb b/spec/ruby/library/thread/queue/clear_spec.rb
new file mode 100644
index 0000000000..3272a5f3e0
--- /dev/null
+++ b/spec/ruby/library/thread/queue/clear_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/clear', __FILE__)
+
+describe "Thread::Queue#clear" do
+ it_behaves_like :queue_clear, :clear, -> { Queue.new }
+
+ # TODO: test for atomicity of Queue#clear
+end
diff --git a/spec/ruby/library/thread/queue/close_spec.rb b/spec/ruby/library/thread/queue/close_spec.rb
new file mode 100644
index 0000000000..728fff1bfa
--- /dev/null
+++ b/spec/ruby/library/thread/queue/close_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/close', __FILE__)
+
+ruby_version_is "2.3" do
+ describe "Queue#close" do
+ it_behaves_like :queue_close, :close, -> { Queue.new }
+ end
+end
diff --git a/spec/ruby/library/thread/queue/closed_spec.rb b/spec/ruby/library/thread/queue/closed_spec.rb
new file mode 100644
index 0000000000..98ce9c70e3
--- /dev/null
+++ b/spec/ruby/library/thread/queue/closed_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/closed', __FILE__)
+
+ruby_version_is "2.3" do
+ describe "Queue#closed?" do
+ it_behaves_like :queue_closed?, :closed?, -> { Queue.new }
+ end
+end
diff --git a/spec/ruby/library/thread/queue/deq_spec.rb b/spec/ruby/library/thread/queue/deq_spec.rb
new file mode 100644
index 0000000000..7b629bafce
--- /dev/null
+++ b/spec/ruby/library/thread/queue/deq_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/deque', __FILE__)
+
+describe "Thread::Queue#deq" do
+ it_behaves_like :queue_deq, :deq, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/queue/empty_spec.rb b/spec/ruby/library/thread/queue/empty_spec.rb
new file mode 100644
index 0000000000..dea7eb658e
--- /dev/null
+++ b/spec/ruby/library/thread/queue/empty_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/empty', __FILE__)
+
+describe "Thread::Queue#empty?" do
+ it_behaves_like :queue_empty?, :empty?, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/queue/enq_spec.rb b/spec/ruby/library/thread/queue/enq_spec.rb
new file mode 100644
index 0000000000..dc2508589e
--- /dev/null
+++ b/spec/ruby/library/thread/queue/enq_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/enque', __FILE__)
+
+describe "Thread::Queue#enq" do
+ it_behaves_like :queue_enq, :enq, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/queue/length_spec.rb b/spec/ruby/library/thread/queue/length_spec.rb
new file mode 100644
index 0000000000..f33e51a971
--- /dev/null
+++ b/spec/ruby/library/thread/queue/length_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/length', __FILE__)
+
+describe "Thread::Queue#length" do
+ it_behaves_like :queue_length, :length, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/queue/num_waiting_spec.rb b/spec/ruby/library/thread/queue/num_waiting_spec.rb
new file mode 100644
index 0000000000..253ef8a476
--- /dev/null
+++ b/spec/ruby/library/thread/queue/num_waiting_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/num_waiting', __FILE__)
+
+describe "Thread::Queue#num_waiting" do
+ it_behaves_like :queue_num_waiting, :num_waiting, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/queue/pop_spec.rb b/spec/ruby/library/thread/queue/pop_spec.rb
new file mode 100644
index 0000000000..e812e9442e
--- /dev/null
+++ b/spec/ruby/library/thread/queue/pop_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/deque', __FILE__)
+
+describe "Thread::Queue#pop" do
+ it_behaves_like :queue_deq, :pop, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/queue/push_spec.rb b/spec/ruby/library/thread/queue/push_spec.rb
new file mode 100644
index 0000000000..2f1a31315d
--- /dev/null
+++ b/spec/ruby/library/thread/queue/push_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/enque', __FILE__)
+
+describe "Thread::Queue#push" do
+ it_behaves_like :queue_enq, :push, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/queue/shift_spec.rb b/spec/ruby/library/thread/queue/shift_spec.rb
new file mode 100644
index 0000000000..16164a72ec
--- /dev/null
+++ b/spec/ruby/library/thread/queue/shift_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/deque', __FILE__)
+
+describe "Thread::Queue#shift" do
+ it_behaves_like :queue_deq, :shift, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/queue/size_spec.rb b/spec/ruby/library/thread/queue/size_spec.rb
new file mode 100644
index 0000000000..4b148aecd3
--- /dev/null
+++ b/spec/ruby/library/thread/queue/size_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/length', __FILE__)
+
+describe "Thread::Queue#size" do
+ it_behaves_like :queue_length, :size, -> { Queue.new }
+end
diff --git a/spec/ruby/library/thread/shared/queue/clear.rb b/spec/ruby/library/thread/shared/queue/clear.rb
new file mode 100644
index 0000000000..59ea37d615
--- /dev/null
+++ b/spec/ruby/library/thread/shared/queue/clear.rb
@@ -0,0 +1,10 @@
+describe :queue_clear, shared: true do
+ it "removes all objects from the queue" do
+ queue = @object.call
+ queue << Object.new
+ queue << 1
+ queue.empty?.should be_false
+ queue.clear
+ queue.empty?.should be_true
+ end
+end
diff --git a/spec/ruby/library/thread/shared/queue/close.rb b/spec/ruby/library/thread/shared/queue/close.rb
new file mode 100644
index 0000000000..4457f3ae8b
--- /dev/null
+++ b/spec/ruby/library/thread/shared/queue/close.rb
@@ -0,0 +1,26 @@
+describe :queue_close, shared: true do
+ it "closes the queue and returns nil for further #pop" do
+ q = @object.call
+ q << 1
+ q.close
+ q.pop.should == 1
+ q.pop.should == nil
+ q.pop.should == nil
+ end
+
+ it "prevents further #push" do
+ q = @object.call
+ q.close
+ lambda {
+ q << 1
+ }.should raise_error(ClosedQueueError)
+ end
+
+ it "may be called multiple times" do
+ q = @object.call
+ q.close
+ q.closed?.should be_true
+ q.close # no effect
+ q.closed?.should be_true
+ end
+end
diff --git a/spec/ruby/library/thread/shared/queue/closed.rb b/spec/ruby/library/thread/shared/queue/closed.rb
new file mode 100644
index 0000000000..b3cea0c524
--- /dev/null
+++ b/spec/ruby/library/thread/shared/queue/closed.rb
@@ -0,0 +1,12 @@
+describe :queue_closed?, shared: true do
+ it "returns false initially" do
+ queue = @object.call
+ queue.closed?.should be_false
+ end
+
+ it "returns true when the queue is closed" do
+ queue = @object.call
+ queue.close
+ queue.closed?.should be_true
+ end
+end
diff --git a/spec/ruby/library/thread/shared/queue/deque.rb b/spec/ruby/library/thread/shared/queue/deque.rb
new file mode 100644
index 0000000000..1b06dffa2c
--- /dev/null
+++ b/spec/ruby/library/thread/shared/queue/deque.rb
@@ -0,0 +1,37 @@
+describe :queue_deq, shared: true do
+ it "removes an item from the Queue" do
+ q = @object.call
+ q << Object.new
+ q.size.should == 1
+ q.send(@method)
+ q.size.should == 0
+ end
+
+ it "returns items in the order they were added" do
+ q = @object.call
+ q << 1
+ q << 2
+ q.send(@method).should == 1
+ q.send(@method).should == 2
+ end
+
+ it "blocks the thread until there are items in the queue" do
+ q = @object.call
+ v = 0
+
+ th = Thread.new do
+ q.send(@method)
+ v = 1
+ end
+
+ v.should == 0
+ q << Object.new
+ th.join
+ v.should == 1
+ end
+
+ it "raises a ThreadError if Queue is empty" do
+ q = @object.call
+ lambda { q.send(@method,true) }.should raise_error(ThreadError)
+ end
+end
diff --git a/spec/ruby/library/thread/shared/queue/empty.rb b/spec/ruby/library/thread/shared/queue/empty.rb
new file mode 100644
index 0000000000..4acd831d48
--- /dev/null
+++ b/spec/ruby/library/thread/shared/queue/empty.rb
@@ -0,0 +1,12 @@
+describe :queue_empty?, shared: true do
+ it "returns true on an empty Queue" do
+ queue = @object.call
+ queue.empty?.should be_true
+ end
+
+ it "returns false when Queue is not empty" do
+ queue = @object.call
+ queue << Object.new
+ queue.empty?.should be_false
+ end
+end
diff --git a/spec/ruby/library/thread/shared/queue/enque.rb b/spec/ruby/library/thread/shared/queue/enque.rb
new file mode 100644
index 0000000000..36b98d3a07
--- /dev/null
+++ b/spec/ruby/library/thread/shared/queue/enque.rb
@@ -0,0 +1,10 @@
+describe :queue_enq, shared: true do
+ it "adds an element to the Queue" do
+ q = @object.call
+ q.size.should == 0
+ q.send(@method, Object.new)
+ q.size.should == 1
+ q.send(@method, Object.new)
+ q.size.should == 2
+ end
+end
diff --git a/spec/ruby/library/thread/shared/queue/length.rb b/spec/ruby/library/thread/shared/queue/length.rb
new file mode 100644
index 0000000000..a0143a4e19
--- /dev/null
+++ b/spec/ruby/library/thread/shared/queue/length.rb
@@ -0,0 +1,9 @@
+describe :queue_length, shared: true do
+ it "returns the number of elements" do
+ q = @object.call
+ q.send(@method).should == 0
+ q << Object.new
+ q << Object.new
+ q.send(@method).should == 2
+ end
+end
diff --git a/spec/ruby/library/thread/shared/queue/num_waiting.rb b/spec/ruby/library/thread/shared/queue/num_waiting.rb
new file mode 100644
index 0000000000..b054951e45
--- /dev/null
+++ b/spec/ruby/library/thread/shared/queue/num_waiting.rb
@@ -0,0 +1,16 @@
+describe :queue_num_waiting, shared: true do
+ it "reports the number of threads waiting on the queue" do
+ q = @object.call
+ threads = []
+
+ 5.times do |i|
+ q.num_waiting.should == i
+ t = Thread.new { q.deq }
+ Thread.pass until q.num_waiting == i+1
+ threads << t
+ end
+
+ threads.each { q.enq Object.new }
+ threads.each {|t| t.join }
+ end
+end
diff --git a/spec/ruby/library/thread/sizedqueue/append_spec.rb b/spec/ruby/library/thread/sizedqueue/append_spec.rb
new file mode 100644
index 0000000000..2799472767
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/append_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/enque', __FILE__)
+require File.expand_path('../shared/enque', __FILE__)
+
+describe "Thread::SizedQueue#<<" do
+ it_behaves_like :queue_enq, :<<, -> { SizedQueue.new(10) }
+end
+
+describe "Thread::SizedQueue#<<" do
+ it_behaves_like :sizedqueue_enq, :<<
+end
diff --git a/spec/ruby/library/thread/sizedqueue/clear_spec.rb b/spec/ruby/library/thread/sizedqueue/clear_spec.rb
new file mode 100644
index 0000000000..7dc328803a
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/clear_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/clear', __FILE__)
+
+describe "Thread::SizedQueue#clear" do
+ it_behaves_like :queue_clear, :clear, -> { SizedQueue.new(10) }
+
+ # TODO: test for atomicity of Queue#clear
+end
diff --git a/spec/ruby/library/thread/sizedqueue/close_spec.rb b/spec/ruby/library/thread/sizedqueue/close_spec.rb
new file mode 100644
index 0000000000..465b9ea091
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/close_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/close', __FILE__)
+
+ruby_version_is "2.3" do
+ describe "SizedQueue#close" do
+ it_behaves_like :queue_close, :close, -> { SizedQueue.new(10) }
+ end
+end
diff --git a/spec/ruby/library/thread/sizedqueue/closed_spec.rb b/spec/ruby/library/thread/sizedqueue/closed_spec.rb
new file mode 100644
index 0000000000..9ec72c1aa7
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/closed_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/closed', __FILE__)
+
+ruby_version_is "2.3" do
+ describe "SizedQueue#closed?" do
+ it_behaves_like :queue_closed?, :closed?, -> { SizedQueue.new(10) }
+ end
+end
diff --git a/spec/ruby/library/thread/sizedqueue/deq_spec.rb b/spec/ruby/library/thread/sizedqueue/deq_spec.rb
new file mode 100644
index 0000000000..cc11319d22
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/deq_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/deque', __FILE__)
+
+describe "Thread::SizedQueue#deq" do
+ it_behaves_like :queue_deq, :deq, -> { SizedQueue.new(10) }
+end
diff --git a/spec/ruby/library/thread/sizedqueue/empty_spec.rb b/spec/ruby/library/thread/sizedqueue/empty_spec.rb
new file mode 100644
index 0000000000..368bb00d5f
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/empty_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/empty', __FILE__)
+
+describe "Thread::SizedQueue#empty?" do
+ it_behaves_like :queue_empty?, :empty?, -> { SizedQueue.new(10) }
+end
diff --git a/spec/ruby/library/thread/sizedqueue/enq_spec.rb b/spec/ruby/library/thread/sizedqueue/enq_spec.rb
new file mode 100644
index 0000000000..a0be7bbf05
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/enq_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/enque', __FILE__)
+require File.expand_path('../shared/enque', __FILE__)
+
+describe "Thread::SizedQueue#enq" do
+ it_behaves_like :queue_enq, :enq, -> { SizedQueue.new(10) }
+end
+
+describe "Thread::SizedQueue#enq" do
+ it_behaves_like :sizedqueue_enq, :enq
+end
diff --git a/spec/ruby/library/thread/sizedqueue/length_spec.rb b/spec/ruby/library/thread/sizedqueue/length_spec.rb
new file mode 100644
index 0000000000..c292883a8e
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/length_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/length', __FILE__)
+
+describe "Thread::SizedQueue#length" do
+ it_behaves_like :queue_length, :length, -> { SizedQueue.new(10) }
+end
diff --git a/spec/ruby/library/thread/sizedqueue/max_spec.rb b/spec/ruby/library/thread/sizedqueue/max_spec.rb
new file mode 100644
index 0000000000..54cc6351bd
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/max_spec.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+
+describe "Thread::SizedQueue#max" do
+ before :each do
+ @sized_queue = SizedQueue.new(5)
+ end
+
+ it "returns the size of the queue" do
+ @sized_queue.max.should == 5
+ end
+end
+
+describe "Thread::SizedQueue#max=" do
+ before :each do
+ @sized_queue = SizedQueue.new(5)
+ end
+
+ it "sets the size of the queue" do
+ @sized_queue.max.should == 5
+ @sized_queue.max = 10
+ @sized_queue.max.should == 10
+ end
+
+ it "does not remove items already in the queue beyond the maximum" do
+ @sized_queue.enq 1
+ @sized_queue.enq 2
+ @sized_queue.enq 3
+ @sized_queue.max = 2
+ (@sized_queue.size > @sized_queue.max).should be_true
+ @sized_queue.deq.should == 1
+ @sized_queue.deq.should == 2
+ @sized_queue.deq.should == 3
+ end
+
+ it "raises a TypeError when given a non-numeric value" do
+ lambda { @sized_queue.max = "foo" }.should raise_error(TypeError)
+ lambda { @sized_queue.max = Object.new }.should raise_error(TypeError)
+ end
+
+ it "raises an argument error when set to zero" do
+ @sized_queue.max.should == 5
+ lambda { @sized_queue.max = 0 }.should raise_error(ArgumentError)
+ @sized_queue.max.should == 5
+ end
+
+ it "raises an argument error when set to a negative number" do
+ @sized_queue.max.should == 5
+ lambda { @sized_queue.max = -1 }.should raise_error(ArgumentError)
+ @sized_queue.max.should == 5
+ end
+end
diff --git a/spec/ruby/library/thread/sizedqueue/new_spec.rb b/spec/ruby/library/thread/sizedqueue/new_spec.rb
new file mode 100644
index 0000000000..a36aa5ed18
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/new_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+
+describe "Thread::SizedQueue#new" do
+ it "returns a new SizedQueue" do
+ SizedQueue.new(1).should be_kind_of(SizedQueue)
+ end
+
+ it "raises a TypeError when the given argument is not Numeric" do
+ lambda { SizedQueue.new("foo") }.should raise_error(TypeError)
+ lambda { SizedQueue.new(Object.new) }.should raise_error(TypeError)
+ end
+
+ it "raises an argument error when no argument is given" do
+ lambda { SizedQueue.new }.should raise_error(ArgumentError)
+ end
+
+ it "raises an argument error when the given argument is zero" do
+ lambda { SizedQueue.new(0) }.should raise_error(ArgumentError)
+ end
+
+ it "raises an argument error when the given argument is negative" do
+ lambda { SizedQueue.new(-1) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/thread/sizedqueue/num_waiting_spec.rb b/spec/ruby/library/thread/sizedqueue/num_waiting_spec.rb
new file mode 100644
index 0000000000..2ce53875cc
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/num_waiting_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/num_waiting', __FILE__)
+
+describe "Thread::SizedQueue#num_waiting" do
+ it_behaves_like :queue_num_waiting, :num_waiting, -> { SizedQueue.new(10) }
+
+ it "reports the number of threads waiting to push" do
+ q = SizedQueue.new(1)
+ q.push(1)
+ t = Thread.new { q.push(2) }
+ sleep 0.05 until t.stop?
+ q.num_waiting.should == 1
+
+ q.pop
+ t.join
+ end
+end
diff --git a/spec/ruby/library/thread/sizedqueue/pop_spec.rb b/spec/ruby/library/thread/sizedqueue/pop_spec.rb
new file mode 100644
index 0000000000..a83ea6406a
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/pop_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/deque', __FILE__)
+
+describe "Thread::SizedQueue#pop" do
+ it_behaves_like :queue_deq, :pop, -> { SizedQueue.new(10) }
+end
diff --git a/spec/ruby/library/thread/sizedqueue/push_spec.rb b/spec/ruby/library/thread/sizedqueue/push_spec.rb
new file mode 100644
index 0000000000..6021a043c9
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/push_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/enque', __FILE__)
+require File.expand_path('../shared/enque', __FILE__)
+
+describe "Thread::SizedQueue#push" do
+ it_behaves_like :queue_enq, :push, -> { SizedQueue.new(10) }
+end
+
+describe "Thread::SizedQueue#push" do
+ it_behaves_like :sizedqueue_enq, :push
+end
diff --git a/spec/ruby/library/thread/sizedqueue/shared/enque.rb b/spec/ruby/library/thread/sizedqueue/shared/enque.rb
new file mode 100644
index 0000000000..627f8bd745
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/shared/enque.rb
@@ -0,0 +1,34 @@
+describe :sizedqueue_enq, shared: true do
+ it "blocks if queued elements exceed size" do
+ q = SizedQueue.new(1)
+
+ q.size.should == 0
+ q.send(@method, :first_element)
+ q.size.should == 1
+
+ blocked_thread = Thread.new { q.send(@method, :second_element) }
+ sleep 0.01 until blocked_thread.stop?
+
+ q.size.should == 1
+ q.pop.should == :first_element
+
+ blocked_thread.join
+ q.size.should == 1
+ q.pop.should == :second_element
+ q.size.should == 0
+ end
+
+ it "raises a ThreadError if queued elements exceed size when not blocking" do
+ q = SizedQueue.new(2)
+
+ non_blocking = true
+ add_to_queue = lambda { q.send(@method, Object.new, non_blocking) }
+
+ q.size.should == 0
+ add_to_queue.call
+ q.size.should == 1
+ add_to_queue.call
+ q.size.should == 2
+ add_to_queue.should raise_error(ThreadError)
+ end
+end
diff --git a/spec/ruby/library/thread/sizedqueue/shift_spec.rb b/spec/ruby/library/thread/sizedqueue/shift_spec.rb
new file mode 100644
index 0000000000..89345718df
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/shift_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/deque', __FILE__)
+
+describe "Thread::SizedQueue#shift" do
+ it_behaves_like :queue_deq, :shift, -> { SizedQueue.new(10) }
+end
diff --git a/spec/ruby/library/thread/sizedqueue/size_spec.rb b/spec/ruby/library/thread/sizedqueue/size_spec.rb
new file mode 100644
index 0000000000..7ab72d91b1
--- /dev/null
+++ b/spec/ruby/library/thread/sizedqueue/size_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'thread'
+require File.expand_path('../../shared/queue/length', __FILE__)
+
+describe "Thread::SizedQueue#size" do
+ it_behaves_like :queue_length, :size, -> { SizedQueue.new(10) }
+end
diff --git a/spec/ruby/library/time/httpdate_spec.rb b/spec/ruby/library/time/httpdate_spec.rb
new file mode 100644
index 0000000000..af3fd83608
--- /dev/null
+++ b/spec/ruby/library/time/httpdate_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'time'
+
+describe "Time.httpdate" do
+ it "parses RFC-2616 strings" do
+ t = Time.utc(1994, 11, 6, 8, 49, 37)
+ t.should == Time.httpdate("Sun, 06 Nov 1994 08:49:37 GMT")
+
+ # relies on Time.parse (not yet implemented)
+ # t.should == Time.httpdate("Sunday, 06-Nov-94 08:49:37 GMT")
+
+ t.should == Time.httpdate("Sun Nov 6 08:49:37 1994")
+ Time.utc(1995, 11, 15, 6, 25, 24).should == Time.httpdate("Wed, 15 Nov 1995 06:25:24 GMT")
+ Time.utc(1995, 11, 15, 4, 58, 8).should == Time.httpdate("Wed, 15 Nov 1995 04:58:08 GMT")
+ Time.utc(1994, 11, 15, 8, 12, 31).should == Time.httpdate("Tue, 15 Nov 1994 08:12:31 GMT")
+ Time.utc(1994, 12, 1, 16, 0, 0).should == Time.httpdate("Thu, 01 Dec 1994 16:00:00 GMT")
+ Time.utc(1994, 10, 29, 19, 43, 31).should == Time.httpdate("Sat, 29 Oct 1994 19:43:31 GMT")
+ Time.utc(1994, 11, 15, 12, 45, 26).should == Time.httpdate("Tue, 15 Nov 1994 12:45:26 GMT")
+ Time.utc(1999, 12, 31, 23, 59, 59).should == Time.httpdate("Fri, 31 Dec 1999 23:59:59 GMT")
+ end
+end
diff --git a/spec/ruby/library/time/iso8601_spec.rb b/spec/ruby/library/time/iso8601_spec.rb
new file mode 100644
index 0000000000..5f324e5ac6
--- /dev/null
+++ b/spec/ruby/library/time/iso8601_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/xmlschema', __FILE__)
+require 'time'
+
+describe "Time.xmlschema" do
+ it_behaves_like :time_xmlschema, :iso8601
+end
diff --git a/spec/ruby/library/time/rfc2822_spec.rb b/spec/ruby/library/time/rfc2822_spec.rb
new file mode 100644
index 0000000000..ac3950440f
--- /dev/null
+++ b/spec/ruby/library/time/rfc2822_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/rfc2822', __FILE__)
+require 'time'
+
+describe "Time.rfc2822" do
+ it_behaves_like :time_rfc2822, :rfc2822
+end
diff --git a/spec/ruby/library/time/rfc822_spec.rb b/spec/ruby/library/time/rfc822_spec.rb
new file mode 100644
index 0000000000..969050d5ac
--- /dev/null
+++ b/spec/ruby/library/time/rfc822_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/rfc2822', __FILE__)
+require 'time'
+
+describe "Time.rfc822" do
+ it_behaves_like :time_rfc2822, :rfc822
+end
diff --git a/spec/ruby/library/time/shared/rfc2822.rb b/spec/ruby/library/time/shared/rfc2822.rb
new file mode 100644
index 0000000000..b7bf0fb5f5
--- /dev/null
+++ b/spec/ruby/library/time/shared/rfc2822.rb
@@ -0,0 +1,65 @@
+describe :time_rfc2822, shared: true do
+ it "parses RFC-822 strings" do
+ t1 = (Time.utc(1976, 8, 26, 14, 30) + 4 * 3600)
+ t2 = Time.rfc2822("26 Aug 76 14:30 EDT")
+ t1.should == t2
+
+ t3 = Time.utc(1976, 8, 27, 9, 32) + 7 * 3600
+ t4 = Time.rfc2822("27 Aug 76 09:32 PDT")
+ t3.should == t4
+ end
+
+ it "parses RFC-2822 strings" do
+ t1 = Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600
+ t2 = Time.rfc2822("Fri, 21 Nov 1997 09:55:06 -0600")
+ t1.should == t2
+
+ t3 = Time.utc(2003, 7, 1, 10, 52, 37) - 2 * 3600
+ t4 = Time.rfc2822("Tue, 1 Jul 2003 10:52:37 +0200")
+ t3.should == t4
+
+ t5 = Time.utc(1997, 11, 21, 10, 1, 10) + 6 * 3600
+ t6 = Time.rfc2822("Fri, 21 Nov 1997 10:01:10 -0600")
+ t5.should == t6
+
+ t7 = Time.utc(1997, 11, 21, 11, 0, 0) + 6 * 3600
+ t8 = Time.rfc2822("Fri, 21 Nov 1997 11:00:00 -0600")
+ t7.should == t8
+
+ t9 = Time.utc(1997, 11, 24, 14, 22, 1) + 8 * 3600
+ t10 = Time.rfc2822("Mon, 24 Nov 1997 14:22:01 -0800")
+ t9.should == t10
+
+ begin
+ Time.at(-1)
+ rescue ArgumentError
+ # ignore
+ else
+ t11 = Time.utc(1969, 2, 13, 23, 32, 54) + 3 * 3600 + 30 * 60
+ t12 = Time.rfc2822("Thu, 13 Feb 1969 23:32:54 -0330")
+ t11.should == t12
+
+ t13 = Time.utc(1969, 2, 13, 23, 32, 0) + 3 * 3600 + 30 * 60
+ t14 = Time.rfc2822(" Thu,
+ 13
+ Feb
+ 1969
+ 23:32
+ -0330 (Newfoundland Time)")
+ t13.should == t14
+ end
+
+ t15 = Time.utc(1997, 11, 21, 9, 55, 6)
+ t16 = Time.rfc2822("21 Nov 97 09:55:06 GMT")
+ t15.should == t16
+
+ t17 = Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600
+ t18 = Time.rfc2822("Fri, 21 Nov 1997 09 : 55 : 06 -0600")
+ t17.should == t18
+
+ lambda {
+ # inner comment is not supported.
+ Time.rfc2822("Fri, 21 Nov 1997 09(comment): 55 : 06 -0600")
+ }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/time/shared/xmlschema.rb b/spec/ruby/library/time/shared/xmlschema.rb
new file mode 100644
index 0000000000..44d33cda7e
--- /dev/null
+++ b/spec/ruby/library/time/shared/xmlschema.rb
@@ -0,0 +1,53 @@
+describe :time_xmlschema, shared: true do
+ it "parses ISO-8601 strings" do
+ t = Time.utc(1985, 4, 12, 23, 20, 50, 520000)
+ s = "1985-04-12T23:20:50.52Z"
+ t.should == Time.xmlschema(s)
+ #s.should == t.xmlschema(2)
+
+ t = Time.utc(1996, 12, 20, 0, 39, 57)
+ s = "1996-12-19T16:39:57-08:00"
+ t.should == Time.xmlschema(s)
+ # There is no way to generate time string with arbitrary timezone.
+ s = "1996-12-20T00:39:57Z"
+ t.should == Time.xmlschema(s)
+ #assert_equal(s, t.xmlschema)
+
+ t = Time.utc(1990, 12, 31, 23, 59, 60)
+ s = "1990-12-31T23:59:60Z"
+ t.should == Time.xmlschema(s)
+ # leap second is representable only if timezone file has it.
+ s = "1990-12-31T15:59:60-08:00"
+ t.should == Time.xmlschema(s)
+
+ begin
+ Time.at(-1)
+ rescue ArgumentError
+ # ignore
+ else
+ t = Time.utc(1937, 1, 1, 11, 40, 27, 870000)
+ s = "1937-01-01T12:00:27.87+00:20"
+ t.should == Time.xmlschema(s)
+ end
+
+ # more
+
+ # (Time.utc(1999, 5, 31, 13, 20, 0) + 5 * 3600).should == Time.xmlschema("1999-05-31T13:20:00-05:00")
+ # (Time.local(2000, 1, 20, 12, 0, 0)).should == Time.xmlschema("2000-01-20T12:00:00")
+ # (Time.utc(2000, 1, 20, 12, 0, 0)).should == Time.xmlschema("2000-01-20T12:00:00Z")
+ # (Time.utc(2000, 1, 20, 12, 0, 0) - 12 * 3600).should == Time.xmlschema("2000-01-20T12:00:00+12:00")
+ # (Time.utc(2000, 1, 20, 12, 0, 0) + 13 * 3600).should == Time.xmlschema("2000-01-20T12:00:00-13:00")
+ # (Time.utc(2000, 3, 4, 23, 0, 0) - 3 * 3600).should == Time.xmlschema("2000-03-04T23:00:00+03:00")
+ # (Time.utc(2000, 3, 4, 20, 0, 0)).should == Time.xmlschema("2000-03-04T20:00:00Z")
+ # (Time.local(2000, 1, 15, 0, 0, 0)).should == Time.xmlschema("2000-01-15T00:00:00")
+ # (Time.local(2000, 2, 15, 0, 0, 0)).should == Time.xmlschema("2000-02-15T00:00:00")
+ # (Time.local(2000, 1, 15, 12, 0, 0)).should == Time.xmlschema("2000-01-15T12:00:00")
+ # (Time.utc(2000, 1, 16, 12, 0, 0)).should == Time.xmlschema("2000-01-16T12:00:00Z")
+ # (Time.local(2000, 1, 1, 12, 0, 0)).should == Time.xmlschema("2000-01-01T12:00:00")
+ # (Time.utc(1999, 12, 31, 23, 0, 0)).should == Time.xmlschema("1999-12-31T23:00:00Z")
+ # (Time.local(2000, 1, 16, 12, 0, 0)).should == Time.xmlschema("2000-01-16T12:00:00")
+ # (Time.local(2000, 1, 16, 0, 0, 0)).should == Time.xmlschema("2000-01-16T00:00:00")
+ # (Time.utc(2000, 1, 12, 12, 13, 14)).should == Time.xmlschema("2000-01-12T12:13:14Z")
+ # (Time.utc(2001, 4, 17, 19, 23, 17, 300000)).should == Time.xmlschema("2001-04-17T19:23:17.3Z")
+ end
+end
diff --git a/spec/ruby/library/time/to_date_spec.rb b/spec/ruby/library/time/to_date_spec.rb
new file mode 100644
index 0000000000..855dc796cf
--- /dev/null
+++ b/spec/ruby/library/time/to_date_spec.rb
@@ -0,0 +1,42 @@
+
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'time'
+
+describe "Time#to_date" do
+ it "yields accurate julian date for ambiguous pre-Gregorian reform value" do
+ Time.utc(1582, 10, 4).to_date.jd.should == Date::ITALY - 11 # 2299150j
+ end
+
+ it "yields accurate julian date for Julian-Gregorian gap value" do
+ Time.utc(1582, 10, 14).to_date.jd.should == Date::ITALY - 1 # 2299160j
+ end
+
+ it "yields accurate julian date for post-Gregorian reform value" do
+ Time.utc(1582, 10, 15).to_date.jd.should == Date::ITALY # 2299161j
+ end
+
+ it "yields same julian day regardless of UTC time value" do
+ Time.utc(1582, 10, 15, 00, 00, 00).to_date.jd.should == Date::ITALY
+ Time.utc(1582, 10, 15, 23, 59, 59).to_date.jd.should == Date::ITALY
+ end
+
+ it "yields same julian day regardless of local time or zone" do
+
+ with_timezone("Pacific/Pago_Pago", -11) do
+ Time.local(1582, 10, 15, 00, 00, 00).to_date.jd.should == Date::ITALY
+ Time.local(1582, 10, 15, 23, 59, 59).to_date.jd.should == Date::ITALY
+ end
+
+ with_timezone("Asia/Kamchatka", +12) do
+ Time.local(1582, 10, 15, 00, 00, 00).to_date.jd.should == Date::ITALY
+ Time.local(1582, 10, 15, 23, 59, 59).to_date.jd.should == Date::ITALY
+ end
+
+ end
+
+ it "yields date with default Calendar reform day" do
+ Time.utc(1582, 10, 4).to_date.start.should == Date::ITALY
+ Time.utc(1582, 10, 14).to_date.start.should == Date::ITALY
+ Time.utc(1582, 10, 15).to_date.start.should == Date::ITALY
+ end
+end
diff --git a/spec/ruby/library/time/xmlschema_spec.rb b/spec/ruby/library/time/xmlschema_spec.rb
new file mode 100644
index 0000000000..14ea081d6e
--- /dev/null
+++ b/spec/ruby/library/time/xmlschema_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/xmlschema', __FILE__)
+require 'time'
+
+describe "Time.xmlschema" do
+ it_behaves_like :time_xmlschema, :xmlschema
+end
diff --git a/spec/ruby/library/timeout/error_spec.rb b/spec/ruby/library/timeout/error_spec.rb
new file mode 100644
index 0000000000..37462ecd49
--- /dev/null
+++ b/spec/ruby/library/timeout/error_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'timeout'
+
+describe "Timeout::Error" do
+ it "is a subclass of RuntimeError" do
+ RuntimeError.should be_ancestor_of(Timeout::Error)
+ end
+end
diff --git a/spec/ruby/library/timeout/timeout_spec.rb b/spec/ruby/library/timeout/timeout_spec.rb
new file mode 100644
index 0000000000..2eccd02097
--- /dev/null
+++ b/spec/ruby/library/timeout/timeout_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'timeout'
+
+describe "Timeout.timeout" do
+ it "raises Timeout::Error when it times out with no specified error type" do
+ lambda {
+ Timeout.timeout(1) do
+ sleep 3
+ end
+ }.should raise_error(Timeout::Error)
+ end
+
+ it "raises specified error type when it times out" do
+ lambda do
+ Timeout.timeout(1, StandardError) do
+ sleep 3
+ end
+ end.should raise_error(StandardError)
+ end
+
+ it "does not wait too long" do
+ before_time = Time.now
+ lambda do
+ Timeout.timeout(1, StandardError) do
+ sleep 3
+ end
+ end.should raise_error(StandardError)
+
+ (Time.now - before_time).should be_close(1.0, 0.5)
+ end
+
+ it "returns back the last value in the block" do
+ Timeout.timeout(1) do
+ 42
+ end.should == 42
+ end
+end
diff --git a/spec/ruby/library/tmpdir/dir/mktmpdir_spec.rb b/spec/ruby/library/tmpdir/dir/mktmpdir_spec.rb
new file mode 100644
index 0000000000..3459a47fe6
--- /dev/null
+++ b/spec/ruby/library/tmpdir/dir/mktmpdir_spec.rb
@@ -0,0 +1,117 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require "tmpdir"
+
+describe "Dir.mktmpdir when passed no arguments" do
+ after :each do
+ Dir.rmdir @tmpdir if File.directory? @tmpdir
+ end
+
+ it "returns the path to the created tmp-dir" do
+ Dir.stub!(:mkdir)
+ Dir.should_receive(:tmpdir).and_return("/tmp")
+ @tmpdir = Dir.mktmpdir
+ @tmpdir.should =~ /^\/tmp\//
+ end
+
+ it "creates a new writable directory in the path provided by Dir.tmpdir" do
+ Dir.should_receive(:tmpdir).and_return(tmp(""))
+ @tmpdir = Dir.mktmpdir
+ File.directory?(@tmpdir).should be_true
+ File.writable?(@tmpdir).should be_true
+ end
+end
+
+describe "Dir.mktmpdir when passed a block" do
+ before :each do
+ @real_tmp_root = tmp('')
+ Dir.stub!(:tmpdir).and_return(@real_tmp_root)
+ FileUtils.stub!(:remove_entry)
+ FileUtils.stub!(:remove_entry_secure)
+ end
+
+ after :each do
+ Dir.rmdir @tmpdir if File.directory? @tmpdir
+ end
+
+ it "yields the path to the passed block" do
+ Dir.stub!(:mkdir)
+ called = nil
+ Dir.mktmpdir do |path|
+ @tmpdir = path
+ called = true
+ path.start_with?(@real_tmp_root).should be_true
+ end
+ called.should be_true
+ end
+
+ it "creates the tmp-dir before yielding" do
+ Dir.should_receive(:tmpdir).and_return(tmp(""))
+ Dir.mktmpdir do |path|
+ @tmpdir = path
+ File.directory?(path).should be_true
+ File.writable?(path).should be_true
+ end
+ end
+
+ it "removes the tmp-dir after executing the block" do
+ Dir.stub!(:mkdir)
+ Dir.mktmpdir do |path|
+ @tmpdir = path
+ FileUtils.should_receive(:remove_entry).with(path)
+ end
+ end
+
+ it "returns the blocks return value" do
+ Dir.stub!(:mkdir)
+ result = Dir.mktmpdir do |path|
+ @tmpdir = path
+ :test
+ end
+ result.should equal(:test)
+ end
+end
+
+describe "Dir.mktmpdir when passed [String]" do
+ before :each do
+ Dir.stub!(:mkdir)
+ Dir.stub!(:tmpdir).and_return("/tmp")
+ end
+
+ after :each do
+ Dir.rmdir @tmpdir if File.directory? @tmpdir
+ end
+
+ it "uses the passed String as a prefix to the tmp-directory" do
+ prefix = "before"
+ @tmpdir = Dir.mktmpdir(prefix)
+ @tmpdir.should =~ /^\/tmp\/#{prefix}/
+ end
+end
+
+describe "Dir.mktmpdir when passed [Array]" do
+ before :each do
+ Dir.stub!(:mkdir)
+ Dir.stub!(:tmpdir).and_return("/tmp")
+ FileUtils.stub!(:remove_entry_secure)
+ end
+
+ after :each do
+ Dir.rmdir @tmpdir if File.directory? @tmpdir
+ end
+
+ it "uses the first element of the passed Array as a prefix and the scond element as a suffix to the tmp-directory" do
+ prefix = "before"
+ suffix = "after"
+
+ @tmpdir = Dir.mktmpdir([prefix, suffix])
+ @tmpdir.should =~ /#{suffix}$/
+ end
+end
+
+describe "Dir.mktmpdir when passed [Object]" do
+ it "raises an ArgumentError" do
+ lambda { Dir.mktmpdir(Object.new) }.should raise_error(ArgumentError)
+ lambda { Dir.mktmpdir(:symbol) }.should raise_error(ArgumentError)
+ lambda { Dir.mktmpdir(10) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/tmpdir/dir/tmpdir_spec.rb b/spec/ruby/library/tmpdir/dir/tmpdir_spec.rb
new file mode 100644
index 0000000000..19d54e03b3
--- /dev/null
+++ b/spec/ruby/library/tmpdir/dir/tmpdir_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require "tmpdir"
+
+describe "Dir.tmpdir" do
+ it "returns the path to a writable and readable directory" do
+ dir = Dir.tmpdir
+ File.directory?(dir).should be_true
+ File.writable?(dir).should be_true
+ end
+end
diff --git a/spec/ruby/library/uri/decode_www_form_component_spec.rb b/spec/ruby/library/uri/decode_www_form_component_spec.rb
new file mode 100644
index 0000000000..04cc634947
--- /dev/null
+++ b/spec/ruby/library/uri/decode_www_form_component_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI.decode_www_form_component" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/decode_www_form_spec.rb b/spec/ruby/library/uri/decode_www_form_spec.rb
new file mode 100644
index 0000000000..d4854a6ece
--- /dev/null
+++ b/spec/ruby/library/uri/decode_www_form_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI.decode_www_form" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/encode_www_form_component_spec.rb b/spec/ruby/library/uri/encode_www_form_component_spec.rb
new file mode 100644
index 0000000000..753b6d50d0
--- /dev/null
+++ b/spec/ruby/library/uri/encode_www_form_component_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI.encode_www_form_component" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/encode_www_form_spec.rb b/spec/ruby/library/uri/encode_www_form_spec.rb
new file mode 100644
index 0000000000..b72b928344
--- /dev/null
+++ b/spec/ruby/library/uri/encode_www_form_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI.encode_www_form" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/eql_spec.rb b/spec/ruby/library/uri/eql_spec.rb
new file mode 100644
index 0000000000..2bbc5291e9
--- /dev/null
+++ b/spec/ruby/library/uri/eql_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/normalization', __FILE__)
+require File.expand_path('../shared/eql', __FILE__)
+require 'uri'
+
+describe "URI#eql?" do
+ it_behaves_like :uri_eql, :eql?
+
+ it_behaves_like :uri_eql_against_other_types, :eql?
+end
diff --git a/spec/ruby/library/uri/equality_spec.rb b/spec/ruby/library/uri/equality_spec.rb
new file mode 100644
index 0000000000..07d48a9583
--- /dev/null
+++ b/spec/ruby/library/uri/equality_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/normalization', __FILE__)
+require File.expand_path('../shared/eql', __FILE__)
+require 'uri'
+
+describe "URI#==" do
+ it "ignores capitalization of host names" do
+ URI("http://exAMPLE.cOm").should == URI("http://example.com")
+ end
+
+ it "ignores capitalization of scheme" do
+ URI("hTTp://example.com").should == URI("http://example.com")
+ end
+
+ it "treats a blank path and a path of '/' as the same" do
+ URI("http://example.com").should == URI("http://example.com/")
+ end
+
+ it "is case sensitive in all components of the URI but the host and scheme" do
+ URI("http://example.com/paTH").should_not == URI("http://example.com/path")
+ URI("http://uSer@example.com").should_not == URI("http://user@example.com")
+ URI("http://example.com/path?quERy").should_not == URI("http://example.com/path?query")
+ URI("http://example.com/#fragMENT").should_not == URI("http://example.com/#fragment")
+ end
+
+ it "differentiates based on port number" do
+ URI("http://example.com:8080").should_not == URI("http://example.com")
+ end
+
+ # Note: The previous tests will be included in following ones
+
+ it_behaves_like :uri_eql, :==
+
+ it_behaves_like :uri_eql_against_other_types, :==
+
+ quarantine! do # Quarantined until redmine:2542 is accepted
+ it "returns true only if the normalized forms are equivalent" do
+ URISpec::NORMALIZED_FORMS.each do |form|
+ normal_uri = URI(form[:normalized])
+ form[:equivalent].each do |same|
+ URI(same).should == normal_uri
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/uri/escape/decode_spec.rb b/spec/ruby/library/uri/escape/decode_spec.rb
new file mode 100644
index 0000000000..34d3e787c4
--- /dev/null
+++ b/spec/ruby/library/uri/escape/decode_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Escape#decode" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/escape/encode_spec.rb b/spec/ruby/library/uri/escape/encode_spec.rb
new file mode 100644
index 0000000000..edde60b3cd
--- /dev/null
+++ b/spec/ruby/library/uri/escape/encode_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Escape#encode" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/escape/escape_spec.rb b/spec/ruby/library/uri/escape/escape_spec.rb
new file mode 100644
index 0000000000..3c6b957b18
--- /dev/null
+++ b/spec/ruby/library/uri/escape/escape_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Escape#escape" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/escape/unescape_spec.rb b/spec/ruby/library/uri/escape/unescape_spec.rb
new file mode 100644
index 0000000000..6a7165a0d3
--- /dev/null
+++ b/spec/ruby/library/uri/escape/unescape_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Escape#unescape" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/extract_spec.rb b/spec/ruby/library/uri/extract_spec.rb
new file mode 100644
index 0000000000..7b660851b6
--- /dev/null
+++ b/spec/ruby/library/uri/extract_spec.rb
@@ -0,0 +1,86 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI.extract" do
+ it "behaves according to its documentation" do
+ URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.").should == ["http://foo.example.org/bla", "mailto:test@example.com"]
+ end
+
+ it "treats contiguous URIs as a single URI" do
+ URI.extract('http://example.jphttp://example.jp').should == ['http://example.jphttp://example.jp']
+ end
+
+ it "treats pretty much anything with a colon as a URI" do
+ URI.extract('From: XXX [mailto:xxx@xxx.xxx.xxx]').should == ['From:', 'mailto:xxx@xxx.xxx.xxx]']
+ end
+
+ it "wraps a URI string in an array" do
+ URI.extract("http://github.com/brixen/rubyspec/tree/master").should == ["http://github.com/brixen/rubyspec/tree/master"]
+ end
+
+ it "pulls a variety of protocol URIs from a string" do
+ URI.extract("this is a string, it has http://rubini.us/ in it").should == ["http://rubini.us/"]
+ URI.extract("mailto:spambait@example.com").should == ["mailto:spambait@example.com"]
+ URI.extract("ftp://ruby-lang.org/").should == ["ftp://ruby-lang.org/"]
+ URI.extract("https://mail.google.com").should == ["https://mail.google.com"]
+ URI.extract("anything://example.com/").should == ["anything://example.com/"]
+ end
+
+ it "pulls all URIs within a string in order into an array when a block is not given" do
+ URI.extract("1.3. Example URI
+
+ The following examples illustrate URI that are in common use.
+
+ ftp://ftp.is.co.za/rfc/rfc1808.txt
+ -- ftp scheme for File Transfer Protocol services
+
+ gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles
+ -- gopher scheme for Gopher and Gopher+ Protocol services
+
+ http://www.math.uio.no/faq/compression-faq/part1.html
+ -- http scheme for Hypertext Transfer Protocol services
+
+ mailto:mduerst@ifi.unizh.ch
+ -- mailto scheme for electronic mail addresses
+
+ news:comp.infosystems.www.servers.unix
+ -- news scheme for USENET news groups and articles
+
+ telnet://melvyl.ucop.edu/
+ -- telnet scheme for interactive services via the TELNET Protocol
+ ").should == ["ftp://ftp.is.co.za/rfc/rfc1808.txt","gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles","http://www.math.uio.no/faq/compression-faq/part1.html","mailto:mduerst@ifi.unizh.ch","news:comp.infosystems.www.servers.unix","telnet://melvyl.ucop.edu/"]
+ end
+
+ it "yields each URI in the given string in order to a block, if given, and returns nil" do
+ results = ["http://foo.example.org/bla", "mailto:test@example.com"]
+ URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.") {|uri|
+ uri.should == results.shift
+ }.should == nil
+ results.should == []
+ end
+
+ it "allows the user to specify a list of acceptable protocols of URIs to scan for" do
+ URI.extract("1.3. Example URI
+
+ The following examples illustrate URI that are in common use.
+
+ ftp://ftp.is.co.za/rfc/rfc1808.txt
+ -- ftp scheme for File Transfer Protocol services
+
+ gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles
+ -- gopher scheme for Gopher and Gopher+ Protocol services
+
+ http://www.math.uio.no/faq/compression-faq/part1.html
+ -- http scheme for Hypertext Transfer Protocol services
+
+ mailto:mduerst@ifi.unizh.ch
+ -- mailto scheme for electronic mail addresses
+
+ news:comp.infosystems.www.servers.unix
+ -- news scheme for USENET news groups and articles
+
+ telnet://melvyl.ucop.edu/
+ -- telnet scheme for interactive services via the TELNET Protocol
+ ", ["http","ftp","mailto"]).should == ["ftp://ftp.is.co.za/rfc/rfc1808.txt","http://www.math.uio.no/faq/compression-faq/part1.html","mailto:mduerst@ifi.unizh.ch"]
+ end
+end
diff --git a/spec/ruby/library/uri/fixtures/classes.rb b/spec/ruby/library/uri/fixtures/classes.rb
new file mode 100644
index 0000000000..e1179307cc
--- /dev/null
+++ b/spec/ruby/library/uri/fixtures/classes.rb
@@ -0,0 +1,11 @@
+require 'uri'
+
+module URISpec
+ def self.components(uri)
+ result = {}
+ uri.component.each do |component|
+ result[component] = uri.send(component)
+ end
+ result
+ end
+end
diff --git a/spec/ruby/library/uri/fixtures/normalization.rb b/spec/ruby/library/uri/fixtures/normalization.rb
new file mode 100644
index 0000000000..cbc26c9b48
--- /dev/null
+++ b/spec/ruby/library/uri/fixtures/normalization.rb
@@ -0,0 +1,54 @@
+module URISpec
+ # Not an exhaustive list. Refer to rfc3986
+ NORMALIZED_FORMS = [
+ { normalized: "http://example.com/",
+ equivalent: %w{ hTTp://example.com/
+ http://exaMple.com/
+ http://exa%4dple.com/
+ http://exa%4Dple.com/
+ http://exa%6dple.com/
+ http://exa%6Dple.com/
+ http://@example.com/
+ http://example.com:/
+ http://example.com:80/
+ http://example.com
+ },
+ different: %w{ http://example.com/#
+ http://example.com/?
+ http://example.com:8888/
+ http:///example.com
+ http:example.com
+ https://example.com/
+ },
+ },
+ { normalized: "http://example.com/index.html",
+ equivalent: %w{ http://example.com/index.ht%6dl
+ http://example.com/index.ht%6Dl
+ },
+ different: %w{ http://example.com/index.hTMl
+ http://example.com/index.ht%4dl
+ http://example.com/index
+ http://example.com/
+ http://example.com/
+ },
+ },
+ { normalized: "http://example.com/x?y#z",
+ equivalent: %w{ http://example.com/x?y#%7a
+ http://example.com/x?y#%7A
+ http://example.com/x?%79#z
+ },
+ different: %w{ http://example.com/x?Y#z
+ http://example.com/x?y#Z
+ http://example.com/x?y=#z
+ http://example.com/x?y
+ http://example.com/x#z
+ },
+ },
+ { normalized: "http://example.com/x?q=a%20b",
+ equivalent: %w{
+ },
+ different: %w{ http://example.com/x?q=a+b
+ },
+ },
+ ]
+end
diff --git a/spec/ruby/library/uri/ftp/build_spec.rb b/spec/ruby/library/uri/ftp/build_spec.rb
new file mode 100644
index 0000000000..c7765e2868
--- /dev/null
+++ b/spec/ruby/library/uri/ftp/build_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::FTP.build" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ftp/merge_spec.rb b/spec/ruby/library/uri/ftp/merge_spec.rb
new file mode 100644
index 0000000000..b766e992ca
--- /dev/null
+++ b/spec/ruby/library/uri/ftp/merge_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::FTP#merge" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ftp/new2_spec.rb b/spec/ruby/library/uri/ftp/new2_spec.rb
new file mode 100644
index 0000000000..a43916af6a
--- /dev/null
+++ b/spec/ruby/library/uri/ftp/new2_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::FTP.new2" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ftp/path_spec.rb b/spec/ruby/library/uri/ftp/path_spec.rb
new file mode 100644
index 0000000000..9e1a00602f
--- /dev/null
+++ b/spec/ruby/library/uri/ftp/path_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::FTP#path=" do
+ before :each do
+ @url = URI.parse('ftp://example.com')
+ end
+
+ it "does not require a leading /" do
+ @url.path = 'foo'
+ @url.path.should == 'foo'
+ end
+
+ it "does not strip the leading /" do
+ @url.path = '/foo'
+ @url.path.should == '/foo'
+ end
+end
+
+describe "URI::FTP#path" do
+ it "unescapes the leading /" do
+ url = URI.parse('ftp://example.com/%2Ffoo')
+
+ url.path.should == '/foo'
+ end
+end
diff --git a/spec/ruby/library/uri/ftp/set_typecode_spec.rb b/spec/ruby/library/uri/ftp/set_typecode_spec.rb
new file mode 100644
index 0000000000..b815bc8740
--- /dev/null
+++ b/spec/ruby/library/uri/ftp/set_typecode_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::FTP#set_typecode" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ftp/to_s_spec.rb b/spec/ruby/library/uri/ftp/to_s_spec.rb
new file mode 100644
index 0000000000..e4e2832e86
--- /dev/null
+++ b/spec/ruby/library/uri/ftp/to_s_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+
+describe "URI::FTP#to_s" do
+ before :each do
+ @url = URI.parse('ftp://example.com')
+ end
+
+ it "escapes the leading /" do
+ @url.path = '/foo'
+
+ @url.to_s.should == 'ftp://example.com/%2Ffoo'
+ end
+end
diff --git a/spec/ruby/library/uri/ftp/typecode_spec.rb b/spec/ruby/library/uri/ftp/typecode_spec.rb
new file mode 100644
index 0000000000..b298c2ae98
--- /dev/null
+++ b/spec/ruby/library/uri/ftp/typecode_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::FTP#typecode" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::FTP#typecode=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/absolute_spec.rb b/spec/ruby/library/uri/generic/absolute_spec.rb
new file mode 100644
index 0000000000..4f6526b827
--- /dev/null
+++ b/spec/ruby/library/uri/generic/absolute_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#absolute" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#absolute?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/build2_spec.rb b/spec/ruby/library/uri/generic/build2_spec.rb
new file mode 100644
index 0000000000..0b9a6788f6
--- /dev/null
+++ b/spec/ruby/library/uri/generic/build2_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic.build2" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/build_spec.rb b/spec/ruby/library/uri/generic/build_spec.rb
new file mode 100644
index 0000000000..6fa5d6ac55
--- /dev/null
+++ b/spec/ruby/library/uri/generic/build_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic.build" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/coerce_spec.rb b/spec/ruby/library/uri/generic/coerce_spec.rb
new file mode 100644
index 0000000000..1b1a040f63
--- /dev/null
+++ b/spec/ruby/library/uri/generic/coerce_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#coerce" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/component_ary_spec.rb b/spec/ruby/library/uri/generic/component_ary_spec.rb
new file mode 100644
index 0000000000..3244073e0e
--- /dev/null
+++ b/spec/ruby/library/uri/generic/component_ary_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#component_ary" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/component_spec.rb b/spec/ruby/library/uri/generic/component_spec.rb
new file mode 100644
index 0000000000..6fb83d7796
--- /dev/null
+++ b/spec/ruby/library/uri/generic/component_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#component" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic.component" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/default_port_spec.rb b/spec/ruby/library/uri/generic/default_port_spec.rb
new file mode 100644
index 0000000000..d1e0ce2d3f
--- /dev/null
+++ b/spec/ruby/library/uri/generic/default_port_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#default_port" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic.default_port" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/eql_spec.rb b/spec/ruby/library/uri/generic/eql_spec.rb
new file mode 100644
index 0000000000..65f9204a19
--- /dev/null
+++ b/spec/ruby/library/uri/generic/eql_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#eql?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/equal_value_spec.rb b/spec/ruby/library/uri/generic/equal_value_spec.rb
new file mode 100644
index 0000000000..f41b202498
--- /dev/null
+++ b/spec/ruby/library/uri/generic/equal_value_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#==" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/fragment_spec.rb b/spec/ruby/library/uri/generic/fragment_spec.rb
new file mode 100644
index 0000000000..de6f4e078d
--- /dev/null
+++ b/spec/ruby/library/uri/generic/fragment_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#fragment" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#fragment=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/hash_spec.rb b/spec/ruby/library/uri/generic/hash_spec.rb
new file mode 100644
index 0000000000..3410558067
--- /dev/null
+++ b/spec/ruby/library/uri/generic/hash_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#hash" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/hierarchical_spec.rb b/spec/ruby/library/uri/generic/hierarchical_spec.rb
new file mode 100644
index 0000000000..1c90dc4f8f
--- /dev/null
+++ b/spec/ruby/library/uri/generic/hierarchical_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#hierarchical?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/host_spec.rb b/spec/ruby/library/uri/generic/host_spec.rb
new file mode 100644
index 0000000000..6fb6c1c36a
--- /dev/null
+++ b/spec/ruby/library/uri/generic/host_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#host" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#host=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/inspect_spec.rb b/spec/ruby/library/uri/generic/inspect_spec.rb
new file mode 100644
index 0000000000..696c3308d4
--- /dev/null
+++ b/spec/ruby/library/uri/generic/inspect_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#inspect" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/merge_spec.rb b/spec/ruby/library/uri/generic/merge_spec.rb
new file mode 100644
index 0000000000..63642197e1
--- /dev/null
+++ b/spec/ruby/library/uri/generic/merge_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#merge" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#merge!" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/minus_spec.rb b/spec/ruby/library/uri/generic/minus_spec.rb
new file mode 100644
index 0000000000..3426a6068b
--- /dev/null
+++ b/spec/ruby/library/uri/generic/minus_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#-" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/normalize_spec.rb b/spec/ruby/library/uri/generic/normalize_spec.rb
new file mode 100644
index 0000000000..ac02b644d0
--- /dev/null
+++ b/spec/ruby/library/uri/generic/normalize_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#normalize" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#normalize!" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/opaque_spec.rb b/spec/ruby/library/uri/generic/opaque_spec.rb
new file mode 100644
index 0000000000..f418c220f2
--- /dev/null
+++ b/spec/ruby/library/uri/generic/opaque_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#opaque" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#opaque=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/password_spec.rb b/spec/ruby/library/uri/generic/password_spec.rb
new file mode 100644
index 0000000000..087db60fb9
--- /dev/null
+++ b/spec/ruby/library/uri/generic/password_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#password" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#password=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/path_spec.rb b/spec/ruby/library/uri/generic/path_spec.rb
new file mode 100644
index 0000000000..5ea60b5418
--- /dev/null
+++ b/spec/ruby/library/uri/generic/path_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#path" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#path=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/plus_spec.rb b/spec/ruby/library/uri/generic/plus_spec.rb
new file mode 100644
index 0000000000..3d1c031022
--- /dev/null
+++ b/spec/ruby/library/uri/generic/plus_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#+" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/port_spec.rb b/spec/ruby/library/uri/generic/port_spec.rb
new file mode 100644
index 0000000000..148e84ff14
--- /dev/null
+++ b/spec/ruby/library/uri/generic/port_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#port" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#port=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/query_spec.rb b/spec/ruby/library/uri/generic/query_spec.rb
new file mode 100644
index 0000000000..945fdc06a3
--- /dev/null
+++ b/spec/ruby/library/uri/generic/query_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#query" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#query=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/registry_spec.rb b/spec/ruby/library/uri/generic/registry_spec.rb
new file mode 100644
index 0000000000..6a48b25465
--- /dev/null
+++ b/spec/ruby/library/uri/generic/registry_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#registry" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#registry=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/relative_spec.rb b/spec/ruby/library/uri/generic/relative_spec.rb
new file mode 100644
index 0000000000..09730fa4eb
--- /dev/null
+++ b/spec/ruby/library/uri/generic/relative_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#relative?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/route_from_spec.rb b/spec/ruby/library/uri/generic/route_from_spec.rb
new file mode 100644
index 0000000000..03321cbf0d
--- /dev/null
+++ b/spec/ruby/library/uri/generic/route_from_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#route_from" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/route_to_spec.rb b/spec/ruby/library/uri/generic/route_to_spec.rb
new file mode 100644
index 0000000000..a12e1f7649
--- /dev/null
+++ b/spec/ruby/library/uri/generic/route_to_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#route_to" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/scheme_spec.rb b/spec/ruby/library/uri/generic/scheme_spec.rb
new file mode 100644
index 0000000000..fa3dfcb8aa
--- /dev/null
+++ b/spec/ruby/library/uri/generic/scheme_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#scheme" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#scheme=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/select_spec.rb b/spec/ruby/library/uri/generic/select_spec.rb
new file mode 100644
index 0000000000..5cc104f5dd
--- /dev/null
+++ b/spec/ruby/library/uri/generic/select_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#select" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_fragment_spec.rb b/spec/ruby/library/uri/generic/set_fragment_spec.rb
new file mode 100644
index 0000000000..cebad46585
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_fragment_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_fragment" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_host_spec.rb b/spec/ruby/library/uri/generic/set_host_spec.rb
new file mode 100644
index 0000000000..357b7a6889
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_host_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_host" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_opaque_spec.rb b/spec/ruby/library/uri/generic/set_opaque_spec.rb
new file mode 100644
index 0000000000..afd6597675
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_opaque_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_opaque" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_password_spec.rb b/spec/ruby/library/uri/generic/set_password_spec.rb
new file mode 100644
index 0000000000..15b4fdc37d
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_password_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_password" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_path_spec.rb b/spec/ruby/library/uri/generic/set_path_spec.rb
new file mode 100644
index 0000000000..b4366d789c
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_path_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_path" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_port_spec.rb b/spec/ruby/library/uri/generic/set_port_spec.rb
new file mode 100644
index 0000000000..aa65bb96e3
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_port_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_port" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_query_spec.rb b/spec/ruby/library/uri/generic/set_query_spec.rb
new file mode 100644
index 0000000000..b1c25e56ca
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_query_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_query" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_registry_spec.rb b/spec/ruby/library/uri/generic/set_registry_spec.rb
new file mode 100644
index 0000000000..602f868ac1
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_registry_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_registry" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_scheme_spec.rb b/spec/ruby/library/uri/generic/set_scheme_spec.rb
new file mode 100644
index 0000000000..e1a94c5b1a
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_scheme_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_scheme" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_user_spec.rb b/spec/ruby/library/uri/generic/set_user_spec.rb
new file mode 100644
index 0000000000..36a6ac9e85
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_user_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_user" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/set_userinfo_spec.rb b/spec/ruby/library/uri/generic/set_userinfo_spec.rb
new file mode 100644
index 0000000000..cbe80d9809
--- /dev/null
+++ b/spec/ruby/library/uri/generic/set_userinfo_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#set_userinfo" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/to_s_spec.rb b/spec/ruby/library/uri/generic/to_s_spec.rb
new file mode 100644
index 0000000000..c0a0f803ef
--- /dev/null
+++ b/spec/ruby/library/uri/generic/to_s_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#to_s" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/use_registry_spec.rb b/spec/ruby/library/uri/generic/use_registry_spec.rb
new file mode 100644
index 0000000000..4e7ae6a5cf
--- /dev/null
+++ b/spec/ruby/library/uri/generic/use_registry_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic.use_registry" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/user_spec.rb b/spec/ruby/library/uri/generic/user_spec.rb
new file mode 100644
index 0000000000..b785ef6879
--- /dev/null
+++ b/spec/ruby/library/uri/generic/user_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#user" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#user=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/generic/userinfo_spec.rb b/spec/ruby/library/uri/generic/userinfo_spec.rb
new file mode 100644
index 0000000000..5d0fc50b65
--- /dev/null
+++ b/spec/ruby/library/uri/generic/userinfo_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Generic#userinfo" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::Generic#userinfo=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/http/build_spec.rb b/spec/ruby/library/uri/http/build_spec.rb
new file mode 100644
index 0000000000..85103167e0
--- /dev/null
+++ b/spec/ruby/library/uri/http/build_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::HTTP.build" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/http/request_uri_spec.rb b/spec/ruby/library/uri/http/request_uri_spec.rb
new file mode 100644
index 0000000000..85d89aba77
--- /dev/null
+++ b/spec/ruby/library/uri/http/request_uri_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::HTTP.request_uri" do
+ it "returns a string of the path + query" do
+ URI("http://reddit.com/r/ruby/").request_uri.should == "/r/ruby/"
+ URI("http://reddit.com/r/ruby/search?q=rubinius").request_uri.should == "/r/ruby/search?q=rubinius"
+ end
+
+ it "returns '/' if the path of the URI is blank" do
+ URI("http://ruby.reddit.com").request_uri.should == "/"
+ end
+end
+describe "URI::HTTP#request_uri" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/join_spec.rb b/spec/ruby/library/uri/join_spec.rb
new file mode 100644
index 0000000000..681ba45cc7
--- /dev/null
+++ b/spec/ruby/library/uri/join_spec.rb
@@ -0,0 +1,57 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI.join" do
+ it "returns a URI object of the concatenation of a protocol and domain, and a path" do
+ URI.join("http://localhost/","main.rbx").should == URI.parse("http://localhost/main.rbx")
+ end
+
+ it "accepts URI objects" do
+ URI.join(URI("http://localhost/"),"main.rbx").should == URI.parse("http://localhost/main.rbx")
+ URI.join("http://localhost/",URI("main.rbx")).should == URI.parse("http://localhost/main.rbx")
+ URI.join(URI("http://localhost/"),URI("main.rbx")).should == URI.parse("http://localhost/main.rbx")
+ end
+
+ it "accepts string-like arguments with to_str" do
+ str = mock('string-like')
+ str.should_receive(:to_str).and_return("http://ruby-lang.org")
+ str2 = mock('string-like also')
+ str2.should_receive(:to_str).and_return("foo/bar")
+ URI.join(str, str2).should == URI.parse("http://ruby-lang.org/foo/bar")
+ end
+
+ it "raises an error if given no argument" do
+ lambda{ URI.join }.should raise_error
+ end
+
+ it "doesn't create redundant '/'s" do
+ URI.join("http://localhost/", "/main.rbx").should == URI.parse("http://localhost/main.rbx")
+ end
+
+ it "discards arguments given before an absolute uri" do
+ URI.join("http://localhost/a/b/c/d", "http://ruby-lang.com/foo", "bar").should == URI.parse("http://ruby-lang.com/bar")
+ end
+
+ it "resolves .. in paths" do
+ URI.join("http://localhost/a/b/c/d", "../../e/f", "g/h/../i").to_s.should == "http://localhost/a/e/g/i"
+ end
+end
+
+
+# assert_equal(URI.parse('http://foo/bar'), URI.join('http://foo/bar'))
+# assert_equal(URI.parse('http://foo/bar'), URI.join('http://foo', 'bar'))
+# assert_equal(URI.parse('http://foo/bar/'), URI.join('http://foo', 'bar/'))
+#
+# assert_equal(URI.parse('http://foo/baz'), URI.join('http://foo', 'bar', 'baz'))
+# assert_equal(URI.parse('http://foo/baz'), URI.join('http://foo', 'bar', '/baz'))
+# assert_equal(URI.parse('http://foo/baz/'), URI.join('http://foo', 'bar', '/baz/'))
+# assert_equal(URI.parse('http://foo/bar/baz'), URI.join('http://foo', 'bar/', 'baz'))
+# assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar', 'baz', 'hoge'))
+#
+# assert_equal(URI.parse('http://foo/bar/baz'), URI.join('http://foo', 'bar/baz'))
+# assert_equal(URI.parse('http://foo/bar/hoge'), URI.join('http://foo', 'bar/baz', 'hoge'))
+# assert_equal(URI.parse('http://foo/bar/baz/hoge'), URI.join('http://foo', 'bar/baz/', 'hoge'))
+# assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar/baz', '/hoge'))
+# assert_equal(URI.parse('http://foo/bar/hoge'), URI.join('http://foo', 'bar/baz', 'hoge'))
+# assert_equal(URI.parse('http://foo/bar/baz/hoge'), URI.join('http://foo', 'bar/baz/', 'hoge'))
+# assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar/baz', '/hoge'))
diff --git a/spec/ruby/library/uri/ldap/attributes_spec.rb b/spec/ruby/library/uri/ldap/attributes_spec.rb
new file mode 100644
index 0000000000..2309de7c62
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/attributes_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#attributes" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::LDAP#attributes=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/build_spec.rb b/spec/ruby/library/uri/ldap/build_spec.rb
new file mode 100644
index 0000000000..99e2611b1f
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/build_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP.build" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/dn_spec.rb b/spec/ruby/library/uri/ldap/dn_spec.rb
new file mode 100644
index 0000000000..b1371611d3
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/dn_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#dn" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::LDAP#dn=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/extensions_spec.rb b/spec/ruby/library/uri/ldap/extensions_spec.rb
new file mode 100644
index 0000000000..2d9b09e6a7
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/extensions_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#extensions" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::LDAP#extensions=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/filter_spec.rb b/spec/ruby/library/uri/ldap/filter_spec.rb
new file mode 100644
index 0000000000..1f996339db
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/filter_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#filter" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::LDAP#filter=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/hierarchical_spec.rb b/spec/ruby/library/uri/ldap/hierarchical_spec.rb
new file mode 100644
index 0000000000..97c23a7f0c
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/hierarchical_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#hierarchical?" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/scope_spec.rb b/spec/ruby/library/uri/ldap/scope_spec.rb
new file mode 100644
index 0000000000..d4a02e08f0
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/scope_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#scope" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::LDAP#scope=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/set_attributes_spec.rb b/spec/ruby/library/uri/ldap/set_attributes_spec.rb
new file mode 100644
index 0000000000..1bbcb34837
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/set_attributes_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#set_attributes" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/set_dn_spec.rb b/spec/ruby/library/uri/ldap/set_dn_spec.rb
new file mode 100644
index 0000000000..abb640b585
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/set_dn_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#set_dn" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/set_extensions_spec.rb b/spec/ruby/library/uri/ldap/set_extensions_spec.rb
new file mode 100644
index 0000000000..5cd2077aab
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/set_extensions_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#set_extensions" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/set_filter_spec.rb b/spec/ruby/library/uri/ldap/set_filter_spec.rb
new file mode 100644
index 0000000000..f1b8e5e595
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/set_filter_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#set_filter" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/ldap/set_scope_spec.rb b/spec/ruby/library/uri/ldap/set_scope_spec.rb
new file mode 100644
index 0000000000..5a0841cfd8
--- /dev/null
+++ b/spec/ruby/library/uri/ldap/set_scope_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::LDAP#set_scope" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/mailto/build_spec.rb b/spec/ruby/library/uri/mailto/build_spec.rb
new file mode 100644
index 0000000000..cb57f0c794
--- /dev/null
+++ b/spec/ruby/library/uri/mailto/build_spec.rb
@@ -0,0 +1,98 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Mailto.build" do
+ it "conforms to the MatzRuby tests" do
+ ok = []
+ bad = []
+
+ # RFC2368, 6. Examples
+ # mailto:chris@example.com
+ ok << ["mailto:chris@example.com"]
+ ok[-1] << ["chris@example.com", nil]
+ ok[-1] << {to: "chris@example.com"}
+
+ # mailto:infobot@example.com?subject=current-issue
+ ok << ["mailto:infobot@example.com?subject=current-issue"]
+ ok[-1] << ["infobot@example.com", ["subject=current-issue"]]
+ ok[-1] << {to: "infobot@example.com",
+ headers: ["subject=current-issue"]}
+
+ # mailto:infobot@example.com?body=send%20current-issue
+ ok << ["mailto:infobot@example.com?body=send%20current-issue"]
+ ok[-1] << ["infobot@example.com", ["body=send%20current-issue"]]
+ ok[-1] << {to: "infobot@example.com",
+ headers: ["body=send%20current-issue"]}
+
+ # mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index
+ ok << ["mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index"]
+ ok[-1] << ["infobot@example.com",
+ ["body=send%20current-issue%0D%0Asend%20index"]]
+ ok[-1] << {to: "infobot@example.com",
+ headers: ["body=send%20current-issue%0D%0Asend%20index"]}
+
+ # mailto:foobar@example.com?In-Reply-To=%3c3469A91.D10AF4C@example.com
+ ok << ["mailto:foobar@example.com?In-Reply-To=%3c3469A91.D10AF4C@example.com"]
+ ok[-1] << ["foobar@example.com",
+ ["In-Reply-To=%3c3469A91.D10AF4C@example.com"]]
+ ok[-1] << {to: "foobar@example.com",
+ headers: ["In-Reply-To=%3c3469A91.D10AF4C@example.com"]}
+
+ # mailto:majordomo@example.com?body=subscribe%20bamboo-l
+ ok << ["mailto:majordomo@example.com?body=subscribe%20bamboo-l"]
+ ok[-1] << ["majordomo@example.com", ["body=subscribe%20bamboo-l"]]
+ ok[-1] << {to: "majordomo@example.com",
+ headers: ["body=subscribe%20bamboo-l"]}
+
+ # mailto:joe@example.com?cc=bob@example.com&body=hello
+ ok << ["mailto:joe@example.com?cc=bob@example.com&body=hello"]
+ ok[-1] << ["joe@example.com", ["cc=bob@example.com", "body=hello"]]
+ ok[-1] << {to: "joe@example.com",
+ headers: ["cc=bob@example.com", "body=hello"]}
+
+ # mailto:?to=joe@example.com&cc=bob@example.com&body=hello
+ ok << ["mailto:?to=joe@example.com&cc=bob@example.com&body=hello"]
+ ok[-1] << [nil,
+ ["to=joe@example.com", "cc=bob@example.com", "body=hello"]]
+ ok[-1] << {headers: ["to=joe@example.com", "cc=bob@example.com", "body=hello"]}
+
+ # mailto:gorby%25kremvax@example.com
+ ok << ["mailto:gorby%25kremvax@example.com"]
+ ok[-1] << ["gorby%25kremvax@example.com", nil]
+ ok[-1] << {to: "gorby%25kremvax@example.com"}
+
+ # mailto:unlikely%3Faddress@example.com?blat=foop
+ ok << ["mailto:unlikely%3Faddress@example.com?blat=foop"]
+ ok[-1] << ["unlikely%3Faddress@example.com", ["blat=foop"]]
+ ok[-1] << {to: "unlikely%3Faddress@example.com",
+ headers: ["blat=foop"]}
+
+ ok_all = ok.flatten.join("\0")
+
+ # mailto:joe@example.com?cc=bob@example.com?body=hello ; WRONG!
+ bad << ["joe@example.com", ["cc=bob@example.com?body=hello"]]
+
+ # mailto:javascript:alert()
+ bad << ["javascript:alert()", []]
+
+ # '=' which is in hname or hvalue is wrong.
+ bad << ["foo@example.jp?subject=1+1=2", []]
+
+ ok.each do |x|
+ URI::MailTo.build(x[1]).to_s.should == x[0]
+ URI::MailTo.build(x[2]).to_s.should == x[0]
+ end
+
+ bad.each do |x|
+ lambda { URI::MailTo.build(x) }.should raise_error(URI::InvalidComponentError)
+ end
+
+ ok.flatten.join("\0").should == ok_all
+ end
+end
+
+
+
+describe "URI::MailTo.build" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/mailto/headers_spec.rb b/spec/ruby/library/uri/mailto/headers_spec.rb
new file mode 100644
index 0000000000..844fdee714
--- /dev/null
+++ b/spec/ruby/library/uri/mailto/headers_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::MailTo#headers" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::MailTo#headers=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/mailto/set_headers_spec.rb b/spec/ruby/library/uri/mailto/set_headers_spec.rb
new file mode 100644
index 0000000000..c1384d5dca
--- /dev/null
+++ b/spec/ruby/library/uri/mailto/set_headers_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::MailTo#set_headers" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/mailto/set_to_spec.rb b/spec/ruby/library/uri/mailto/set_to_spec.rb
new file mode 100644
index 0000000000..a8351a2092
--- /dev/null
+++ b/spec/ruby/library/uri/mailto/set_to_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::MailTo#set_to" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/mailto/to_mailtext_spec.rb b/spec/ruby/library/uri/mailto/to_mailtext_spec.rb
new file mode 100644
index 0000000000..4c7a48874f
--- /dev/null
+++ b/spec/ruby/library/uri/mailto/to_mailtext_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::MailTo#to_mailtext" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/mailto/to_rfc822text_spec.rb b/spec/ruby/library/uri/mailto/to_rfc822text_spec.rb
new file mode 100644
index 0000000000..e769f62deb
--- /dev/null
+++ b/spec/ruby/library/uri/mailto/to_rfc822text_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::MailTo#to_rfc822text" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/mailto/to_s_spec.rb b/spec/ruby/library/uri/mailto/to_s_spec.rb
new file mode 100644
index 0000000000..2709d19d27
--- /dev/null
+++ b/spec/ruby/library/uri/mailto/to_s_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::MailTo#to_s" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/mailto/to_spec.rb b/spec/ruby/library/uri/mailto/to_spec.rb
new file mode 100644
index 0000000000..f30d23dd53
--- /dev/null
+++ b/spec/ruby/library/uri/mailto/to_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::MailTo#to" do
+ it "needs to be reviewed for spec completeness"
+end
+
+describe "URI::MailTo#to=" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/merge_spec.rb b/spec/ruby/library/uri/merge_spec.rb
new file mode 100644
index 0000000000..c62e80d6b2
--- /dev/null
+++ b/spec/ruby/library/uri/merge_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI#merge" do
+ it "returns the receiver and the argument, joined as per URI.join" do
+ URI("http://localhost/").merge("main.rbx").should == URI.parse("http://localhost/main.rbx")
+ URI("http://localhost/a/b/c/d").merge("http://ruby-lang.com/foo").should == URI.parse("http://ruby-lang.com/foo")
+ URI("http://localhost/a/b/c/d").merge("../../e/f").to_s.should == "http://localhost/a/e/f"
+ end
+
+ it "accepts URI objects as argument" do
+ URI("http://localhost/").merge(URI("main.rbx")).should == URI.parse("http://localhost/main.rbx")
+ end
+
+ it "accepts a string-like argument" do
+ str = mock('string-like')
+ str.should_receive(:to_str).and_return("foo/bar")
+ URI("http://localhost/").merge(str).should == URI.parse("http://localhost/foo/bar")
+ end
+end
diff --git a/spec/ruby/library/uri/normalize_spec.rb b/spec/ruby/library/uri/normalize_spec.rb
new file mode 100644
index 0000000000..079a9ad61d
--- /dev/null
+++ b/spec/ruby/library/uri/normalize_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/normalization', __FILE__)
+require 'uri'
+
+describe "URI#normalize" do
+ it "adds a / onto the end of the URI if the path is blank" do
+ no_path = URI("http://example.com")
+ no_path.to_s.should_not == "http://example.com/"
+ no_path.normalize.to_s.should == "http://example.com/"
+ end
+
+ it "downcases the host of the URI" do
+ uri = URI("http://exAMPLE.cOm/")
+ uri.to_s.should_not == "http://example.com/"
+ uri.normalize.to_s.should == "http://example.com/"
+ end
+
+ # The previous tests are included by the one below
+
+ quarantine! do # Quarantined until redmine:2542 is accepted
+ it "respects RFC 3986" do
+ URISpec::NORMALIZED_FORMS.each do |form|
+ normal_uri = URI(form[:normalized])
+ normalized = normal_uri.normalize.to_s
+ normal_uri.to_s.should == normalized
+ form[:equivalent].each do |same|
+ URI(same).normalize.to_s.should == normalized
+ end
+ form[:different].each do |other|
+ URI(other).normalize.to_s.should_not == normalized
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/uri/parse_spec.rb b/spec/ruby/library/uri/parse_spec.rb
new file mode 100644
index 0000000000..4aa84ae2ee
--- /dev/null
+++ b/spec/ruby/library/uri/parse_spec.rb
@@ -0,0 +1,203 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "URI.parse" do
+
+ it "returns a URI::HTTP object when parsing an HTTP URI" do
+ URI.parse("http://www.example.com/").should be_kind_of(URI::HTTP)
+ end
+
+ it "populates the components of a parsed URI::HTTP, setting the port to 80 by default" do
+ # general case
+ URISpec.components(URI.parse("http://user:pass@example.com/path/?query=val&q2=val2#fragment")).should == {
+ scheme: "http",
+ userinfo: "user:pass",
+ host: "example.com",
+ port: 80,
+ path: "/path/",
+ query: "query=val&q2=val2",
+ fragment: "fragment"
+ }
+
+ # multiple paths
+ URISpec.components(URI.parse("http://a/b/c/d;p?q")).should == {
+ scheme: "http",
+ userinfo: nil,
+ host: "a",
+ port: 80,
+ path: "/b/c/d;p",
+ query: "q",
+ fragment: nil
+ }
+
+ # multi-level domain
+ URISpec.components(URI.parse('http://www.math.uio.no/faq/compression-faq/part1.html')).should == {
+ scheme: "http",
+ userinfo: nil,
+ host: "www.math.uio.no",
+ port: 80,
+ path: "/faq/compression-faq/part1.html",
+ query: nil,
+ fragment: nil
+ }
+ end
+
+ it "parses out the port number of a URI, when given" do
+ URI.parse("http://example.com:8080/").port.should == 8080
+ end
+
+ it "returns a URI::HTTPS object when parsing an HTTPS URI" do
+ URI.parse("https://important-intern-net.net").should be_kind_of(URI::HTTPS)
+ end
+
+ it "sets the port of a parsed https URI to 443 by default" do
+ URI.parse("https://example.com/").port.should == 443
+ end
+
+ it "populates the components of a parsed URI::FTP object" do
+ # generic, empty password.
+ url = URI.parse("ftp://anonymous@ruby-lang.org/pub/ruby/1.8/ruby-1.8.6.tar.bz2;type=i")
+ url.should be_kind_of(URI::FTP)
+ URISpec.components(url).should == {
+ scheme: "ftp",
+ userinfo: "anonymous",
+ host: "ruby-lang.org",
+ port: 21,
+ path: "pub/ruby/1.8/ruby-1.8.6.tar.bz2",
+ typecode: "i"
+ }
+
+ # multidomain, no user or password
+ url = URI.parse('ftp://ftp.is.co.za/rfc/rfc1808.txt')
+ url.should be_kind_of(URI::FTP)
+ URISpec.components(url).should == {
+ scheme: "ftp",
+ userinfo: nil,
+ host: "ftp.is.co.za",
+ port: 21,
+ path: "rfc/rfc1808.txt",
+ typecode: nil
+ }
+
+ # empty user
+ url = URI.parse('ftp://:pass@localhost/')
+ url.should be_kind_of(URI::FTP)
+ URISpec.components(url).should == {
+ scheme: "ftp",
+ userinfo: ":pass",
+ host: "localhost",
+ port: 21,
+ path: "",
+ typecode: nil
+ }
+ url.password.should == "pass"
+ end
+
+ it "returns a URI::LDAP object when parsing an LDAP URI" do
+ #taken from http://www.faqs.org/rfcs/rfc2255.html 'cause I don't really know what an LDAP url looks like
+ ldap_uris = %w{ ldap:///o=University%20of%20Michigan,c=US ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US?postalAddress ldap://host.com:6666/o=University%20of%20Michigan,c=US??sub?(cn=Babs%20Jensen) ldap://ldap.itd.umich.edu/c=GB?objectClass?one ldap://ldap.question.com/o=Question%3f,c=US?mail ldap://ldap.netscape.com/o=Babsco,c=US??(int=%5c00%5c00%5c00%5c04) ldap:///??sub??bindname=cn=Manager%2co=Foo ldap:///??sub??!bindname=cn=Manager%2co=Foo }
+ ldap_uris.each do |ldap_uri|
+ URI.parse(ldap_uri).should be_kind_of(URI::LDAP)
+ end
+ end
+
+ it "populates the components of a parsed URI::LDAP object" do
+ URISpec.components(URI.parse("ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US?postalAddress?scope?filter?extensions")).should == {
+ scheme: "ldap",
+ host: "ldap.itd.umich.edu",
+ port: 389,
+ dn: "o=University%20of%20Michigan,c=US",
+ attributes: "postalAddress",
+ scope: "scope",
+ filter: "filter",
+ extensions: "extensions"
+ }
+ end
+
+ it "returns a URI::MailTo object when passed a mailto URI" do
+ URI.parse("mailto:spam@mailinator.com").should be_kind_of(URI::MailTo)
+ end
+
+ it "populates the components of a parsed URI::MailTo object" do
+ URISpec.components(URI.parse("mailto:spam@mailinator.com?subject=Discounts%20On%20Imported%20methods!!!&body=Exciting%20offer")).should == {
+ scheme: "mailto",
+ to: "spam@mailinator.com",
+ headers: [["subject","Discounts%20On%20Imported%20methods!!!"],
+ ["body", "Exciting%20offer"]]
+ }
+ end
+
+ # TODO
+ # Test registry
+ it "does its best to extract components from URI::Generic objects" do
+ # generic
+ URISpec.components(URI("scheme://userinfo@host/path?query#fragment")).should == {
+ scheme: "scheme",
+ userinfo: "userinfo",
+ host: "host",
+ port: nil,
+ path: "/path",
+ query: "query",
+ fragment: "fragment",
+ registry: nil,
+ opaque: nil
+ }
+
+ # gopher
+ gopher = URI.parse('gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles')
+ gopher.should be_kind_of(URI::Generic)
+
+ URISpec.components(gopher).should == {
+ scheme: "gopher",
+ userinfo: nil,
+ host: "spinaltap.micro.umn.edu",
+ port: nil,
+ path: "/00/Weather/California/Los%20Angeles",
+ query: nil,
+ fragment: nil,
+ registry: nil,
+ opaque: nil
+ }
+
+ # news
+ news = URI.parse('news:comp.infosystems.www.servers.unix')
+ news.should be_kind_of(URI::Generic)
+ URISpec.components(news).should == {
+ scheme: "news",
+ userinfo: nil,
+ host: nil,
+ port: nil,
+ path: nil,
+ query: nil,
+ fragment: nil,
+ registry: nil,
+ opaque: "comp.infosystems.www.servers.unix"
+ }
+
+ # telnet
+ telnet = URI.parse('telnet://melvyl.ucop.edu/')
+ telnet.should be_kind_of(URI::Generic)
+ URISpec.components(telnet).should == {
+ scheme: "telnet",
+ userinfo: nil,
+ host: "melvyl.ucop.edu",
+ port: nil,
+ path: "/",
+ query: nil,
+ fragment: nil,
+ registry: nil,
+ opaque: nil
+ }
+
+ # files
+ file_l = URI.parse('file:///foo/bar.txt')
+ file_l.should be_kind_of(URI::Generic)
+ file = URI.parse('file:/foo/bar.txt')
+ file.should be_kind_of(URI::Generic)
+ end
+
+ it "doesn't raise errors on URIs which has underscore in reg_name" do
+ URI.parse('http://a_b:80/').host.should == "a_b"
+ URI.parse('http://a_b/').host.should == "a_b"
+ end
+end
diff --git a/spec/ruby/library/uri/parser/escape_spec.rb b/spec/ruby/library/uri/parser/escape_spec.rb
new file mode 100644
index 0000000000..8682e0ebce
--- /dev/null
+++ b/spec/ruby/library/uri/parser/escape_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Parser#escape" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/parser/extract_spec.rb b/spec/ruby/library/uri/parser/extract_spec.rb
new file mode 100644
index 0000000000..5dac947060
--- /dev/null
+++ b/spec/ruby/library/uri/parser/extract_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../shared/extract', __FILE__)
+require 'uri'
+
+describe "URI::Parser#extract" do
+ it_behaves_like :uri_extract, :extract, URI::Parser.new
+end
diff --git a/spec/ruby/library/uri/parser/inspect_spec.rb b/spec/ruby/library/uri/parser/inspect_spec.rb
new file mode 100644
index 0000000000..2eaeeeafee
--- /dev/null
+++ b/spec/ruby/library/uri/parser/inspect_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Parser#split" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/parser/join_spec.rb b/spec/ruby/library/uri/parser/join_spec.rb
new file mode 100644
index 0000000000..1800a16236
--- /dev/null
+++ b/spec/ruby/library/uri/parser/join_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../shared/join', __FILE__)
+require 'uri'
+
+describe "URI::Parser#join" do
+ it_behaves_like :uri_join, :join, URI::Parser.new
+end
diff --git a/spec/ruby/library/uri/parser/make_regexp_spec.rb b/spec/ruby/library/uri/parser/make_regexp_spec.rb
new file mode 100644
index 0000000000..e27f0d14db
--- /dev/null
+++ b/spec/ruby/library/uri/parser/make_regexp_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Parser#make_regexp" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/parser/parse_spec.rb b/spec/ruby/library/uri/parser/parse_spec.rb
new file mode 100644
index 0000000000..76c1970645
--- /dev/null
+++ b/spec/ruby/library/uri/parser/parse_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/parse', __FILE__)
+
+describe "URI::Parser#parse" do
+ it_behaves_like :uri_parse, :parse, URI::Parser.new
+end
diff --git a/spec/ruby/library/uri/parser/split_spec.rb b/spec/ruby/library/uri/parser/split_spec.rb
new file mode 100644
index 0000000000..2eaeeeafee
--- /dev/null
+++ b/spec/ruby/library/uri/parser/split_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Parser#split" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/parser/unescape_spec.rb b/spec/ruby/library/uri/parser/unescape_spec.rb
new file mode 100644
index 0000000000..8ffc534226
--- /dev/null
+++ b/spec/ruby/library/uri/parser/unescape_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Parser#unescape" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/plus_spec.rb b/spec/ruby/library/uri/plus_spec.rb
new file mode 100644
index 0000000000..45c1aa5e57
--- /dev/null
+++ b/spec/ruby/library/uri/plus_spec.rb
@@ -0,0 +1,459 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+#an alias of URI#merge
+describe "URI#+" do
+ it "replaces the end of the path of the URI when added to a string that looks like a relative path" do
+ (URI('http://foo') + 'bar').should == URI("http://foo/bar")
+ (URI('http://foo/baz') + 'bar').should == URI("http://foo/bar")
+ (URI('http://foo/baz/') + 'bar').should == URI("http://foo/baz/bar")
+ (URI('mailto:foo@example.com') + "#bar").should == URI("mailto:foo@example.com#bar")
+ end
+
+ it "replaces the entire path of the URI when added to a string that begins with a /" do
+ (URI('http://foo/baz/') + '/bar').should == URI("http://foo/bar")
+ end
+
+ it "replaces the entire url when added to a string that looks like a full url" do
+ (URI.parse('http://a/b') + 'http://x/y').should == URI("http://x/y")
+ (URI.parse('telnet:example.com') + 'http://x/y').should == URI("http://x/y")
+ end
+
+ it "canonicalizes the URI's path, removing ../'s" do
+ (URI.parse('http://a/b/c/../') + "./").should == URI("http://a/b/")
+ (URI.parse('http://a/b/c/../') + ".").should == URI("http://a/b/")
+ (URI.parse('http://a/b/c/') + "../").should == URI("http://a/b/")
+ (URI.parse('http://a/b/c/../../') + "./").should == URI("http://a/")
+ (URI.parse('http://a/b/c/') + "../e/").should == URI("http://a/b/e/")
+ (URI.parse('http://a/b/c/') + "../e/../").should == URI("http://a/b/")
+ (URI.parse('http://a/b/../c/') + ".").should == URI("http://a/c/")
+
+ (URI.parse('http://a/b/c/../../../') + ".").should == URI("http://a/")
+ end
+
+ it "doesn't conconicalize the path when adding to the empty string" do
+ (URI.parse('http://a/b/c/../') + "").should == URI("http://a/b/c/../")
+ end
+
+ it "raises a URI::BadURIError when adding two relative URIs" do
+ lambda {URI.parse('a/b/c') + "d"}.should raise_error(URI::BadURIError)
+ end
+
+ #Todo: make more BDD?
+ it "conforms to the merge specifications from rfc 2396" do
+ @url = 'http://a/b/c/d;p?q'
+ @base_url = URI.parse(@url)
+
+# http://a/b/c/d;p?q
+# g:h = g:h
+ url = @base_url.merge('g:h')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g:h'
+ url = @base_url.route_to('g:h')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g:h'
+
+# http://a/b/c/d;p?q
+# g = http://a/b/c/g
+ url = @base_url.merge('g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g'
+ url = @base_url.route_to('http://a/b/c/g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g'
+
+# http://a/b/c/d;p?q
+# ./g = http://a/b/c/g
+ url = @base_url.merge('./g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g'
+ url = @base_url.route_to('http://a/b/c/g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == './g' # ok
+ url.to_s.should == 'g'
+
+# http://a/b/c/d;p?q
+# g/ = http://a/b/c/g/
+ url = @base_url.merge('g/')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g/'
+ url = @base_url.route_to('http://a/b/c/g/')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g/'
+
+# http://a/b/c/d;p?q
+# /g = http://a/g
+ url = @base_url.merge('/g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/g'
+ url = @base_url.route_to('http://a/g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == '/g' # ok
+ url.to_s.should == '../../g'
+
+# http://a/b/c/d;p?q
+# //g = http://g
+ url = @base_url.merge('//g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://g'
+ url = @base_url.route_to('http://g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '//g'
+
+# http://a/b/c/d;p?q
+# ?y = http://a/b/c/?y
+ url = @base_url.merge('?y')
+ url.should be_kind_of(URI::HTTP)
+
+ url.to_s.should == 'http://a/b/c/d;p?y'
+
+ url = @base_url.route_to('http://a/b/c/?y')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '?y'
+
+# http://a/b/c/d;p?q
+# g?y = http://a/b/c/g?y
+ url = @base_url.merge('g?y')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g?y'
+ url = @base_url.route_to('http://a/b/c/g?y')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g?y'
+
+# http://a/b/c/d;p?q
+# #s = (current document)#s
+ url = @base_url.merge('#s')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == @base_url.to_s + '#s'
+ url = @base_url.route_to(@base_url.to_s + '#s')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '#s'
+
+# http://a/b/c/d;p?q
+# g#s = http://a/b/c/g#s
+ url = @base_url.merge('g#s')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g#s'
+ url = @base_url.route_to('http://a/b/c/g#s')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g#s'
+
+# http://a/b/c/d;p?q
+# g?y#s = http://a/b/c/g?y#s
+ url = @base_url.merge('g?y#s')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g?y#s'
+ url = @base_url.route_to('http://a/b/c/g?y#s')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g?y#s'
+
+# http://a/b/c/d;p?q
+# ;x = http://a/b/c/;x
+ url = @base_url.merge(';x')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/;x'
+ url = @base_url.route_to('http://a/b/c/;x')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == ';x'
+
+# http://a/b/c/d;p?q
+# g;x = http://a/b/c/g;x
+ url = @base_url.merge('g;x')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g;x'
+ url = @base_url.route_to('http://a/b/c/g;x')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g;x'
+
+# http://a/b/c/d;p?q
+# g;x?y#s = http://a/b/c/g;x?y#s
+ url = @base_url.merge('g;x?y#s')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g;x?y#s'
+ url = @base_url.route_to('http://a/b/c/g;x?y#s')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g;x?y#s'
+
+# http://a/b/c/d;p?q
+# . = http://a/b/c/
+ url = @base_url.merge('.')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/'
+ url = @base_url.route_to('http://a/b/c/')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == '.' # ok
+ url.to_s.should == './'
+
+# http://a/b/c/d;p?q
+# ./ = http://a/b/c/
+ url = @base_url.merge('./')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/'
+ url = @base_url.route_to('http://a/b/c/')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == './'
+
+# http://a/b/c/d;p?q
+# .. = http://a/b/
+ url = @base_url.merge('..')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/'
+ url = @base_url.route_to('http://a/b/')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == '..' # ok
+ url.to_s.should == '../'
+
+# http://a/b/c/d;p?q
+# ../ = http://a/b/
+ url = @base_url.merge('../')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/'
+ url = @base_url.route_to('http://a/b/')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '../'
+
+# http://a/b/c/d;p?q
+# ../g = http://a/b/g
+ url = @base_url.merge('../g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/g'
+ url = @base_url.route_to('http://a/b/g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '../g'
+
+# http://a/b/c/d;p?q
+# ../.. = http://a/
+ url = @base_url.merge('../..')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/'
+ url = @base_url.route_to('http://a/')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == '../..' # ok
+ url.to_s.should == '../../'
+
+# http://a/b/c/d;p?q
+# ../../ = http://a/
+ url = @base_url.merge('../../')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/'
+ url = @base_url.route_to('http://a/')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '../../'
+
+# http://a/b/c/d;p?q
+# ../../g = http://a/g
+ url = @base_url.merge('../../g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/g'
+ url = @base_url.route_to('http://a/g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '../../g'
+
+# http://a/b/c/d;p?q
+# <> = (current document)
+ url = @base_url.merge('')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/d;p?q'
+ url = @base_url.route_to('http://a/b/c/d;p?q')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == ''
+
+# http://a/b/c/d;p?q
+# /./g = http://a/./g
+ url = @base_url.merge('/./g')
+ url.should be_kind_of(URI::HTTP)
+
+ url.to_s.should == 'http://a/g'
+
+ url = @base_url.route_to('http://a/./g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '/./g'
+
+# http://a/b/c/d;p?q
+# /../g = http://a/../g
+ url = @base_url.merge('/../g')
+ url.should be_kind_of(URI::HTTP)
+
+ url.to_s.should == 'http://a/g'
+
+ url = @base_url.route_to('http://a/../g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '/../g'
+
+# http://a/b/c/d;p?q
+# g. = http://a/b/c/g.
+ url = @base_url.merge('g.')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g.'
+ url = @base_url.route_to('http://a/b/c/g.')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g.'
+
+# http://a/b/c/d;p?q
+# .g = http://a/b/c/.g
+ url = @base_url.merge('.g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/.g'
+ url = @base_url.route_to('http://a/b/c/.g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '.g'
+
+# http://a/b/c/d;p?q
+# g.. = http://a/b/c/g..
+ url = @base_url.merge('g..')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g..'
+ url = @base_url.route_to('http://a/b/c/g..')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g..'
+
+# http://a/b/c/d;p?q
+# ..g = http://a/b/c/..g
+ url = @base_url.merge('..g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/..g'
+ url = @base_url.route_to('http://a/b/c/..g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == '..g'
+
+# http://a/b/c/d;p?q
+# ../../../g = http://a/../g
+ url = @base_url.merge('../../../g')
+ url.should be_kind_of(URI::HTTP)
+
+ url.to_s.should == 'http://a/g'
+
+ url = @base_url.route_to('http://a/../g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == '../../../g' # ok? yes, it confuses you
+ url.to_s.should == '/../g' # and it is clearly
+
+# http://a/b/c/d;p?q
+# ../../../../g = http://a/../../g
+ url = @base_url.merge('../../../../g')
+ url.should be_kind_of(URI::HTTP)
+
+ url.to_s.should == 'http://a/g'
+
+ url = @base_url.route_to('http://a/../../g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == '../../../../g' # ok? yes, it confuses you
+ url.to_s.should == '/../../g' # and it is clearly
+
+# http://a/b/c/d;p?q
+# ./../g = http://a/b/g
+ url = @base_url.merge('./../g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/g'
+ url = @base_url.route_to('http://a/b/g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == './../g' # ok
+ url.to_s.should == '../g'
+
+# http://a/b/c/d;p?q
+# ./g/. = http://a/b/c/g/
+ url = @base_url.merge('./g/.')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g/'
+ url = @base_url.route_to('http://a/b/c/g/')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == './g/.' # ok
+ url.to_s.should == 'g/'
+
+# http://a/b/c/d;p?q
+# g/./h = http://a/b/c/g/h
+ url = @base_url.merge('g/./h')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g/h'
+ url = @base_url.route_to('http://a/b/c/g/h')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == 'g/./h' # ok
+ url.to_s.should == 'g/h'
+
+# http://a/b/c/d;p?q
+# g/../h = http://a/b/c/h
+ url = @base_url.merge('g/../h')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/h'
+ url = @base_url.route_to('http://a/b/c/h')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == 'g/../h' # ok
+ url.to_s.should == 'h'
+
+# http://a/b/c/d;p?q
+# g;x=1/./y = http://a/b/c/g;x=1/y
+ url = @base_url.merge('g;x=1/./y')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g;x=1/y'
+ url = @base_url.route_to('http://a/b/c/g;x=1/y')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == 'g;x=1/./y' # ok
+ url.to_s.should == 'g;x=1/y'
+
+# http://a/b/c/d;p?q
+# g;x=1/../y = http://a/b/c/y
+ url = @base_url.merge('g;x=1/../y')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/y'
+ url = @base_url.route_to('http://a/b/c/y')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should_not == 'g;x=1/../y' # ok
+ url.to_s.should == 'y'
+
+# http://a/b/c/d;p?q
+# g?y/./x = http://a/b/c/g?y/./x
+ url = @base_url.merge('g?y/./x')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g?y/./x'
+ url = @base_url.route_to('http://a/b/c/g?y/./x')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g?y/./x'
+
+# http://a/b/c/d;p?q
+# g?y/../x = http://a/b/c/g?y/../x
+ url = @base_url.merge('g?y/../x')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g?y/../x'
+ url = @base_url.route_to('http://a/b/c/g?y/../x')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g?y/../x'
+
+# http://a/b/c/d;p?q
+# g#s/./x = http://a/b/c/g#s/./x
+ url = @base_url.merge('g#s/./x')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g#s/./x'
+ url = @base_url.route_to('http://a/b/c/g#s/./x')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g#s/./x'
+
+# http://a/b/c/d;p?q
+# g#s/../x = http://a/b/c/g#s/../x
+ url = @base_url.merge('g#s/../x')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http://a/b/c/g#s/../x'
+ url = @base_url.route_to('http://a/b/c/g#s/../x')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'g#s/../x'
+
+# http://a/b/c/d;p?q
+# http:g = http:g ; for validating parsers
+# | http://a/b/c/g ; for backwards compatibility
+ url = @base_url.merge('http:g')
+ url.should be_kind_of(URI::HTTP)
+ url.to_s.should == 'http:g'
+ url = @base_url.route_to('http:g')
+ url.should be_kind_of(URI::Generic)
+ url.to_s.should == 'http:g'
+ end
+end
+
+#TODO: incorporate these tests:
+#
+# u = URI.parse('http://foo/bar/baz')
+# assert_equal(nil, u.merge!(""))
+# assert_equal(nil, u.merge!(u))
+# assert(nil != u.merge!("."))
+# assert_equal('http://foo/bar/', u.to_s)
+# assert(nil != u.merge!("../baz"))
+# assert_equal('http://foo/baz', u.to_s)
diff --git a/spec/ruby/library/uri/regexp_spec.rb b/spec/ruby/library/uri/regexp_spec.rb
new file mode 100644
index 0000000000..cf63507013
--- /dev/null
+++ b/spec/ruby/library/uri/regexp_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+#I'm more or less ok with these limited tests, as the more extensive extract tests
+#use URI.regexp
+describe "URI.regexp" do
+ it "behaves according to the MatzRuby tests" do
+ URI.regexp.should == URI.regexp
+ 'x http:// x'.slice(URI.regexp).should == 'http://'
+ 'x http:// x'.slice(URI.regexp(['http'])).should == 'http://'
+ 'x http:// x ftp://'.slice(URI.regexp(['http'])).should == 'http://'
+ 'http://'.slice(URI.regexp([])).should == nil
+ ''.slice(URI.regexp).should == nil
+ 'xxxx'.slice(URI.regexp).should == nil
+ ':'.slice(URI.regexp).should == nil
+ 'From:'.slice(URI.regexp).should == 'From:'
+ end
+end
diff --git a/spec/ruby/library/uri/route_from_spec.rb b/spec/ruby/library/uri/route_from_spec.rb
new file mode 100644
index 0000000000..11a2c44f90
--- /dev/null
+++ b/spec/ruby/library/uri/route_from_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI#route_from" do
+
+ #this could be split out a good bit better
+ it "gives the minimal difference between the current URI and the target" do
+ URI("http://example.com/a.html").route_from('http://example.com/a.html').to_s.should == ""
+ URI("http://example.com/a.html").route_from('http://example.com/b.html').to_s.should == "a.html"
+ URI("http://example.com/a/").route_from('http://example.com/b/').to_s.should == "../a/"
+ URI("http://example.com/b/").route_from('http://example.com/a/c').to_s.should == "../b/"
+ URI("http://example.com/b/").route_from('http://example.com/a/b/').to_s.should == "../../b/"
+ URI("http://example.com/b/").route_from('http://EXAMPLE.cOm/a/b/').to_s.should == "../../b/"
+ URI("http://example.net/b/").route_from('http://example.com/a/b/').to_s.should == "//example.net/b/"
+ URI("mailto:foo@example.com#bar").route_from('mailto:foo@example.com').to_s.should == "#bar"
+ end
+
+ it "accepts a string-like argument" do
+ str = mock('string-like')
+ str.should_receive(:to_str).and_return("http://example.com/b.html")
+ URI("http://example.com/a.html").route_from(str).to_s.should == "a.html"
+ end
+end
diff --git a/spec/ruby/library/uri/route_to_spec.rb b/spec/ruby/library/uri/route_to_spec.rb
new file mode 100644
index 0000000000..2eb68afdfd
--- /dev/null
+++ b/spec/ruby/library/uri/route_to_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI#route_to" do
+
+ #this could be split out a good bit better
+ it "gives the minimal difference between the current URI and the target" do
+ URI("http://example.com/a.html").route_to('http://example.com/a.html').to_s.should == ""
+ URI("http://example.com/a.html").route_to('http://example.com/b.html').to_s.should == "b.html"
+ URI("http://example.com/a/").route_to('http://example.com/b/').to_s.should == "../b/"
+ URI("http://example.com/a/c").route_to('http://example.com/b/').to_s.should == "../b/"
+ URI("http://example.com/a/b/").route_to('http://example.com/b/').to_s.should == "../../b/"
+ URI("http://example.com/a/b/").route_to('http://EXAMPLE.cOm/b/').to_s.should == "../../b/"
+ URI("http://example.com/a/b/").route_to('http://example.net/b/').to_s.should == "//example.net/b/"
+ URI("mailto:foo@example.com").route_to('mailto:foo@example.com#bar').to_s.should == "#bar"
+
+ #this was a little surprising to me
+ URI("mailto:foo@example.com#bar").route_to('mailto:foo@example.com').to_s.should == ""
+ end
+
+ it "accepts a string-like argument" do
+ str = mock('string-like')
+ str.should_receive(:to_str).and_return("http://example.com/b.html")
+ URI("http://example.com/a.html").route_to(str).to_s.should == "b.html"
+ end
+end
diff --git a/spec/ruby/library/uri/select_spec.rb b/spec/ruby/library/uri/select_spec.rb
new file mode 100644
index 0000000000..46474757cc
--- /dev/null
+++ b/spec/ruby/library/uri/select_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI#select" do
+ it "takes any number of component names as symbols, and returns an array of those components" do
+ URI("http://host:8080/path/").select.should == []
+ URI("http://host:8080/path/").select(:scheme,:host,:port,:path).should == [
+ "http","host",8080,"/path/"]
+ end
+
+ it "returns nil for any valid component that isn't set and doesn't have a default" do
+ uri = URI("http://host")
+ uri.select(:userinfo, :query, :fragment).should == [nil] * 3
+ uri.select(:port, :path).should == [80, '']
+ end
+
+ it "raises an ArgumentError if a component is requested that isn't valid under the given scheme" do
+ [
+ lambda {URI("mailto:spam@mailinator.com").select(:path)},
+ lambda {URI("http://blog.blag.web").select(:typecode)},
+ ].each do |select_lambda|
+ select_lambda.should raise_error(ArgumentError)
+ end
+ end
+
+ it "raises an ArgumentError if given strings rather than symbols" do
+ lambda {
+ URI("http://host:8080/path/").select("scheme","host","port",'path')
+ }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/library/uri/set_component_spec.rb b/spec/ruby/library/uri/set_component_spec.rb
new file mode 100644
index 0000000000..9b8372108a
--- /dev/null
+++ b/spec/ruby/library/uri/set_component_spec.rb
@@ -0,0 +1,47 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+#TODO: make this more BDD
+describe "URI#select" do
+ it "conforms to the MatzRuby tests" do
+ uri = URI.parse('http://foo:bar@baz')
+ (uri.user = 'oof').should == 'oof'
+ uri.to_s.should == 'http://oof:bar@baz'
+ (uri.password = 'rab').should == 'rab'
+ uri.to_s.should == 'http://oof:rab@baz'
+ (uri.userinfo = 'foo').should == 'foo'
+ uri.to_s.should == 'http://foo:rab@baz'
+ (uri.userinfo = ['foo', 'bar']).should == ['foo', 'bar']
+ uri.to_s.should == 'http://foo:bar@baz'
+ (uri.userinfo = ['foo']).should == ['foo']
+ uri.to_s.should == 'http://foo:bar@baz'
+ (uri.host = 'zab').should == 'zab'
+ uri.to_s.should == 'http://foo:bar@zab'
+ (uri.port = 8080).should == 8080
+ uri.to_s.should == 'http://foo:bar@zab:8080'
+ (uri.path = '/').should == '/'
+ uri.to_s.should == 'http://foo:bar@zab:8080/'
+ (uri.query = 'a=1').should == 'a=1'
+ uri.to_s.should == 'http://foo:bar@zab:8080/?a=1'
+ (uri.fragment = 'b123').should == 'b123'
+ uri.to_s.should == 'http://foo:bar@zab:8080/?a=1#b123'
+
+ uri = URI.parse('http://example.com')
+ lambda { uri.password = 'bar' }.should raise_error(URI::InvalidURIError)
+ uri.userinfo = 'foo:bar'
+ uri.to_s.should == 'http://foo:bar@example.com'
+ lambda { uri.registry = 'bar' }.should raise_error(URI::InvalidURIError)
+ lambda { uri.opaque = 'bar' }.should raise_error(URI::InvalidURIError)
+
+ uri = URI.parse('mailto:foo@example.com')
+ lambda { uri.user = 'bar' }.should raise_error(URI::InvalidURIError)
+ lambda { uri.password = 'bar' }.should raise_error(URI::InvalidURIError)
+ lambda { uri.userinfo = ['bar', 'baz'] }.should raise_error(URI::InvalidURIError)
+ lambda { uri.host = 'bar' }.should raise_error(URI::InvalidURIError)
+ lambda { uri.port = 'bar' }.should raise_error(URI::InvalidURIError)
+ lambda { uri.path = 'bar' }.should raise_error(URI::InvalidURIError)
+ lambda { uri.query = 'bar' }.should raise_error(URI::InvalidURIError)
+ end
+end
+
+
diff --git a/spec/ruby/library/uri/shared/eql.rb b/spec/ruby/library/uri/shared/eql.rb
new file mode 100644
index 0000000000..2cc960d39a
--- /dev/null
+++ b/spec/ruby/library/uri/shared/eql.rb
@@ -0,0 +1,17 @@
+describe :uri_eql, shared: true do
+ it "returns false if the normalized forms are different" do
+ URISpec::NORMALIZED_FORMS.each do |form|
+ normal_uri = URI(form[:normalized])
+ form[:different].each do |other|
+ URI(other).send(@method, normal_uri).should be_false
+ end
+ end
+ end
+end
+
+describe :uri_eql_against_other_types, shared: true do
+ it "returns false for when compared to non-uri objects" do
+ URI("http://example.com/").send(@method, "http://example.com/").should be_false
+ URI("http://example.com/").send(@method, nil).should be_false
+ end
+end
diff --git a/spec/ruby/library/uri/shared/extract.rb b/spec/ruby/library/uri/shared/extract.rb
new file mode 100644
index 0000000000..efe60ae4b9
--- /dev/null
+++ b/spec/ruby/library/uri/shared/extract.rb
@@ -0,0 +1,83 @@
+describe :uri_extract, shared: true do
+ it "behaves according to its documentation" do
+ @object.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.").should == ["http://foo.example.org/bla", "mailto:test@example.com"]
+ end
+
+ it "treats contiguous URIs as a single URI" do
+ @object.extract('http://example.jphttp://example.jp').should == ['http://example.jphttp://example.jp']
+ end
+
+ it "treats pretty much anything with a colon as a URI" do
+ @object.extract('From: XXX [mailto:xxx@xxx.xxx.xxx]').should == ['From:', 'mailto:xxx@xxx.xxx.xxx]']
+ end
+
+ it "wraps a URI string in an array" do
+ @object.extract("http://github.com/brixen/rubyspec/tree/master").should == ["http://github.com/brixen/rubyspec/tree/master"]
+ end
+
+ it "pulls a variety of protocol URIs from a string" do
+ @object.extract("this is a string, it has http://rubini.us/ in it").should == ["http://rubini.us/"]
+ @object.extract("mailto:spambait@example.com").should == ["mailto:spambait@example.com"]
+ @object.extract("ftp://ruby-lang.org/").should == ["ftp://ruby-lang.org/"]
+ @object.extract("https://mail.google.com").should == ["https://mail.google.com"]
+ @object.extract("anything://example.com/").should == ["anything://example.com/"]
+ end
+
+ it "pulls all URIs within a string in order into an array when a block is not given" do
+ @object.extract("1.3. Example URI
+
+ The following examples illustrate URI that are in common use.
+
+ ftp://ftp.is.co.za/rfc/rfc1808.txt
+ -- ftp scheme for File Transfer Protocol services
+
+ gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles
+ -- gopher scheme for Gopher and Gopher+ Protocol services
+
+ http://www.math.uio.no/faq/compression-faq/part1.html
+ -- http scheme for Hypertext Transfer Protocol services
+
+ mailto:mduerst@ifi.unizh.ch
+ -- mailto scheme for electronic mail addresses
+
+ news:comp.infosystems.www.servers.unix
+ -- news scheme for USENET news groups and articles
+
+ telnet://melvyl.ucop.edu/
+ -- telnet scheme for interactive services via the TELNET Protocol
+ ").should == ["ftp://ftp.is.co.za/rfc/rfc1808.txt","gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles","http://www.math.uio.no/faq/compression-faq/part1.html","mailto:mduerst@ifi.unizh.ch","news:comp.infosystems.www.servers.unix","telnet://melvyl.ucop.edu/"]
+ end
+
+ it "yields each URI in the given string in order to a block, if given, and returns nil" do
+ results = ["http://foo.example.org/bla", "mailto:test@example.com"]
+ @object.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.") {|uri|
+ uri.should == results.shift
+ }.should == nil
+ results.should == []
+ end
+
+ it "allows the user to specify a list of acceptable protocols of URIs to scan for" do
+ @object.extract("1.3. Example URI
+
+ The following examples illustrate URI that are in common use.
+
+ ftp://ftp.is.co.za/rfc/rfc1808.txt
+ -- ftp scheme for File Transfer Protocol services
+
+ gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles
+ -- gopher scheme for Gopher and Gopher+ Protocol services
+
+ http://www.math.uio.no/faq/compression-faq/part1.html
+ -- http scheme for Hypertext Transfer Protocol services
+
+ mailto:mduerst@ifi.unizh.ch
+ -- mailto scheme for electronic mail addresses
+
+ news:comp.infosystems.www.servers.unix
+ -- news scheme for USENET news groups and articles
+
+ telnet://melvyl.ucop.edu/
+ -- telnet scheme for interactive services via the TELNET Protocol
+ ", ["http","ftp","mailto"]).should == ["ftp://ftp.is.co.za/rfc/rfc1808.txt","http://www.math.uio.no/faq/compression-faq/part1.html","mailto:mduerst@ifi.unizh.ch"]
+ end
+end
diff --git a/spec/ruby/library/uri/shared/join.rb b/spec/ruby/library/uri/shared/join.rb
new file mode 100644
index 0000000000..dfe44e9be2
--- /dev/null
+++ b/spec/ruby/library/uri/shared/join.rb
@@ -0,0 +1,54 @@
+describe :uri_join, shared: true do
+ it "returns a URI object of the concatenation of a protocol and domain, and a path" do
+ @object.join("http://localhost/","main.rbx").should == URI.parse("http://localhost/main.rbx")
+ end
+
+ it "accepts URI objects" do
+ @object.join(URI("http://localhost/"),"main.rbx").should == URI.parse("http://localhost/main.rbx")
+ @object.join("http://localhost/",URI("main.rbx")).should == URI.parse("http://localhost/main.rbx")
+ @object.join(URI("http://localhost/"),URI("main.rbx")).should == URI.parse("http://localhost/main.rbx")
+ end
+
+ it "accepts string-like arguments with to_str" do
+ str = mock('string-like')
+ str.should_receive(:to_str).and_return("http://ruby-lang.org")
+ str2 = mock('string-like also')
+ str2.should_receive(:to_str).and_return("foo/bar")
+ @object.join(str, str2).should == URI.parse("http://ruby-lang.org/foo/bar")
+ end
+
+ it "raises an error if given no argument" do
+ lambda{ @object.join }.should raise_error
+ end
+
+ it "doesn't create redundant '/'s" do
+ @object.join("http://localhost/", "/main.rbx").should == URI.parse("http://localhost/main.rbx")
+ end
+
+ it "discards arguments given before an absolute uri" do
+ @object.join("http://localhost/a/b/c/d", "http://ruby-lang.com/foo", "bar").should == URI.parse("http://ruby-lang.com/bar")
+ end
+
+ it "resolves .. in paths" do
+ @object.join("http://localhost/a/b/c/d", "../../e/f", "g/h/../i").to_s.should == "http://localhost/a/e/g/i"
+ end
+end
+
+
+# assert_equal(URI.parse('http://foo/bar'), URI.join('http://foo/bar'))
+# assert_equal(URI.parse('http://foo/bar'), URI.join('http://foo', 'bar'))
+# assert_equal(URI.parse('http://foo/bar/'), URI.join('http://foo', 'bar/'))
+#
+# assert_equal(URI.parse('http://foo/baz'), URI.join('http://foo', 'bar', 'baz'))
+# assert_equal(URI.parse('http://foo/baz'), URI.join('http://foo', 'bar', '/baz'))
+# assert_equal(URI.parse('http://foo/baz/'), URI.join('http://foo', 'bar', '/baz/'))
+# assert_equal(URI.parse('http://foo/bar/baz'), URI.join('http://foo', 'bar/', 'baz'))
+# assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar', 'baz', 'hoge'))
+#
+# assert_equal(URI.parse('http://foo/bar/baz'), URI.join('http://foo', 'bar/baz'))
+# assert_equal(URI.parse('http://foo/bar/hoge'), URI.join('http://foo', 'bar/baz', 'hoge'))
+# assert_equal(URI.parse('http://foo/bar/baz/hoge'), URI.join('http://foo', 'bar/baz/', 'hoge'))
+# assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar/baz', '/hoge'))
+# assert_equal(URI.parse('http://foo/bar/hoge'), URI.join('http://foo', 'bar/baz', 'hoge'))
+# assert_equal(URI.parse('http://foo/bar/baz/hoge'), URI.join('http://foo', 'bar/baz/', 'hoge'))
+# assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar/baz', '/hoge'))
diff --git a/spec/ruby/library/uri/shared/parse.rb b/spec/ruby/library/uri/shared/parse.rb
new file mode 100644
index 0000000000..5ecbffcaf2
--- /dev/null
+++ b/spec/ruby/library/uri/shared/parse.rb
@@ -0,0 +1,199 @@
+describe :uri_parse, shared: true do
+ it "returns a URI::HTTP object when parsing an HTTP URI" do
+ @object.parse("http://www.example.com/").should be_kind_of(URI::HTTP)
+ end
+
+ it "populates the components of a parsed URI::HTTP, setting the port to 80 by default" do
+ # general case
+ URISpec.components(@object.parse("http://user:pass@example.com/path/?query=val&q2=val2#fragment")).should == {
+ scheme: "http",
+ userinfo: "user:pass",
+ host: "example.com",
+ port: 80,
+ path: "/path/",
+ query: "query=val&q2=val2",
+ fragment: "fragment"
+ }
+
+ # multiple paths
+ URISpec.components(@object.parse("http://a/b/c/d;p?q")).should == {
+ scheme: "http",
+ userinfo: nil,
+ host: "a",
+ port: 80,
+ path: "/b/c/d;p",
+ query: "q",
+ fragment: nil
+ }
+
+ # multi-level domain
+ URISpec.components(@object.parse('http://www.math.uio.no/faq/compression-faq/part1.html')).should == {
+ scheme: "http",
+ userinfo: nil,
+ host: "www.math.uio.no",
+ port: 80,
+ path: "/faq/compression-faq/part1.html",
+ query: nil,
+ fragment: nil
+ }
+ end
+
+ it "parses out the port number of a URI, when given" do
+ @object.parse("http://example.com:8080/").port.should == 8080
+ end
+
+ it "returns a URI::HTTPS object when parsing an HTTPS URI" do
+ @object.parse("https://important-intern-net.net").should be_kind_of(URI::HTTPS)
+ end
+
+ it "sets the port of a parsed https URI to 443 by default" do
+ @object.parse("https://example.com/").port.should == 443
+ end
+
+ it "populates the components of a parsed URI::FTP object" do
+ # generic, empty password.
+ url = @object.parse("ftp://anonymous@ruby-lang.org/pub/ruby/1.8/ruby-1.8.6.tar.bz2;type=i")
+ url.should be_kind_of(URI::FTP)
+ URISpec.components(url).should == {
+ scheme: "ftp",
+ userinfo: "anonymous",
+ host: "ruby-lang.org",
+ port: 21,
+ path: "pub/ruby/1.8/ruby-1.8.6.tar.bz2",
+ typecode: "i"
+ }
+
+ # multidomain, no user or password
+ url = @object.parse('ftp://ftp.is.co.za/rfc/rfc1808.txt')
+ url.should be_kind_of(URI::FTP)
+ URISpec.components(url).should == {
+ scheme: "ftp",
+ userinfo: nil,
+ host: "ftp.is.co.za",
+ port: 21,
+ path: "rfc/rfc1808.txt",
+ typecode: nil
+ }
+
+ # empty user
+ url = @object.parse('ftp://:pass@localhost/')
+ url.should be_kind_of(URI::FTP)
+ URISpec.components(url).should == {
+ scheme: "ftp",
+ userinfo: ":pass",
+ host: "localhost",
+ port: 21,
+ path: "",
+ typecode: nil
+ }
+ url.password.should == "pass"
+ end
+
+ it "returns a URI::LDAP object when parsing an LDAP URI" do
+ #taken from http://www.faqs.org/rfcs/rfc2255.html 'cause I don't really know what an LDAP url looks like
+ ldap_uris = %w{ ldap:///o=University%20of%20Michigan,c=US ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US?postalAddress ldap://host.com:6666/o=University%20of%20Michigan,c=US??sub?(cn=Babs%20Jensen) ldap://ldap.itd.umich.edu/c=GB?objectClass?one ldap://ldap.question.com/o=Question%3f,c=US?mail ldap://ldap.netscape.com/o=Babsco,c=US??(int=%5c00%5c00%5c00%5c04) ldap:///??sub??bindname=cn=Manager%2co=Foo ldap:///??sub??!bindname=cn=Manager%2co=Foo }
+ ldap_uris.each do |ldap_uri|
+ @object.parse(ldap_uri).should be_kind_of(URI::LDAP)
+ end
+ end
+
+ it "populates the components of a parsed URI::LDAP object" do
+ URISpec.components(@object.parse("ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US?postalAddress?scope?filter?extensions")).should == {
+ scheme: "ldap",
+ host: "ldap.itd.umich.edu",
+ port: 389,
+ dn: "o=University%20of%20Michigan,c=US",
+ attributes: "postalAddress",
+ scope: "scope",
+ filter: "filter",
+ extensions: "extensions"
+ }
+ end
+
+ it "returns a URI::MailTo object when passed a mailto URI" do
+ @object.parse("mailto:spam@mailinator.com").should be_kind_of(URI::MailTo)
+ end
+
+ it "populates the components of a parsed URI::MailTo object" do
+ URISpec.components(@object.parse("mailto:spam@mailinator.com?subject=Discounts%20On%20Imported%20methods!!!&body=Exciting%20offer")).should == {
+ scheme: "mailto",
+ to: "spam@mailinator.com",
+ headers: [["subject","Discounts%20On%20Imported%20methods!!!"],
+ ["body", "Exciting%20offer"]]
+ }
+ end
+
+ # TODO
+ # Test registry
+ it "does its best to extract components from URI::Generic objects" do
+ # generic
+ URISpec.components(URI("scheme://userinfo@host/path?query#fragment")).should == {
+ scheme: "scheme",
+ userinfo: "userinfo",
+ host: "host",
+ port: nil,
+ path: "/path",
+ query: "query",
+ fragment: "fragment",
+ registry: nil,
+ opaque: nil
+ }
+
+ # gopher
+ gopher = @object.parse('gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles')
+ gopher.should be_kind_of(URI::Generic)
+
+ URISpec.components(gopher).should == {
+ scheme: "gopher",
+ userinfo: nil,
+ host: "spinaltap.micro.umn.edu",
+ port: nil,
+ path: "/00/Weather/California/Los%20Angeles",
+ query: nil,
+ fragment: nil,
+ registry: nil,
+ opaque: nil
+ }
+
+ # news
+ news = @object.parse('news:comp.infosystems.www.servers.unix')
+ news.should be_kind_of(URI::Generic)
+ URISpec.components(news).should == {
+ scheme: "news",
+ userinfo: nil,
+ host: nil,
+ port: nil,
+ path: nil,
+ query: nil,
+ fragment: nil,
+ registry: nil,
+ opaque: "comp.infosystems.www.servers.unix"
+ }
+
+ # telnet
+ telnet = @object.parse('telnet://melvyl.ucop.edu/')
+ telnet.should be_kind_of(URI::Generic)
+ URISpec.components(telnet).should == {
+ scheme: "telnet",
+ userinfo: nil,
+ host: "melvyl.ucop.edu",
+ port: nil,
+ path: "/",
+ query: nil,
+ fragment: nil,
+ registry: nil,
+ opaque: nil
+ }
+
+ # files
+ file_l = @object.parse('file:///foo/bar.txt')
+ file_l.should be_kind_of(URI::Generic)
+ file = @object.parse('file:/foo/bar.txt')
+ file.should be_kind_of(URI::Generic)
+ end
+
+ it "raises errors on malformed URIs" do
+ lambda { @object.parse('http://a_b:80/') }.should raise_error(URI::InvalidURIError)
+ lambda { @object.parse('http://a_b/') }.should raise_error(URI::InvalidURIError)
+ end
+end
diff --git a/spec/ruby/library/uri/split_spec.rb b/spec/ruby/library/uri/split_spec.rb
new file mode 100644
index 0000000000..f0ab6ff35c
--- /dev/null
+++ b/spec/ruby/library/uri/split_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI.split" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/uri/uri_spec.rb b/spec/ruby/library/uri/uri_spec.rb
new file mode 100644
index 0000000000..90936a770f
--- /dev/null
+++ b/spec/ruby/library/uri/uri_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'uri'
+
+#the testing is light here as this is an alias for URI.parse
+
+#we're just testing that the method ends up in the right place
+describe "the URI method" do
+ it "parses a given URI, returning a URI object" do
+ result = URI.parse("http://ruby-lang.org")
+ URI("http://ruby-lang.org").should == result
+ Kernel::URI("http://ruby-lang.org").should == result
+ end
+
+ it "converts its argument with to_str" do
+ str = mock('string-like')
+ str.should_receive(:to_str).and_return("http://ruby-lang.org")
+ URI(str).should == URI.parse("http://ruby-lang.org")
+ end
+
+ it "returns the argument if it is a URI object" do
+ result = URI.parse("http://ruby-lang.org")
+ URI(result).should equal(result)
+ end
+
+ #apparently this was a concern? imported from MRI tests
+ it "does not add a URI method to Object instances" do
+ lambda {Object.new.URI("http://ruby-lang.org/")}.should raise_error(NoMethodError)
+ end
+end
diff --git a/spec/ruby/library/uri/util/make_components_hash_spec.rb b/spec/ruby/library/uri/util/make_components_hash_spec.rb
new file mode 100644
index 0000000000..0f491112e8
--- /dev/null
+++ b/spec/ruby/library/uri/util/make_components_hash_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'uri'
+
+describe "URI::Util.make_components_hash" do
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/weakref/__getobj___spec.rb b/spec/ruby/library/weakref/__getobj___spec.rb
new file mode 100644
index 0000000000..e75b8f4704
--- /dev/null
+++ b/spec/ruby/library/weakref/__getobj___spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "WeakRef#__getobj__" do
+ it "returns the object if it is reachable" do
+ obj = Object.new
+ ref = WeakRef.new(obj)
+ ref.__getobj__.should equal(obj)
+ end
+
+ it "raises WeakRef::RefError if the object is no longer reachable" do
+ ref = WeakRefSpec.make_dead_weakref
+ lambda {
+ ref.__getobj__
+ }.should raise_error(WeakRef::RefError)
+ end
+end
diff --git a/spec/ruby/library/weakref/fixtures/classes.rb b/spec/ruby/library/weakref/fixtures/classes.rb
new file mode 100644
index 0000000000..560c58b041
--- /dev/null
+++ b/spec/ruby/library/weakref/fixtures/classes.rb
@@ -0,0 +1,24 @@
+require 'weakref'
+
+# From MRI test_weakref.rb
+class WeakRefSpec
+ def self.make_weakref(level = 10)
+ if level > 0
+ make_weakref(level - 1)
+ else
+ WeakRef.new(Object.new)
+ end
+ end
+
+ def self.make_dead_weakref
+ weaks = []
+ weak = nil
+ 10_000.times do
+ weaks << make_weakref
+ GC.start
+ GC.start
+ break if weak = weaks.find { |w| !w.weakref_alive? }
+ end
+ weak
+ end
+end
diff --git a/spec/ruby/library/weakref/send_spec.rb b/spec/ruby/library/weakref/send_spec.rb
new file mode 100644
index 0000000000..173e1055dd
--- /dev/null
+++ b/spec/ruby/library/weakref/send_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'weakref'
+
+describe "WeakRef#__send__" do
+ module WeakRefSpecs
+ class << self
+ def delegated_method
+ :result
+ end
+
+ def protected_method
+ :result
+ end
+ protected :protected_method
+
+ def private_method
+ :result
+ end
+ private :private_method
+ end
+ end
+
+ it "delegates to public methods of the weakly-referenced object" do
+ wr = WeakRef.new(WeakRefSpecs)
+ wr.delegated_method.should == :result
+ end
+
+ it "delegates to protected methods of the weakly-referenced object" do
+ wr = WeakRef.new(WeakRefSpecs)
+ lambda { wr.protected_method }.should raise_error(NameError)
+ end
+
+ it "does not delegate to private methods of the weakly-referenced object" do
+ wr = WeakRef.new(WeakRefSpecs)
+ lambda { wr.private_method }.should raise_error(NameError)
+ end
+end
diff --git a/spec/ruby/library/weakref/weakref_alive_spec.rb b/spec/ruby/library/weakref/weakref_alive_spec.rb
new file mode 100644
index 0000000000..b3c2eab620
--- /dev/null
+++ b/spec/ruby/library/weakref/weakref_alive_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "WeakRef#weakref_alive?" do
+ it "returns true if the object is reachable" do
+ obj = Object.new
+ ref = WeakRef.new(obj)
+ ref.weakref_alive?.should == true
+ end
+
+ it "returns a falsey value if the object is no longer reachable" do
+ ref = WeakRefSpec.make_dead_weakref
+ [false, nil].should include(ref.weakref_alive?)
+ end
+end
diff --git a/spec/ruby/library/win32ole/fixtures/classes.rb b/spec/ruby/library/win32ole/fixtures/classes.rb
new file mode 100644
index 0000000000..830b1be0b5
--- /dev/null
+++ b/spec/ruby/library/win32ole/fixtures/classes.rb
@@ -0,0 +1,14 @@
+module WIN32OLESpecs
+ def self.new_ole(name)
+ retried = false
+ begin
+ WIN32OLE.new(name)
+ rescue WIN32OLERuntimeError => e
+ unless retried
+ retried = true
+ retry
+ end
+ raise e
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/_getproperty_spec.rb b/spec/ruby/library/win32ole/win32ole/_getproperty_spec.rb
new file mode 100644
index 0000000000..650a641f5b
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/_getproperty_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#_getproperty" do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ end
+
+ after :each do
+ @ie.Quit
+ end
+
+ it "gets name" do
+ @ie._getproperty(0, [], []).should =~ /explorer/i
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/_invoke_spec.rb b/spec/ruby/library/win32ole/win32ole/_invoke_spec.rb
new file mode 100644
index 0000000000..c2fe9a8490
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/_invoke_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#_invoke" do
+ before :each do
+ @shell = WIN32OLESpecs.new_ole 'Shell.application'
+ end
+
+ it "raises ArgumentError if insufficient number of arguments are given" do
+ lambda { @shell._invoke() }.should raise_error ArgumentError
+ lambda { @shell._invoke(0) }.should raise_error ArgumentError
+ lambda { @shell._invoke(0, []) }.should raise_error ArgumentError
+ end
+
+ it "dispatches the method bound to a specific ID" do
+ @shell._invoke(0x60020002, [37], [WIN32OLE::VARIANT::VT_VARIANT]).title.should =~ /System32/i
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole/codepage_spec.rb b/spec/ruby/library/win32ole/win32ole/codepage_spec.rb
new file mode 100644
index 0000000000..c84593871d
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/codepage_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE.codepage=" do
+ it "sets codepage" do
+ cp = WIN32OLE.codepage
+ WIN32OLE.codepage = WIN32OLE::CP_UTF8
+ WIN32OLE.codepage.should == WIN32OLE::CP_UTF8
+ WIN32OLE.codepage = cp
+ end
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole/connect_spec.rb b/spec/ruby/library/win32ole/win32ole/connect_spec.rb
new file mode 100644
index 0000000000..ee480a727c
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/connect_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE.connect" do
+ it "creates WIN32OLE object given valid argument" do
+ obj = WIN32OLE.connect("winmgmts:")
+ obj.should be_kind_of WIN32OLE
+ end
+
+ it "raises TypeError when given invalid argument" do
+ lambda { WIN32OLE.connect 1 }.should raise_error TypeError
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/const_load_spec.rb b/spec/ruby/library/win32ole/win32ole/const_load_spec.rb
new file mode 100644
index 0000000000..a3c50f215e
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/const_load_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE.const_load when passed Shell.Application OLE object" do
+ before :each do
+ @win32ole = WIN32OLESpecs.new_ole 'Shell.Application'
+ end
+
+ it "loads constant SsfWINDOWS into WIN32OLE namespace" do
+ WIN32OLE.const_defined?(:SsfWINDOWS).should be_false
+ WIN32OLE.const_load @win32ole
+ WIN32OLE.const_defined?(:SsfWINDOWS).should be_true
+ end
+ end
+
+ describe "WIN32OLE.const_load when namespace is specified" do
+ before :each do
+ module WIN32OLE_RUBYSPEC; end
+ @win32ole = WIN32OLESpecs.new_ole 'Shell.Application'
+ end
+
+ it "loads constants into given namespace" do
+ module WIN32OLE_RUBYSPEC; end
+
+ WIN32OLE_RUBYSPEC.const_defined?(:SsfWINDOWS).should be_false
+ WIN32OLE.const_load @win32ole, WIN32OLE_RUBYSPEC
+ WIN32OLE_RUBYSPEC.const_defined?(:SsfWINDOWS).should be_true
+
+ end
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole/constants_spec.rb b/spec/ruby/library/win32ole/win32ole/constants_spec.rb
new file mode 100644
index 0000000000..2a04511305
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/constants_spec.rb
@@ -0,0 +1,44 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE class" do
+ it "defines constant CP_ACP" do
+ WIN32OLE::CP_ACP.should == 0
+ end
+
+ it "defines constant CP_OEMCP" do
+ WIN32OLE::CP_OEMCP.should == 1
+ end
+
+ it "defines constant CP_MACCP" do
+ WIN32OLE::CP_MACCP.should == 2
+ end
+
+ it "defines constant CP_THREAD_ACP" do
+ WIN32OLE::CP_THREAD_ACP.should == 3
+ end
+
+ it "defines constant CP_SYMBOL" do
+ WIN32OLE::CP_SYMBOL.should == 42
+ end
+
+ it "defines constant CP_UTF7" do
+ WIN32OLE::CP_UTF7.should == 65000
+ end
+
+ it "defines constant CP_UTF8" do
+ WIN32OLE::CP_UTF8.should == 65001
+ end
+
+ it "defines constant LOCALE_SYSTEM_DEFAULT" do
+ WIN32OLE::LOCALE_SYSTEM_DEFAULT.should == 0x0800
+ end
+
+ it "defines constant LOCALE_USER_DEFAULT" do
+ WIN32OLE::LOCALE_USER_DEFAULT.should == 0x0400
+ end
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole/create_guid_spec.rb b/spec/ruby/library/win32ole/win32ole/create_guid_spec.rb
new file mode 100644
index 0000000000..17a7df10be
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/create_guid_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE.create_guid" do
+ it "generates guid with valid format" do
+ WIN32OLE.create_guid.should =~ /^\{[A-Z0-9]{8}\-[A-Z0-9]{4}\-[A-Z0-9]{4}\-[A-Z0-9]{4}\-[A-Z0-9]{12}/
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/invoke_spec.rb b/spec/ruby/library/win32ole/win32ole/invoke_spec.rb
new file mode 100644
index 0000000000..41752de359
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/invoke_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#invoke" do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ end
+
+ after :each do
+ @ie.Quit
+ end
+
+ it "get name by invoking 'Name' OLE method" do
+ @ie.invoke('Name').should =~ /explorer/i
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/locale_spec.rb b/spec/ruby/library/win32ole/win32ole/locale_spec.rb
new file mode 100644
index 0000000000..7cf4d9bc98
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/locale_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE.locale" do
+ it "gets locale" do
+ WIN32OLE.locale.should == WIN32OLE::LOCALE_SYSTEM_DEFAULT
+ end
+ end
+
+ describe "WIN32OLE.locale=" do
+ it "sets locale to Japanese, if available" do
+ begin
+ begin
+ WIN32OLE.locale = 1041
+ rescue WIN32OLERuntimeError
+ STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_locale_set is skipped(Japanese locale is not installed)")
+ return
+ end
+
+ WIN32OLE.locale.should == 1041
+ WIN32OLE.locale = WIN32OLE::LOCALE_SYSTEM_DEFAULT
+ lambda { WIN32OLE.locale = 111 }.should raise_error WIN32OLERuntimeError
+ WIN32OLE.locale.should == WIN32OLE::LOCALE_SYSTEM_DEFAULT
+ ensure
+ WIN32OLE.locale.should == WIN32OLE::LOCALE_SYSTEM_DEFAULT
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/new_spec.rb b/spec/ruby/library/win32ole/win32ole/new_spec.rb
new file mode 100644
index 0000000000..78f141b608
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/new_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLESpecs.new_ole" do
+ it "creates a WIN32OLE object from OLE server name" do
+ shell = WIN32OLESpecs.new_ole 'Shell.Application'
+ shell.should be_kind_of WIN32OLE
+ end
+
+ it "creates a WIN32OLE object from valid CLSID" do
+ shell = WIN32OLESpecs.new_ole("{13709620-C279-11CE-A49E-444553540000}")
+ shell.should be_kind_of WIN32OLE
+ end
+
+ it "raises TypeError if argument cannot be converted to String" do
+ lambda { WIN32OLESpecs.new_ole(42) }.should raise_error( TypeError )
+ end
+
+ it "raises WIN32OLERuntimeError if invalid string is given" do
+ lambda { WIN32OLESpecs.new_ole('foo') }.should raise_error( WIN32OLERuntimeError )
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb
new file mode 100644
index 0000000000..82b5eb2680
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#ole_func_methods" do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ end
+
+ after :each do
+ @ie.Quit
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @ie.ole_func_methods(1) }.should raise_error ArgumentError
+ end
+
+ it "returns an array of WIN32OLE_METHODs" do
+ @ie.ole_func_methods.all? { |m| m.kind_of? WIN32OLE_METHOD }.should be_true
+ end
+
+ it "contains a 'AddRef' method for Internet Explorer" do
+ @ie.ole_func_methods.map { |m| m.name }.include?('AddRef').should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb
new file mode 100644
index 0000000000..3ec92d3efc
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#ole_get_methods" do
+
+ before :each do
+ @win32ole = WIN32OLESpecs.new_ole('Shell.Application')
+ end
+
+ it "returns an array of WIN32OLE_METHOD objects" do
+ @win32ole.ole_get_methods.all? {|m| m.kind_of? WIN32OLE_METHOD}.should be_true
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_method_help_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_method_help_spec.rb
new file mode 100644
index 0000000000..45b8e93eac
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/ole_method_help_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../shared/ole_method', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#ole_method_help" do
+ it_behaves_like :win32ole_ole_method, :ole_method_help
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_method_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_method_spec.rb
new file mode 100644
index 0000000000..cb1d1d172b
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/ole_method_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../shared/ole_method', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#ole_method" do
+ it_behaves_like :win32ole_ole_method, :ole_method
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb
new file mode 100644
index 0000000000..bba2aa73ae
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#ole_methods" do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ end
+
+ after :each do
+ @ie.Quit
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @ie.ole_methods(1) }.should raise_error ArgumentError
+ end
+
+ it "returns an array of WIN32OLE_METHODs" do
+ @ie.ole_methods.all? { |m| m.kind_of? WIN32OLE_METHOD }.should be_true
+ end
+
+ it "contains a 'AddRef' method for Internet Explorer" do
+ @ie.ole_methods.map { |m| m.name }.include?('AddRef').should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb
new file mode 100644
index 0000000000..eede93bb87
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#ole_obj_help" do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ end
+
+ after :each do
+ @ie.Quit
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @ie.ole_obj_help(1) }.should raise_error ArgumentError
+ end
+
+ it "returns an instance of WIN32OLE_TYPE" do
+ @ie.ole_obj_help.kind_of?(WIN32OLE_TYPE).should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb
new file mode 100644
index 0000000000..5334e7a47d
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#ole_put_methods" do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ end
+
+ after :each do
+ @ie.Quit
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @ie.ole_put_methods(1) }.should raise_error ArgumentError
+ end
+
+ it "returns an array of WIN32OLE_METHODs" do
+ @ie.ole_put_methods.all? { |m| m.kind_of? WIN32OLE_METHOD }.should be_true
+ end
+
+ it "contains a 'Height' method for Internet Explorer" do
+ @ie.ole_put_methods.map { |m| m.name }.include?('Height').should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/setproperty_spec.rb b/spec/ruby/library/win32ole/win32ole/setproperty_spec.rb
new file mode 100644
index 0000000000..ae08e63f78
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/setproperty_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../shared/setproperty', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE#setproperty" do
+ it_behaves_like :win32ole_setproperty, :setproperty
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole/shared/ole_method.rb b/spec/ruby/library/win32ole/win32ole/shared/ole_method.rb
new file mode 100644
index 0000000000..668000c1fc
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/shared/ole_method.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe :win32ole_ole_method, shared: true do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ end
+
+ after :each do
+ @ie.Quit
+ end
+
+ it "raises ArgumentError if no argument is given" do
+ lambda { @ie.send(@method) }.should raise_error ArgumentError
+ end
+
+ it "returns the WIN32OLE_METHOD 'Quit' if given 'Quit'" do
+ result = @ie.send(@method, "Quit")
+ result.kind_of?(WIN32OLE_METHOD).should be_true
+ result.name.should == 'Quit'
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole/shared/setproperty.rb b/spec/ruby/library/win32ole/win32ole/shared/setproperty.rb
new file mode 100644
index 0000000000..9703e402bf
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole/shared/setproperty.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe :win32ole_setproperty, shared: true do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ end
+
+ after :each do
+ @ie.Quit
+ end
+
+ it "raises ArgumentError if no argument is given" do
+ lambda { @ie.send(@method) }.should raise_error ArgumentError
+ end
+
+ it "sets height to 500 and returns nil" do
+ height = 500
+ result = @ie.send(@method, 'Height', height)
+ result.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_event/new_spec.rb b/spec/ruby/library/win32ole/win32ole_event/new_spec.rb
new file mode 100644
index 0000000000..5fffac535e
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_event/new_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_EVENT.new" do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ end
+
+ after :each do
+ @ie.Quit if @ie
+ end
+
+ it "raises TypeError given invalid argument" do
+ lambda { WIN32OLE_EVENT.new "A" }.should raise_error TypeError
+ end
+
+ it "raises RuntimeError if event does not exist" do
+ lambda { WIN32OLE_EVENT.new(@ie, 'A') }.should raise_error RuntimeError
+ end
+
+ it "raises RuntimeError if OLE object has no events" do
+ dict = WIN32OLESpecs.new_ole('Scripting.Dictionary')
+ lambda { WIN32OLE_EVENT.new(dict) }.should raise_error RuntimeError
+ end
+
+ it "creates WIN32OLE_EVENT object" do
+ ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
+ ev.should be_kind_of WIN32OLE_EVENT
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb b/spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb
new file mode 100644
index 0000000000..6bf8d2e1da
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb
@@ -0,0 +1,62 @@
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ def default_handler(event, *args)
+ @event += event
+ end
+
+ def alternate_handler(event, *args)
+ @event2 = "alternate"
+ end
+
+ def handler3(event, *args)
+ @event3 += event
+ end
+
+
+ describe "WIN32OLE_EVENT#on_event with no argument" do
+ before :each do
+ @ie = WIN32OLESpecs.new_ole('InternetExplorer.Application')
+ @ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
+ @event = ''
+ @event2 = ''
+ @event3 = ''
+ @ie.StatusBar = true
+ end
+
+ after :each do
+ @ie.Quit
+ end
+
+ it "sets event handler properly, and the handler is invoked by event loop" do
+ @ev.on_event { |*args| default_handler(*args) }
+ @ie.StatusText='hello'
+ WIN32OLE_EVENT.message_loop
+ @event.should =~ /StatusTextChange/
+ end
+
+ it "accepts a String argument, sets event handler properly, and the handler is invoked by event loop" do
+ @ev.on_event("StatusTextChange") { |*args| @event = 'foo' }
+ @ie.StatusText='hello'
+ WIN32OLE_EVENT.message_loop
+ @event.should =~ /foo/
+ end
+
+ it "registers multiple event handlers for the same event" do
+ @ev.on_event("StatusTextChange") { |*args| default_handler(*args) }
+ @ev.on_event("StatusTextChange") { |*args| alternate_handler(*args) }
+ @ie.StatusText= 'hello'
+ WIN32OLE_EVENT.message_loop
+ @event2.should == 'alternate'
+ end
+
+ it "accepts a Symbol argument, sets event handler properly, and the handler is invoked by event loop" do
+ @ev.on_event(:StatusTextChange) { |*args| @event = 'foo' }
+ @ie.StatusText='hello'
+ WIN32OLE_EVENT.message_loop
+ @event.should =~ /foo/
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb b/spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb
new file mode 100644
index 0000000000..840cdf72b8
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#dispid" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @m = WIN32OLE_METHOD.new(ole_type, "namespace")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m.dispid(0) }.should raise_error ArgumentError
+ end
+
+ it "returns expected dispatch ID for Shell's 'namespace' method" do
+ @m.dispid.should == 1610743810 # value found in MRI's test
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb b/spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb
new file mode 100644
index 0000000000..9d3ca2b8e4
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb
@@ -0,0 +1,26 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#event_interface" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Internet Controls", "WebBrowser")
+ @navigate_method = WIN32OLE_METHOD.new(ole_type, "NavigateComplete")
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @namespace_method = WIN32OLE_METHOD.new(ole_type, "namespace")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @navigate_method.event_interface(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected string for browser's 'NavigateComplete' method" do
+ @navigate_method.event_interface.should == "DWebBrowserEvents"
+ end
+
+ it "returns nil if method has no event interface" do
+ @namespace_method.event_interface.should be_nil
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/event_spec.rb b/spec/ruby/library/win32ole/win32ole_method/event_spec.rb
new file mode 100644
index 0000000000..25435438aa
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/event_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#event?" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Internet Controls", "WebBrowser")
+ @navigate_method = WIN32OLE_METHOD.new(ole_type, "NavigateComplete")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @navigate_method.event?(1) }.should raise_error ArgumentError
+ end
+
+ it "returns true for browser's 'NavigateComplete' method" do
+ @navigate_method.event?.should be_true
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb b/spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb
new file mode 100644
index 0000000000..c0e66a7a18
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb
@@ -0,0 +1,26 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#helpcontext" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Internet Controls", "WebBrowser")
+ @navigate_method = WIN32OLE_METHOD.new(ole_type, "NavigateComplete")
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @navigate_method.helpcontext(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for browser's 'NavigateComplete' method" do
+ @navigate_method.helpcontext.should == 0
+ end
+
+ it "returns expected value for Scripting Runtime's 'name' method" do
+ @m_file_name.helpcontext.should == 2181996 # value indicated in MRI's test
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb b/spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb
new file mode 100644
index 0000000000..72cc4da16b
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#helpfile" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_file_name.helpfile(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Scripting Runtime's 'File' method" do
+ @m_file_name.helpfile.should =~ /VBENLR.*\.CHM$/i
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb b/spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb
new file mode 100644
index 0000000000..60105d0aa2
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#helpstring" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_file_name.helpstring(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Scripting Runtime's 'File' method" do
+ @m_file_name.helpstring.should == "Get name of file" # value indicated in MRI's test
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb b/spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb
new file mode 100644
index 0000000000..cf0a74bbce
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#invkind" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_file_name.invkind(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Scripting Runtime's 'name' method" do
+ @m_file_name.invkind.should == 2
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb b/spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb
new file mode 100644
index 0000000000..4d2af8fb0c
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#invoke_kind" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_file_name.invoke_kind(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Scripting Runtime's 'name' method" do
+ @m_file_name.invoke_kind.should =~ /^(UNKNOWN|PROPERTY|PROPERTYGET|PROPERTYPUT|PROPERTYPUTREF|FUNC)$/
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/name_spec.rb b/spec/ruby/library/win32ole/win32ole_method/name_spec.rb
new file mode 100644
index 0000000000..0c2b3eeba0
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/name_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../shared/name', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#name" do
+ it_behaves_like :win32ole_method_name, :name
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/new_spec.rb b/spec/ruby/library/win32ole/win32ole_method/new_spec.rb
new file mode 100644
index 0000000000..fc8d1d7691
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/new_spec.rb
@@ -0,0 +1,33 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD.new" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ it "raises TypeError when given non-strings" do
+ lambda { WIN32OLE_METHOD.new(1, 2) }.should raise_error TypeError
+ end
+
+ it "raises ArgumentError if only 1 arugment is given" do
+ lambda { WIN32OLE_METHOD.new("hello") }.should raise_error ArgumentError
+ lambda { WIN32OLE_METHOD.new(@ole_type) }.should raise_error ArgumentError
+ end
+
+ it "returns a valid WIN32OLE_METHOD object" do
+ WIN32OLE_METHOD.new(@ole_type, "Open").should be_kind_of WIN32OLE_METHOD
+ WIN32OLE_METHOD.new(@ole_type, "open").should be_kind_of WIN32OLE_METHOD
+ end
+
+ it "raises WIN32OLERuntimeError if the method does not exist" do
+ lambda { WIN32OLE_METHOD.new(@ole_type, "NonexistentMethod") }.should raise_error WIN32OLERuntimeError
+ end
+
+ it "raises TypeError if second argument is not a String" do
+ lambda { WIN32OLE_METHOD.new(@ole_type, 5) }.should raise_error TypeError
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb b/spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb
new file mode 100644
index 0000000000..e436441409
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb
@@ -0,0 +1,21 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#offset_vtbl" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_file_name.offset_vtbl(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Scripting Runtime's 'name' method" do
+ pointer_size = RUBY_PLATFORM =~ /\bx64\b/ ? 64 : 1.size * 8
+ @m_file_name.offset_vtbl.should == pointer_size
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/params_spec.rb b/spec/ruby/library/win32ole/win32ole_method/params_spec.rb
new file mode 100644
index 0000000000..08c7f04bdd
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/params_spec.rb
@@ -0,0 +1,28 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#params" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_file_name.params(1) }.should raise_error ArgumentError
+ end
+
+ it "returns empty array for Scripting Runtime's 'name' method" do
+ @m_file_name.params.should be_kind_of Array
+ @m_file_name.params.should be_empty
+ end
+
+ it "returns 4-element array of WIN32OLE_PARAM for Shell's 'BrowseForFolder' method" do
+ @m_browse_for_folder.params.all? { |p| p.kind_of? WIN32OLE_PARAM }.should be_true
+ @m_browse_for_folder.params.size == 4
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb b/spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb
new file mode 100644
index 0000000000..b8f2bbe084
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb
@@ -0,0 +1,21 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#return_type_detail" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_browse_for_folder.return_type_detail(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Shell Control's 'BrowseForFolder' method" do
+ @m_browse_for_folder.return_type_detail.should be_kind_of Array
+ @m_browse_for_folder.return_type_detail.should == ['PTR', 'USERDEFINED', 'Folder']
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb b/spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb
new file mode 100644
index 0000000000..b68481fe59
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#return_type" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_file_name.return_type(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Scripting Runtime's 'name' method" do
+ @m_file_name.return_type.should == 'BSTR'
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb b/spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb
new file mode 100644
index 0000000000..f236de01f9
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#return_vtype" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_browse_for_folder.return_vtype(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Shell Control's 'BrowseForFolder' method" do
+ @m_browse_for_folder.return_vtype.should == 26
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/shared/name.rb b/spec/ruby/library/win32ole/win32ole_method/shared/name.rb
new file mode 100644
index 0000000000..2be6478a6e
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/shared/name.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe :win32ole_method_name, shared: true do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_file_name.send(@method, 1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Scripting Runtime's 'name' method" do
+ @m_file_name.send(@method).should == 'Name' # note the capitalization
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb b/spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb
new file mode 100644
index 0000000000..a63c50474c
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#size_opt_params" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_browse_for_folder.size_opt_params(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Shell Control's 'BrowseForFolder' method" do
+ @m_browse_for_folder.size_opt_params.should == 1
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb b/spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb
new file mode 100644
index 0000000000..fe93d5bc66
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#size_params" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_browse_for_folder.size_params(1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Shell Control's 'BrowseForFolder' method" do
+ @m_browse_for_folder.size_params.should == 4
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb b/spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb
new file mode 100644
index 0000000000..95fd2fcdb5
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../shared/name', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#name" do
+ it_behaves_like :win32ole_method_name, :to_s
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/visible_spec.rb b/spec/ruby/library/win32ole/win32ole_method/visible_spec.rb
new file mode 100644
index 0000000000..b49fac6066
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_method/visible_spec.rb
@@ -0,0 +1,20 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_METHOD#visible?" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @m_browse_for_folder.visible?(1) }.should raise_error ArgumentError
+ end
+
+ it "returns true for Shell Control's 'BrowseForFolder' method" do
+ @m_browse_for_folder.visible?.should be_true
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_param/default_spec.rb b/spec/ruby/library/win32ole/win32ole_param/default_spec.rb
new file mode 100644
index 0000000000..7a1337ec7c
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_param/default_spec.rb
@@ -0,0 +1,31 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_PARAM#default" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ @params = m_browse_for_folder.params
+
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile")
+ @param_overwritefiles = m_copyfile.params[2]
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @params[0].default(1) }.should raise_error ArgumentError
+ end
+
+ it "returns nil for each of WIN32OLE_PARAM for Shell's 'BrowseForFolder' method" do
+ @params.each do |p|
+ p.default.should be_nil
+ end
+ end
+
+ it "returns true for 3rd parameter of FileSystemObject's 'CopyFile' method" do
+ @param_overwritefiles.default.should == true # not be_true
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_param/input_spec.rb b/spec/ruby/library/win32ole/win32ole_param/input_spec.rb
new file mode 100644
index 0000000000..bdf4bccc79
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_param/input_spec.rb
@@ -0,0 +1,21 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_PARAM#input?" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile")
+ @param_overwritefiles = m_copyfile.params[2]
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @param_overwritefiles.input?(1) }.should raise_error ArgumentError
+ end
+
+ it "returns true for 3rd parameter of FileSystemObject's 'CopyFile' method" do
+ @param_overwritefiles.input?.should == true
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_param/name_spec.rb b/spec/ruby/library/win32ole/win32ole_param/name_spec.rb
new file mode 100644
index 0000000000..b3c947d6fb
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_param/name_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../shared/name', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_PARAM#name" do
+ it_behaves_like :win32ole_param_name, :name
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb b/spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb
new file mode 100644
index 0000000000..3ba51c02f1
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb
@@ -0,0 +1,21 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_PARAM#ole_type_detail" do
+ before :each do
+ ole_type_detail = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE_METHOD.new(ole_type_detail, "CopyFile")
+ @param_overwritefiles = m_copyfile.params[2]
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @param_overwritefiles.ole_type_detail(1) }.should raise_error ArgumentError
+ end
+
+ it "returns ['BOOL'] for 3rd parameter of FileSystemObject's 'CopyFile' method" do
+ @param_overwritefiles.ole_type_detail.should == ['BOOL']
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb b/spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb
new file mode 100644
index 0000000000..52bee2c9b8
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb
@@ -0,0 +1,21 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_PARAM#ole_type" do
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile")
+ @param_overwritefiles = m_copyfile.params[2]
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @param_overwritefiles.ole_type(1) }.should raise_error ArgumentError
+ end
+
+ it "returns 'BOOL' for 3rd parameter of FileSystemObject's 'CopyFile' method" do
+ @param_overwritefiles.ole_type.should == 'BOOL'
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_param/optional_spec.rb b/spec/ruby/library/win32ole/win32ole_param/optional_spec.rb
new file mode 100644
index 0000000000..2476df8641
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_param/optional_spec.rb
@@ -0,0 +1,21 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_PARAM#optional?" do
+ before :each do
+ ole_type_detail = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE_METHOD.new(ole_type_detail, "CopyFile")
+ @param_overwritefiles = m_copyfile.params[2]
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @param_overwritefiles.optional?(1) }.should raise_error ArgumentError
+ end
+
+ it "returns true for 3rd parameter of FileSystemObject's 'CopyFile' method" do
+ @param_overwritefiles.optional?.should be_true
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_param/retval_spec.rb b/spec/ruby/library/win32ole/win32ole_param/retval_spec.rb
new file mode 100644
index 0000000000..90946c0774
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_param/retval_spec.rb
@@ -0,0 +1,21 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_PARAM#retval?" do
+ before :each do
+ ole_type_detail = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE_METHOD.new(ole_type_detail, "CopyFile")
+ @param_overwritefiles = m_copyfile.params[2]
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @param_overwritefiles.retval?(1) }.should raise_error ArgumentError
+ end
+
+ it "returns false for 3rd parameter of FileSystemObject's 'CopyFile' method" do
+ @param_overwritefiles.retval?.should be_false
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_param/shared/name.rb b/spec/ruby/library/win32ole/win32ole_param/shared/name.rb
new file mode 100644
index 0000000000..b7892d92fb
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_param/shared/name.rb
@@ -0,0 +1,21 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe :win32ole_param_name, shared: true do
+ before :each do
+ ole_type_detail = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE_METHOD.new(ole_type_detail, "CopyFile")
+ @param_overwritefiles = m_copyfile.params[2]
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @param_overwritefiles.send(@method, 1) }.should raise_error ArgumentError
+ end
+
+ it "returns expected value for Scripting Runtime's 'name' method" do
+ @param_overwritefiles.send(@method).should == 'OverWriteFiles' # note the capitalization
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb b/spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb
new file mode 100644
index 0000000000..7852bb0494
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../shared/name', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_PARAM#to_s" do
+ it_behaves_like :win32ole_param_name, :to_s
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/guid_spec.rb b/spec/ruby/library/win32ole/win32ole_type/guid_spec.rb
new file mode 100644
index 0000000000..25907c8e32
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/guid_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#guid for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns String with expected format" do
+ @ole_type.guid.should =~ /\A\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}\z/
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb b/spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb
new file mode 100644
index 0000000000..d436835188
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#helpcontext for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns an Integer" do
+ @ole_type.helpcontext.should be_kind_of Integer
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb b/spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb
new file mode 100644
index 0000000000..01e6945138
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#helpfile for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns an empty string" do
+ @ole_type.helpfile.should be_empty
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb b/spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb
new file mode 100644
index 0000000000..3bd2cbe5dd
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#helpstring for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns expected string" do
+ @ole_type.helpstring.should == "Shell Object Type Information"
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb b/spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb
new file mode 100644
index 0000000000..7dae16617d
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#major_version for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns an Integer" do
+ @ole_type.major_version.should be_kind_of Integer
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb b/spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb
new file mode 100644
index 0000000000..ff412dd100
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#minor_version for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns an Integer" do
+ @ole_type.minor_version.should be_kind_of Integer
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/name_spec.rb b/spec/ruby/library/win32ole/win32ole_type/name_spec.rb
new file mode 100644
index 0000000000..b395cf05d5
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/name_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../shared/name', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#name" do
+ it_behaves_like :win32ole_type_name, :name
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/new_spec.rb b/spec/ruby/library/win32ole/win32ole_type/new_spec.rb
new file mode 100644
index 0000000000..9443a64c75
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/new_spec.rb
@@ -0,0 +1,37 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE.new" do
+ it "raises ArgumentError with no argument" do
+ lambda { WIN32OLE_TYPE.new }.should raise_error ArgumentError
+ end
+
+ it "raises ArgumentError with invalid string" do
+ lambda { WIN32OLE_TYPE.new("foo") }.should raise_error ArgumentError
+ end
+
+ it "raises TypeError if second argument is not a String" do
+ lambda { WIN32OLE_TYPE.new(1,2) }.should raise_error TypeError
+ lambda { WIN32OLE_TYPE.new('Microsoft Shell Controls And Automation',2) }.
+ should raise_error TypeError
+ end
+
+ it "raise WIN32OLERuntimeError if OLE object specified is not found" do
+ lambda { WIN32OLE_TYPE.new('Microsoft Shell Controls And Automation','foo') }.
+ should raise_error WIN32OLERuntimeError
+ lambda { WIN32OLE_TYPE.new('Microsoft Shell Controls And Automation','Application') }.
+ should raise_error WIN32OLERuntimeError
+ end
+
+ it "creates WIN32OLE_TYPE object from name and valid type" do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ ole_type.should be_kind_of WIN32OLE_TYPE
+ end
+
+ it "creates WIN32OLE_TYPE object from CLSID and valid type" do
+ ole_type2 = WIN32OLE_TYPE.new("{13709620-C279-11CE-A49E-444553540000}", "Shell")
+ ole_type2.should be_kind_of WIN32OLE_TYPE
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb b/spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb
new file mode 100644
index 0000000000..0ce0fc98a4
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE.ole_classes for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns array of WIN32OLE_TYPEs" do
+ WIN32OLE_TYPE.ole_classes("Microsoft Shell Controls And Automation").all? {|e| e.kind_of? WIN32OLE_TYPE }.should be_true
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb b/spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb
new file mode 100644
index 0000000000..9265549d20
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#ole_methods for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns an Integer" do
+ @ole_type.ole_methods.all? { |m| m.kind_of? WIN32OLE_METHOD }.should be_true
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb b/spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb
new file mode 100644
index 0000000000..2bc19aa85e
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#ole_type for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns string 'Class'" do
+ @ole_type.ole_type.should == "Class"
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/progid_spec.rb b/spec/ruby/library/win32ole/win32ole_type/progid_spec.rb
new file mode 100644
index 0000000000..f0d80ba39e
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/progid_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#progid for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns expected string" do
+ @ole_type.progid.should == "Shell.Application.1"
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/progids_spec.rb b/spec/ruby/library/win32ole/win32ole_type/progids_spec.rb
new file mode 100644
index 0000000000..0cdd3514e3
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/progids_spec.rb
@@ -0,0 +1,14 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE.progids" do
+ it "raises ArgumentError if an argument is given" do
+ lambda { WIN32OLE_TYPE.progids(1) }.should raise_error ArgumentError
+ end
+
+ it "returns an array containing 'Shell.Explorer'" do
+ WIN32OLE_TYPE.progids().include?('Shell.Explorer').should be_true
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/shared/name.rb b/spec/ruby/library/win32ole/win32ole_type/shared/name.rb
new file mode 100644
index 0000000000..6484ef0ef8
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/shared/name.rb
@@ -0,0 +1,19 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe :win32ole_type_name, shared: true do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ end
+
+ it "raises ArgumentError if argument is given" do
+ lambda { @ole_type.send(@method, 1) }.should raise_error ArgumentError
+ end
+
+ it "returns a String" do
+ @ole_type.send(@method).should == 'ShellSpecialFolderConstants'
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb b/spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb
new file mode 100644
index 0000000000..71e304d80a
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#src_type for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns nil" do
+ @ole_type.src_type.should be_nil
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb b/spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb
new file mode 100644
index 0000000000..5a50bd11de
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../shared/name', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#to_s" do
+ it_behaves_like :win32ole_type_name, :to_s
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb b/spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb
new file mode 100644
index 0000000000..35f3562721
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#typekind for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns an Integer" do
+ @ole_type.typekind.should be_kind_of Integer
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb b/spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb
new file mode 100644
index 0000000000..3a28c0496c
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb
@@ -0,0 +1,22 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE.typelibs for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "raises ArgumentError if any argument is give" do
+ lambda { WIN32OLE_TYPE.typelibs(1) }.should raise_error ArgumentError
+ end
+
+ it "returns array of type libraries" do
+ WIN32OLE_TYPE.typelibs().include?("Microsoft Shell Controls And Automation").should be_true
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/variables_spec.rb b/spec/ruby/library/win32ole/win32ole_type/variables_spec.rb
new file mode 100644
index 0000000000..fbf3dd0341
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/variables_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#variables for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns an empty array" do
+ @ole_type.variables.should == []
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_type/visible_spec.rb b/spec/ruby/library/win32ole/win32ole_type/visible_spec.rb
new file mode 100644
index 0000000000..403b2b843b
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_type/visible_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_TYPE#visible? for Shell Controls" do
+ before :each do
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ after :each do
+ @ole_type = nil
+ end
+
+ it "returns true" do
+ @ole_type.visible?.should be_true
+ end
+
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/name_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/name_spec.rb
new file mode 100644
index 0000000000..724fd5c70a
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_variable/name_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../shared/name', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_VARIABLE#name" do
+ it_behaves_like :win32ole_variable_new, :name
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb
new file mode 100644
index 0000000000..dab4edabaa
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb
@@ -0,0 +1,19 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_VARIABLE#ole_type_detail" do
+ # not sure how WIN32OLE_VARIABLE objects are supposed to be generated
+ # WIN32OLE_VARIABLE.new even seg faults in some cases
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ @var = ole_type.variables[0]
+ end
+
+ it "returns a nonempty Array" do
+ @var.ole_type_detail.should be_kind_of Array
+ @var.ole_type_detail.should_not be_empty
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb
new file mode 100644
index 0000000000..d08acc9bde
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_VARIABLE#ole_type" do
+ # not sure how WIN32OLE_VARIABLE objects are supposed to be generated
+ # WIN32OLE_VARIABLE.new even seg faults in some cases
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ @var = ole_type.variables[0]
+ end
+
+ it "returns a String" do
+ @var.ole_type.should be_kind_of String
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/shared/name.rb b/spec/ruby/library/win32ole/win32ole_variable/shared/name.rb
new file mode 100644
index 0000000000..033e830fac
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_variable/shared/name.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe :win32ole_variable_new, shared: true do
+ # not sure how WIN32OLE_VARIABLE objects are supposed to be generated
+ # WIN32OLE_VARIABLE.new even seg faults in some cases
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ @var = ole_type.variables[0]
+ end
+
+ it "returns a String" do
+ @var.send(@method).should be_kind_of String
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/to_s_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/to_s_spec.rb
new file mode 100644
index 0000000000..9853f91801
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_variable/to_s_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../shared/name', __FILE__)
+
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_VARIABLE#to_s" do
+ it_behaves_like :win32ole_variable_new, :to_s
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb
new file mode 100644
index 0000000000..c15f64c2c5
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb
@@ -0,0 +1,19 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_VARIABLE#value" do
+ # not sure how WIN32OLE_VARIABLE objects are supposed to be generated
+ # WIN32OLE_VARIABLE.new even seg faults in some cases
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ @var = ole_type.variables[0]
+ end
+
+ it "returns a Integer" do
+ # according to doc, this could return nil
+ @var.value.should be_kind_of Integer
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb
new file mode 100644
index 0000000000..4cca7f8874
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb
@@ -0,0 +1,19 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_VARIABLE#variable_kind" do
+ # not sure how WIN32OLE_VARIABLE objects are supposed to be generated
+ # WIN32OLE_VARIABLE.new even seg faults in some cases
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ @var = ole_type.variables[0]
+ end
+
+ it "returns a String" do
+ @var.variable_kind.should be_kind_of String
+ @var.variable_kind.should == 'CONSTANT'
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb
new file mode 100644
index 0000000000..56cd1c337a
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb
@@ -0,0 +1,19 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_VARIABLE#varkind" do
+ # TODO review
+ # not sure how WIN32OLE_VARIABLE objects are supposed to be generated
+ # WIN32OLE_VARIABLE.new even seg faults in some cases
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ @var = ole_type.variables[0]
+ end
+
+ it "returns an Integer" do
+ @var.varkind.should be_kind_of Integer
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb
new file mode 100644
index 0000000000..7f7a557b57
--- /dev/null
+++ b/spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb
@@ -0,0 +1,18 @@
+platform_is :windows do
+ require 'win32ole'
+
+ describe "WIN32OLE_VARIABLE#visible?" do
+ # not sure how WIN32OLE_VARIABLE objects are supposed to be generated
+ # WIN32OLE_VARIABLE.new even seg faults in some cases
+ before :each do
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ @var = ole_type.variables[0]
+ end
+
+ it "returns a String" do
+ @var.visible?.should be_true
+ end
+
+ end
+
+end
diff --git a/spec/ruby/library/yaml/add_builtin_type_spec.rb b/spec/ruby/library/yaml/add_builtin_type_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/add_builtin_type_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/add_domain_type_spec.rb b/spec/ruby/library/yaml/add_domain_type_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/add_domain_type_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/add_private_type_spec.rb b/spec/ruby/library/yaml/add_private_type_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/add_private_type_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/add_ruby_type_spec.rb b/spec/ruby/library/yaml/add_ruby_type_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/add_ruby_type_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/detect_implicit_spec.rb b/spec/ruby/library/yaml/detect_implicit_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/detect_implicit_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/dump_spec.rb b/spec/ruby/library/yaml/dump_spec.rb
new file mode 100644
index 0000000000..c3613521e0
--- /dev/null
+++ b/spec/ruby/library/yaml/dump_spec.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+
+# TODO: WTF is this using a global?
+describe "YAML.dump" do
+ after :each do
+ rm_r $test_file
+ end
+
+ it "converts an object to YAML and write result to io when io provided" do
+ File.open($test_file, 'w' ) do |io|
+ YAML.dump( ['badger', 'elephant', 'tiger'], io )
+ end
+ YAML.load_file($test_file).should == ['badger', 'elephant', 'tiger']
+ end
+
+ it "returns a string containing dumped YAML when no io provided" do
+ YAML.dump( :locked ).should match_yaml("--- :locked\n")
+ end
+
+ it "returns the same string that #to_yaml on objects" do
+ ["a", "b", "c"].to_yaml.should == YAML.dump(["a", "b", "c"])
+ end
+
+ it "dumps strings into YAML strings" do
+ YAML.dump("str").should match_yaml("--- str\n")
+ end
+
+ it "dumps hashes into YAML key-values" do
+ YAML.dump({ "a" => "b" }).should match_yaml("--- \na: b\n")
+ end
+
+ it "dumps Arrays into YAML collection" do
+ YAML.dump(["a", "b", "c"]).should match_yaml("--- \n- a\n- b\n- c\n")
+ end
+
+ it "dumps an OpenStruct" do
+ require "ostruct"
+ os = OpenStruct.new("age" => 20, "name" => "John")
+ YAML.dump(os).should match_yaml("--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n")
+ end
+
+ it "dumps a File without any state" do
+ file = File.new(__FILE__)
+ begin
+ YAML.dump(file).should match_yaml("--- !ruby/object:File {}\n")
+ ensure
+ file.close
+ end
+ end
+end
diff --git a/spec/ruby/library/yaml/dump_stream_spec.rb b/spec/ruby/library/yaml/dump_stream_spec.rb
new file mode 100644
index 0000000000..918b62607f
--- /dev/null
+++ b/spec/ruby/library/yaml/dump_stream_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "YAML.dump_stream" do
+ it "returns a YAML stream containing the objects passed" do
+ YAML.dump_stream('foo', 20, [], {}).should match_yaml("--- foo\n--- 20\n--- []\n\n--- {}\n\n")
+ end
+end
diff --git a/spec/ruby/library/yaml/each_node_spec.rb b/spec/ruby/library/yaml/each_node_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/each_node_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/emitter_spec.rb b/spec/ruby/library/yaml/emitter_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/emitter_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/fixtures/common.rb b/spec/ruby/library/yaml/fixtures/common.rb
new file mode 100644
index 0000000000..1d868806f1
--- /dev/null
+++ b/spec/ruby/library/yaml/fixtures/common.rb
@@ -0,0 +1,10 @@
+begin
+ require 'syck'
+rescue LoadError
+ # do nothing
+end
+
+require 'yaml'
+
+$test_file = tmp("yaml_test_file")
+$test_parse_file = File.dirname(__FILE__) + "/test_yaml.yml"
diff --git a/spec/ruby/library/yaml/fixtures/example_class.rb b/spec/ruby/library/yaml/fixtures/example_class.rb
new file mode 100644
index 0000000000..751435a305
--- /dev/null
+++ b/spec/ruby/library/yaml/fixtures/example_class.rb
@@ -0,0 +1,5 @@
+class FooBar
+ def initialize(name)
+ @name = name
+ end
+end
diff --git a/spec/ruby/library/yaml/fixtures/strings.rb b/spec/ruby/library/yaml/fixtures/strings.rb
new file mode 100644
index 0000000000..6f66dc3659
--- /dev/null
+++ b/spec/ruby/library/yaml/fixtures/strings.rb
@@ -0,0 +1,36 @@
+$complex_key_1 = <<EOY
+ ? # PLAY SCHEDULE
+ - Detroit Tigers
+ - Chicago Cubs
+ :
+ - 2001-07-23
+
+ ? [ New York Yankees,
+ Atlanta Braves ]
+ : [ 2001-07-02, 2001-08-12,
+ 2001-08-14 ]
+EOY
+
+$to_yaml_hash =
+<<EOY
+-
+ avg: 0.278
+ hr: 65
+ name: Mark McGwire
+-
+ avg: 0.288
+ hr: 63
+ name: Sammy Sosa
+EOY
+
+$multidocument = <<EOY
+---
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
+
+# Team ranking
+---
+- Chicago Cubs
+- St Louis Cardinals
+EOY
diff --git a/spec/ruby/library/yaml/fixtures/test_yaml.yml b/spec/ruby/library/yaml/fixtures/test_yaml.yml
new file mode 100644
index 0000000000..efe3b5cc1a
--- /dev/null
+++ b/spec/ruby/library/yaml/fixtures/test_yaml.yml
@@ -0,0 +1,2 @@
+project:
+ name: RubySpec
diff --git a/spec/ruby/library/yaml/generic_parser_spec.rb b/spec/ruby/library/yaml/generic_parser_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/generic_parser_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/load_documents_spec.rb b/spec/ruby/library/yaml/load_documents_spec.rb
new file mode 100644
index 0000000000..77d6dd8ae1
--- /dev/null
+++ b/spec/ruby/library/yaml/load_documents_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+require File.expand_path('../fixtures/strings', __FILE__)
+require File.expand_path('../shared/each_document', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ describe "YAML.load_documents" do
+ it_behaves_like :yaml_each_document, :load_documents
+ end
+end
diff --git a/spec/ruby/library/yaml/load_file_spec.rb b/spec/ruby/library/yaml/load_file_spec.rb
new file mode 100644
index 0000000000..d9ba5bedb1
--- /dev/null
+++ b/spec/ruby/library/yaml/load_file_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "YAML.load_file" do
+ after :each do
+ rm_r $test_file
+ end
+
+ it "returns a hash" do
+ File.open($test_file,'w' ){|io| YAML.dump( {"bar"=>2, "car"=>1}, io ) }
+ YAML.load_file($test_file).should == {"bar"=>2, "car"=>1}
+ end
+end
diff --git a/spec/ruby/library/yaml/load_spec.rb b/spec/ruby/library/yaml/load_spec.rb
new file mode 100644
index 0000000000..7c5a33d52f
--- /dev/null
+++ b/spec/ruby/library/yaml/load_spec.rb
@@ -0,0 +1,116 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+require File.expand_path('../fixtures/strings', __FILE__)
+
+describe "YAML.load" do
+ after :each do
+ rm_r $test_file
+ end
+
+ it "returns a document from current io stream when io provided" do
+ File.open($test_file, 'w') do |io|
+ YAML.dump( ['badger', 'elephant', 'tiger'], io )
+ end
+ File.open($test_file) { |yf| YAML.load( yf ) }.should == ['badger', 'elephant', 'tiger']
+ end
+
+ it "loads strings" do
+ strings = ["str",
+ " str",
+ "'str'",
+ "str",
+ " str",
+ "'str'",
+ "\"str\"",
+ "\n str",
+ "--- str",
+ "---\nstr",
+ "--- \nstr",
+ "--- \n str",
+ "--- 'str'"
+ ]
+ strings.each do |str|
+ YAML.load(str).should == "str"
+ end
+ end
+
+ it "fails on invalid keys" do
+ if YAML.to_s == "Psych"
+ error = Psych::SyntaxError
+ else
+ error = ArgumentError
+ end
+ lambda { YAML.load("key1: value\ninvalid_key") }.should raise_error(error)
+ end
+
+ it "accepts symbols" do
+ YAML.load( "--- :locked" ).should == :locked
+ end
+
+ it "accepts numbers" do
+ YAML.load("47").should == 47
+ YAML.load("-1").should == -1
+ end
+
+ it "accepts collections" do
+ expected = ["a", "b", "c"]
+ YAML.load("--- \n- a\n- b\n- c\n").should == expected
+ YAML.load("--- [a, b, c]").should == expected
+ YAML.load("[a, b, c]").should == expected
+ end
+
+ it "parses start markers" do
+ YAML.load("---\n").should == nil
+ YAML.load("--- ---\n").should == "---"
+ YAML.load("--- abc").should == "abc"
+ end
+
+ it "works with block sequence shortcuts" do
+ block_seq = "- - - one\n - two\n - three"
+ YAML.load(block_seq).should == [[["one", "two", "three"]]]
+ end
+
+ it "works on complex keys" do
+ require 'date'
+ expected = {
+ [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ],
+ [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ),
+ Date.new( 2001, 8, 12 ),
+ Date.new( 2001, 8, 14 ) ]
+ }
+ YAML.load($complex_key_1).should == expected
+ end
+
+ it "loads a symbol key that contains spaces" do
+ string = ":user name: This is the user name."
+ expected = { :"user name" => "This is the user name."}
+ YAML.load(string).should == expected
+ end
+
+ describe "with iso8601 timestamp" do
+ it "computes the microseconds" do
+ [ [YAML.load("2011-03-22t23:32:11.2233+01:00"), 223300],
+ [YAML.load("2011-03-22t23:32:11.0099+01:00"), 9900],
+ [YAML.load("2011-03-22t23:32:11.000076+01:00"), 76]
+ ].should be_computed_by(:usec)
+ end
+
+ it "rounds values smaller than 1 usec to 0 " do
+ YAML.load("2011-03-22t23:32:11.000000342222+01:00").usec.should == 0
+ end
+ end
+
+ it "loads an OpenStruct" do
+ require "ostruct"
+ os = OpenStruct.new("age" => 20, "name" => "John")
+ loaded = YAML.load("--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n")
+ loaded.should == os
+ end
+
+ it "loads a File but raise an error when used as it is uninitialized" do
+ loaded = YAML.load("--- !ruby/object:File {}\n")
+ lambda {
+ loaded.read(1)
+ }.should raise_error(IOError)
+ end
+end
diff --git a/spec/ruby/library/yaml/load_stream_spec.rb b/spec/ruby/library/yaml/load_stream_spec.rb
new file mode 100644
index 0000000000..f134f4642f
--- /dev/null
+++ b/spec/ruby/library/yaml/load_stream_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+require File.expand_path('../fixtures/strings', __FILE__)
+require File.expand_path('../shared/each_document', __FILE__)
+
+describe "YAML.load_stream" do
+ it_behaves_like :yaml_each_document, :load_stream
+end
diff --git a/spec/ruby/library/yaml/object_maker_spec.rb b/spec/ruby/library/yaml/object_maker_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/object_maker_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/parse_documents_spec.rb b/spec/ruby/library/yaml/parse_documents_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/parse_documents_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/parse_file_spec.rb b/spec/ruby/library/yaml/parse_file_spec.rb
new file mode 100644
index 0000000000..d8980135f5
--- /dev/null
+++ b/spec/ruby/library/yaml/parse_file_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "YAML#parse_file" do
+ quarantine! do
+ it "returns a YAML::Syck::Map object after parsing a YAML file" do
+ YAML.parse_file($test_parse_file).should be_kind_of(YAML::Syck::Map)
+ end
+ end
+end
diff --git a/spec/ruby/library/yaml/parse_spec.rb b/spec/ruby/library/yaml/parse_spec.rb
new file mode 100644
index 0000000000..137fc23cf8
--- /dev/null
+++ b/spec/ruby/library/yaml/parse_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "YAML#parse with an empty string" do
+ it "returns false" do
+ YAML.parse('').should be_false
+ end
+end
+
+describe "YAML#parse" do
+ before :each do
+ @string_yaml = "foo".to_yaml
+ end
+
+ it "returns the value from the object" do
+ if YAML.to_s == "Psych"
+ YAML.parse(@string_yaml).to_ruby.should == "foo"
+ else
+ YAML.parse(@string_yaml).value.should == "foo"
+ end
+ end
+end
diff --git a/spec/ruby/library/yaml/parser_spec.rb b/spec/ruby/library/yaml/parser_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/parser_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/quick_emit_spec.rb b/spec/ruby/library/yaml/quick_emit_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/quick_emit_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/read_type_class_spec.rb b/spec/ruby/library/yaml/read_type_class_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/read_type_class_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/shared/each_document.rb b/spec/ruby/library/yaml/shared/each_document.rb
new file mode 100644
index 0000000000..5d9d240005
--- /dev/null
+++ b/spec/ruby/library/yaml/shared/each_document.rb
@@ -0,0 +1,18 @@
+describe :yaml_each_document, shared: true do
+ it "calls the block on each succesive document" do
+ documents = []
+ YAML.send(@method, $multidocument) do |doc|
+ documents << doc
+ end
+ documents.should == [["Mark McGwire", "Sammy Sosa", "Ken Griffey"],
+ ["Chicago Cubs", "St Louis Cardinals"]]
+ end
+
+ it "works on files" do
+ File.open($test_parse_file, "r") do |file|
+ YAML.send(@method, file) do |doc|
+ doc.should == {"project"=>{"name"=>"RubySpec"}}
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/yaml/tagurize_spec.rb b/spec/ruby/library/yaml/tagurize_spec.rb
new file mode 100644
index 0000000000..f6025cbea3
--- /dev/null
+++ b/spec/ruby/library/yaml/tagurize_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+
+ruby_version_is ''...'2.5' do
+ describe "YAML.tagurize" do
+ it "converts a type_id to a taguri" do
+ YAML.tagurize('wtf').should == "tag:yaml.org,2002:wtf"
+ YAML.tagurize(1).should == 1
+ end
+ end
+end
diff --git a/spec/ruby/library/yaml/to_yaml_spec.rb b/spec/ruby/library/yaml/to_yaml_spec.rb
new file mode 100644
index 0000000000..d129fe2d79
--- /dev/null
+++ b/spec/ruby/library/yaml/to_yaml_spec.rb
@@ -0,0 +1,99 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+require File.expand_path('../fixtures/example_class', __FILE__)
+
+describe "Object#to_yaml" do
+
+ it "returns the YAML representation of an Array object" do
+ %w( 30 ruby maz irb 99 ).to_yaml.gsub("'", '"').should match_yaml("--- \n- \"30\"\n- ruby\n- maz\n- irb\n- \"99\"\n")
+ end
+
+ it "returns the YAML representation of a Hash object" do
+ { "a" => "b"}.to_yaml.should match_yaml("--- \na: b\n")
+ end
+
+ it "returns the YAML representation of a Class object" do
+ FooBar.new("baz").to_yaml.should match_yaml("--- !ruby/object:FooBar\nname: baz\n")
+
+ end
+
+ it "returns the YAML representation of a Date object" do
+ require 'date'
+ Date.parse('1997/12/30').to_yaml.should match_yaml("--- 1997-12-30\n")
+ end
+
+ it "returns the YAML representation of a FalseClass" do
+ false_klass = false
+ false_klass.should be_kind_of(FalseClass)
+ false_klass.to_yaml.should match_yaml("--- false\n")
+ end
+
+ it "returns the YAML representation of a Float object" do
+ float = 1.2
+ float.should be_kind_of(Float)
+ float.to_yaml.should match_yaml("--- 1.2\n")
+ end
+
+ it "returns the YAML representation of an Integer object" do
+ int = 20
+ int.should be_kind_of(Integer)
+ int.to_yaml.should match_yaml("--- 20\n")
+ end
+
+ it "returns the YAML representation of a NilClass object" do
+ nil_klass = nil
+ nil_klass.should be_kind_of(NilClass)
+ nil_klass.to_yaml.should match_yaml("--- \n")
+ end
+
+ it "returns the YAML represenation of a RegExp object" do
+ Regexp.new('^a-z+:\\s+\w+').to_yaml.should match_yaml("--- !ruby/regexp /^a-z+:\\s+\\w+/\n")
+ end
+
+ it "returns the YAML representation of a String object" do
+ "I love Ruby".to_yaml.should match_yaml("--- I love Ruby\n")
+ end
+
+ it "returns the YAML representation of a Struct object" do
+ Person = Struct.new(:name, :gender)
+ Person.new("Jane", "female").to_yaml.should match_yaml("--- !ruby/struct:Person\nname: Jane\ngender: female\n")
+ end
+
+ it "returns the YAML representation of a Symbol object" do
+ :symbol.to_yaml.should match_yaml("--- :symbol\n")
+ end
+
+ it "returns the YAML representation of a Time object" do
+ Time.utc(2000,"jan",1,20,15,1).to_yaml.sub(/\.0+/, "").should match_yaml("--- 2000-01-01 20:15:01 Z\n")
+ end
+
+ it "returns the YAML representation of a TrueClass" do
+ true_klass = true
+ true_klass.should be_kind_of(TrueClass)
+ true_klass.to_yaml.should match_yaml("--- true\n")
+ end
+
+ it "returns the YAML representation of a Error object" do
+ StandardError.new("foobar").to_yaml.should match_yaml("--- !ruby/exception:StandardError\nmessage: foobar\n")
+ end
+
+ it "returns the YAML representation for Range objects" do
+ yaml = Range.new(1,3).to_yaml
+ yaml.include?("!ruby/range").should be_true
+ yaml.include?("begin: 1").should be_true
+ yaml.include?("end: 3").should be_true
+ yaml.include?("excl: false").should be_true
+ end
+
+ it "returns the YAML representation of numeric constants" do
+ nan_value.to_yaml.downcase.should match_yaml("--- .nan\n")
+ infinity_value.to_yaml.downcase.should match_yaml("--- .inf\n")
+ (-infinity_value).to_yaml.downcase.should match_yaml("--- -.inf\n")
+ (0.0).to_yaml.should match_yaml("--- 0.0\n")
+ end
+
+ it "returns the YAML representation of an array of hashes" do
+ players = [{"a" => "b"}, {"b" => "c"}]
+ players.to_yaml.should match_yaml("--- \n- a: b\n- b: c\n")
+ end
+end
diff --git a/spec/ruby/library/yaml/transfer_spec.rb b/spec/ruby/library/yaml/transfer_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/transfer_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/yaml/try_implicit_spec.rb b/spec/ruby/library/yaml/try_implicit_spec.rb
new file mode 100644
index 0000000000..a8af231b47
--- /dev/null
+++ b/spec/ruby/library/yaml/try_implicit_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
diff --git a/spec/ruby/library/zlib/adler32_spec.rb b/spec/ruby/library/zlib/adler32_spec.rb
new file mode 100644
index 0000000000..1767dc2011
--- /dev/null
+++ b/spec/ruby/library/zlib/adler32_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib.adler32" do
+ it "calculates Adler checksum for string" do
+ Zlib.adler32("").should == 1
+ Zlib.adler32(" ").should == 2162721
+ Zlib.adler32("123456789").should == 152961502
+ Zlib.adler32("!@#\{$\}%^&**()").should == 365495023
+ Zlib.adler32("to be or not to be" * 22).should == 3979904837
+ Zlib.adler32("0").should == 3211313
+ Zlib.adler32((2**32).to_s).should == 193331739
+ Zlib.adler32((2**64).to_s).should == 723452953
+ end
+
+ it "calculates Adler checksum for string and initial Adler value" do
+ test_string = "This is a test string! How exciting!%?"
+ Zlib.adler32(test_string, 0).should == 63900955
+ Zlib.adler32(test_string, 1).should == 66391324
+ Zlib.adler32(test_string, 2**8).should == 701435419
+ Zlib.adler32(test_string, 2**16).should == 63966491
+ lambda { Zlib.adler32(test_string, 2**128) }.should raise_error(RangeError)
+ end
+
+ it "calculates the Adler checksum for string and initial Adler value for Bignums" do
+ test_string = "This is a test string! How exciting!%?"
+ Zlib.adler32(test_string, 2**30).should == 1137642779
+ end
+
+ it "assumes that the initial value is given to adler, if adler is omitted" do
+ orig_crc = Zlib.adler32
+ Zlib.adler32("").should == Zlib.adler32("", orig_crc)
+ Zlib.adler32(" ").should == Zlib.adler32(" ", orig_crc)
+ Zlib.adler32("123456789").should == Zlib.adler32("123456789", orig_crc)
+ Zlib.adler32("!@#\{$\}%^&**()").should == Zlib.adler32("!@#\{$\}%^&**()", orig_crc)
+ Zlib.adler32("to be or not to be" * 22).should == Zlib.adler32("to be or not to be" * 22, orig_crc)
+ Zlib.adler32("0").should == Zlib.adler32("0", orig_crc)
+ Zlib.adler32((2**32).to_s).should == Zlib.adler32((2**32).to_s, orig_crc)
+ Zlib.adler32((2**64).to_s).should == Zlib.adler32((2**64).to_s, orig_crc)
+ end
+
+ it "it returns the CRC initial value, if string is omitted" do
+ Zlib.adler32.should == 1
+ end
+
+end
diff --git a/spec/ruby/library/zlib/crc32_spec.rb b/spec/ruby/library/zlib/crc32_spec.rb
new file mode 100644
index 0000000000..22d1dac28b
--- /dev/null
+++ b/spec/ruby/library/zlib/crc32_spec.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib.crc32" do
+ it "calculates CRC checksum for string" do
+ Zlib.crc32("").should == 0
+ Zlib.crc32(" ").should == 3916222277
+ Zlib.crc32("123456789").should == 3421780262
+ Zlib.crc32("!@#\{$\}%^&**()").should == 2824518887
+ Zlib.crc32("to be or not to be" * 22).should == 1832379978
+ Zlib.crc32("0").should == 4108050209
+ Zlib.crc32((2**32).to_s).should == 3267533297
+ Zlib.crc32((2**64).to_s).should == 653721760
+ end
+
+ it "calculates CRC checksum for string and initial CRC value" do
+ test_string = "This is a test string! How exciting!%?"
+ # Zlib.crc32(test_string, -2**28).should == 3230195786
+ # Zlib.crc32(test_string, -2**20).should == 2770207303
+ # Zlib.crc32(test_string, -2**16).should == 2299432960
+ # Zlib.crc32(test_string, -2**8).should == 861809849
+ # Zlib.crc32(test_string, -1).should == 2170124077
+ Zlib.crc32(test_string, 0).should == 3864990561
+ Zlib.crc32(test_string, 1).should == 1809313411
+ Zlib.crc32(test_string, 2**8).should == 1722745982
+ Zlib.crc32(test_string, 2**16).should == 1932511220
+ lambda { Zlib.crc32(test_string, 2**128) }.should raise_error(RangeError)
+ end
+
+ it "calculates the CRC checksum for string and initial CRC value for Bignums" do
+ test_string = "This is a test string! How exciting!%?"
+ # Zlib.crc32(test_string, -2**30).should == 277228695
+ Zlib.crc32(test_string, 2**30).should == 46597132
+ end
+
+ it "assumes that the initial value is given to crc, if crc is omitted" do
+ orig_crc = Zlib.crc32
+ Zlib.crc32("").should == Zlib.crc32("", orig_crc)
+ Zlib.crc32(" ").should == Zlib.crc32(" ", orig_crc)
+ Zlib.crc32("123456789").should == Zlib.crc32("123456789", orig_crc)
+ Zlib.crc32("!@#\{$\}%^&**()").should == Zlib.crc32("!@#\{$\}%^&**()", orig_crc)
+ Zlib.crc32("to be or not to be" * 22).should == Zlib.crc32("to be or not to be" * 22, orig_crc)
+ Zlib.crc32("0").should == Zlib.crc32("0", orig_crc)
+ Zlib.crc32((2**32).to_s).should == Zlib.crc32((2**32).to_s, orig_crc)
+ Zlib.crc32((2**64).to_s).should == Zlib.crc32((2**64).to_s, orig_crc)
+ end
+
+ it "it returns the CRC initial value, if string is omitted" do
+ Zlib.crc32.should == 0
+ end
+
+end
diff --git a/spec/ruby/library/zlib/crc_table_spec.rb b/spec/ruby/library/zlib/crc_table_spec.rb
new file mode 100644
index 0000000000..22aaa32233
--- /dev/null
+++ b/spec/ruby/library/zlib/crc_table_spec.rb
@@ -0,0 +1,75 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require "zlib"
+
+describe "Zlib.crc_table" do
+
+ it "returns the same value as zlib's get_crc_table()" do
+ Zlib.crc_table.should == [
+ 0, 1996959894, 3993919788, 2567524794,
+ 124634137, 1886057615, 3915621685, 2657392035,
+ 249268274, 2044508324, 3772115230, 2547177864,
+ 162941995, 2125561021, 3887607047, 2428444049,
+ 498536548, 1789927666, 4089016648, 2227061214,
+ 450548861, 1843258603, 4107580753, 2211677639,
+ 325883990, 1684777152, 4251122042, 2321926636,
+ 335633487, 1661365465, 4195302755, 2366115317,
+ 997073096, 1281953886, 3579855332, 2724688242,
+ 1006888145, 1258607687, 3524101629, 2768942443,
+ 901097722, 1119000684, 3686517206, 2898065728,
+ 853044451, 1172266101, 3705015759, 2882616665,
+ 651767980, 1373503546, 3369554304, 3218104598,
+ 565507253, 1454621731, 3485111705, 3099436303,
+ 671266974, 1594198024, 3322730930, 2970347812,
+ 795835527, 1483230225, 3244367275, 3060149565,
+ 1994146192, 31158534, 2563907772, 4023717930,
+ 1907459465, 112637215, 2680153253, 3904427059,
+ 2013776290, 251722036, 2517215374, 3775830040,
+ 2137656763, 141376813, 2439277719, 3865271297,
+ 1802195444, 476864866, 2238001368, 4066508878,
+ 1812370925, 453092731, 2181625025, 4111451223,
+ 1706088902, 314042704, 2344532202, 4240017532,
+ 1658658271, 366619977, 2362670323, 4224994405,
+ 1303535960, 984961486, 2747007092, 3569037538,
+ 1256170817, 1037604311, 2765210733, 3554079995,
+ 1131014506, 879679996, 2909243462, 3663771856,
+ 1141124467, 855842277, 2852801631, 3708648649,
+ 1342533948, 654459306, 3188396048, 3373015174,
+ 1466479909, 544179635, 3110523913, 3462522015,
+ 1591671054, 702138776, 2966460450, 3352799412,
+ 1504918807, 783551873, 3082640443, 3233442989,
+ 3988292384, 2596254646, 62317068, 1957810842,
+ 3939845945, 2647816111, 81470997, 1943803523,
+ 3814918930, 2489596804, 225274430, 2053790376,
+ 3826175755, 2466906013, 167816743, 2097651377,
+ 4027552580, 2265490386, 503444072, 1762050814,
+ 4150417245, 2154129355, 426522225, 1852507879,
+ 4275313526, 2312317920, 282753626, 1742555852,
+ 4189708143, 2394877945, 397917763, 1622183637,
+ 3604390888, 2714866558, 953729732, 1340076626,
+ 3518719985, 2797360999, 1068828381, 1219638859,
+ 3624741850, 2936675148, 906185462, 1090812512,
+ 3747672003, 2825379669, 829329135, 1181335161,
+ 3412177804, 3160834842, 628085408, 1382605366,
+ 3423369109, 3138078467, 570562233, 1426400815,
+ 3317316542, 2998733608, 733239954, 1555261956,
+ 3268935591, 3050360625, 752459403, 1541320221,
+ 2607071920, 3965973030, 1969922972, 40735498,
+ 2617837225, 3943577151, 1913087877, 83908371,
+ 2512341634, 3803740692, 2075208622, 213261112,
+ 2463272603, 3855990285, 2094854071, 198958881,
+ 2262029012, 4057260610, 1759359992, 534414190,
+ 2176718541, 4139329115, 1873836001, 414664567,
+ 2282248934, 4279200368, 1711684554, 285281116,
+ 2405801727, 4167216745, 1634467795, 376229701,
+ 2685067896, 3608007406, 1308918612, 956543938,
+ 2808555105, 3495958263, 1231636301, 1047427035,
+ 2932959818, 3654703836, 1088359270, 936918000,
+ 2847714899, 3736837829, 1202900863, 817233897,
+ 3183342108, 3401237130, 1404277552, 615818150,
+ 3134207493, 3453421203, 1423857449, 601450431,
+ 3009837614, 3294710456, 1567103746, 711928724,
+ 3020668471, 3272380065, 1510334235, 755167117,
+ ]
+ end
+
+end
diff --git a/spec/ruby/library/zlib/deflate/append_spec.rb b/spec/ruby/library/zlib/deflate/append_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/deflate/append_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/deflate/deflate_spec.rb b/spec/ruby/library/zlib/deflate/deflate_spec.rb
new file mode 100644
index 0000000000..44b3389701
--- /dev/null
+++ b/spec/ruby/library/zlib/deflate/deflate_spec.rb
@@ -0,0 +1,128 @@
+require 'zlib'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "Zlib::Deflate.deflate" do
+ it "deflates some data" do
+ data = Array.new(10,0).pack('C*')
+
+ zipped = Zlib::Deflate.deflate data
+
+ zipped.should == [120, 156, 99, 96, 128, 1, 0, 0, 10, 0, 1].pack('C*')
+ end
+
+ it "deflates lots of data" do
+ data = "\000" * 32 * 1024
+
+ zipped = Zlib::Deflate.deflate data
+
+ zipped.should == ([120, 156, 237, 193, 1, 1, 0, 0] +
+ [0, 128, 144, 254, 175, 238, 8, 10] +
+ Array.new(31, 0) +
+ [24, 128, 0, 0, 1]).pack('C*')
+ end
+
+ it "deflates chunked data" do
+ random_generator = Random.new(0)
+ deflated = ''
+
+ Zlib.deflate(random_generator.bytes(20000)) do |chunk|
+ deflated << chunk
+ end
+
+ deflated.length.should == 20016
+ end
+end
+
+describe "Zlib::Deflate#deflate" do
+ before :each do
+ @deflator = Zlib::Deflate.new
+ end
+
+ it "deflates some data" do
+ data = "\000" * 10
+
+ zipped = @deflator.deflate data, Zlib::FINISH
+ @deflator.finish
+
+ zipped.should == [120, 156, 99, 96, 128, 1, 0, 0, 10, 0, 1].pack('C*')
+ end
+
+ it "deflates lots of data" do
+ data = "\000" * 32 * 1024
+
+ zipped = @deflator.deflate data, Zlib::FINISH
+ @deflator.finish
+
+ zipped.should == ([120, 156, 237, 193, 1, 1, 0, 0] +
+ [0, 128, 144, 254, 175, 238, 8, 10] +
+ Array.new(31, 0) +
+ [24, 128, 0, 0, 1]).pack('C*')
+ end
+end
+
+describe "Zlib::Deflate#deflate" do
+
+ before :each do
+ @deflator = Zlib::Deflate.new
+ @random_generator = Random.new(0)
+ @original = ''
+ @chunks = []
+ end
+
+ describe "without break" do
+
+ before do
+ 2.times do
+ @input = @random_generator.bytes(20000)
+ @original << @input
+ @deflator.deflate(@input) do |chunk|
+ @chunks << chunk
+ end
+ end
+ end
+
+ it "deflates chunked data" do
+ @deflator.finish
+ @chunks.map { |chunk| chunk.length }.should == [16384, 16384]
+ end
+
+ it "deflates chunked data with final chunk" do
+ final = @deflator.finish
+ final.length.should == 7253
+ end
+
+ it "deflates chunked data without errors" do
+ final = @deflator.finish
+ @chunks << final
+ @original.should == Zlib.inflate(@chunks.join)
+ end
+
+ end
+
+ describe "with break" do
+ before :each do
+ @input = @random_generator.bytes(20000)
+ @deflator.deflate(@input) do |chunk|
+ @chunks << chunk
+ break
+ end
+ end
+
+ it "deflates only first chunk" do
+ @deflator.finish
+ @chunks.map { |chunk| chunk.length }.should == [16384]
+ end
+
+ it "deflates chunked data with final chunk" do
+ final = @deflator.finish
+ final.length.should == 3632
+ end
+
+ it "deflates chunked data without errors" do
+ final = @deflator.finish
+ @chunks << final
+ @input.should == Zlib.inflate(@chunks.join)
+ end
+
+ end
+end
diff --git a/spec/ruby/library/zlib/deflate/flush_spec.rb b/spec/ruby/library/zlib/deflate/flush_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/deflate/flush_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/deflate/new_spec.rb b/spec/ruby/library/zlib/deflate/new_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/deflate/new_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/deflate/params_spec.rb b/spec/ruby/library/zlib/deflate/params_spec.rb
new file mode 100644
index 0000000000..59b1353c07
--- /dev/null
+++ b/spec/ruby/library/zlib/deflate/params_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib::Deflate#params" do
+ it "changes the deflate parameters" do
+ data = 'abcdefghijklm'
+
+ d = Zlib::Deflate.new Zlib::NO_COMPRESSION, Zlib::MAX_WBITS,
+ Zlib::DEF_MEM_LEVEL, Zlib::DEFAULT_STRATEGY
+
+ d << data.slice!(0..10)
+ d.params Zlib::BEST_COMPRESSION, Zlib::DEFAULT_STRATEGY
+ d << data
+
+ Zlib::Inflate.inflate(d.finish).should == 'abcdefghijklm'
+ end
+end
diff --git a/spec/ruby/library/zlib/deflate/set_dictionary_spec.rb b/spec/ruby/library/zlib/deflate/set_dictionary_spec.rb
new file mode 100644
index 0000000000..c5c62d9529
--- /dev/null
+++ b/spec/ruby/library/zlib/deflate/set_dictionary_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib::Deflate#set_dictionary" do
+ it "sets the dictionary" do
+ d = Zlib::Deflate.new
+ d.set_dictionary 'aaaaaaaaaa'
+ d << 'abcdefghij'
+
+ d.finish.should == [120, 187, 20, 225, 3, 203, 75, 76,
+ 74, 78, 73, 77, 75, 207, 200, 204,
+ 2, 0, 21, 134, 3, 248].pack('C*')
+ end
+end
+
diff --git a/spec/ruby/library/zlib/gzipfile/close_spec.rb b/spec/ruby/library/zlib/gzipfile/close_spec.rb
new file mode 100644
index 0000000000..9486d6b9ec
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/close_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "Zlib::GzipFile#close" do
+ it "finishes the stream and closes the io" do
+ io = StringIO.new "".b
+ Zlib::GzipWriter.wrap io do |gzio|
+ gzio.close
+
+ gzio.closed?.should == true
+
+ lambda { gzio.orig_name }.should \
+ raise_error(Zlib::GzipFile::Error, 'closed gzip stream')
+ lambda { gzio.comment }.should \
+ raise_error(Zlib::GzipFile::Error, 'closed gzip stream')
+ end
+
+ io.string[10..-1].should == ([3] + Array.new(9,0)).pack('C*')
+ end
+end
+
diff --git a/spec/ruby/library/zlib/gzipfile/closed_spec.rb b/spec/ruby/library/zlib/gzipfile/closed_spec.rb
new file mode 100644
index 0000000000..69785bc41c
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/closed_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "Zlib::GzipFile#closed?" do
+ it "returns the closed status" do
+ io = StringIO.new
+ Zlib::GzipWriter.wrap io do |gzio|
+ gzio.closed?.should == false
+
+ gzio.close
+
+ gzio.closed?.should == true
+ end
+ end
+end
+
diff --git a/spec/ruby/library/zlib/gzipfile/comment_spec.rb b/spec/ruby/library/zlib/gzipfile/comment_spec.rb
new file mode 100644
index 0000000000..638e85a4a7
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/comment_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "Zlib::GzipFile#comment" do
+ before :each do
+ @io = StringIO.new
+ end
+
+ it "returns the name" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.comment = 'name'
+
+ gzio.comment.should == 'name'
+ end
+ end
+
+ it "raises an error on a closed stream" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.close
+
+ lambda { gzio.comment }.should \
+ raise_error(Zlib::GzipFile::Error, 'closed gzip stream')
+ end
+ end
+end
+
diff --git a/spec/ruby/library/zlib/gzipfile/crc_spec.rb b/spec/ruby/library/zlib/gzipfile/crc_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/crc_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipfile/finish_spec.rb b/spec/ruby/library/zlib/gzipfile/finish_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/finish_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipfile/level_spec.rb b/spec/ruby/library/zlib/gzipfile/level_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/level_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipfile/mtime_spec.rb b/spec/ruby/library/zlib/gzipfile/mtime_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/mtime_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipfile/orig_name_spec.rb b/spec/ruby/library/zlib/gzipfile/orig_name_spec.rb
new file mode 100644
index 0000000000..42a3b2f376
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/orig_name_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "Zlib::GzipFile#orig_name" do
+ before :each do
+ @io = StringIO.new
+ end
+
+ it "returns the name" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.orig_name = 'name'
+
+ gzio.orig_name.should == 'name'
+ end
+ end
+
+ it "raises an error on a closed stream" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.close
+
+ lambda { gzio.orig_name }.should \
+ raise_error(Zlib::GzipFile::Error, 'closed gzip stream')
+ end
+ end
+end
+
diff --git a/spec/ruby/library/zlib/gzipfile/os_code_spec.rb b/spec/ruby/library/zlib/gzipfile/os_code_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/os_code_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipfile/sync_spec.rb b/spec/ruby/library/zlib/gzipfile/sync_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/sync_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipfile/to_io_spec.rb b/spec/ruby/library/zlib/gzipfile/to_io_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/to_io_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipfile/wrap_spec.rb b/spec/ruby/library/zlib/gzipfile/wrap_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipfile/wrap_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipreader/each_byte_spec.rb b/spec/ruby/library/zlib/gzipreader/each_byte_spec.rb
new file mode 100644
index 0000000000..6da9ac8323
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/each_byte_spec.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "GzipReader#each_byte" do
+
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+
+ @io = StringIO.new @zip
+ ScratchPad.clear
+ end
+
+ it "calls the given block for each byte in the stream, passing the byte as an argument" do
+ gz = Zlib::GzipReader.new @io
+
+ ScratchPad.record []
+ gz.each_byte { |b| ScratchPad << b }
+
+ ScratchPad.recorded.should == [49, 50, 51, 52, 53, 97, 98, 99, 100, 101]
+ end
+
+ it "returns an enumerator, which yields each byte in the stream, when no block is passed" do
+ gz = Zlib::GzipReader.new @io
+ enum = gz.each_byte
+
+ ScratchPad.record []
+ while true
+ begin
+ ScratchPad << enum.next
+ rescue StopIteration
+ break
+ end
+ end
+
+ ScratchPad.recorded.should == [49, 50, 51, 52, 53, 97, 98, 99, 100, 101]
+ end
+
+ it "increments position before calling the block" do
+ gz = Zlib::GzipReader.new @io
+
+ i = 1
+ gz.each_byte do |ignore|
+ gz.pos.should == i
+ i += 1
+ end
+ end
+
+end
diff --git a/spec/ruby/library/zlib/gzipreader/each_line_spec.rb b/spec/ruby/library/zlib/gzipreader/each_line_spec.rb
new file mode 100644
index 0000000000..7ff116a258
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/each_line_spec.rb
@@ -0,0 +1,5 @@
+require File.expand_path('../shared/each', __FILE__)
+
+describe "GzipReader#each_line" do
+ it_behaves_like :gzipreader_each, :each_line
+end
diff --git a/spec/ruby/library/zlib/gzipreader/each_spec.rb b/spec/ruby/library/zlib/gzipreader/each_spec.rb
new file mode 100644
index 0000000000..dd780e4083
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/each_spec.rb
@@ -0,0 +1,5 @@
+require File.expand_path('../shared/each', __FILE__)
+
+describe "GzipReader#each" do
+ it_behaves_like :gzipreader_each, :each
+end
diff --git a/spec/ruby/library/zlib/gzipreader/eof_spec.rb b/spec/ruby/library/zlib/gzipreader/eof_spec.rb
new file mode 100644
index 0000000000..446cbfec37
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/eof_spec.rb
@@ -0,0 +1,56 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "GzipReader#eof?" do
+
+ before :each do
+ @data = '{"a":1234}'
+ @zip = [31, 139, 8, 0, 0, 0, 0, 0, 0, 3, 171, 86, 74, 84, 178, 50,
+ 52, 50, 54, 169, 5, 0, 196, 20, 118, 213, 10, 0, 0, 0].pack('C*')
+ @io = StringIO.new @zip
+ end
+
+ it "returns true when at EOF" do
+ gz = Zlib::GzipReader.new @io
+ gz.eof?.should be_false
+ gz.read
+ gz.eof?.should be_true
+ end
+
+ it "returns true when at EOF with the exact length of uncompressed data" do
+ gz = Zlib::GzipReader.new @io
+ gz.eof?.should be_false
+ gz.read(10)
+ gz.eof?.should be_true
+ end
+
+ it "returns true when at EOF with a length greater than the size of uncompressed data" do
+ gz = Zlib::GzipReader.new @io
+ gz.eof?.should be_false
+ gz.read(11)
+ gz.eof?.should be_true
+ end
+
+ it "returns false when at EOF when there's data left in the buffer to read" do
+ gz = Zlib::GzipReader.new @io
+ gz.read(9)
+ gz.eof?.should be_false
+ gz.read
+ gz.eof?.should be_true
+ end
+
+ # This is especially important for JRuby, since eof? there
+ # is more than just a simple accessor.
+ it "does not affect the reading data" do
+ gz = Zlib::GzipReader.new @io
+ 0.upto(9) do |i|
+ gz.eof?.should be_false
+ gz.read(1).should == @data[i, 1]
+ end
+ gz.eof?.should be_true
+ gz.read().should == ""
+ gz.eof?.should be_true
+ end
+
+end
diff --git a/spec/ruby/library/zlib/gzipreader/getc_spec.rb b/spec/ruby/library/zlib/gzipreader/getc_spec.rb
new file mode 100644
index 0000000000..a3c4aecf76
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/getc_spec.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "GzipReader#getc" do
+
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+ @io = StringIO.new @zip
+ end
+
+ it "returns the next character from the stream" do
+ gz = Zlib::GzipReader.new @io
+ gz.pos.should == 0
+
+ gz.getc.should == '1'
+ gz.getc.should == '2'
+ gz.getc.should == '3'
+ gz.getc.should == '4'
+ gz.getc.should == '5'
+ end
+
+ it "increments position" do
+ gz = Zlib::GzipReader.new @io
+ (0..@data.size).each do |i|
+ gz.pos.should == i
+ gz.getc
+ end
+ end
+
+ it "returns nil at the end of the stream" do
+ gz = Zlib::GzipReader.new @io
+ gz.read
+ pos = gz.pos
+ gz.getc.should be_nil
+ gz.pos.should == pos
+ end
+
+end
diff --git a/spec/ruby/library/zlib/gzipreader/gets_spec.rb b/spec/ruby/library/zlib/gzipreader/gets_spec.rb
new file mode 100644
index 0000000000..d49adc2850
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/gets_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+require 'stringio'
+
+describe 'GzipReader#gets' do
+ describe 'with "" separator' do
+ it 'reads paragraphs skipping newlines' do
+ # gz contains "\n\n\n\n\n123\n45\n\n\n\n\nabc\nde\n\n\n\n\n"
+ gz = Zlib::GzipReader.new(
+ StringIO.new(
+ [31, 139, 8, 0, 223, 152, 48, 89, 0, 3, 227, 226, 2, 2, 67, 35,
+ 99, 46, 19, 83, 16, 139, 43, 49, 41, 153, 43, 37, 21, 204, 4, 0,
+ 32, 119, 45, 184, 27, 0, 0, 0].pack('C*')
+ )
+ )
+
+ gz.gets('').should == "123\n45\n\n"
+ gz.gets('').should == "abc\nde\n\n"
+ gz.eof?.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/zlib/gzipreader/lineno_spec.rb b/spec/ruby/library/zlib/gzipreader/lineno_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/lineno_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipreader/new_spec.rb b/spec/ruby/library/zlib/gzipreader/new_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/new_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipreader/open_spec.rb b/spec/ruby/library/zlib/gzipreader/open_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/open_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipreader/pos_spec.rb b/spec/ruby/library/zlib/gzipreader/pos_spec.rb
new file mode 100644
index 0000000000..66fbf388d8
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/pos_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "GzipReader#pos" do
+
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+ @io = StringIO.new @zip
+ end
+
+ it "returns the position" do
+ gz = Zlib::GzipReader.new @io
+
+ gz.pos.should == 0
+
+ gz.read 5
+ gz.pos.should == 5
+
+ gz.read
+ gz.pos.should == @data.length
+ end
+
+end
+
diff --git a/spec/ruby/library/zlib/gzipreader/read_spec.rb b/spec/ruby/library/zlib/gzipreader/read_spec.rb
new file mode 100644
index 0000000000..337f507502
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/read_spec.rb
@@ -0,0 +1,68 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "GzipReader#read" do
+
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+ @io = StringIO.new @zip
+ end
+
+ it "with no arguments reads the entire content of a gzip file" do
+ gz = Zlib::GzipReader.new @io
+ gz.read.should == @data
+ end
+
+ it "with nil length argument reads the entire content of a gzip file" do
+ gz = Zlib::GzipReader.new @io
+ gz.read(nil).should == @data
+ end
+
+ it "reads the contents up to a certain size" do
+ gz = Zlib::GzipReader.new @io
+ gz.read(5).should == @data[0...5]
+ gz.read(5).should == @data[5...10]
+ end
+
+ it "does not accept a negative length to read" do
+ gz = Zlib::GzipReader.new @io
+ lambda {
+ gz.read(-1)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "returns an empty string if a 0 length is given" do
+ gz = Zlib::GzipReader.new @io
+ gz.read(0).should == ""
+ end
+
+ it "respects :external_encoding option" do
+ gz = Zlib::GzipReader.new(@io, external_encoding: 'UTF-8')
+ gz.read.encoding.should == Encoding::UTF_8
+
+ @io.rewind
+ gz = Zlib::GzipReader.new(@io, external_encoding: 'UTF-16LE')
+ gz.read.encoding.should == Encoding::UTF_16LE
+ end
+
+ describe "at the end of data" do
+ it "returns empty string if length prameter is not specified or 0" do
+ gz = Zlib::GzipReader.new @io
+ gz.read # read till the end
+ gz.read(0).should == ""
+ gz.read().should == ""
+ gz.read(nil).should == ""
+ end
+
+ it "returns nil if length prameter is positive" do
+ gz = Zlib::GzipReader.new @io
+ gz.read # read till the end
+ gz.read(1).should be_nil
+ gz.read(2**16).should be_nil
+ end
+ end
+
+end
diff --git a/spec/ruby/library/zlib/gzipreader/readchar_spec.rb b/spec/ruby/library/zlib/gzipreader/readchar_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/readchar_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipreader/readline_spec.rb b/spec/ruby/library/zlib/gzipreader/readline_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/readline_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipreader/readlines_spec.rb b/spec/ruby/library/zlib/gzipreader/readlines_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/readlines_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipreader/readpartial_spec.rb b/spec/ruby/library/zlib/gzipreader/readpartial_spec.rb
new file mode 100644
index 0000000000..2cdef54fd1
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/readpartial_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe 'GzipReader#readpartial' do
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+ @io = StringIO.new(@zip)
+ end
+
+ it 'accepts nil buffer' do
+ gz = Zlib::GzipReader.new(@io)
+ gz.readpartial(5, nil).should == '12345'
+ end
+end
diff --git a/spec/ruby/library/zlib/gzipreader/rewind_spec.rb b/spec/ruby/library/zlib/gzipreader/rewind_spec.rb
new file mode 100644
index 0000000000..70bee3372d
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/rewind_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "GzipReader#rewind" do
+
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+ @io = StringIO.new @zip
+ ScratchPad.clear
+ end
+
+ it "resets the position of the stream pointer" do
+ gz = Zlib::GzipReader.new @io
+ gz.read
+ gz.pos.should == @data.length
+
+ gz.rewind
+ gz.pos.should == 0
+ gz.lineno.should == 0
+ end
+
+ it "resets the position of the stream pointer to data previously read" do
+ gz = Zlib::GzipReader.new @io
+ first_read = gz.read
+ gz.rewind
+ first_read.should == gz.read
+ end
+
+ it "invokes seek method on the associated IO object" do
+ # first, prepare the mock object:
+ (obj = mock("io")).should_receive(:get_io).any_number_of_times.and_return(@io)
+ def obj.read(args); get_io.read(args); end
+ def obj.seek(pos, whence = 0)
+ ScratchPad.record :seek
+ get_io.seek(pos, whence)
+ end
+
+ gz = Zlib::GzipReader.new(obj)
+ gz.rewind()
+
+ ScratchPad.recorded.should == :seek
+ gz.pos.should == 0
+ gz.read.should == "12345abcde"
+ end
+end
diff --git a/spec/ruby/library/zlib/gzipreader/shared/each.rb b/spec/ruby/library/zlib/gzipreader/shared/each.rb
new file mode 100644
index 0000000000..47cd284b6a
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/shared/each.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe :gzipreader_each, shared: true do
+
+ before :each do
+ @data = "firstline\nsecondline\n\nforthline"
+ @zip = [31, 139, 8, 0, 244, 125, 128, 88, 2, 255, 75, 203, 44, 42, 46, 201,
+ 201, 204, 75, 229, 42, 78, 77, 206, 207, 75, 1, 51, 185, 210,242,
+ 139, 74, 50, 64, 76, 0, 180, 54, 61, 111, 31, 0, 0, 0].pack('C*')
+
+ @io = StringIO.new @zip
+ @gzreader = Zlib::GzipReader.new @io
+ end
+
+ after :each do
+ ScratchPad.clear
+ end
+
+ it "calls the given block for each line in the stream, passing the line as an argument" do
+ ScratchPad.record []
+ @gzreader.send(@method) { |b| ScratchPad << b }
+
+ ScratchPad.recorded.should == ["firstline\n", "secondline\n", "\n", "forthline"]
+ end
+
+ it "returns an enumerator, which yields each byte in the stream, when no block is passed" do
+ enum = @gzreader.send(@method)
+
+ ScratchPad.record []
+ while true
+ begin
+ ScratchPad << enum.next
+ rescue StopIteration
+ break
+ end
+ end
+
+ ScratchPad.recorded.should == ["firstline\n", "secondline\n", "\n", "forthline"]
+ end
+
+ it "increments position before calling the block" do
+ i = 0
+ @gzreader.send(@method) do |line|
+ i += line.length
+ @gzreader.pos.should == i
+ end
+ end
+
+end
diff --git a/spec/ruby/library/zlib/gzipreader/tell_spec.rb b/spec/ruby/library/zlib/gzipreader/tell_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/tell_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipreader/ungetbyte_spec.rb b/spec/ruby/library/zlib/gzipreader/ungetbyte_spec.rb
new file mode 100644
index 0000000000..16f1c12272
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/ungetbyte_spec.rb
@@ -0,0 +1,122 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe 'GzipReader#ungetbyte' do
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+ @io = StringIO.new @zip
+ end
+
+ describe 'at the start of the stream' do
+ before :each do
+ @gz = Zlib::GzipReader.new(@io)
+ end
+
+ describe 'with an integer' do
+ it 'prepends the byte to the stream' do
+ @gz.ungetbyte 0x21
+ @gz.read.should == '!12345abcde'
+ end
+
+ ruby_bug "#13616", ""..."2.6" do
+ it 'decrements pos' do
+ @gz.ungetbyte 0x21
+ @gz.pos.should == -1
+ end
+ end
+ end
+
+ quarantine! do # https://bugs.ruby-lang.org/issues/13675
+ describe 'with nil' do
+ it 'does not prepend anything to the stream' do
+ @gz.ungetbyte nil
+ @gz.read.should == '12345abcde'
+ end
+
+ it 'does not decrement pos' do
+ @gz.ungetbyte nil
+ @gz.pos.should == 0
+ end
+ end
+ end
+ end
+
+ describe 'in the middle of the stream' do
+ before :each do
+ @gz = Zlib::GzipReader.new(@io)
+ @gz.read 5
+ end
+
+ describe 'with an integer' do
+ it 'inserts the corresponding character into the stream' do
+ @gz.ungetbyte 0x21
+ @gz.read.should == '!abcde'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetbyte 0x21
+ @gz.pos.should == 4
+ end
+ end
+
+ quarantine! do # https://bugs.ruby-lang.org/issues/13675
+ describe 'with nil' do
+ it 'does not insert anything into the stream' do
+ @gz.ungetbyte nil
+ @gz.read.should == 'abcde'
+ end
+
+ it 'does not decrement pos' do
+ @gz.ungetbyte nil
+ @gz.pos.should == 5
+ end
+ end
+ end
+ end
+
+ describe 'at the end of the stream' do
+ before :each do
+ @gz = Zlib::GzipReader.new(@io)
+ @gz.read
+ end
+
+ describe 'with an integer' do
+ it 'appends the corresponding character to the stream' do
+ @gz.ungetbyte 0x21
+ @gz.read.should == '!'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetbyte 0x21
+ @gz.pos.should == 9
+ end
+
+ it 'makes eof? false' do
+ @gz.ungetbyte 0x21
+ @gz.eof?.should be_false
+ end
+ end
+
+ quarantine! do # https://bugs.ruby-lang.org/issues/13675
+ describe 'with nil' do
+ it 'does not append anything to the stream' do
+ @gz.ungetbyte nil
+ @gz.read.should == ''
+ end
+
+ it 'does not decrement pos' do
+ @gz.ungetbyte nil
+ @gz.pos.should == 10
+ end
+
+ it 'does not make eof? false' do
+ @gz.ungetbyte nil
+ @gz.eof?.should be_true
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/zlib/gzipreader/ungetc_spec.rb b/spec/ruby/library/zlib/gzipreader/ungetc_spec.rb
new file mode 100644
index 0000000000..2d218e8d19
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/ungetc_spec.rb
@@ -0,0 +1,292 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe 'GzipReader#ungetc' do
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+ @io = StringIO.new @zip
+ end
+
+ describe 'at the start of the stream' do
+ before :each do
+ @gz = Zlib::GzipReader.new(@io, external_encoding: Encoding::UTF_8)
+ end
+
+ describe 'with a single-byte character' do
+ it 'prepends the character to the stream' do
+ @gz.ungetc 'x'
+ @gz.read.should == 'x12345abcde'
+ end
+
+ ruby_bug "#13616", ""..."2.6" do
+ it 'decrements pos' do
+ @gz.ungetc 'x'
+ @gz.pos.should == -1
+ end
+ end
+ end
+
+ describe 'with a multi-byte character' do
+ it 'prepends the character to the stream' do
+ @gz.ungetc 'ŷ'
+ @gz.read.should == 'ŷ12345abcde'
+ end
+
+ ruby_bug "#13616", ""..."2.6" do
+ it 'decrements pos' do
+ @gz.ungetc 'ŷ'
+ @gz.pos.should == -2
+ end
+ end
+ end
+
+ describe 'with a multi-character string' do
+ it 'prepends the characters to the stream' do
+ @gz.ungetc 'xŷž'
+ @gz.read.should == 'xŷž12345abcde'
+ end
+
+ ruby_bug "#13616", ""..."2.6" do
+ it 'decrements pos' do
+ @gz.ungetc 'xŷž'
+ @gz.pos.should == -5
+ end
+ end
+ end
+
+ describe 'with an integer' do
+ it 'prepends the corresponding character to the stream' do
+ @gz.ungetc 0x21
+ @gz.read.should == '!12345abcde'
+ end
+
+ ruby_bug "#13616", ""..."2.6" do
+ it 'decrements pos' do
+ @gz.ungetc 0x21
+ @gz.pos.should == -1
+ end
+ end
+ end
+
+ describe 'with an empty string' do
+ it 'does not prepend anything to the stream' do
+ @gz.ungetc ''
+ @gz.read.should == '12345abcde'
+ end
+
+ it 'does not decrement pos' do
+ @gz.ungetc ''
+ @gz.pos.should == 0
+ end
+ end
+
+ quarantine! do # https://bugs.ruby-lang.org/issues/13675
+ describe 'with nil' do
+ it 'does not prepend anything to the stream' do
+ @gz.ungetc nil
+ @gz.read.should == '12345abcde'
+ end
+
+ it 'does not decrement pos' do
+ @gz.ungetc nil
+ @gz.pos.should == 0
+ end
+ end
+ end
+ end
+
+ describe 'in the middle of the stream' do
+ before :each do
+ @gz = Zlib::GzipReader.new(@io, external_encoding: Encoding::UTF_8)
+ @gz.read 5
+ end
+
+ describe 'with a single-byte character' do
+ it 'inserts the character into the stream' do
+ @gz.ungetc 'x'
+ @gz.read.should == 'xabcde'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetc 'x'
+ @gz.pos.should == 4
+ end
+ end
+
+ describe 'with a multi-byte character' do
+ it 'inserts the character into the stream' do
+ @gz.ungetc 'ŷ'
+ @gz.read.should == 'ŷabcde'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetc 'ŷ'
+ @gz.pos.should == 3
+ end
+ end
+
+ describe 'with a multi-character string' do
+ it 'inserts the characters into the stream' do
+ @gz.ungetc 'xŷž'
+ @gz.read.should == 'xŷžabcde'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetc 'xŷž'
+ @gz.pos.should == 0
+ end
+ end
+
+ describe 'with an integer' do
+ it 'inserts the corresponding character into the stream' do
+ @gz.ungetc 0x21
+ @gz.read.should == '!abcde'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetc 0x21
+ @gz.pos.should == 4
+ end
+ end
+
+ describe 'with an empty string' do
+ it 'does not insert anything into the stream' do
+ @gz.ungetc ''
+ @gz.read.should == 'abcde'
+ end
+
+ it 'does not decrement pos' do
+ @gz.ungetc ''
+ @gz.pos.should == 5
+ end
+ end
+
+ quarantine! do # https://bugs.ruby-lang.org/issues/13675
+ describe 'with nil' do
+ it 'does not insert anything into the stream' do
+ @gz.ungetc nil
+ @gz.read.should == 'abcde'
+ end
+
+ it 'does not decrement pos' do
+ @gz.ungetc nil
+ @gz.pos.should == 5
+ end
+ end
+ end
+ end
+
+ describe 'at the end of the stream' do
+ before :each do
+ @gz = Zlib::GzipReader.new(@io, external_encoding: Encoding::UTF_8)
+ @gz.read
+ end
+
+ describe 'with a single-byte character' do
+ it 'appends the character to the stream' do
+ @gz.ungetc 'x'
+ @gz.read.should == 'x'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetc 'x'
+ @gz.pos.should == 9
+ end
+
+ it 'makes eof? false' do
+ @gz.ungetc 'x'
+ @gz.eof?.should be_false
+ end
+ end
+
+ describe 'with a multi-byte character' do
+ it 'appends the character to the stream' do
+ @gz.ungetc 'ŷ'
+ @gz.read.should == 'ŷ'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetc 'ŷ'
+ @gz.pos.should == 8
+ end
+
+ it 'makes eof? false' do
+ @gz.ungetc 'ŷ'
+ @gz.eof?.should be_false
+ end
+ end
+
+ describe 'with a multi-character string' do
+ it 'appends the characters to the stream' do
+ @gz.ungetc 'xŷž'
+ @gz.read.should == 'xŷž'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetc 'xŷž'
+ @gz.pos.should == 5
+ end
+
+ it 'makes eof? false' do
+ @gz.ungetc 'xŷž'
+ @gz.eof?.should be_false
+ end
+ end
+
+ describe 'with an integer' do
+ it 'appends the corresponding character to the stream' do
+ @gz.ungetc 0x21
+ @gz.read.should == '!'
+ end
+
+ it 'decrements pos' do
+ @gz.ungetc 0x21
+ @gz.pos.should == 9
+ end
+
+ it 'makes eof? false' do
+ @gz.ungetc 0x21
+ @gz.eof?.should be_false
+ end
+ end
+
+ describe 'with an empty string' do
+ it 'does not append anything to the stream' do
+ @gz.ungetc ''
+ @gz.read.should == ''
+ end
+
+ it 'does not decrement pos' do
+ @gz.ungetc ''
+ @gz.pos.should == 10
+ end
+
+ it 'does not make eof? false' do
+ @gz.ungetc ''
+ @gz.eof?.should be_true
+ end
+ end
+
+ quarantine! do # https://bugs.ruby-lang.org/issues/13675
+ describe 'with nil' do
+ it 'does not append anything to the stream' do
+ @gz.ungetc nil
+ @gz.read.should == ''
+ end
+
+ it 'does not decrement pos' do
+ @gz.ungetc nil
+ @gz.pos.should == 10
+ end
+
+ it 'does not make eof? false' do
+ @gz.ungetc nil
+ @gz.eof?.should be_true
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/zlib/gzipreader/unused_spec.rb b/spec/ruby/library/zlib/gzipreader/unused_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/unused_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/append_spec.rb b/spec/ruby/library/zlib/gzipwriter/append_spec.rb
new file mode 100644
index 0000000000..922e921840
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/append_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "Zlib::GzipWriter#<<" do
+ before :each do
+ @io = StringIO.new
+ end
+
+ it "returns self" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ (gzio << "test").should equal(gzio)
+ end
+ end
+
+ it "needs to be reviewed for spec completeness"
+end
diff --git a/spec/ruby/library/zlib/gzipwriter/comment_spec.rb b/spec/ruby/library/zlib/gzipwriter/comment_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/comment_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/flush_spec.rb b/spec/ruby/library/zlib/gzipwriter/flush_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/flush_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/mtime_spec.rb b/spec/ruby/library/zlib/gzipwriter/mtime_spec.rb
new file mode 100644
index 0000000000..af7a4ac735
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/mtime_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "Zlib::GzipWriter#mtime=" do
+ before :each do
+ @io = StringIO.new
+ end
+
+ it "sets mtime using Integer" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.mtime = 1
+
+ gzio.mtime.should == Time.at(1)
+ end
+
+ @io.string[4, 4].should == [1,0,0,0].pack('C*')
+ end
+
+ it "sets mtime using Time" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.mtime = Time.at 1
+
+ gzio.mtime.should == Time.at(1)
+ end
+
+ @io.string[4, 4].should == [1,0,0,0].pack('C*')
+ end
+
+ it "raises if the header was written" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.write ''
+
+ lambda { gzio.mtime = nil }.should \
+ raise_error(Zlib::GzipFile::Error, 'header is already written')
+ end
+ end
+end
diff --git a/spec/ruby/library/zlib/gzipwriter/new_spec.rb b/spec/ruby/library/zlib/gzipwriter/new_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/new_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/open_spec.rb b/spec/ruby/library/zlib/gzipwriter/open_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/open_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/orig_name_spec.rb b/spec/ruby/library/zlib/gzipwriter/orig_name_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/orig_name_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/pos_spec.rb b/spec/ruby/library/zlib/gzipwriter/pos_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/pos_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/print_spec.rb b/spec/ruby/library/zlib/gzipwriter/print_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/print_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/printf_spec.rb b/spec/ruby/library/zlib/gzipwriter/printf_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/printf_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/putc_spec.rb b/spec/ruby/library/zlib/gzipwriter/putc_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/putc_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/puts_spec.rb b/spec/ruby/library/zlib/gzipwriter/puts_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/puts_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/tell_spec.rb b/spec/ruby/library/zlib/gzipwriter/tell_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/tell_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/gzipwriter/write_spec.rb b/spec/ruby/library/zlib/gzipwriter/write_spec.rb
new file mode 100644
index 0000000000..5ff4241423
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipwriter/write_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'stringio'
+require 'zlib'
+
+describe "GzipWriter#write" do
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+ @io = StringIO.new "".b
+ end
+
+ it "writes some compressed data" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.write @data
+ end
+
+ # skip gzip header for now
+ @io.string.unpack('C*')[10..-1].should == @zip.unpack('C*')[10..-1]
+ end
+
+ it "returns the number of bytes in the input" do
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.write(@data).should == @data.size
+ end
+ end
+
+ it "handles inputs of 2^23 bytes" do
+ input = '.'.b * (2 ** 23)
+
+ Zlib::GzipWriter.wrap @io do |gzio|
+ gzio.write input
+ end
+ @io.string.size.should == 8176
+ end
+end
diff --git a/spec/ruby/library/zlib/inflate/append_spec.rb b/spec/ruby/library/zlib/inflate/append_spec.rb
new file mode 100644
index 0000000000..a768a766a2
--- /dev/null
+++ b/spec/ruby/library/zlib/inflate/append_spec.rb
@@ -0,0 +1,60 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib::Inflate#<<" do
+ before :all do
+ @foo_deflated = [120, 156, 75, 203, 207, 7, 0, 2, 130, 1, 69].pack('C*')
+ end
+
+ before :each do
+ @z = Zlib::Inflate.new
+ end
+
+ after :each do
+ @z.close unless @z.closed?
+ end
+
+ it "appends data to the input stream" do
+ @z << @foo_deflated
+ @z.finish.should == 'foo'
+ end
+
+ it "treats nil argument as the end of compressed data" do
+ @z = Zlib::Inflate.new
+ @z << @foo_deflated << nil
+ @z.finish.should == 'foo'
+ end
+
+ it "just passes through the data after nil argument" do
+ @z = Zlib::Inflate.new
+ @z << @foo_deflated << nil
+ @z << "-after_nil_data"
+ @z.finish.should == 'foo-after_nil_data'
+ end
+
+ it "properly handles data in chunks" do
+ # add bytes, one by one
+ @foo_deflated.each_byte { |d| @z << d.chr}
+ @z.finish.should == "foo"
+ end
+
+ it "properly handles incomplete data" do
+ # add bytes, one by one
+ @foo_deflated[0, 5].each_byte { |d| @z << d.chr}
+ lambda { @z.finish }.should raise_error(Zlib::BufError)
+ end
+
+ it "properly handles excessive data, byte-by-byte" do
+ # add bytes, one by one
+ data = @foo_deflated * 2
+ data.each_byte { |d| @z << d.chr}
+ @z.finish.should == "foo" + @foo_deflated
+ end
+
+ it "properly handles excessive data, in one go" do
+ # add bytes, one by one
+ data = @foo_deflated * 2
+ @z << data
+ @z.finish.should == "foo" + @foo_deflated
+ end
+end
diff --git a/spec/ruby/library/zlib/inflate/finish_spec.rb b/spec/ruby/library/zlib/inflate/finish_spec.rb
new file mode 100644
index 0000000000..f6e592fb6b
--- /dev/null
+++ b/spec/ruby/library/zlib/inflate/finish_spec.rb
@@ -0,0 +1,28 @@
+require 'zlib'
+
+describe "Zlib::Inflate#finish" do
+
+ before do
+ @zeros = Zlib::Deflate.deflate("0" * 100_000)
+ @inflator = Zlib::Inflate.new
+ @chunks = []
+
+ @inflator.inflate(@zeros) do |chunk|
+ @chunks << chunk
+ break
+ end
+
+ @inflator.finish do |chunk|
+ @chunks << chunk
+ end
+ end
+
+ it "inflates chunked data" do
+ @chunks.map { |chunk| chunk.length }.should == [16384, 16384, 16384, 16384, 16384, 16384, 1696]
+ end
+
+ it "each chunk should have the same prefix" do
+ @chunks.all? { |chunk| chunk =~ /\A0+\z/ }.should be_true
+ end
+
+end
diff --git a/spec/ruby/library/zlib/inflate/inflate_spec.rb b/spec/ruby/library/zlib/inflate/inflate_spec.rb
new file mode 100644
index 0000000000..1fa16d9e98
--- /dev/null
+++ b/spec/ruby/library/zlib/inflate/inflate_spec.rb
@@ -0,0 +1,152 @@
+require 'zlib'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "Zlib::Inflate#inflate" do
+
+ before :each do
+ @inflator = Zlib::Inflate.new
+ end
+ it "inflates some data" do
+ data = [120, 156, 99, 96, 128, 1, 0, 0, 10, 0, 1].pack('C*')
+ unzipped = @inflator.inflate data
+ @inflator.finish
+
+ unzipped.should == "\000" * 10
+ end
+
+ it "inflates lots of data" do
+ data = [120, 156, 237, 193, 1, 1, 0, 0] +
+ [0, 128, 144, 254, 175, 238, 8, 10] +
+ Array.new(31, 0) +
+ [24, 128, 0, 0, 1]
+
+ unzipped = @inflator.inflate data.pack('C*')
+ @inflator.finish
+
+ unzipped.should == "\000" * 32 * 1024
+ end
+
+ it "works in pass-through mode, once finished" do
+ data = [120, 156, 99, 96, 128, 1, 0, 0, 10, 0, 1]
+ @inflator.inflate data.pack('C*')
+ @inflator.finish # this is a precondition
+
+ out = @inflator.inflate('uncompressed_data')
+ out << @inflator.finish
+ out.should == 'uncompressed_data'
+
+ @inflator << ('uncompressed_data') << nil
+ @inflator.finish.should == 'uncompressed_data'
+ end
+
+end
+
+describe "Zlib::Inflate.inflate" do
+
+ it "inflates some data" do
+ data = [120, 156, 99, 96, 128, 1, 0, 0, 10, 0, 1]
+ unzipped = Zlib::Inflate.inflate data.pack('C*')
+
+ unzipped.should == "\000" * 10
+ end
+
+ it "inflates lots of data" do
+ data = [120, 156, 237, 193, 1, 1, 0, 0] +
+ [0, 128, 144, 254, 175, 238, 8, 10] +
+ Array.new(31,0) +
+ [24, 128, 0, 0, 1]
+
+ zipped = Zlib::Inflate.inflate data.pack('C*')
+
+ zipped.should == "\000" * 32 * 1024
+ end
+
+ it "properly handles data in chunks" do
+ data = [120, 156, 75, 203, 207, 7, 0, 2, 130, 1, 69].pack('C*')
+ z = Zlib::Inflate.new
+ # add bytes, one by one
+ result = ""
+ data.each_byte { |d| result << z.inflate(d.chr)}
+ result << z.finish
+ result.should == "foo"
+ end
+
+ it "properly handles incomplete data" do
+ data = [120, 156, 75, 203, 207, 7, 0, 2, 130, 1, 69].pack('C*')[0,5]
+ z = Zlib::Inflate.new
+ # add bytes, one by one, but not all
+ result = ""
+ data.each_byte { |d| result << z.inflate(d.chr)}
+ lambda { result << z.finish }.should raise_error(Zlib::BufError)
+ end
+
+ it "properly handles excessive data, byte-by-byte" do
+ main_data = [120, 156, 75, 203, 207, 7, 0, 2, 130, 1, 69].pack('C*')
+ data = main_data * 2
+ result = ""
+
+ z = Zlib::Inflate.new
+ # add bytes, one by one
+ data.each_byte { |d| result << z.inflate(d.chr)}
+ result << z.finish
+
+ # the first chunk is inflated to its completion,
+ # the second chunk is just passed through.
+ result.should == "foo" + main_data
+ end
+
+ it "properly handles excessive data, in one go" do
+ main_data = [120, 156, 75, 203, 207, 7, 0, 2, 130, 1, 69].pack('C*')
+ data = main_data * 2
+ result = ""
+
+ z = Zlib::Inflate.new
+ result << z.inflate(data)
+ result << z.finish
+
+ # the first chunk is inflated to its completion,
+ # the second chunk is just passed through.
+ result.should == "foo" + main_data
+ end
+end
+
+describe "Zlib::Inflate#inflate" do
+
+ before do
+ @zeros = Zlib::Deflate.deflate("0" * 100_000)
+ @inflator = Zlib::Inflate.new
+ @chunks = []
+ end
+
+ describe "without break" do
+
+ before do
+ @inflator.inflate(@zeros) do |chunk|
+ @chunks << chunk
+ end
+ end
+
+ it "inflates chunked data" do
+ @chunks.map { |chunk| chunk.size }.should == [16384, 16384, 16384, 16384, 16384, 16384, 1696]
+ end
+
+ it "properly handles chunked data" do
+ @chunks.all? { |chunk| chunk =~ /\A0+\z/ }.should be_true
+ end
+ end
+
+ describe "with break" do
+
+ before do
+ @inflator.inflate(@zeros) do |chunk|
+ @chunks << chunk
+ break
+ end
+ end
+
+ it "inflates chunked break" do
+ output = @inflator.inflate nil
+ (100_000 - @chunks.first.length).should == output.length
+ end
+ end
+end
diff --git a/spec/ruby/library/zlib/inflate/new_spec.rb b/spec/ruby/library/zlib/inflate/new_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/inflate/new_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/inflate/set_dictionary_spec.rb b/spec/ruby/library/zlib/inflate/set_dictionary_spec.rb
new file mode 100644
index 0000000000..890815b8e6
--- /dev/null
+++ b/spec/ruby/library/zlib/inflate/set_dictionary_spec.rb
@@ -0,0 +1,21 @@
+# -*- encoding: binary -*-
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib::Inflate#set_dictionary" do
+ it "sets the inflate dictionary" do
+ deflated = "x\273\024\341\003\313KLJNIMK\317\310\314\002\000\025\206\003\370"
+
+ i = Zlib::Inflate.new
+
+ begin
+ i << deflated
+ flunk 'Zlib::NeedDict not raised'
+ rescue Zlib::NeedDict
+ i.set_dictionary 'aaaaaaaaaa'
+ end
+
+ i.finish.should == 'abcdefghij'
+ end
+end
+
diff --git a/spec/ruby/library/zlib/inflate/sync_point_spec.rb b/spec/ruby/library/zlib/inflate/sync_point_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/inflate/sync_point_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/inflate/sync_spec.rb b/spec/ruby/library/zlib/inflate/sync_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/inflate/sync_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zlib_version_spec.rb b/spec/ruby/library/zlib/zlib_version_spec.rb
new file mode 100644
index 0000000000..14fb93ef07
--- /dev/null
+++ b/spec/ruby/library/zlib/zlib_version_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/adler_spec.rb b/spec/ruby/library/zlib/zstream/adler_spec.rb
new file mode 100644
index 0000000000..e562fd260e
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/adler_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib::ZStream#adler" do
+ it "generates hash" do
+ z = Zlib::Deflate.new
+ z << "foo"
+ z.finish
+ z.adler.should == 0x02820145
+ end
+end
diff --git a/spec/ruby/library/zlib/zstream/avail_in_spec.rb b/spec/ruby/library/zlib/zstream/avail_in_spec.rb
new file mode 100644
index 0000000000..25d3219a5a
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/avail_in_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib::ZStream#avail_in" do
+ it "returns bytes in the input buffer" do
+ z = Zlib::Deflate.new
+ z.avail_in.should == 0
+ end
+end
diff --git a/spec/ruby/library/zlib/zstream/avail_out_spec.rb b/spec/ruby/library/zlib/zstream/avail_out_spec.rb
new file mode 100644
index 0000000000..c747bbbc2f
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/avail_out_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib::ZStream#avail_out" do
+ it "returns bytes in the output buffer" do
+ z = Zlib::Deflate.new
+ z.avail_out.should == 0
+ end
+end
diff --git a/spec/ruby/library/zlib/zstream/close_spec.rb b/spec/ruby/library/zlib/zstream/close_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/close_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/closed_spec.rb b/spec/ruby/library/zlib/zstream/closed_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/closed_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/data_type_spec.rb b/spec/ruby/library/zlib/zstream/data_type_spec.rb
new file mode 100644
index 0000000000..614f0d10a2
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/data_type_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib::ZStream#data_type" do
+ it "returns the type of the data in the stream" do
+ z = Zlib::Deflate.new
+ [Zlib::ASCII, Zlib::BINARY, Zlib::UNKNOWN].include?(z.data_type).should == true
+ end
+end
diff --git a/spec/ruby/library/zlib/zstream/end_spec.rb b/spec/ruby/library/zlib/zstream/end_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/end_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/ended_spec.rb b/spec/ruby/library/zlib/zstream/ended_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/ended_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/finish_spec.rb b/spec/ruby/library/zlib/zstream/finish_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/finish_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/finished_spec.rb b/spec/ruby/library/zlib/zstream/finished_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/finished_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/flush_next_in_spec.rb b/spec/ruby/library/zlib/zstream/flush_next_in_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/flush_next_in_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb b/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb
new file mode 100644
index 0000000000..8ba8414cd1
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'zlib'
+
+describe "Zlib::ZStream#flush_next_out" do
+
+ it "flushes the stream and flushes the output buffer" do
+ zs = Zlib::Inflate.new
+ zs << [120, 156, 75, 203, 207, 7, 0, 2, 130, 1, 69].pack('C*')
+
+ zs.flush_next_out.should == 'foo'
+ zs.finished?.should == true
+ zs.flush_next_out.should == ''
+ end
+end
+
+
diff --git a/spec/ruby/library/zlib/zstream/reset_spec.rb b/spec/ruby/library/zlib/zstream/reset_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/reset_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/stream_end_spec.rb b/spec/ruby/library/zlib/zstream/stream_end_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/stream_end_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/total_in_spec.rb b/spec/ruby/library/zlib/zstream/total_in_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/total_in_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
diff --git a/spec/ruby/library/zlib/zstream/total_out_spec.rb b/spec/ruby/library/zlib/zstream/total_out_spec.rb
new file mode 100644
index 0000000000..6a4c1dadb4
--- /dev/null
+++ b/spec/ruby/library/zlib/zstream/total_out_spec.rb
@@ -0,0 +1 @@
+require File.expand_path('../../../../spec_helper', __FILE__)